@pagelines/sdk 1.0.878 → 1.0.879

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 (92) hide show
  1. package/README.md +68 -68
  2. package/dist/BotProvider.js +777 -0
  3. package/dist/BotProvider.js.map +1 -0
  4. package/dist/{AgentWidgetInline.js → BotWidgetInline.js} +8 -8
  5. package/dist/BotWidgetInline.js.map +1 -0
  6. package/dist/{AgentWidgetModal.js → BotWidgetModal.js} +7 -7
  7. package/dist/BotWidgetModal.js.map +1 -0
  8. package/dist/{AgentWrap.js → BotWrap.js} +1174 -1145
  9. package/dist/BotWrap.js.map +1 -0
  10. package/dist/{agent/AgentController.d.ts → bot/BotController.d.ts} +35 -18
  11. package/dist/bot/index.d.ts +14 -0
  12. package/dist/{agent → bot}/schema.d.ts +6 -6
  13. package/dist/{agent/ui/AgentAvatar.vue.d.ts → bot/ui/BotAvatar.vue.d.ts} +6 -6
  14. package/dist/{agent/ui/AgentChat.vue.d.ts → bot/ui/BotChat.vue.d.ts} +5 -5
  15. package/dist/{agent/ui/AgentProvider.vue.d.ts → bot/ui/BotProvider.vue.d.ts} +3 -3
  16. package/dist/{agent/ui/AgentWrap.vue.d.ts → bot/ui/BotWrap.vue.d.ts} +3 -4
  17. package/dist/{agent/ui/ElAgentAbout.vue.d.ts → bot/ui/ElBotAbout.vue.d.ts} +2 -2
  18. package/dist/{agent/ui/ElAgentChat.vue.d.ts → bot/ui/ElBotChat.vue.d.ts} +5 -5
  19. package/dist/{agent/ui/ElAgentChatPreview.vue.d.ts → bot/ui/ElBotChatPreview.vue.d.ts} +1 -1
  20. package/dist/{agent/ui/ElAgentHeader.vue.d.ts → bot/ui/ElBotHeader.vue.d.ts} +2 -2
  21. package/dist/{agent/ui/ElAgentModeSidebar.vue.d.ts → bot/ui/ElBotModeSidebar.vue.d.ts} +2 -2
  22. package/dist/{agent/ui/ElAgentSidebar.vue.d.ts → bot/ui/ElBotSidebar.vue.d.ts} +2 -2
  23. package/dist/bot/ui/ElCreateBot.vue.d.ts +12 -0
  24. package/dist/{agent → bot}/ui/ElModeHeader.vue.d.ts +2 -2
  25. package/dist/{agent → bot}/ui/ElProvisioningStatus.vue.d.ts +1 -1
  26. package/dist/{agent → bot}/ui/VoiceMode.vue.d.ts +4 -4
  27. package/dist/{agent → bot}/utils.d.ts +5 -5
  28. package/dist/{agent → bot}/voice/provider.d.ts +2 -2
  29. package/dist/{agent → bot}/voice/providers/livekit/provider.d.ts +4 -4
  30. package/dist/{agent → bot}/voice/voice-session-client.d.ts +1 -1
  31. package/dist/{agent → bot}/work-journal.d.ts +1 -1
  32. package/dist/{agent.js → bot.js} +83 -80
  33. package/dist/bot.js.map +1 -0
  34. package/dist/clients/BillingClient.d.ts +1 -1
  35. package/dist/clients/BotClient.d.ts +26 -0
  36. package/dist/clients/ChatClient.d.ts +6 -5
  37. package/dist/clients/ComputerClient.d.ts +16 -0
  38. package/dist/clients/UserClient.d.ts +4 -7
  39. package/dist/clients/types.d.ts +7 -2
  40. package/dist/contract/build.d.ts +1 -2
  41. package/dist/index.d.ts +3 -2
  42. package/dist/provider.js +1 -1
  43. package/dist/provider.js.map +1 -1
  44. package/dist/provider2.js +14 -14
  45. package/dist/provider2.js.map +1 -1
  46. package/dist/sdk.css +1 -1
  47. package/dist/sdk.js +4 -4
  48. package/dist/sdkClient.d.ts +33 -376
  49. package/dist/sdkClient.js +168 -170
  50. package/dist/sdkClient.js.map +1 -1
  51. package/dist/useWidgetState.js +9 -9
  52. package/dist/useWidgetState.js.map +1 -1
  53. package/dist/widget/PLWidget.d.ts +6 -6
  54. package/dist/widget/composables/useWidgetState.d.ts +3 -402
  55. package/dist/widget/index.d.ts +2 -2
  56. package/dist/widget/mode.d.ts +2 -2
  57. package/dist/widget/ui/{AgentWidgetInline.vue.d.ts → BotWidgetInline.vue.d.ts} +2 -2
  58. package/dist/widget/ui/{AgentWidgetModal.vue.d.ts → BotWidgetModal.vue.d.ts} +2 -2
  59. package/dist/widget/ui/{AgentWidgetPopup.vue.d.ts → BotWidgetPopup.vue.d.ts} +4 -4
  60. package/dist/widget.js +206 -206
  61. package/dist/widget.js.map +1 -1
  62. package/package.json +5 -5
  63. package/dist/AgentProvider.js +0 -764
  64. package/dist/AgentProvider.js.map +0 -1
  65. package/dist/AgentWidgetInline.js.map +0 -1
  66. package/dist/AgentWidgetModal.js.map +0 -1
  67. package/dist/AgentWrap.js.map +0 -1
  68. package/dist/agent/index.d.ts +0 -14
  69. package/dist/agent/ui/ElCreateAgent.vue.d.ts +0 -277
  70. package/dist/agent.js.map +0 -1
  71. package/dist/clients/AgentClient.d.ts +0 -48
  72. /package/dist/{agent → bot}/VoiceRecorderController.d.ts +0 -0
  73. /package/dist/{agent/ui/AgentInputEmail.vue.d.ts → bot/ui/BotInputEmail.vue.d.ts} +0 -0
  74. /package/dist/{agent/ui/AgentInputOneTimeCode.vue.d.ts → bot/ui/BotInputOneTimeCode.vue.d.ts} +0 -0
  75. /package/dist/{agent/ui/AgentSidebarClose.vue.d.ts → bot/ui/BotSidebarClose.vue.d.ts} +0 -0
  76. /package/dist/{agent/ui/AgentToolActivityGroup.vue.d.ts → bot/ui/BotToolActivityGroup.vue.d.ts} +0 -0
  77. /package/dist/{agent/ui/AgentWidget.vue.d.ts → bot/ui/BotWidget.vue.d.ts} +0 -0
  78. /package/dist/{agent → bot}/ui/ChatCardBlock.vue.d.ts +0 -0
  79. /package/dist/{agent → bot}/ui/ChatRichText.vue.d.ts +0 -0
  80. /package/dist/{agent → bot}/ui/ChatScroller.vue.d.ts +0 -0
  81. /package/dist/{agent → bot}/ui/ChatVisualBlock.vue.d.ts +0 -0
  82. /package/dist/{agent → bot}/ui/ElAuthGate.vue.d.ts +0 -0
  83. /package/dist/{agent → bot}/ui/ElAuthPanel.vue.d.ts +0 -0
  84. /package/dist/{agent/ui/ElAgentButton.vue.d.ts → bot/ui/ElBotButton.vue.d.ts} +0 -0
  85. /package/dist/{agent → bot}/ui/ElSidebar.vue.d.ts +0 -0
  86. /package/dist/{agent → bot}/ui/VoiceHistogramController.d.ts +0 -0
  87. /package/dist/{agent → bot}/ui/chat-diagram-layout.d.ts +0 -0
  88. /package/dist/{agent → bot}/ui/chat-visual-format.d.ts +0 -0
  89. /package/dist/{agent → bot}/ui/voice-mode-presentation.d.ts +0 -0
  90. /package/dist/{agent → bot}/voice/voice-error-copy.d.ts +0 -0
  91. /package/dist/{agent → bot}/voice/voice-work-state.d.ts +0 -0
  92. /package/dist/widget/ui/{AgentWidgetOnboard.vue.d.ts → BotWidgetOnboard.vue.d.ts} +0 -0
@@ -1,19 +1,19 @@
1
1
  import "./rolldown-runtime.js";
2
- import { c as e, s as t } from "./sdkClient.js";
3
- import { f as n, i as r, m as i, n as a, p as o, r as s, t as c } from "./AgentWrap.js";
4
- import { n as l, t as u } from "./AgentProvider.js";
2
+ import { c as e, l as t } from "./sdkClient.js";
3
+ import { f as n, i as r, n as i, r as a, t as o } from "./BotWrap.js";
4
+ import { i as s, n as c, r as l, t as u } from "./BotProvider.js";
5
5
  import { n as d, t as f } from "./provider.js";
6
- import { SettingsObject as p, readChatEventStream as m, zVoiceSessionMint as h } from "@pagelines/core";
7
- import { Fragment as g, createBlock as _, createCommentVNode as v, createElementBlock as y, createElementVNode as b, createVNode as x, defineComponent as S, nextTick as C, normalizeClass as w, normalizeStyle as T, openBlock as E, ref as D, renderList as O, watch as k, withCtx as A } from "vue";
8
- //#region agent/ui/AgentWidget.vue?vue&type=script&setup=true&lang.ts
9
- var j = {
6
+ import { SettingsObject as p, detectBrowserTimezone as m, readChatEventStream as h, zVoiceSessionMint as g } from "@pagelines/core";
7
+ import { Fragment as _, createBlock as v, createCommentVNode as y, createElementBlock as b, createElementVNode as x, createVNode as S, defineComponent as C, nextTick as w, normalizeClass as T, normalizeStyle as E, openBlock as D, ref as O, renderList as k, watch as A, withCtx as j } from "vue";
8
+ //#region bot/ui/BotWidget.vue?vue&type=script&setup=true&lang.ts
9
+ var M = {
10
10
  key: 0,
11
11
  class: "relative h-full w-full"
12
- }, M = { class: "group relative h-full w-full rounded-3xl overflow-hidden shadow-lg transition-all duration-300 ease-[cubic-bezier(0.25,1,0.33,1)] hover:shadow-2xl hover:translate-y-[-1px] hover:brightness-110 active:scale-[1.06] active:-translate-y-0.5 active:duration-100" }, N = ["src", "alt"], P = {
12
+ }, N = { class: "group relative h-full w-full rounded-3xl overflow-hidden shadow-lg transition-all duration-300 ease-[cubic-bezier(0.25,1,0.33,1)] hover:shadow-2xl hover:translate-y-[-1px] hover:brightness-110 active:scale-[1.06] active:-translate-y-0.5 active:duration-100" }, P = ["src", "alt"], F = {
13
13
  key: 0,
14
14
  class: "absolute top-0.5 right-0.5"
15
- }, F = /* @__PURE__ */ S({
16
- __name: "AgentWidget",
15
+ }, I = /* @__PURE__ */ C({
16
+ __name: "BotWidget",
17
17
  props: {
18
18
  sdk: {},
19
19
  handle: {},
@@ -22,12 +22,12 @@ var j = {
22
22
  position: {}
23
23
  },
24
24
  setup(e, { expose: t }) {
25
- let n = e, r = D(!1), i = D(!1);
25
+ let n = e, r = O(!1), i = O(!1);
26
26
  function toggle() {
27
27
  r.value = !r.value;
28
28
  }
29
- k(r, async (e) => {
30
- e ? (await C(), setTimeout(() => {
29
+ A(r, async (e) => {
30
+ e ? (await w(), setTimeout(() => {
31
31
  i.value = !0;
32
32
  }, 400)) : i.value = !1;
33
33
  });
@@ -44,33 +44,33 @@ var j = {
44
44
  toggle,
45
45
  open,
46
46
  close
47
- }), (t, a) => (E(), _(c, {
47
+ }), (t, a) => (D(), v(o, {
48
48
  sdk: e.sdk,
49
49
  handle: e.handle,
50
50
  context: e.context,
51
51
  "first-message": e.firstMessage
52
52
  }, {
53
- default: A(({ agent: t, sdk: o }) => [t ? (E(), y("div", {
53
+ default: j(({ bot: t, sdk: o }) => [t ? (D(), b("div", {
54
54
  key: 0,
55
- class: w(["fixed z-[999999] pointer-events-auto", [n.position === "bottom-left" ? "bottom-6 left-6" : n.position === "top-right" ? "top-6 right-6" : n.position === "top-left" ? "top-6 left-6" : "bottom-6 right-6"]])
56
- }, [b("div", {
57
- class: w(["transition-all duration-500 ease-[cubic-bezier(0.25,1,0.33,1)] transform-gpu", [r.value ? "widget-expanded w-96 h-[600px] max-w-[calc(100vw-48px)] max-h-[calc(100vh-48px)] rounded-3xl opacity-100 scale-100" : "widget-button w-[80px] h-[80px] opacity-100 scale-100 flex items-center justify-center cursor-pointer"]]),
58
- style: T({ "transform-origin": n.position === "bottom-left" ? "bottom left" : n.position === "top-right" ? "top right" : n.position === "top-left" ? "top left" : "bottom right" }),
55
+ class: T(["fixed z-[999999] pointer-events-auto", [n.position === "bottom-left" ? "bottom-6 left-6" : n.position === "top-right" ? "top-6 right-6" : n.position === "top-left" ? "top-6 left-6" : "bottom-6 right-6"]])
56
+ }, [x("div", {
57
+ class: T(["transition-all duration-500 ease-[cubic-bezier(0.25,1,0.33,1)] transform-gpu", [r.value ? "widget-expanded w-96 h-[600px] max-w-[calc(100vw-48px)] max-h-[calc(100vh-48px)] rounded-3xl opacity-100 scale-100" : "widget-button w-[80px] h-[80px] opacity-100 scale-100 flex items-center justify-center cursor-pointer"]]),
58
+ style: E({ "transform-origin": n.position === "bottom-left" ? "bottom left" : n.position === "top-right" ? "top right" : n.position === "top-left" ? "top left" : "bottom right" }),
59
59
  onClick: a[0] || (a[0] = (e) => r.value ? void 0 : toggle())
60
- }, [r.value ? v("", !0) : (E(), y("div", j, [b("div", M, [b("img", {
60
+ }, [r.value ? y("", !0) : (D(), b("div", M, [x("div", N, [x("img", {
61
61
  src: t.avatarUrl.value,
62
62
  alt: `${t.displayName.value} assistant`,
63
63
  class: "h-full w-full object-cover pointer-events-none",
64
64
  width: "80",
65
65
  height: "80"
66
- }, null, 8, N), a[1] || (a[1] = b("div", { class: "absolute inset-0 pointer-events-none bg-gradient-to-br from-transparent via-black/10 to-black/40 opacity-60 transition-opacity duration-300 group-hover:opacity-40" }, null, -1))]), t.state.value.lifecycle === "running" ? (E(), y("div", P, [...a[2] || (a[2] = [b("div", {
66
+ }, null, 8, P), a[1] || (a[1] = x("div", { class: "absolute inset-0 pointer-events-none bg-gradient-to-br from-transparent via-black/10 to-black/40 opacity-60 transition-opacity duration-300 group-hover:opacity-40" }, null, -1))]), t.state.value.lifecycle === "running" ? (D(), b("div", F, [...a[2] || (a[2] = [x("div", {
67
67
  class: "size-3 bg-green-500 rounded-full ring-2 ring-white absolute animate-ping",
68
68
  style: { "animation-duration": "3s" }
69
- }, null, -1), b("div", { class: "size-3 bg-green-500 rounded-full ring-2 ring-white" }, null, -1)])])) : v("", !0)])), r.value && t ? (E(), _(l, {
69
+ }, null, -1), x("div", { class: "size-3 bg-green-500 rounded-full ring-2 ring-white" }, null, -1)])])) : y("", !0)])), r.value && t ? (D(), v(c, {
70
70
  key: 1,
71
71
  class: "rounded-3xl shadow-2xl border border-white/10",
72
72
  sdk: o,
73
- agent: t,
73
+ bot: t,
74
74
  context: e.context,
75
75
  "first-message": e.firstMessage,
76
76
  "has-close": !0,
@@ -78,11 +78,11 @@ var j = {
78
78
  onClose: handleClose
79
79
  }, null, 8, [
80
80
  "sdk",
81
- "agent",
81
+ "bot",
82
82
  "context",
83
83
  "first-message",
84
84
  "is-active"
85
- ])) : v("", !0)], 6)], 2)) : v("", !0)]),
85
+ ])) : y("", !0)], 6)], 2)) : y("", !0)]),
86
86
  _: 1
87
87
  }, 8, [
88
88
  "sdk",
@@ -91,29 +91,29 @@ var j = {
91
91
  "first-message"
92
92
  ]));
93
93
  }
94
- }), I = ["data-sender"], L = /* @__PURE__ */ S({
95
- __name: "ElAgentChatPreview",
94
+ }), L = ["data-sender"], R = /* @__PURE__ */ C({
95
+ __name: "ElBotChatPreview",
96
96
  props: {
97
97
  messages: {},
98
98
  variant: {}
99
99
  },
100
100
  setup(e) {
101
- return (t, n) => (E(), y("div", {
102
- class: w(["@container/chat-preview flex flex-col gap-3", e.variant === "dark" ? "text-white" : "text-slate-950"]),
103
- "data-test": "agent-chat-preview"
104
- }, [(E(!0), y(g, null, O(e.messages, (t, n) => (E(), y("div", {
101
+ return (t, n) => (D(), b("div", {
102
+ class: T(["@container/chat-preview flex flex-col gap-3", e.variant === "dark" ? "text-white" : "text-slate-950"]),
103
+ "data-test": "bot-chat-preview"
104
+ }, [(D(!0), b(_, null, k(e.messages, (t, n) => (D(), b("div", {
105
105
  key: `${t.sender}-${n}`,
106
- class: w(["flex", t.sender === "user" ? "justify-end" : "justify-start"]),
107
- "data-test": "agent-chat-preview-message",
106
+ class: T(["flex", t.sender === "user" ? "justify-end" : "justify-start"]),
107
+ "data-test": "bot-chat-preview-message",
108
108
  "data-sender": t.sender
109
- }, [b("div", { class: w(["max-w-[88%] rounded-2xl px-4 py-3 text-sm shadow-sm @sm/chat-preview:max-w-[78%]", t.sender === "user" ? "bg-slate-950 text-white" : e.variant === "dark" ? "border border-white/10 bg-white/10 text-white" : "border border-slate-200 bg-white text-slate-950"]) }, [x(r, {
109
+ }, [x("div", { class: T(["max-w-[88%] rounded-2xl px-4 py-3 text-sm shadow-sm @sm/chat-preview:max-w-[78%]", t.sender === "user" ? "bg-slate-950 text-white" : e.variant === "dark" ? "border border-white/10 bg-white/10 text-white" : "border border-slate-200 bg-white text-slate-950"]) }, [S(r, {
110
110
  text: t.text,
111
111
  inverted: t.sender === "user" || e.variant === "dark"
112
- }, null, 8, ["text", "inverted"])], 2)], 10, I))), 128))], 2));
112
+ }, null, 8, ["text", "inverted"])], 2)], 10, L))), 128))], 2));
113
113
  }
114
114
  });
115
115
  //#endregion
116
- //#region agent/voice/voice-work-state.ts
116
+ //#region bot/voice/voice-work-state.ts
117
117
  function createVoiceWorkState() {
118
118
  return { turnIds: /* @__PURE__ */ new Set() };
119
119
  }
@@ -150,30 +150,30 @@ function reduceVoiceWorkEvent(e, t) {
150
150
  } : e;
151
151
  }
152
152
  //#endregion
153
- //#region agent/voice/voice-session-client.ts
154
- var R = {
153
+ //#region bot/voice/voice-session-client.ts
154
+ var z = {
155
155
  start: "/audio/start-call.mp3",
156
156
  end: "/audio/end-call.mp3"
157
- }, z = .7, B = 50, V = 15e3, H = 3e3;
157
+ }, B = .7, V = 50, H = 15e3, U = 3e3;
158
158
  function unlockAudio(e, t) {
159
159
  for (let n of e) n.muted = !0, n.play().catch(() => {}), n.pause(), n.currentTime = 0, n.muted = !1, n.volume = t;
160
160
  }
161
161
  function createBrowserVoiceChimePlayer(e) {
162
- let t = Object.fromEntries(Object.entries(R).map(([t, n]) => {
162
+ let t = Object.fromEntries(Object.entries(z).map(([t, n]) => {
163
163
  let r = new Audio(`${e}${n}`);
164
- return r.preload = "auto", r.volume = z, [t, r];
164
+ return r.preload = "auto", r.volume = B, [t, r];
165
165
  }));
166
166
  return {
167
167
  play: (e) => {
168
168
  t[e].currentTime = 0, t[e].play().catch(() => {});
169
169
  },
170
- unlock: () => unlockAudio(Object.values(t), z)
170
+ unlock: () => unlockAudio(Object.values(t), B)
171
171
  };
172
172
  }
173
- var U = .16;
173
+ var W = .16;
174
174
  function createBrowserVoiceWorkCue(e) {
175
175
  let t = new Audio(`${e}/audio/thinking.mp3`);
176
- return t.preload = "auto", t.loop = !0, t.volume = U, {
176
+ return t.preload = "auto", t.loop = !0, t.volume = W, {
177
177
  setActive: (e) => {
178
178
  if (e) {
179
179
  t.play().catch(() => {});
@@ -181,19 +181,19 @@ function createBrowserVoiceWorkCue(e) {
181
181
  }
182
182
  t.pause(), t.currentTime = 0;
183
183
  },
184
- unlock: () => unlockAudio([t], U)
184
+ unlock: () => unlockAudio([t], W)
185
185
  };
186
186
  }
187
187
  var VoiceSessionClient = class extends p {
188
- constructor(e) {
189
- super("VoiceSessionClient", e), t(this, "state", D("idle")), t(this, "isMuted", D(!1)), t(this, "provider", void 0), t(this, "teardownPromise", void 0), t(this, "providerName", void 0), t(this, "chime", void 0), t(this, "workCue", void 0), t(this, "generation", 0), t(this, "levelTimer", void 0), t(this, "startAtMs", 0), t(this, "liveAtMs", 0), t(this, "firstPlaybackEmitted", !1), t(this, "mutePending", !1), t(this, "conversationId", void 0), t(this, "workAbort", void 0), t(this, "workState", createVoiceWorkState()), t(this, "workCuePlaying", !1), t(this, "workCueWanted", !1), t(this, "workCuePending", void 0), t(this, "thinking", !1), t(this, "speaking", {
188
+ constructor(t) {
189
+ super("VoiceSessionClient", t), e(this, "state", O("idle")), e(this, "isMuted", O(!1)), e(this, "provider", void 0), e(this, "teardownPromise", void 0), e(this, "providerName", void 0), e(this, "chime", void 0), e(this, "workCue", void 0), e(this, "generation", 0), e(this, "levelTimer", void 0), e(this, "startAtMs", 0), e(this, "liveAtMs", 0), e(this, "firstPlaybackEmitted", !1), e(this, "mutePending", !1), e(this, "conversationId", void 0), e(this, "workAbort", void 0), e(this, "workState", createVoiceWorkState()), e(this, "workCuePlaying", !1), e(this, "workCueWanted", !1), e(this, "workCuePending", void 0), e(this, "thinking", !1), e(this, "speaking", {
190
190
  user: !1,
191
- agent: !1
192
- }), this.chime = e.playChime ? {
193
- play: e.playChime,
191
+ bot: !1
192
+ }), this.chime = t.playChime ? {
193
+ play: t.playChime,
194
194
  unlock: () => {}
195
- } : void 0, this.workCue = e.setWorkCue ? {
196
- setActive: e.setWorkCue,
195
+ } : void 0, this.workCue = t.setWorkCue ? {
196
+ setActive: t.setWorkCue,
197
197
  unlock: () => {}
198
198
  } : void 0;
199
199
  }
@@ -232,7 +232,7 @@ var VoiceSessionClient = class extends p {
232
232
  let i = r.connect({
233
233
  onDisconnected: (e) => {
234
234
  if (!(n !== this.generation || this.provider !== r)) {
235
- if (this.state.value === "live" && e === "agent") {
235
+ if (this.state.value === "live" && e === "bot") {
236
236
  this.generation++, this.playChime("end"), this.setState("ended"), this.teardown();
237
237
  return;
238
238
  }
@@ -254,7 +254,7 @@ var VoiceSessionClient = class extends p {
254
254
  }), a;
255
255
  try {
256
256
  await Promise.race([i, new Promise((e, t) => {
257
- a = setTimeout(() => t(Object.assign(/* @__PURE__ */ Error("Voice connection timed out."), { code: "VOICE_CONNECT_TIMEOUT" })), V);
257
+ a = setTimeout(() => t(Object.assign(/* @__PURE__ */ Error("Voice connection timed out."), { code: "VOICE_CONNECT_TIMEOUT" })), H);
258
258
  })]);
259
259
  } catch (e) {
260
260
  if (i.then(() => r.disconnect()).catch(() => {}), n !== this.generation || this.provider !== r) return;
@@ -313,7 +313,7 @@ var VoiceSessionClient = class extends p {
313
313
  let e = !!this.workState.activeTurnId;
314
314
  this.workState = createVoiceWorkState(), this.thinking = !1, e && this.settings.onWorkChange?.({ active: !1 }), this.setSpeaking({
315
315
  user: !1,
316
- agent: !1
316
+ bot: !1
317
317
  }), this.settings.onThinkingChange?.(!1), this.workCueWanted = !1, this.workCuePending !== void 0 && (clearTimeout(this.workCuePending), this.workCuePending = void 0), this.setWorkCue(!1), this.levelTimer !== void 0 && (clearInterval(this.levelTimer), this.levelTimer = void 0);
318
318
  let t = this.provider;
319
319
  return this.provider = void 0, this.isMuted.value = !1, this.settings.onLevel?.({
@@ -324,9 +324,9 @@ var VoiceSessionClient = class extends p {
324
324
  startLevelTimer(e, t) {
325
325
  this.levelTimer === void 0 && (this.levelTimer = setInterval(() => {
326
326
  if (t !== this.generation || this.provider !== e) return;
327
- let n = e.sampleLevel(this.speaking.agent ? "playback" : this.speaking.user ? "mic" : void 0);
327
+ let n = e.sampleLevel(this.speaking.bot ? "playback" : this.speaking.user ? "mic" : void 0);
328
328
  n && (this.settings.onLevel?.(n), !this.firstPlaybackEmitted && n.source === "playback" && d(n.level) && this.liveAtMs > 0 && (this.firstPlaybackEmitted = !0, this.emitMetric("voice.first_playback", Date.now() - this.liveAtMs)));
329
- }, B));
329
+ }, V));
330
330
  }
331
331
  authHeaders() {
332
332
  return this.settings.token ? { Authorization: `Bearer ${this.settings.token}` } : {};
@@ -338,16 +338,16 @@ var VoiceSessionClient = class extends p {
338
338
  body: {
339
339
  ...e,
340
340
  client: "web",
341
- agentId: this.settings.agentId,
341
+ botId: this.settings.botId,
342
342
  ...this.conversationId ? { conversationId: this.conversationId } : {}
343
343
  }
344
344
  }).catch(() => {});
345
345
  }
346
- startWorkStream(t, n) {
346
+ startWorkStream(e, n) {
347
347
  this.workAbort?.abort();
348
348
  let r = new AbortController();
349
349
  this.workAbort = r;
350
- let i = e(this.settings.apiBase, this.settings.isDev), a = this.settings.fetchFn ?? fetch, o = this.settings.latestSequence ? `${i}/api/conversations/${encodeURIComponent(t)}/stream?since=${encodeURIComponent(this.settings.latestSequence)}` : `${i}/api/conversations/${encodeURIComponent(t)}/stream`;
350
+ let i = t(this.settings.apiBase, this.settings.isDev), a = this.settings.fetchFn ?? fetch, o = this.settings.latestSequence ? `${i}/api/conversations/${encodeURIComponent(e)}/stream?since=${encodeURIComponent(this.settings.latestSequence)}` : `${i}/api/conversations/${encodeURIComponent(e)}/stream`;
351
351
  (async () => {
352
352
  let e = await a(o, {
353
353
  headers: {
@@ -357,7 +357,7 @@ var VoiceSessionClient = class extends p {
357
357
  credentials: "include",
358
358
  signal: r.signal
359
359
  });
360
- if (!(!e.ok || !e.body)) for await (let t of m(e.body.getReader())) {
360
+ if (!(!e.ok || !e.body)) for await (let t of h(e.body.getReader())) {
361
361
  if (r.signal.aborted || n !== this.generation) return;
362
362
  let e = this.workState, i = reduceVoiceWorkEvent(e, t);
363
363
  i !== e && (this.workState = i, (i.activeTurnId !== e.activeTurnId || i.description !== e.description) && (this.settings.onWorkChange?.({
@@ -370,18 +370,18 @@ var VoiceSessionClient = class extends p {
370
370
  setSpeaking(e) {
371
371
  let t = {
372
372
  user: e.user && !this.isMuted.value,
373
- agent: e.agent
373
+ bot: e.bot
374
374
  };
375
- t.user === this.speaking.user && t.agent === this.speaking.agent || (this.speaking = t, this.settings.onSpeakingChange?.(t), this.updateWorkCue());
375
+ t.user === this.speaking.user && t.bot === this.speaking.bot || (this.speaking = t, this.settings.onSpeakingChange?.(t), this.updateWorkCue());
376
376
  }
377
377
  updateWorkCue() {
378
- let e = this.state.value === "live" && (this.thinking || !!this.workState.activeTurnId) && !this.speaking.user && !this.speaking.agent;
378
+ let e = this.state.value === "live" && (this.thinking || !!this.workState.activeTurnId) && !this.speaking.user && !this.speaking.bot;
379
379
  if (e !== this.workCueWanted) {
380
380
  if (this.workCueWanted = e, this.workCuePending !== void 0 && (clearTimeout(this.workCuePending), this.workCuePending = void 0), e) {
381
381
  let e = this.generation;
382
382
  this.workCuePending = setTimeout(() => {
383
383
  this.workCuePending = void 0, e === this.generation && this.workCueWanted && this.setWorkCue(!0);
384
- }, this.settings.workCueDelayMs ?? H);
384
+ }, this.settings.workCueDelayMs ?? U);
385
385
  return;
386
386
  }
387
387
  this.setWorkCue(!1);
@@ -391,24 +391,24 @@ var VoiceSessionClient = class extends p {
391
391
  this.workCuePlaying !== e && (this.workCuePlaying = e, this.ensureWorkCue().setActive(e));
392
392
  }
393
393
  ensureWorkCue() {
394
- return this.workCue ?? (this.workCue = createBrowserVoiceWorkCue(e(this.settings.apiBase, this.settings.isDev))), this.workCue;
394
+ return this.workCue ?? (this.workCue = createBrowserVoiceWorkCue(t(this.settings.apiBase, this.settings.isDev))), this.workCue;
395
395
  }
396
396
  ensureChime() {
397
- return this.chime ?? (this.chime = createBrowserVoiceChimePlayer(e(this.settings.apiBase, this.settings.isDev))), this.chime;
397
+ return this.chime ?? (this.chime = createBrowserVoiceChimePlayer(t(this.settings.apiBase, this.settings.isDev))), this.chime;
398
398
  }
399
399
  playChime(e) {
400
400
  this.ensureChime().play(e);
401
401
  }
402
- async post(t) {
403
- let n = e(this.settings.apiBase, this.settings.isDev), r = await (this.settings.fetchFn ?? fetch)(`${n}${t.path}`, {
402
+ async post(e) {
403
+ let n = t(this.settings.apiBase, this.settings.isDev), r = await (this.settings.fetchFn ?? fetch)(`${n}${e.path}`, {
404
404
  method: "POST",
405
405
  headers: {
406
406
  "Content-Type": "application/json",
407
407
  ...this.authHeaders()
408
408
  },
409
409
  credentials: "include",
410
- keepalive: t.keepalive,
411
- body: JSON.stringify(t.body)
410
+ keepalive: e.keepalive,
411
+ body: JSON.stringify(e.body)
412
412
  }), i = await r.json();
413
413
  if (!r.ok || !i.ok) {
414
414
  let e = i.ok ? `HTTP ${r.status}` : i.error, t = !i.ok && i.code ? i.code : "VOICE_MINT_FAILED";
@@ -423,19 +423,22 @@ var VoiceSessionClient = class extends p {
423
423
  body: {
424
424
  orgId: this.settings.orgId,
425
425
  participants: [{
426
- type: "agent",
427
- id: this.settings.agentId
426
+ type: "bot",
427
+ id: this.settings.botId
428
428
  }]
429
429
  }
430
430
  })).conversationId, e !== this.generation)) return null;
431
- let n = await this.post({
431
+ let n = m(), r = await this.post({
432
432
  path: "/api/voice/sessions",
433
- body: { conversationId: t }
433
+ body: {
434
+ conversationId: t,
435
+ ...n ? { viewerTimezone: n } : {}
436
+ }
434
437
  });
435
438
  if (e !== this.generation) return null;
436
- let r = h.safeParse(n);
437
- if (!r.success) throw Object.assign(/* @__PURE__ */ Error("Voice session mint returned an unexpected shape."), { code: "VOICE_MINT_INVALID" });
438
- return this.conversationId = t, r.data;
439
+ let i = g.safeParse(r);
440
+ if (!i.success) throw Object.assign(/* @__PURE__ */ Error("Voice session mint returned an unexpected shape."), { code: "VOICE_MINT_INVALID" });
441
+ return this.conversationId = t, i.data;
439
442
  }
440
443
  toSessionError(e, t) {
441
444
  return e instanceof Error ? {
@@ -448,6 +451,6 @@ var VoiceSessionClient = class extends p {
448
451
  }
449
452
  };
450
453
  //#endregion
451
- export { o as AGENT_MODES, i as Agent, l as AgentChat, n as AgentChatController, n as AgentController, u as AgentProvider, F as AgentWidget, c as AgentWrap, a as ElAgentChat, L as ElAgentChatPreview, s as VoiceMode, VoiceSessionClient };
454
+ export { l as BOT_MODES, s as Bot, c as BotChat, n as BotChatController, u as BotProvider, I as BotWidget, o as BotWrap, i as ElBotChat, R as ElBotChatPreview, a as VoiceMode, VoiceSessionClient };
452
455
 
453
- //# sourceMappingURL=agent.js.map
456
+ //# sourceMappingURL=bot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bot.js","names":[],"sources":["../bot/ui/BotWidget.vue","../bot/ui/BotWidget.vue","../bot/ui/ElBotChatPreview.vue","../bot/ui/ElBotChatPreview.vue","../bot/voice/voice-work-state.ts","../bot/voice/voice-session-client.ts"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { PageLinesSDK } from '../../sdkClient'\nimport { nextTick, ref, watch } from 'vue'\nimport BotChat from './BotChat.vue'\nimport BotWrap from './BotWrap.vue'\n\ninterface Props {\n sdk?: PageLinesSDK\n handle: string\n context?: string\n firstMessage?: string\n position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'\n}\n\nconst props = defineProps<Props>()\nconst isOpen = ref(false)\nconst isBotActive = ref(false)\n\nfunction toggle() {\n isOpen.value = !isOpen.value\n}\n\n// Watch isOpen to delay bot activation for smooth transition\nwatch(isOpen, async (newValue) => {\n if (newValue) {\n // When opening, delay bot activation until transition starts\n await nextTick()\n setTimeout(() => {\n isBotActive.value = true\n }, 400) // Delay to let container expand first\n } else {\n // When closing, immediately deactivate bot\n isBotActive.value = false\n }\n})\n\nfunction open() {\n isOpen.value = true\n}\n\nfunction close() {\n isOpen.value = false\n}\n\nfunction handleClose() {\n close()\n}\n\ndefineExpose({\n toggle,\n open,\n close,\n})\n</script>\n\n<template>\n <BotWrap\n v-slot=\"{ bot, sdk: resolvedSdk }\"\n :sdk=\"sdk\"\n :handle=\"handle\"\n :context=\"context\"\n :first-message=\"firstMessage\"\n >\n <!-- Fixed Widget Wrapper -->\n <div\n v-if=\"bot\"\n class=\"fixed z-[999999] pointer-events-auto\"\n :class=\"[\n props.position === 'bottom-left' ? 'bottom-6 left-6'\n : props.position === 'top-right' ? 'top-6 right-6'\n : props.position === 'top-left' ? 'top-6 left-6'\n : 'bottom-6 right-6',\n ]\"\n >\n <!-- Widget Content with Transition -->\n <div\n class=\"transition-all duration-500 ease-[cubic-bezier(0.25,1,0.33,1)] transform-gpu\"\n :class=\"[\n isOpen\n ? 'widget-expanded w-96 h-[600px] max-w-[calc(100vw-48px)] max-h-[calc(100vh-48px)] rounded-3xl opacity-100 scale-100'\n : 'widget-button w-[80px] h-[80px] opacity-100 scale-100 flex items-center justify-center cursor-pointer',\n ]\"\n :style=\"{\n 'transform-origin':\n props.position === 'bottom-left' ? 'bottom left'\n : props.position === 'top-right' ? 'top right'\n : props.position === 'top-left' ? 'top left'\n : 'bottom right',\n }\"\n @click=\"!isOpen ? toggle() : undefined\"\n >\n <!-- Button Content (visible when closed) -->\n <div v-if=\"!isOpen\" class=\"relative h-full w-full\">\n <div class=\"group relative h-full w-full rounded-3xl overflow-hidden shadow-lg transition-all duration-300 ease-[cubic-bezier(0.25,1,0.33,1)] hover:shadow-2xl hover:translate-y-[-1px] hover:brightness-110 active:scale-[1.06] active:-translate-y-0.5 active:duration-100\">\n <img\n :src=\"bot.avatarUrl.value\"\n :alt=\"`${bot.displayName.value} assistant`\"\n class=\"h-full w-full object-cover pointer-events-none\"\n width=\"80\"\n height=\"80\"\n />\n <!-- Gradient overlay for contrast -->\n <div class=\"absolute inset-0 pointer-events-none bg-gradient-to-br from-transparent via-black/10 to-black/40 opacity-60 transition-opacity duration-300 group-hover:opacity-40\" />\n </div>\n <!-- Online indicator -->\n <div v-if=\"bot.state.value.lifecycle === 'running'\" class=\"absolute top-0.5 right-0.5\">\n <div class=\"size-3 bg-green-500 rounded-full ring-2 ring-white absolute animate-ping\" style=\"animation-duration: 3s;\" />\n <div class=\"size-3 bg-green-500 rounded-full ring-2 ring-white\" />\n </div>\n </div>\n\n <!-- Chat Content (visible when open) -->\n <BotChat\n v-if=\"isOpen && bot\"\n class=\"rounded-3xl shadow-2xl border border-white/10\"\n :sdk=\"resolvedSdk\"\n :bot=\"bot\"\n :context=\"context\"\n :first-message=\"firstMessage\"\n :has-close=\"true\"\n :is-active=\"isBotActive\"\n @close=\"handleClose\"\n />\n </div>\n </div>\n </BotWrap>\n</template>\n","<script setup lang=\"ts\">\nimport type { PageLinesSDK } from '../../sdkClient'\nimport { nextTick, ref, watch } from 'vue'\nimport BotChat from './BotChat.vue'\nimport BotWrap from './BotWrap.vue'\n\ninterface Props {\n sdk?: PageLinesSDK\n handle: string\n context?: string\n firstMessage?: string\n position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'\n}\n\nconst props = defineProps<Props>()\nconst isOpen = ref(false)\nconst isBotActive = ref(false)\n\nfunction toggle() {\n isOpen.value = !isOpen.value\n}\n\n// Watch isOpen to delay bot activation for smooth transition\nwatch(isOpen, async (newValue) => {\n if (newValue) {\n // When opening, delay bot activation until transition starts\n await nextTick()\n setTimeout(() => {\n isBotActive.value = true\n }, 400) // Delay to let container expand first\n } else {\n // When closing, immediately deactivate bot\n isBotActive.value = false\n }\n})\n\nfunction open() {\n isOpen.value = true\n}\n\nfunction close() {\n isOpen.value = false\n}\n\nfunction handleClose() {\n close()\n}\n\ndefineExpose({\n toggle,\n open,\n close,\n})\n</script>\n\n<template>\n <BotWrap\n v-slot=\"{ bot, sdk: resolvedSdk }\"\n :sdk=\"sdk\"\n :handle=\"handle\"\n :context=\"context\"\n :first-message=\"firstMessage\"\n >\n <!-- Fixed Widget Wrapper -->\n <div\n v-if=\"bot\"\n class=\"fixed z-[999999] pointer-events-auto\"\n :class=\"[\n props.position === 'bottom-left' ? 'bottom-6 left-6'\n : props.position === 'top-right' ? 'top-6 right-6'\n : props.position === 'top-left' ? 'top-6 left-6'\n : 'bottom-6 right-6',\n ]\"\n >\n <!-- Widget Content with Transition -->\n <div\n class=\"transition-all duration-500 ease-[cubic-bezier(0.25,1,0.33,1)] transform-gpu\"\n :class=\"[\n isOpen\n ? 'widget-expanded w-96 h-[600px] max-w-[calc(100vw-48px)] max-h-[calc(100vh-48px)] rounded-3xl opacity-100 scale-100'\n : 'widget-button w-[80px] h-[80px] opacity-100 scale-100 flex items-center justify-center cursor-pointer',\n ]\"\n :style=\"{\n 'transform-origin':\n props.position === 'bottom-left' ? 'bottom left'\n : props.position === 'top-right' ? 'top right'\n : props.position === 'top-left' ? 'top left'\n : 'bottom right',\n }\"\n @click=\"!isOpen ? toggle() : undefined\"\n >\n <!-- Button Content (visible when closed) -->\n <div v-if=\"!isOpen\" class=\"relative h-full w-full\">\n <div class=\"group relative h-full w-full rounded-3xl overflow-hidden shadow-lg transition-all duration-300 ease-[cubic-bezier(0.25,1,0.33,1)] hover:shadow-2xl hover:translate-y-[-1px] hover:brightness-110 active:scale-[1.06] active:-translate-y-0.5 active:duration-100\">\n <img\n :src=\"bot.avatarUrl.value\"\n :alt=\"`${bot.displayName.value} assistant`\"\n class=\"h-full w-full object-cover pointer-events-none\"\n width=\"80\"\n height=\"80\"\n />\n <!-- Gradient overlay for contrast -->\n <div class=\"absolute inset-0 pointer-events-none bg-gradient-to-br from-transparent via-black/10 to-black/40 opacity-60 transition-opacity duration-300 group-hover:opacity-40\" />\n </div>\n <!-- Online indicator -->\n <div v-if=\"bot.state.value.lifecycle === 'running'\" class=\"absolute top-0.5 right-0.5\">\n <div class=\"size-3 bg-green-500 rounded-full ring-2 ring-white absolute animate-ping\" style=\"animation-duration: 3s;\" />\n <div class=\"size-3 bg-green-500 rounded-full ring-2 ring-white\" />\n </div>\n </div>\n\n <!-- Chat Content (visible when open) -->\n <BotChat\n v-if=\"isOpen && bot\"\n class=\"rounded-3xl shadow-2xl border border-white/10\"\n :sdk=\"resolvedSdk\"\n :bot=\"bot\"\n :context=\"context\"\n :first-message=\"firstMessage\"\n :has-close=\"true\"\n :is-active=\"isBotActive\"\n @close=\"handleClose\"\n />\n </div>\n </div>\n </BotWrap>\n</template>\n","<script setup lang=\"ts\">\nimport ChatRichText from './ChatRichText.vue'\n\nexport type ChatPreviewMessage = {\n sender: 'user' | 'bot'\n text: string\n}\n\ndefineProps<{\n messages: ChatPreviewMessage[]\n variant?: 'light' | 'dark'\n}>()\n</script>\n\n<template>\n <div\n class=\"@container/chat-preview flex flex-col gap-3\"\n :class=\"variant === 'dark' ? 'text-white' : 'text-slate-950'\"\n data-test=\"bot-chat-preview\"\n >\n <div\n v-for=\"(message, index) in messages\"\n :key=\"`${message.sender}-${index}`\"\n class=\"flex\"\n :class=\"message.sender === 'user' ? 'justify-end' : 'justify-start'\"\n data-test=\"bot-chat-preview-message\"\n :data-sender=\"message.sender\"\n >\n <div\n class=\"max-w-[88%] rounded-2xl px-4 py-3 text-sm shadow-sm @sm/chat-preview:max-w-[78%]\"\n :class=\"message.sender === 'user'\n ? 'bg-slate-950 text-white'\n : variant === 'dark'\n ? 'border border-white/10 bg-white/10 text-white'\n : 'border border-slate-200 bg-white text-slate-950'\"\n >\n <ChatRichText\n :text=\"message.text\"\n :inverted=\"message.sender === 'user' || variant === 'dark'\"\n />\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport ChatRichText from './ChatRichText.vue'\n\nexport type ChatPreviewMessage = {\n sender: 'user' | 'bot'\n text: string\n}\n\ndefineProps<{\n messages: ChatPreviewMessage[]\n variant?: 'light' | 'dark'\n}>()\n</script>\n\n<template>\n <div\n class=\"@container/chat-preview flex flex-col gap-3\"\n :class=\"variant === 'dark' ? 'text-white' : 'text-slate-950'\"\n data-test=\"bot-chat-preview\"\n >\n <div\n v-for=\"(message, index) in messages\"\n :key=\"`${message.sender}-${index}`\"\n class=\"flex\"\n :class=\"message.sender === 'user' ? 'justify-end' : 'justify-start'\"\n data-test=\"bot-chat-preview-message\"\n :data-sender=\"message.sender\"\n >\n <div\n class=\"max-w-[88%] rounded-2xl px-4 py-3 text-sm shadow-sm @sm/chat-preview:max-w-[78%]\"\n :class=\"message.sender === 'user'\n ? 'bg-slate-950 text-white'\n : variant === 'dark'\n ? 'border border-white/10 bg-white/10 text-white'\n : 'border border-slate-200 bg-white text-slate-950'\"\n >\n <ChatRichText\n :text=\"message.text\"\n :inverted=\"message.sender === 'user' || variant === 'dark'\"\n />\n </div>\n </div>\n </div>\n</template>\n","import type { ChatEvent } from '@pagelines/core'\n\nexport interface VoiceWorkState {\n turnIds: ReadonlySet<string>\n activeTurnId?: string\n description?: string\n}\n\nexport function createVoiceWorkState(): VoiceWorkState {\n return { turnIds: new Set() }\n}\n\n/** Project canonical conversation events onto the one active voice work line. */\nexport function reduceVoiceWorkEvent(state: VoiceWorkState, event: ChatEvent): VoiceWorkState {\n if (event.event === 'message') {\n const message = event.data.message\n if (message.role === 'user' && message.metadata?.clientContext === 'voice') {\n return { ...state, turnIds: new Set(state.turnIds).add(message.messageId) }\n }\n const turnId = typeof message.metadata?.turnId === 'string' ? message.metadata.turnId : undefined\n if (turnId && state.turnIds.has(turnId)) {\n const turnIds = new Set(state.turnIds)\n turnIds.delete(turnId)\n return state.activeTurnId === turnId ? { turnIds } : { ...state, turnIds }\n }\n return state\n }\n\n const turnId = 'turnId' in event.data && typeof event.data.turnId === 'string'\n ? event.data.turnId\n : undefined\n if (!turnId || !state.turnIds.has(turnId))\n return state\n\n if (event.event === 'working_state') {\n return {\n ...state,\n activeTurnId: turnId,\n description: event.data.description.trim() || 'Working on it',\n }\n }\n if (event.event === 'tool_activity' && event.data.status === 'started') {\n return {\n ...state,\n activeTurnId: turnId,\n description: event.data.label,\n }\n }\n if (event.event === 'working_end' || event.event === 'stream_end')\n return { ...state, activeTurnId: undefined, description: undefined }\n return state\n}\n","/** Provider-neutral voice session state machine for web clients. */\nimport type { ApiResponse, VoiceClientMetric, VoiceSessionMint } from '@pagelines/core'\nimport type { Ref } from 'vue'\nimport type {\n CreateVoiceProviderClient,\n VoiceLevelEvent,\n VoiceProviderClient,\n VoiceSessionError,\n VoiceSpeakingState,\n} from './provider'\nimport { detectBrowserTimezone, readChatEventStream, SettingsObject, zVoiceSessionMint } from '@pagelines/core'\nimport { ref } from 'vue'\nimport { resolveApiBase } from '../../api'\nimport { createVoiceProviderClient, isVoiceAudible } from './provider'\nimport { createVoiceWorkState, reduceVoiceWorkEvent } from './voice-work-state'\n\nexport type { VoiceLevelEvent, VoiceSessionError, VoiceSpeakingState } from './provider'\nexport { isVoiceAudible, VOICE_SPECTRUM_BANDS, voiceSpectrum } from './provider'\n\nexport type VoiceSessionClientState = 'idle' | 'minting' | 'connecting' | 'live' | 'ended'\nexport type VoiceChimeKind = 'start' | 'end'\nexport interface VoiceWorkStatus { active: boolean, description?: string }\n\n/** Client-owned latency phases — speech-end-to-first-text is measured on the handler. */\nexport type VoiceMetric = Pick<VoiceClientMetric, 'name' | 'durationMs' | 'provider' | 'phase' | 'code'>\nexport type VoiceMetricName = VoiceMetric['name']\n\nexport interface VoiceClientHandlers {\n onStateChange?: (state: VoiceSessionClientState) => void\n onLevel?: (event: VoiceLevelEvent) => void\n onError?: (error: VoiceSessionError) => void\n onThinkingChange?: (thinking: boolean) => void\n onSpeakingChange?: (state: VoiceSpeakingState) => void\n /** Fire-and-forget latency phases for product observability. */\n onMetric?: (metric: VoiceMetric) => void\n onWorkChange?: (work: VoiceWorkStatus) => void\n}\n\nexport interface VoiceSessionClientSettings extends VoiceClientHandlers, Record<string, unknown> {\n botId: string\n orgId: string\n conversationId?: string\n /** Last message already loaded by the host; the work stream starts after it. */\n latestSequence?: string\n apiBase?: string\n isDev?: boolean\n token?: string\n fetchFn?: typeof fetch\n /** Provider composition seam; the default dynamically loads the minted provider. */\n createProvider?: CreateVoiceProviderClient\n playChime?: (kind: VoiceChimeKind) => void\n /** Test seam; production uses the quiet looping work asset. */\n setWorkCue?: (active: boolean) => void\n /** Test seam; production waits WORK_CUE_DELAY_MS before the work loop starts. */\n workCueDelayMs?: number\n}\n\nconst CHIME_PATHS: Record<VoiceChimeKind, string> = {\n start: '/audio/start-call.mp3',\n end: '/audio/end-call.mp3',\n}\nconst CHIME_VOLUME = 0.7\nconst LEVEL_INTERVAL_MS = 50\nconst CONNECT_TIMEOUT_MS = 15_000\n/** Waiting must outlive this before the loop starts — normal turns stay silent. */\nconst WORK_CUE_DELAY_MS = 3_000\n\n/**\n * A chime player plus the one call that makes it audible later.\n *\n * `unlock` must run inside the user gesture that starts the call. The start\n * chime plays after minting and connecting — seconds of async — by which\n * time the gesture has expired and the autoplay policy rejects `play()`.\n * The rejection is swallowed (a missing cue must never take a call down),\n * so the failure is completely silent: exactly the reported bug, a call that\n * connects without ever announcing itself.\n */\nexport interface VoiceChimePlayer {\n play: (kind: VoiceChimeKind) => void\n unlock: () => void\n}\n\n/**\n * Mark elements user-activated so they can be played later without a gesture.\n *\n * Two details decide whether this works, and both are easy to get wrong:\n *\n * `muted`, not `volume` — iOS Safari treats `HTMLMediaElement.volume` as\n * read-only, so silencing by volume is a no-op there and the unlock plays the\n * cue out loud at full volume. iOS is the platform whose policy makes this\n * necessary at all, so getting it wrong there defeats the whole exercise.\n *\n * Stop synchronously, not from the `play()` promise. That promise settles only\n * once playback actually begins, which on a slow connection can be after the\n * real cue has been asked for — the pending stop then pauses the cue the\n * moment it starts. The activation is granted when `play()` is *called* inside\n * the gesture, so pausing on the next line keeps it and removes the race. The\n * interrupted `play()` rejects with `AbortError`; that is expected.\n */\nfunction unlockAudio(elements: HTMLAudioElement[], volume: number): void {\n for (const audio of elements) {\n audio.muted = true\n void audio.play().catch(() => {})\n audio.pause()\n audio.currentTime = 0\n audio.muted = false\n audio.volume = volume\n }\n}\n\n/**\n * The readiness cue is the only signal an eyes-off user gets, so it is served\n * from the API origin rather than the embedding page — a relative path would\n * silently 404 wherever the SDK is not hosted by the app itself.\n */\nexport function createBrowserVoiceChimePlayer(apiBase: string): VoiceChimePlayer {\n const players = Object.fromEntries(Object.entries(CHIME_PATHS).map(([kind, path]) => {\n const audio = new Audio(`${apiBase}${path}`)\n audio.preload = 'auto'\n audio.volume = CHIME_VOLUME\n return [kind, audio]\n })) as Record<VoiceChimeKind, HTMLAudioElement>\n return {\n play: (kind) => {\n players[kind].currentTime = 0\n // Still guarded: a browser that refuses anyway must not break the call.\n void players[kind].play().catch(() => {})\n },\n unlock: () => unlockAudio(Object.values(players), CHIME_VOLUME),\n }\n}\n\nconst WORK_CUE_VOLUME = 0.16\n\n/**\n * The work loop has the chime's problem and worse odds: it first plays from a\n * `WORK_CUE_DELAY_MS` timer, so it is *never* inside a gesture. It needs the\n * same unlock, which is why the session unlocks its audio as a set rather than\n * each caller solving it alone.\n */\nfunction createBrowserVoiceWorkCue(apiBase: string): { setActive: (active: boolean) => void, unlock: () => void } {\n const audio = new Audio(`${apiBase}/audio/thinking.mp3`)\n audio.preload = 'auto'\n audio.loop = true\n audio.volume = WORK_CUE_VOLUME\n return {\n setActive: (active) => {\n if (active) {\n void audio.play().catch(() => {})\n return\n }\n audio.pause()\n audio.currentTime = 0\n },\n unlock: () => unlockAudio([audio], WORK_CUE_VOLUME),\n }\n}\n\nexport class VoiceSessionClient extends SettingsObject<VoiceSessionClientSettings> {\n readonly state: Ref<VoiceSessionClientState> = ref('idle')\n readonly isMuted: Ref<boolean> = ref(false)\n\n private provider?: VoiceProviderClient\n private teardownPromise?: Promise<void>\n private providerName?: VoiceSessionMint['provider']\n private chime?: VoiceChimePlayer\n private workCue?: { setActive: (active: boolean) => void, unlock: () => void }\n private generation = 0\n private levelTimer: ReturnType<typeof setInterval> | undefined\n private startAtMs = 0\n private liveAtMs = 0\n private firstPlaybackEmitted = false\n private mutePending = false\n private conversationId?: string\n private workAbort?: AbortController\n private workState = createVoiceWorkState()\n private workCuePlaying = false\n private workCueWanted = false\n private workCuePending?: ReturnType<typeof setTimeout>\n private thinking = false\n private speaking: VoiceSpeakingState = { user: false, bot: false }\n\n constructor(settings: VoiceSessionClientSettings) {\n super('VoiceSessionClient', settings)\n // The injected seam is a bare function; tests do not need unlocking.\n this.chime = settings.playChime ? { play: settings.playChime, unlock: () => {} } : undefined\n this.workCue = settings.setWorkCue ? { setActive: settings.setWorkCue, unlock: () => {} } : undefined\n }\n\n async start(): Promise<void> {\n if (this.state.value !== 'idle')\n return\n // Before the first await, while the tap that started the call still\n // counts as consent. Everything after this point is async — the chimes\n // wait on minting and connecting, the work loop on a 3s timer — so this\n // is the only moment any of them can be authorised.\n this.ensureChime().unlock()\n this.ensureWorkCue().unlock()\n const generation = ++this.generation\n this.startAtMs = Date.now()\n this.liveAtMs = 0\n this.providerName = undefined\n this.firstPlaybackEmitted = false\n this.workState = createVoiceWorkState()\n this.thinking = false\n this.setState('minting')\n try {\n const mint = await this.mintSession(generation)\n if (!mint || generation !== this.generation)\n return\n if (this.conversationId)\n this.startWorkStream(this.conversationId, generation)\n this.setState('connecting')\n await this.connect({ mint, generation })\n } catch (error) {\n if (generation !== this.generation)\n return\n this.fail(this.toSessionError(error, 'VOICE_MINT_FAILED'))\n }\n }\n\n async end(): Promise<void> {\n if (this.state.value === 'idle')\n return\n if (this.state.value === 'ended')\n return this.teardown()\n const shouldChime = this.state.value === 'live'\n this.generation++\n if (shouldChime)\n this.playChime('end')\n this.setState('ended')\n await this.teardown()\n }\n\n private async connect(args: { mint: VoiceSessionMint, generation: number }): Promise<void> {\n const { mint, generation } = args\n this.providerName = mint.provider\n const provider = await (this.settings.createProvider ?? createVoiceProviderClient)(mint)\n if (generation !== this.generation) {\n await provider.disconnect().catch(() => {})\n return\n }\n this.provider = provider\n\n const connectPromise = provider.connect({\n onDisconnected: (cause) => {\n if (generation !== this.generation || this.provider !== provider)\n return\n if (this.state.value === 'live' && cause === 'bot') {\n this.generation++\n this.playChime('end')\n this.setState('ended')\n void this.teardown()\n return\n }\n this.fail({\n code: this.state.value === 'live' ? 'VOICE_CONNECTION_LOST' : 'VOICE_CONNECT_FAILED',\n message: this.state.value === 'live'\n ? 'The voice connection dropped.'\n : 'Could not open the voice connection.',\n })\n },\n onError: error => {\n if (generation === this.generation && this.provider === provider)\n this.fail(error)\n },\n onThinkingChange: thinking => {\n if (generation === this.generation && this.provider === provider) {\n this.thinking = thinking\n this.settings.onThinkingChange?.(thinking)\n this.updateWorkCue()\n }\n },\n onSpeakingChange: state => {\n if (generation === this.generation && this.provider === provider)\n this.setSpeaking(state)\n },\n })\n let timeoutId: ReturnType<typeof setTimeout> | undefined\n try {\n await Promise.race([\n connectPromise,\n new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => reject(Object.assign(new Error('Voice connection timed out.'), { code: 'VOICE_CONNECT_TIMEOUT' })), CONNECT_TIMEOUT_MS)\n }),\n ])\n } catch (error) {\n void connectPromise.then(() => provider.disconnect()).catch(() => {})\n if (generation !== this.generation || this.provider !== provider)\n return\n this.fail(this.toSessionError(error, 'VOICE_CONNECT_FAILED'))\n return\n } finally {\n if (timeoutId)\n clearTimeout(timeoutId)\n }\n if (generation !== this.generation || this.provider !== provider)\n return\n\n this.startLevelTimer(provider, generation)\n this.liveAtMs = Date.now()\n this.setState('live')\n this.updateWorkCue()\n this.emitMetric('voice.ready', this.liveAtMs - this.startAtMs)\n this.playChime('start')\n }\n\n /** True while a live provider can accept typed text as a spoken turn. */\n get canSendUserMessage(): boolean {\n return this.state.value === 'live' && !!this.provider?.sendUserMessage\n }\n\n sendUserMessage(text: string): boolean {\n const body = text.trim()\n if (!body || !this.canSendUserMessage)\n return false\n this.provider!.sendUserMessage!(body)\n return true\n }\n\n /** Returns the applied state, or undefined when mute is unavailable or fails. */\n async toggleMuted(): Promise<boolean | undefined> {\n const provider = this.provider\n if (this.state.value !== 'live' || !provider?.setMuted || this.mutePending)\n return undefined\n const generation = this.generation\n const next = !this.isMuted.value\n this.mutePending = true\n try {\n await provider.setMuted(next)\n if (generation !== this.generation || this.provider !== provider || this.state.value !== 'live')\n return undefined\n this.isMuted.value = next\n // Mute clears the caller's activity and nothing else: working, thinking,\n // and playback carry on.\n if (next && this.speaking.user)\n this.setSpeaking({ ...this.speaking, user: false })\n return next\n }\n catch {\n return undefined\n }\n finally {\n this.mutePending = false\n }\n }\n\n private emitMetric(name: VoiceMetricName, durationMs: number, details: Pick<VoiceMetric, 'phase' | 'code'> = {}): void {\n const metric: VoiceMetric = {\n name,\n durationMs: Math.max(0, Math.round(durationMs)),\n ...(this.providerName ? { provider: this.providerName } : {}),\n ...details,\n }\n this.settings.onMetric?.(metric)\n this.postMetric(metric)\n }\n\n private setState(state: VoiceSessionClientState): void {\n if (this.state.value === state)\n return\n this.state.value = state\n this.settings.onStateChange?.(state)\n }\n\n private fail(error: VoiceSessionError): void {\n const shouldChime = this.state.value === 'live'\n if (this.startAtMs > 0) {\n this.emitMetric('voice.failed', Date.now() - this.startAtMs, {\n phase: this.state.value,\n code: error.code,\n })\n }\n this.generation++\n if (shouldChime)\n this.playChime('end')\n this.settings.onError?.(error)\n this.setState('ended')\n void this.teardown()\n }\n\n private teardown(): Promise<void> {\n if (this.teardownPromise)\n return this.teardownPromise\n this.workAbort?.abort()\n this.workAbort = undefined\n const hadWork = !!this.workState.activeTurnId\n this.workState = createVoiceWorkState()\n this.thinking = false\n if (hadWork)\n this.settings.onWorkChange?.({ active: false })\n this.setSpeaking({ user: false, bot: false })\n this.settings.onThinkingChange?.(false)\n this.workCueWanted = false\n if (this.workCuePending !== undefined) {\n clearTimeout(this.workCuePending)\n this.workCuePending = undefined\n }\n this.setWorkCue(false)\n if (this.levelTimer !== undefined) {\n clearInterval(this.levelTimer)\n this.levelTimer = undefined\n }\n const provider = this.provider\n this.provider = undefined\n this.isMuted.value = false\n this.settings.onLevel?.({ source: 'playback', level: 0 })\n this.teardownPromise = provider?.disconnect().catch(() => {}) ?? Promise.resolve()\n return this.teardownPromise\n }\n\n private startLevelTimer(provider: VoiceProviderClient, generation: number): void {\n if (this.levelTimer !== undefined)\n return\n this.levelTimer = setInterval(() => {\n if (generation !== this.generation || this.provider !== provider)\n return\n // The transport's speaker state picks the meter: the mic analyser hears\n // the speaker too, so \"loudest wins\" flickered green over the assistant.\n const level = provider.sampleLevel(this.speaking.bot ? 'playback' : this.speaking.user ? 'mic' : undefined)\n if (!level)\n return\n this.settings.onLevel?.(level)\n if (\n !this.firstPlaybackEmitted\n && level.source === 'playback'\n && isVoiceAudible(level.level)\n && this.liveAtMs > 0\n ) {\n this.firstPlaybackEmitted = true\n this.emitMetric('voice.first_playback', Date.now() - this.liveAtMs)\n }\n }, LEVEL_INTERVAL_MS)\n }\n\n private authHeaders(): Record<string, string> {\n return this.settings.token ? { Authorization: `Bearer ${this.settings.token}` } : {}\n }\n\n private postMetric(metric: VoiceMetric): void {\n void this.post<{ recorded: boolean }>({\n path: '/api/voice/metrics',\n keepalive: true,\n body: {\n ...metric,\n client: 'web',\n botId: this.settings.botId,\n ...(this.conversationId ? { conversationId: this.conversationId } : {}),\n },\n }).catch(() => {})\n }\n\n private startWorkStream(conversationId: string, generation: number): void {\n this.workAbort?.abort()\n const abort = new AbortController()\n this.workAbort = abort\n const apiBase = resolveApiBase(this.settings.apiBase, this.settings.isDev)\n const fetchFn = this.settings.fetchFn ?? fetch\n const streamUrl = this.settings.latestSequence\n ? `${apiBase}/api/conversations/${encodeURIComponent(conversationId)}/stream?since=${encodeURIComponent(this.settings.latestSequence)}`\n : `${apiBase}/api/conversations/${encodeURIComponent(conversationId)}/stream`\n void (async () => {\n const response = await fetchFn(streamUrl, {\n headers: { Accept: 'text/event-stream', ...this.authHeaders() },\n credentials: 'include',\n signal: abort.signal,\n })\n if (!response.ok || !response.body)\n return\n for await (const event of readChatEventStream(response.body.getReader())) {\n if (abort.signal.aborted || generation !== this.generation)\n return\n const previous = this.workState\n const next = reduceVoiceWorkEvent(previous, event)\n if (next === previous)\n continue\n this.workState = next\n if (next.activeTurnId !== previous.activeTurnId || next.description !== previous.description) {\n this.settings.onWorkChange?.({\n active: !!next.activeTurnId,\n ...(next.description ? { description: next.description } : {}),\n })\n this.updateWorkCue()\n }\n }\n })().catch(() => {})\n }\n\n private setSpeaking(next: VoiceSpeakingState): void {\n const applied = { user: next.user && !this.isMuted.value, bot: next.bot }\n if (applied.user === this.speaking.user && applied.bot === this.speaking.bot)\n return\n this.speaking = applied\n this.settings.onSpeakingChange?.(applied)\n this.updateWorkCue()\n }\n\n /**\n * Duck on speech, not on energy: room tone kept the loop from ever\n * starting. The loop starts only once waiting outlives the dwell — a blip\n * shorter than that is a normal turn and stays silent.\n */\n private updateWorkCue(): void {\n const wanted = this.state.value === 'live'\n && (this.thinking || !!this.workState.activeTurnId)\n && !this.speaking.user\n && !this.speaking.bot\n if (wanted === this.workCueWanted)\n return\n this.workCueWanted = wanted\n if (this.workCuePending !== undefined) {\n clearTimeout(this.workCuePending)\n this.workCuePending = undefined\n }\n if (wanted) {\n const generation = this.generation\n this.workCuePending = setTimeout(() => {\n this.workCuePending = undefined\n if (generation === this.generation && this.workCueWanted)\n this.setWorkCue(true)\n }, this.settings.workCueDelayMs ?? WORK_CUE_DELAY_MS)\n return\n }\n this.setWorkCue(false)\n }\n\n private setWorkCue(active: boolean): void {\n if (this.workCuePlaying === active)\n return\n this.workCuePlaying = active\n this.ensureWorkCue().setActive(active)\n }\n\n private ensureWorkCue(): { setActive: (active: boolean) => void, unlock: () => void } {\n this.workCue ??= createBrowserVoiceWorkCue(resolveApiBase(this.settings.apiBase, this.settings.isDev))\n return this.workCue\n }\n\n private ensureChime(): VoiceChimePlayer {\n this.chime ??= createBrowserVoiceChimePlayer(resolveApiBase(this.settings.apiBase, this.settings.isDev))\n return this.chime\n }\n\n private playChime(kind: VoiceChimeKind): void {\n this.ensureChime().play(kind)\n }\n\n private async post<T>(args: { path: string, body: unknown, keepalive?: boolean }): Promise<T> {\n const apiBase = resolveApiBase(this.settings.apiBase, this.settings.isDev)\n const fetchFn = this.settings.fetchFn ?? fetch\n const res = await fetchFn(`${apiBase}${args.path}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...this.authHeaders() },\n credentials: 'include',\n keepalive: args.keepalive,\n body: JSON.stringify(args.body),\n })\n const result = await res.json() as ApiResponse<T>\n if (!res.ok || !result.ok) {\n const message = !result.ok ? result.error : `HTTP ${res.status}`\n const code = !result.ok && result.code ? result.code : 'VOICE_MINT_FAILED'\n throw Object.assign(new Error(message || 'Voice request failed.'), { code })\n }\n return result.data\n }\n\n private async mintSession(generation: number): Promise<VoiceSessionMint | null> {\n let conversationId = this.settings.conversationId\n if (!conversationId) {\n conversationId = (await this.post<{ conversationId: string }>({\n path: '/api/conversations',\n body: {\n orgId: this.settings.orgId,\n participants: [{ type: 'bot', id: this.settings.botId }],\n },\n })).conversationId\n if (generation !== this.generation)\n return null\n }\n\n const viewerTimezone = detectBrowserTimezone()\n const data = await this.post<unknown>({\n path: '/api/voice/sessions',\n body: { conversationId, ...(viewerTimezone ? { viewerTimezone } : {}) },\n })\n if (generation !== this.generation)\n return null\n const parsed = zVoiceSessionMint.safeParse(data)\n if (!parsed.success)\n throw Object.assign(new Error('Voice session mint returned an unexpected shape.'), { code: 'VOICE_MINT_INVALID' })\n this.conversationId = conversationId\n return parsed.data\n }\n\n private toSessionError(error: unknown, fallbackCode: string): VoiceSessionError {\n return error instanceof Error\n ? {\n code: 'code' in error ? String((error as Error & { code: unknown }).code) : fallbackCode,\n message: error.message,\n }\n : { code: fallbackCode, message: 'Voice session failed to start.' }\n }\n}\n"],"mappings":"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"}
@@ -3,7 +3,7 @@ export interface BillingStatus {
3
3
  plan?: string;
4
4
  status: string;
5
5
  hasActiveBilling: boolean;
6
- maxAgents: number;
6
+ maxBots: number;
7
7
  trialEnd?: string;
8
8
  trialDaysRemaining?: number;
9
9
  paymentRecovery?: {
@@ -0,0 +1,26 @@
1
+ import { BotData, ComputerData, Bot, Computer } from '@pagelines/core';
2
+ import { SDKContext } from './types';
3
+ export declare class BotClient {
4
+ private ctx;
5
+ private computers;
6
+ private bots;
7
+ constructor(ctx: Pick<SDKContext, 'apiFetch'>);
8
+ get(botId: string): Bot | undefined;
9
+ computer(computerId: string): Computer | undefined;
10
+ all(): Bot[];
11
+ hydrate(roster: {
12
+ computers: ComputerData[];
13
+ bots: BotData[];
14
+ }): Bot[];
15
+ clear(): void;
16
+ webhook<T = Record<string, unknown>>(args: {
17
+ botId: string;
18
+ key: string;
19
+ type: string;
20
+ data: T;
21
+ meta?: Record<string, unknown>;
22
+ }): Promise<{
23
+ ok: boolean;
24
+ error?: string;
25
+ }>;
26
+ }
@@ -1,5 +1,5 @@
1
1
  import { ChatAttachmentInput, ChatToolActivityData, ChatStreamError } from '@pagelines/core';
2
- import { ChatMessage } from '../agent/schema';
2
+ import { ChatMessage } from '../bot/schema';
3
3
  import { SDKContext } from './types';
4
4
  type CancelConversationTurnResponse = {
5
5
  cancelled: boolean;
@@ -13,7 +13,7 @@ export declare class ChatClient {
13
13
  turnId?: string;
14
14
  }): Promise<CancelConversationTurnResponse>;
15
15
  /**
16
- * Public/visitor chat — anonymous chat against an agent's public handle,
16
+ * Public/visitor chat — anonymous chat against an bot's public handle,
17
17
  * routed through the messaging substrate. Same SSE wire format as
18
18
  * `chatStreamAuthenticated` — the only difference is the route (no auth,
19
19
  * handle-based lookup, anonymousId instead of userId).
@@ -42,14 +42,15 @@ export declare class ChatClient {
42
42
  * sequence, then POST /api/messages. Opening the stream before send keeps
43
43
  * fast working_state / message_delta frames from outrunning the subscriber.
44
44
  * Same callback contract as `chatStream` so callers don't need transport details.
45
- * Mirrors `src/modules/agent/client.ts → sendChatMessageStream`.
45
+ * Mirrors `src/modules/bot/client.ts → sendChatMessageStream`.
46
46
  */
47
47
  chatStreamAuthenticated(args: {
48
- agentId: string;
48
+ botId: string;
49
+ orgId: string;
49
50
  message: string;
50
51
  attachments?: ChatAttachmentInput[];
51
- /** Reserved — substrate resolves conversation server-side from (userId, agentId). */
52
52
  conversationId?: string;
53
+ latestSequence?: string | null;
53
54
  /** Reserved — substrate replays history from the canonical messages table. */
54
55
  history?: Array<{
55
56
  role: 'user' | 'assistant';
@@ -0,0 +1,16 @@
1
+ import { Bot, CreateComputerBody, LiveStatus } from '@pagelines/core';
2
+ import { SDKContext } from './types';
3
+ import { BotClient } from './BotClient';
4
+ export declare class ComputerClient {
5
+ private ctx;
6
+ private registry;
7
+ constructor(ctx: Pick<SDKContext, 'apiFetch' | 'logger' | 'token'>, registry: Pick<BotClient, 'hydrate' | 'computer'>);
8
+ create(body: CreateComputerBody): Promise<Bot>;
9
+ getLiveStatus(computerId: string): Promise<LiveStatus>;
10
+ waitUntilReady(args: {
11
+ computerId: string;
12
+ onStatus?: (lifecycle: LiveStatus['lifecycle']) => void;
13
+ timeoutMs?: number;
14
+ pollIntervalMs?: number;
15
+ }): Promise<void>;
16
+ }
@@ -1,18 +1,15 @@
1
- import { AgentConfig } from '@pagelines/core';
1
+ import { Bot } from '@pagelines/core';
2
2
  import { SDKContext } from './types';
3
3
  export declare class UserClient {
4
4
  private ctx;
5
5
  constructor(ctx: SDKContext);
6
- getPublicAgent(args: {
6
+ getPublicBot(args: {
7
7
  handle: string;
8
- }): Promise<AgentConfig | undefined>;
9
- getAgentByEmail(args: {
10
- email: string;
11
- }): Promise<AgentConfig | undefined>;
8
+ }): Promise<Bot | undefined>;
12
9
  generateAnonId(): string;
13
10
  track(args: {
14
11
  event: 'view_profile' | 'profile_interaction';
15
- agentId: string;
12
+ botId: string;
16
13
  properties?: Record<string, any>;
17
14
  }): void;
18
15
  }
@@ -1,4 +1,4 @@
1
- import { AgentConfig, ApiResponse, EnrichedUser, LogHelper } from '@pagelines/core';
1
+ import { Bot, BotData, ComputerData, ApiResponse, EnrichedUser, LogHelper } from '@pagelines/core';
2
2
  import { ComputedRef, Ref } from 'vue';
3
3
  import { SDKStorage } from '../sdkStorage';
4
4
  export interface SDKContext {
@@ -9,7 +9,12 @@ export interface SDKContext {
9
9
  token: Ref<string | null>;
10
10
  loading: Ref<boolean>;
11
11
  error: Ref<string | null>;
12
- currentAgent: ComputedRef<AgentConfig | undefined>;
12
+ currentBot: ComputedRef<Bot | undefined>;
13
+ hydrateRoster: (roster: {
14
+ computers: ComputerData[];
15
+ bots: BotData[];
16
+ }) => Bot[];
17
+ clearRoster: () => void;
13
18
  storage: SDKStorage;
14
19
  sessionId: string;
15
20
  logger: LogHelper;