@kibee/contracts 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +588 -0
- package/dist/index.d.ts +588 -0
- package/dist/index.js +76 -0
- package/dist/index.mjs +47 -0
- package/package.json +22 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frozen Sprint 1 contract. Edits require joint sign-off from Track A
|
|
3
|
+
* (broker) and Track B (macOS) leads.
|
|
4
|
+
*
|
|
5
|
+
* Spec: docs/superpowers/specs/2026-04-28-bee-mesh-sprint-plan-design.md
|
|
6
|
+
* Section 2 (Architecture — mesh of bees), Section 3 (Source-of-truth
|
|
7
|
+
* contracts).
|
|
8
|
+
*
|
|
9
|
+
* Mirrored to Swift in apps/macos-kibee (Sprint 1 T5/T7 — BridgeEnvelope
|
|
10
|
+
* Swift port lands in Sprint 4 convergence).
|
|
11
|
+
*
|
|
12
|
+
* Wire-stable note: the string raw values for `SurfaceId` and
|
|
13
|
+
* `BridgeEventType` (e.g. "presence:hello") are part of the wire format.
|
|
14
|
+
* Do not rename or re-shape them in the Swift mirror — they must JSON-encode
|
|
15
|
+
* to the exact same strings.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Surfaces that participate in the bee mesh. Every BridgeEnvelope declares
|
|
19
|
+
* its source and target by surface id.
|
|
20
|
+
*/
|
|
21
|
+
type SurfaceId = "web" | "extension" | "desktop";
|
|
22
|
+
/**
|
|
23
|
+
* The frozen event-type union for the cross-surface bus. Adding a new event
|
|
24
|
+
* type after Sprint 1 requires joint sign-off from both track leads.
|
|
25
|
+
*/
|
|
26
|
+
type BridgeEventType = "presence:hello" | "presence:bye" | "flow:handoff" | "flow:resume" | "pointer:show" | "memory:share" | "voice:state" | "capture:promote" | "tenant:attach" | "tenant:detach";
|
|
27
|
+
/**
|
|
28
|
+
* The wire format for every cross-surface message. `tenantId` is `null`
|
|
29
|
+
* when the surface is in personal mode (not attached to a workspace).
|
|
30
|
+
*/
|
|
31
|
+
interface BridgeEnvelope<T = unknown> {
|
|
32
|
+
/** Protocol version. Bump on any breaking change. */
|
|
33
|
+
v: 1;
|
|
34
|
+
source: SurfaceId;
|
|
35
|
+
/** A specific surface or "broadcast" to all subscribers in the same scope. */
|
|
36
|
+
target: SurfaceId | "broadcast";
|
|
37
|
+
/** Null in personal mode; required for tenant-attached and admin-attached modes. */
|
|
38
|
+
tenantId: string | null;
|
|
39
|
+
workspaceId: string | null;
|
|
40
|
+
/** Stable across surfaces for the same visitor. Drives the fan-out scope. */
|
|
41
|
+
visitorId: string;
|
|
42
|
+
sessionId: string | null;
|
|
43
|
+
type: BridgeEventType;
|
|
44
|
+
/** Wall-clock millis at emit. */
|
|
45
|
+
ts: number;
|
|
46
|
+
payload: T;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Type guard usable at runtime when receiving an envelope from the wire.
|
|
50
|
+
* Validates every field strictly — unknown surface ids, unknown event types,
|
|
51
|
+
* missing fields, or arrays are all rejected. Use at the trust boundary
|
|
52
|
+
* (broker, SDK receive handler, Swift port) before treating data as a
|
|
53
|
+
* `BridgeEnvelope`.
|
|
54
|
+
*/
|
|
55
|
+
declare function isBridgeEnvelope(value: unknown): value is BridgeEnvelope;
|
|
56
|
+
/**
|
|
57
|
+
* Claims extracted from the bridge JWT after `authenticateBridgeUpgrade`
|
|
58
|
+
* succeeds. Shared between the broker and the route to keep the trust
|
|
59
|
+
* boundary consistent.
|
|
60
|
+
*/
|
|
61
|
+
interface BridgeClaims {
|
|
62
|
+
visitorId: string;
|
|
63
|
+
tenantId: string | null;
|
|
64
|
+
workspaceId: string | null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Frozen Sprint 1 contract. Edits require joint sign-off from Track A
|
|
69
|
+
* (broker) and Track B (macOS) leads.
|
|
70
|
+
*
|
|
71
|
+
* Spec: docs/superpowers/specs/2026-04-28-bee-mesh-sprint-plan-design.md
|
|
72
|
+
* Section 3 (Source-of-truth contracts).
|
|
73
|
+
*
|
|
74
|
+
* Mirrored to Swift in apps/macos-kibee/Sources/KiBee/BeeBuddyState.swift
|
|
75
|
+
* (Sprint 1 T5). The Swift `allowedTransitions` table must match
|
|
76
|
+
* BUDDY_TRANSITIONS below exactly.
|
|
77
|
+
*/
|
|
78
|
+
/**
|
|
79
|
+
* The macOS Buddy state machine. Frozen end of Sprint 1 — additions require
|
|
80
|
+
* joint sign-off from both track leads.
|
|
81
|
+
*
|
|
82
|
+
* Transition table (15 transitions, including cancel/escape paths to ambient):
|
|
83
|
+
*
|
|
84
|
+
* ambient → listening (voice hotkey)
|
|
85
|
+
* ambient → actionRing (hover 400ms over bee)
|
|
86
|
+
*
|
|
87
|
+
* listening → thinking (transcript finalized)
|
|
88
|
+
* listening → ambient (cancel / hotkey released / silence timeout)
|
|
89
|
+
*
|
|
90
|
+
* thinking → speaking (Claude responds)
|
|
91
|
+
* thinking → ambient (cancel / response error)
|
|
92
|
+
*
|
|
93
|
+
* speaking → pointing (POINT tag parsed)
|
|
94
|
+
* speaking → followUp (TTS finishes, no point tag)
|
|
95
|
+
* speaking → ambient (cancel / TTS interrupted)
|
|
96
|
+
*
|
|
97
|
+
* pointing → followUp (TTS finishes after point)
|
|
98
|
+
* pointing → ambient (cancel / target lost)
|
|
99
|
+
*
|
|
100
|
+
* followUp → ambient (silence timeout)
|
|
101
|
+
* followUp → listening (auto re-listen)
|
|
102
|
+
*
|
|
103
|
+
* actionRing → ambient (mouse leaves bee region)
|
|
104
|
+
* actionRing → listening (tap mic icon)
|
|
105
|
+
*
|
|
106
|
+
* Self-transitions are not allowed. The Swift mirror in
|
|
107
|
+
* apps/macos-kibee/Sources/KiBee/BeeBuddyState.swift uses the same table.
|
|
108
|
+
*/
|
|
109
|
+
type BuddyState = "ambient" | "listening" | "thinking" | "speaking" | "pointing" | "followUp" | "actionRing";
|
|
110
|
+
/**
|
|
111
|
+
* Allowed transitions, expressed as `from → to[]`. Used by tests and by the
|
|
112
|
+
* Swift state machine to reject illegal transitions.
|
|
113
|
+
*/
|
|
114
|
+
declare const BUDDY_TRANSITIONS: Record<BuddyState, BuddyState[]>;
|
|
115
|
+
declare function canTransition(from: BuddyState, to: BuddyState): boolean;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Frozen Sprint 2 contract. Edits require joint sign-off.
|
|
119
|
+
*
|
|
120
|
+
* Spec: docs/superpowers/specs/2026-04-28-bee-mesh-sprint-plan-design.md
|
|
121
|
+
* Section 4 Sprint 2 row.
|
|
122
|
+
*
|
|
123
|
+
* The macOS Buddy calls `GET /v1/identity` after Auth0 sign-in to obtain
|
|
124
|
+
* the canonical visitor record. Web SDK gets the same `visitorId` from
|
|
125
|
+
* the existing visitor cookie path (no contract change there).
|
|
126
|
+
*/
|
|
127
|
+
/**
|
|
128
|
+
* The canonical visitor identity returned to any surface authenticating
|
|
129
|
+
* a real human. Stable for the lifetime of the user account.
|
|
130
|
+
*
|
|
131
|
+
* Note: structurally identical to `BridgeClaims` (bridge.ts) by design —
|
|
132
|
+
* same shape, different trust boundaries (HTTP response vs JWT claims).
|
|
133
|
+
* Do not unify; their lifecycles diverge in S3+.
|
|
134
|
+
*/
|
|
135
|
+
interface VisitorIdentity {
|
|
136
|
+
/** Stable identifier for the authenticated user across all surfaces. */
|
|
137
|
+
visitorId: string;
|
|
138
|
+
/**
|
|
139
|
+
* Same value as `workspaceId` today (workspaces ARE tenants in the
|
|
140
|
+
* current schema). Kept as a separate field so the two can diverge
|
|
141
|
+
* without a contract break in future sprints.
|
|
142
|
+
*/
|
|
143
|
+
tenantId: string | null;
|
|
144
|
+
/**
|
|
145
|
+
* For users with multiple workspace memberships, this is the OLDEST
|
|
146
|
+
* by `createdAt`. Workspace switching is a future feature (Sprint 6+
|
|
147
|
+
* tenant attachment). `null` means the user is in personal mode.
|
|
148
|
+
*/
|
|
149
|
+
workspaceId: string | null;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Optional payload on `GET /v1/identity` (sent in body for first-time
|
|
153
|
+
* users only — typically the macOS app on first launch). Web surfaces
|
|
154
|
+
* never send this since they already have a visitor cookie.
|
|
155
|
+
*/
|
|
156
|
+
interface IdentityRequest {
|
|
157
|
+
contactHint?: {
|
|
158
|
+
email?: string;
|
|
159
|
+
auth0Sub?: string;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Response envelope. `issuedAt` lets clients age out the local cache.
|
|
164
|
+
*/
|
|
165
|
+
interface IdentityResponse {
|
|
166
|
+
identity: VisitorIdentity;
|
|
167
|
+
/** Wall-clock millis at issue (matches BridgeEnvelope.ts convention). */
|
|
168
|
+
issuedAt: number;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
type HighlightVariant = "pulse" | "ring" | "soft";
|
|
172
|
+
interface TargetRef {
|
|
173
|
+
kibeeId?: string;
|
|
174
|
+
selector?: string;
|
|
175
|
+
textHints?: string[];
|
|
176
|
+
/**
|
|
177
|
+
* Legacy compatibility for older prototypes.
|
|
178
|
+
*/
|
|
179
|
+
beeId?: string;
|
|
180
|
+
}
|
|
181
|
+
interface RegisteredTarget {
|
|
182
|
+
id: string;
|
|
183
|
+
label: string;
|
|
184
|
+
target: TargetRef;
|
|
185
|
+
description?: string;
|
|
186
|
+
phrases?: string[];
|
|
187
|
+
}
|
|
188
|
+
interface VisibleTarget extends RegisteredTarget {
|
|
189
|
+
matchedText?: string;
|
|
190
|
+
}
|
|
191
|
+
interface FlowMoveOptions {
|
|
192
|
+
duration?: number;
|
|
193
|
+
offsetX?: number;
|
|
194
|
+
offsetY?: number;
|
|
195
|
+
}
|
|
196
|
+
type FlowCommand = {
|
|
197
|
+
type: "fly_to";
|
|
198
|
+
target: TargetRef;
|
|
199
|
+
message?: string;
|
|
200
|
+
highlight?: HighlightVariant;
|
|
201
|
+
moveTo?: FlowMoveOptions;
|
|
202
|
+
} | {
|
|
203
|
+
type: "highlight";
|
|
204
|
+
target: TargetRef;
|
|
205
|
+
variant?: HighlightVariant;
|
|
206
|
+
} | {
|
|
207
|
+
type: "wait_for_click";
|
|
208
|
+
target: TargetRef;
|
|
209
|
+
timeoutMs?: number;
|
|
210
|
+
} | {
|
|
211
|
+
type: "wait_for_input";
|
|
212
|
+
target: TargetRef;
|
|
213
|
+
timeoutMs?: number;
|
|
214
|
+
} | {
|
|
215
|
+
type: "speak";
|
|
216
|
+
message: string;
|
|
217
|
+
} | {
|
|
218
|
+
type: "celebrate";
|
|
219
|
+
message?: string;
|
|
220
|
+
} | {
|
|
221
|
+
type: "end_flow";
|
|
222
|
+
status: "completed" | "abandoned";
|
|
223
|
+
message?: string;
|
|
224
|
+
};
|
|
225
|
+
interface FlowDefinition {
|
|
226
|
+
id: string;
|
|
227
|
+
title: string;
|
|
228
|
+
pageId: string;
|
|
229
|
+
goal: string;
|
|
230
|
+
audience?: string;
|
|
231
|
+
introMessage?: string;
|
|
232
|
+
phrases?: string[];
|
|
233
|
+
steps: FlowCommand[];
|
|
234
|
+
/**
|
|
235
|
+
* Optional cross-site continuation steps executed by the extension on external pages.
|
|
236
|
+
* Each step targets a page the SaaS does not control (e.g. stripe.com, meta.com).
|
|
237
|
+
*/
|
|
238
|
+
crossSiteSteps?: CrossSiteFlowStep[];
|
|
239
|
+
/**
|
|
240
|
+
* External hostnames this flow may navigate to.
|
|
241
|
+
* Must be a subset of the tenant's allowedExternalHosts.
|
|
242
|
+
*/
|
|
243
|
+
externalHosts?: string[];
|
|
244
|
+
/**
|
|
245
|
+
* The surface this flow is pinned to. Drives cross-surface `flow:handoff`
|
|
246
|
+
* routing — if the visitor's current surface != `surface` (and `surface`
|
|
247
|
+
* is not "both"), the broker emits a handoff so the other surface's bee
|
|
248
|
+
* can pick the flow up. Defaults to `"web"` at the DB layer.
|
|
249
|
+
*/
|
|
250
|
+
surface?: "web" | "desktop" | "both";
|
|
251
|
+
}
|
|
252
|
+
interface SessionState {
|
|
253
|
+
id: string;
|
|
254
|
+
visitorId: string;
|
|
255
|
+
pageId: string;
|
|
256
|
+
flowId?: string;
|
|
257
|
+
currentStepIndex: number;
|
|
258
|
+
status: "idle" | "active" | "completed" | "abandoned";
|
|
259
|
+
startedAt: string;
|
|
260
|
+
updatedAt: string;
|
|
261
|
+
/** Present when session is linked to a CRM contact (e.g. admin session detail). */
|
|
262
|
+
contactId?: string | null;
|
|
263
|
+
}
|
|
264
|
+
interface IntentMatch {
|
|
265
|
+
flowId: string | null;
|
|
266
|
+
confidence: number;
|
|
267
|
+
message: string;
|
|
268
|
+
/**
|
|
269
|
+
* Surface the matched flow is pinned to, or undefined when no flow matched.
|
|
270
|
+
* Used by the route to decide whether to emit a `flow:handoff` envelope on
|
|
271
|
+
* the bridge. The literal union mirrors `FlowDefinition.surface` — the
|
|
272
|
+
* runtime emitter still tolerates unknown strings (it no-ops outside this
|
|
273
|
+
* union), but the type narrowing prevents accidental writes of values like
|
|
274
|
+
* `"mobile"` or `"extension"` typechecking silently.
|
|
275
|
+
*/
|
|
276
|
+
flowSurface?: "web" | "desktop" | "both";
|
|
277
|
+
/** Present only in dev/debug mode — stripped before client delivery in production. */
|
|
278
|
+
_debug?: {
|
|
279
|
+
flowScore: number;
|
|
280
|
+
journeyScore: number;
|
|
281
|
+
pageCtxScore: number;
|
|
282
|
+
frictionPenalty: number;
|
|
283
|
+
fusedScore: number;
|
|
284
|
+
tier: "high" | "medium" | "low" | "none";
|
|
285
|
+
method: "fusion" | "phrase" | "none";
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Discriminated union of known event metadata shapes.
|
|
290
|
+
* The catch-all `Record<string, unknown>` arm preserves forward-compatibility
|
|
291
|
+
* for unknown event types — all existing callers that pass untyped objects
|
|
292
|
+
* remain valid.
|
|
293
|
+
*/
|
|
294
|
+
type EventMetadata = {
|
|
295
|
+
eventType: "page_identified";
|
|
296
|
+
title?: string;
|
|
297
|
+
url?: string;
|
|
298
|
+
referrer?: string;
|
|
299
|
+
} | {
|
|
300
|
+
eventType: "element_clicked";
|
|
301
|
+
kibeeId?: string;
|
|
302
|
+
selector?: string;
|
|
303
|
+
label?: string;
|
|
304
|
+
/** X / Y relative to viewport as 0–1 fractions */
|
|
305
|
+
relX?: number;
|
|
306
|
+
relY?: number;
|
|
307
|
+
} | {
|
|
308
|
+
eventType: "scroll_depth";
|
|
309
|
+
/** 0–1 fraction of page scrolled when threshold was crossed */
|
|
310
|
+
depth: number;
|
|
311
|
+
/** Milliseconds since page load when the threshold was first crossed */
|
|
312
|
+
dwellMs: number;
|
|
313
|
+
} | {
|
|
314
|
+
eventType: "bee_dismissed";
|
|
315
|
+
flowId?: string;
|
|
316
|
+
stepIndex?: number;
|
|
317
|
+
reason?: "manual" | "timeout" | "page_nav";
|
|
318
|
+
} | {
|
|
319
|
+
eventType: "flow_step_completed";
|
|
320
|
+
flowId: string;
|
|
321
|
+
stepIndex: number;
|
|
322
|
+
dwellMs?: number;
|
|
323
|
+
} | {
|
|
324
|
+
eventType: "intent_submitted";
|
|
325
|
+
input: string;
|
|
326
|
+
resolvedFlowId?: string;
|
|
327
|
+
confidence?: number;
|
|
328
|
+
} | {
|
|
329
|
+
eventType: "pairing_started";
|
|
330
|
+
/** Public tenant ID of the SaaS that initiated pairing */
|
|
331
|
+
tenantPublicId: string;
|
|
332
|
+
/** Hostname of the SaaS page where pairing was established */
|
|
333
|
+
originHost: string;
|
|
334
|
+
/** Shared session ID adopted for the pairing */
|
|
335
|
+
sessionId: string;
|
|
336
|
+
} | {
|
|
337
|
+
eventType: "pairing_ended";
|
|
338
|
+
reason: "tab_closed" | "tab_navigated" | "ttl_expired" | "user_request" | "session_expired";
|
|
339
|
+
/** Number of cross-site steps completed before pairing ended */
|
|
340
|
+
stepsCompleted: number;
|
|
341
|
+
} | {
|
|
342
|
+
eventType: "cross_site_step_completed";
|
|
343
|
+
/** Hostname where the step was executed, e.g. "stripe.com" */
|
|
344
|
+
externalHost: string;
|
|
345
|
+
stepIndex: number;
|
|
346
|
+
flowId: string;
|
|
347
|
+
dwellMs?: number;
|
|
348
|
+
} | Record<string, unknown>;
|
|
349
|
+
interface AnalyticsEvent {
|
|
350
|
+
type: string;
|
|
351
|
+
pageId: string;
|
|
352
|
+
timestamp: string;
|
|
353
|
+
visitorId?: string;
|
|
354
|
+
sessionId?: string;
|
|
355
|
+
flowId?: string;
|
|
356
|
+
targetId?: string;
|
|
357
|
+
metadata?: EventMetadata;
|
|
358
|
+
}
|
|
359
|
+
interface StartSessionRequest {
|
|
360
|
+
visitorId: string;
|
|
361
|
+
pageId: string;
|
|
362
|
+
flowId?: string;
|
|
363
|
+
}
|
|
364
|
+
interface ResolveIntentRequest {
|
|
365
|
+
input: string;
|
|
366
|
+
pageId: string;
|
|
367
|
+
visibleTargets: VisibleTarget[];
|
|
368
|
+
/** Optional: passed through to inference_outcomes for outcome tracking */
|
|
369
|
+
sessionId?: string;
|
|
370
|
+
/**
|
|
371
|
+
* Optional: stable visitor identifier shared across surfaces. Required for
|
|
372
|
+
* cross-surface `flow:handoff` emission. When omitted, no handoff is emitted
|
|
373
|
+
* (back-compat with older SDKs that haven't been updated for Sprint 4).
|
|
374
|
+
*/
|
|
375
|
+
visitorId?: string;
|
|
376
|
+
/**
|
|
377
|
+
* Optional: the surface the request originated from ("web" | "desktop" |
|
|
378
|
+
* "extension"). Required for cross-surface `flow:handoff` emission. When
|
|
379
|
+
* omitted, no handoff is emitted.
|
|
380
|
+
*/
|
|
381
|
+
currentSource?: "web" | "desktop" | "extension";
|
|
382
|
+
}
|
|
383
|
+
interface RecoveryRequest {
|
|
384
|
+
pageId: string;
|
|
385
|
+
target: TargetRef;
|
|
386
|
+
visibleTargets: VisibleTarget[];
|
|
387
|
+
}
|
|
388
|
+
interface RecoveryResponse {
|
|
389
|
+
target: TargetRef | null;
|
|
390
|
+
confidence: number;
|
|
391
|
+
message: string;
|
|
392
|
+
}
|
|
393
|
+
interface TrackEventRequest {
|
|
394
|
+
event: AnalyticsEvent;
|
|
395
|
+
}
|
|
396
|
+
type DockPositionPreset = "bottom-right" | "bottom-left" | "top-right" | "top-left";
|
|
397
|
+
interface DockInlineAnchor {
|
|
398
|
+
/** CSS selector or HTMLElement for the container to render inside */
|
|
399
|
+
container: string | HTMLElement;
|
|
400
|
+
/** Alignment within container */
|
|
401
|
+
align?: "left" | "center" | "right";
|
|
402
|
+
}
|
|
403
|
+
type DockPositionConfig = DockPositionPreset | {
|
|
404
|
+
preset: DockPositionPreset;
|
|
405
|
+
offsetX?: number;
|
|
406
|
+
offsetY?: number;
|
|
407
|
+
} | {
|
|
408
|
+
custom: {
|
|
409
|
+
x: number;
|
|
410
|
+
y: number;
|
|
411
|
+
};
|
|
412
|
+
} | {
|
|
413
|
+
inline: DockInlineAnchor;
|
|
414
|
+
};
|
|
415
|
+
interface AdminSessionSummary {
|
|
416
|
+
id: string;
|
|
417
|
+
pageId: string;
|
|
418
|
+
flowId?: string;
|
|
419
|
+
status: SessionState["status"];
|
|
420
|
+
startedAt: string;
|
|
421
|
+
updatedAt: string;
|
|
422
|
+
eventCount: number;
|
|
423
|
+
}
|
|
424
|
+
/** Who produced a message in the chat thread.
|
|
425
|
+
* - `customer`: visitor's own input (echoed in their panel, primary in admin)
|
|
426
|
+
* - `agent`: human support agent
|
|
427
|
+
* - `ai`: KiBee bee's freeform reply (Claude Haiku) or matched flow message
|
|
428
|
+
* - `system`: thread-level annotation (escalations, take-overs, releases)
|
|
429
|
+
*/
|
|
430
|
+
type ChatSender = "agent" | "customer" | "ai" | "system";
|
|
431
|
+
/** Whether the conversation is currently driven by the AI or a human agent.
|
|
432
|
+
* Set per-session; flips on take-over / release. The visitor SDK uses this
|
|
433
|
+
* to hide its "talk to a human" chip when an agent is already on. */
|
|
434
|
+
type ChatMode = "ai" | "human";
|
|
435
|
+
interface ChatMessage {
|
|
436
|
+
id: string;
|
|
437
|
+
sessionId: string;
|
|
438
|
+
sender: ChatSender;
|
|
439
|
+
text: string;
|
|
440
|
+
timestamp: string;
|
|
441
|
+
}
|
|
442
|
+
interface VisitorPollResponse {
|
|
443
|
+
messages: ChatMessage[];
|
|
444
|
+
mode: ChatMode;
|
|
445
|
+
/** True when an agent has taken over (assigned_agent_id IS NOT NULL). */
|
|
446
|
+
hasAgent: boolean;
|
|
447
|
+
/** Page-level friction score (0-100), used by the SDK to surface the
|
|
448
|
+
* proactive "want a guided tour?" prompt. */
|
|
449
|
+
frictionScore: number;
|
|
450
|
+
/** The session's last_message_at — clients echo it back as `?since=` on
|
|
451
|
+
* the next poll. */
|
|
452
|
+
lastMessageAt: string | null;
|
|
453
|
+
}
|
|
454
|
+
interface MessageTemplate {
|
|
455
|
+
id: string;
|
|
456
|
+
label: string;
|
|
457
|
+
body: string;
|
|
458
|
+
kind: "greeting" | "ack" | "handoff" | "custom";
|
|
459
|
+
createdAt: string;
|
|
460
|
+
updatedAt: string;
|
|
461
|
+
}
|
|
462
|
+
interface PushFlowRequest {
|
|
463
|
+
flowId: string;
|
|
464
|
+
/** Optional cross-site continuation steps, executed by the extension on external pages */
|
|
465
|
+
crossSiteSteps?: CrossSiteFlowStep[];
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* A flow step that executes on an external page not controlled by the SaaS.
|
|
469
|
+
* Must use textHints only — kibeeId and selector are unavailable on third-party pages.
|
|
470
|
+
*/
|
|
471
|
+
interface CrossSiteFlowStep {
|
|
472
|
+
/** Hostname the step executes on, e.g. "stripe.com" */
|
|
473
|
+
externalHost: string;
|
|
474
|
+
/** Path glob pattern, e.g. "/dashboard/apikeys*" — matches any path if absent */
|
|
475
|
+
pathPattern?: string;
|
|
476
|
+
/** Message shown to user before they navigate to the external page */
|
|
477
|
+
navigationMessage?: string;
|
|
478
|
+
/** The flow command to execute. Target must use textHints only. */
|
|
479
|
+
command: {
|
|
480
|
+
type: FlowCommand["type"];
|
|
481
|
+
message?: string;
|
|
482
|
+
/** textHints only — kibeeId and selector are disallowed for cross-site steps */
|
|
483
|
+
target?: {
|
|
484
|
+
textHints: string[];
|
|
485
|
+
};
|
|
486
|
+
timeoutMs?: number;
|
|
487
|
+
status?: "completed" | "abandoned";
|
|
488
|
+
variant?: HighlightVariant;
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
/** An item in the cross-site flow queue delivered to the extension via polling */
|
|
492
|
+
interface CrossSiteFlowQueueItem {
|
|
493
|
+
flowId: string;
|
|
494
|
+
flowTitle: string;
|
|
495
|
+
crossSiteSteps: CrossSiteFlowStep[];
|
|
496
|
+
/** Unix ms — item expires if not picked up by the extension */
|
|
497
|
+
expiresAt: number;
|
|
498
|
+
}
|
|
499
|
+
/** Sent by the extension content script to the embedded SDK page to initiate pairing */
|
|
500
|
+
interface KiBeePairRequest {
|
|
501
|
+
type: "KIBEE_PAIR_REQUEST";
|
|
502
|
+
/** chrome.runtime.id of the extension */
|
|
503
|
+
extensionId: string;
|
|
504
|
+
/** Manifest version string of the extension */
|
|
505
|
+
version: string;
|
|
506
|
+
}
|
|
507
|
+
/** Sent by the embedded SDK back to the extension content script to accept pairing */
|
|
508
|
+
interface KiBeePairAccept {
|
|
509
|
+
type: "KIBEE_PAIR_ACCEPT";
|
|
510
|
+
/** Public tenant identifier (same as websiteId) */
|
|
511
|
+
tenantPublicId: string;
|
|
512
|
+
/**
|
|
513
|
+
* The SaaS session ID — extension adopts this for all subordinate API calls.
|
|
514
|
+
* Analytics for both surfaces land in one session timeline.
|
|
515
|
+
*/
|
|
516
|
+
sessionId: string;
|
|
517
|
+
/** Domains the extension may activate on in subordinate mode, server-enforced by the API */
|
|
518
|
+
allowedExternalHosts: string[];
|
|
519
|
+
/** Pre-queued cross-site flows to execute on allowed external hosts */
|
|
520
|
+
flowQueue: CrossSiteFlowQueueItem[];
|
|
521
|
+
/** Pairing validity window in milliseconds, e.g. 1_800_000 (30 min) */
|
|
522
|
+
ttlMs: number;
|
|
523
|
+
/**
|
|
524
|
+
* Short-lived server-issued credential for the extension to authenticate
|
|
525
|
+
* subordinate polling requests. Scoped to this session only.
|
|
526
|
+
*/
|
|
527
|
+
pairingToken: string;
|
|
528
|
+
}
|
|
529
|
+
/** Sent by the extension content script to the embedded SDK to reject pairing */
|
|
530
|
+
interface KiBeePairReject {
|
|
531
|
+
type: "KIBEE_PAIR_REJECT";
|
|
532
|
+
reason: string;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Pairing state persisted in chrome.storage.local under key "kibee_pairing".
|
|
536
|
+
* Cleared on unpair. extensionVisitorId is NEVER overwritten by pairing.
|
|
537
|
+
*/
|
|
538
|
+
interface PairingState {
|
|
539
|
+
tenantPublicId: string;
|
|
540
|
+
/** The SaaS session ID shared for this pairing — used for all subordinate API calls */
|
|
541
|
+
sessionId: string;
|
|
542
|
+
/** Hostname of the SaaS page where the handshake started, e.g. "acme.com" */
|
|
543
|
+
originHostname: string;
|
|
544
|
+
/** Chrome tab ID where the handshake started — monitored for close/navigate-away */
|
|
545
|
+
originTabId: number;
|
|
546
|
+
/** Domains the extension may operate on in subordinate mode */
|
|
547
|
+
allowedExternalHosts: string[];
|
|
548
|
+
/** Cross-site flow steps cached from the last poll response */
|
|
549
|
+
flowQueue: CrossSiteFlowQueueItem[];
|
|
550
|
+
/** Short-lived token for authenticating subordinate polling requests */
|
|
551
|
+
pairingToken: string;
|
|
552
|
+
/** Unix ms when pairing was established */
|
|
553
|
+
pairedAt: number;
|
|
554
|
+
/** How long the pairing is valid in milliseconds */
|
|
555
|
+
ttlMs: number;
|
|
556
|
+
/**
|
|
557
|
+
* Index of the cross-site flow step currently executing.
|
|
558
|
+
* null = idle (no step in progress).
|
|
559
|
+
* Used to decide immediate vs deferred unpair when origin tab closes.
|
|
560
|
+
*/
|
|
561
|
+
activeFlowStepIndex: number | null;
|
|
562
|
+
/**
|
|
563
|
+
* Set to true when origin tab closes while a step is in progress.
|
|
564
|
+
* Content script detects this after step completion and clears pairing.
|
|
565
|
+
*/
|
|
566
|
+
pendingUnpair: boolean;
|
|
567
|
+
/**
|
|
568
|
+
* The extension's own permanent visitor ID.
|
|
569
|
+
* Preserved independently of pairing — NEVER replaced by the SaaS visitor ID.
|
|
570
|
+
* Used for event attribution even in subordinate mode.
|
|
571
|
+
*/
|
|
572
|
+
extensionVisitorId: string;
|
|
573
|
+
}
|
|
574
|
+
interface PushTargetsRequest {
|
|
575
|
+
targets: TargetRef[];
|
|
576
|
+
highlight?: HighlightVariant;
|
|
577
|
+
}
|
|
578
|
+
interface WidgetConfig {
|
|
579
|
+
position: DockPositionConfig;
|
|
580
|
+
size: number;
|
|
581
|
+
theme: {
|
|
582
|
+
primary: string;
|
|
583
|
+
tooltipBg: string;
|
|
584
|
+
tooltipColor: string;
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
export { type AdminSessionSummary, type AnalyticsEvent, BUDDY_TRANSITIONS, type BridgeClaims, type BridgeEnvelope, type BridgeEventType, type BuddyState, type ChatMessage, type ChatMode, type ChatSender, type CrossSiteFlowQueueItem, type CrossSiteFlowStep, type DockInlineAnchor, type DockPositionConfig, type DockPositionPreset, type EventMetadata, type FlowCommand, type FlowDefinition, type FlowMoveOptions, type HighlightVariant, type IdentityRequest, type IdentityResponse, type IntentMatch, type KiBeePairAccept, type KiBeePairReject, type KiBeePairRequest, type MessageTemplate, type PairingState, type PushFlowRequest, type PushTargetsRequest, type RecoveryRequest, type RecoveryResponse, type RegisteredTarget, type ResolveIntentRequest, type SessionState, type StartSessionRequest, type SurfaceId, type TargetRef, type TrackEventRequest, type VisibleTarget, type VisitorIdentity, type VisitorPollResponse, type WidgetConfig, canTransition, isBridgeEnvelope };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Frozen Sprint 1 contract. Edits require joint sign-off from Track A
|
|
3
|
+
* (broker) and Track B (macOS) leads.
|
|
4
|
+
*
|
|
5
|
+
* Spec: docs/superpowers/specs/2026-04-28-bee-mesh-sprint-plan-design.md
|
|
6
|
+
* Section 2 (Architecture — mesh of bees), Section 3 (Source-of-truth
|
|
7
|
+
* contracts).
|
|
8
|
+
*
|
|
9
|
+
* Mirrored to Swift in apps/macos-kibee (Sprint 1 T5/T7 — BridgeEnvelope
|
|
10
|
+
* Swift port lands in Sprint 4 convergence).
|
|
11
|
+
*
|
|
12
|
+
* Wire-stable note: the string raw values for `SurfaceId` and
|
|
13
|
+
* `BridgeEventType` (e.g. "presence:hello") are part of the wire format.
|
|
14
|
+
* Do not rename or re-shape them in the Swift mirror — they must JSON-encode
|
|
15
|
+
* to the exact same strings.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Surfaces that participate in the bee mesh. Every BridgeEnvelope declares
|
|
19
|
+
* its source and target by surface id.
|
|
20
|
+
*/
|
|
21
|
+
type SurfaceId = "web" | "extension" | "desktop";
|
|
22
|
+
/**
|
|
23
|
+
* The frozen event-type union for the cross-surface bus. Adding a new event
|
|
24
|
+
* type after Sprint 1 requires joint sign-off from both track leads.
|
|
25
|
+
*/
|
|
26
|
+
type BridgeEventType = "presence:hello" | "presence:bye" | "flow:handoff" | "flow:resume" | "pointer:show" | "memory:share" | "voice:state" | "capture:promote" | "tenant:attach" | "tenant:detach";
|
|
27
|
+
/**
|
|
28
|
+
* The wire format for every cross-surface message. `tenantId` is `null`
|
|
29
|
+
* when the surface is in personal mode (not attached to a workspace).
|
|
30
|
+
*/
|
|
31
|
+
interface BridgeEnvelope<T = unknown> {
|
|
32
|
+
/** Protocol version. Bump on any breaking change. */
|
|
33
|
+
v: 1;
|
|
34
|
+
source: SurfaceId;
|
|
35
|
+
/** A specific surface or "broadcast" to all subscribers in the same scope. */
|
|
36
|
+
target: SurfaceId | "broadcast";
|
|
37
|
+
/** Null in personal mode; required for tenant-attached and admin-attached modes. */
|
|
38
|
+
tenantId: string | null;
|
|
39
|
+
workspaceId: string | null;
|
|
40
|
+
/** Stable across surfaces for the same visitor. Drives the fan-out scope. */
|
|
41
|
+
visitorId: string;
|
|
42
|
+
sessionId: string | null;
|
|
43
|
+
type: BridgeEventType;
|
|
44
|
+
/** Wall-clock millis at emit. */
|
|
45
|
+
ts: number;
|
|
46
|
+
payload: T;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Type guard usable at runtime when receiving an envelope from the wire.
|
|
50
|
+
* Validates every field strictly — unknown surface ids, unknown event types,
|
|
51
|
+
* missing fields, or arrays are all rejected. Use at the trust boundary
|
|
52
|
+
* (broker, SDK receive handler, Swift port) before treating data as a
|
|
53
|
+
* `BridgeEnvelope`.
|
|
54
|
+
*/
|
|
55
|
+
declare function isBridgeEnvelope(value: unknown): value is BridgeEnvelope;
|
|
56
|
+
/**
|
|
57
|
+
* Claims extracted from the bridge JWT after `authenticateBridgeUpgrade`
|
|
58
|
+
* succeeds. Shared between the broker and the route to keep the trust
|
|
59
|
+
* boundary consistent.
|
|
60
|
+
*/
|
|
61
|
+
interface BridgeClaims {
|
|
62
|
+
visitorId: string;
|
|
63
|
+
tenantId: string | null;
|
|
64
|
+
workspaceId: string | null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Frozen Sprint 1 contract. Edits require joint sign-off from Track A
|
|
69
|
+
* (broker) and Track B (macOS) leads.
|
|
70
|
+
*
|
|
71
|
+
* Spec: docs/superpowers/specs/2026-04-28-bee-mesh-sprint-plan-design.md
|
|
72
|
+
* Section 3 (Source-of-truth contracts).
|
|
73
|
+
*
|
|
74
|
+
* Mirrored to Swift in apps/macos-kibee/Sources/KiBee/BeeBuddyState.swift
|
|
75
|
+
* (Sprint 1 T5). The Swift `allowedTransitions` table must match
|
|
76
|
+
* BUDDY_TRANSITIONS below exactly.
|
|
77
|
+
*/
|
|
78
|
+
/**
|
|
79
|
+
* The macOS Buddy state machine. Frozen end of Sprint 1 — additions require
|
|
80
|
+
* joint sign-off from both track leads.
|
|
81
|
+
*
|
|
82
|
+
* Transition table (15 transitions, including cancel/escape paths to ambient):
|
|
83
|
+
*
|
|
84
|
+
* ambient → listening (voice hotkey)
|
|
85
|
+
* ambient → actionRing (hover 400ms over bee)
|
|
86
|
+
*
|
|
87
|
+
* listening → thinking (transcript finalized)
|
|
88
|
+
* listening → ambient (cancel / hotkey released / silence timeout)
|
|
89
|
+
*
|
|
90
|
+
* thinking → speaking (Claude responds)
|
|
91
|
+
* thinking → ambient (cancel / response error)
|
|
92
|
+
*
|
|
93
|
+
* speaking → pointing (POINT tag parsed)
|
|
94
|
+
* speaking → followUp (TTS finishes, no point tag)
|
|
95
|
+
* speaking → ambient (cancel / TTS interrupted)
|
|
96
|
+
*
|
|
97
|
+
* pointing → followUp (TTS finishes after point)
|
|
98
|
+
* pointing → ambient (cancel / target lost)
|
|
99
|
+
*
|
|
100
|
+
* followUp → ambient (silence timeout)
|
|
101
|
+
* followUp → listening (auto re-listen)
|
|
102
|
+
*
|
|
103
|
+
* actionRing → ambient (mouse leaves bee region)
|
|
104
|
+
* actionRing → listening (tap mic icon)
|
|
105
|
+
*
|
|
106
|
+
* Self-transitions are not allowed. The Swift mirror in
|
|
107
|
+
* apps/macos-kibee/Sources/KiBee/BeeBuddyState.swift uses the same table.
|
|
108
|
+
*/
|
|
109
|
+
type BuddyState = "ambient" | "listening" | "thinking" | "speaking" | "pointing" | "followUp" | "actionRing";
|
|
110
|
+
/**
|
|
111
|
+
* Allowed transitions, expressed as `from → to[]`. Used by tests and by the
|
|
112
|
+
* Swift state machine to reject illegal transitions.
|
|
113
|
+
*/
|
|
114
|
+
declare const BUDDY_TRANSITIONS: Record<BuddyState, BuddyState[]>;
|
|
115
|
+
declare function canTransition(from: BuddyState, to: BuddyState): boolean;
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Frozen Sprint 2 contract. Edits require joint sign-off.
|
|
119
|
+
*
|
|
120
|
+
* Spec: docs/superpowers/specs/2026-04-28-bee-mesh-sprint-plan-design.md
|
|
121
|
+
* Section 4 Sprint 2 row.
|
|
122
|
+
*
|
|
123
|
+
* The macOS Buddy calls `GET /v1/identity` after Auth0 sign-in to obtain
|
|
124
|
+
* the canonical visitor record. Web SDK gets the same `visitorId` from
|
|
125
|
+
* the existing visitor cookie path (no contract change there).
|
|
126
|
+
*/
|
|
127
|
+
/**
|
|
128
|
+
* The canonical visitor identity returned to any surface authenticating
|
|
129
|
+
* a real human. Stable for the lifetime of the user account.
|
|
130
|
+
*
|
|
131
|
+
* Note: structurally identical to `BridgeClaims` (bridge.ts) by design —
|
|
132
|
+
* same shape, different trust boundaries (HTTP response vs JWT claims).
|
|
133
|
+
* Do not unify; their lifecycles diverge in S3+.
|
|
134
|
+
*/
|
|
135
|
+
interface VisitorIdentity {
|
|
136
|
+
/** Stable identifier for the authenticated user across all surfaces. */
|
|
137
|
+
visitorId: string;
|
|
138
|
+
/**
|
|
139
|
+
* Same value as `workspaceId` today (workspaces ARE tenants in the
|
|
140
|
+
* current schema). Kept as a separate field so the two can diverge
|
|
141
|
+
* without a contract break in future sprints.
|
|
142
|
+
*/
|
|
143
|
+
tenantId: string | null;
|
|
144
|
+
/**
|
|
145
|
+
* For users with multiple workspace memberships, this is the OLDEST
|
|
146
|
+
* by `createdAt`. Workspace switching is a future feature (Sprint 6+
|
|
147
|
+
* tenant attachment). `null` means the user is in personal mode.
|
|
148
|
+
*/
|
|
149
|
+
workspaceId: string | null;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Optional payload on `GET /v1/identity` (sent in body for first-time
|
|
153
|
+
* users only — typically the macOS app on first launch). Web surfaces
|
|
154
|
+
* never send this since they already have a visitor cookie.
|
|
155
|
+
*/
|
|
156
|
+
interface IdentityRequest {
|
|
157
|
+
contactHint?: {
|
|
158
|
+
email?: string;
|
|
159
|
+
auth0Sub?: string;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Response envelope. `issuedAt` lets clients age out the local cache.
|
|
164
|
+
*/
|
|
165
|
+
interface IdentityResponse {
|
|
166
|
+
identity: VisitorIdentity;
|
|
167
|
+
/** Wall-clock millis at issue (matches BridgeEnvelope.ts convention). */
|
|
168
|
+
issuedAt: number;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
type HighlightVariant = "pulse" | "ring" | "soft";
|
|
172
|
+
interface TargetRef {
|
|
173
|
+
kibeeId?: string;
|
|
174
|
+
selector?: string;
|
|
175
|
+
textHints?: string[];
|
|
176
|
+
/**
|
|
177
|
+
* Legacy compatibility for older prototypes.
|
|
178
|
+
*/
|
|
179
|
+
beeId?: string;
|
|
180
|
+
}
|
|
181
|
+
interface RegisteredTarget {
|
|
182
|
+
id: string;
|
|
183
|
+
label: string;
|
|
184
|
+
target: TargetRef;
|
|
185
|
+
description?: string;
|
|
186
|
+
phrases?: string[];
|
|
187
|
+
}
|
|
188
|
+
interface VisibleTarget extends RegisteredTarget {
|
|
189
|
+
matchedText?: string;
|
|
190
|
+
}
|
|
191
|
+
interface FlowMoveOptions {
|
|
192
|
+
duration?: number;
|
|
193
|
+
offsetX?: number;
|
|
194
|
+
offsetY?: number;
|
|
195
|
+
}
|
|
196
|
+
type FlowCommand = {
|
|
197
|
+
type: "fly_to";
|
|
198
|
+
target: TargetRef;
|
|
199
|
+
message?: string;
|
|
200
|
+
highlight?: HighlightVariant;
|
|
201
|
+
moveTo?: FlowMoveOptions;
|
|
202
|
+
} | {
|
|
203
|
+
type: "highlight";
|
|
204
|
+
target: TargetRef;
|
|
205
|
+
variant?: HighlightVariant;
|
|
206
|
+
} | {
|
|
207
|
+
type: "wait_for_click";
|
|
208
|
+
target: TargetRef;
|
|
209
|
+
timeoutMs?: number;
|
|
210
|
+
} | {
|
|
211
|
+
type: "wait_for_input";
|
|
212
|
+
target: TargetRef;
|
|
213
|
+
timeoutMs?: number;
|
|
214
|
+
} | {
|
|
215
|
+
type: "speak";
|
|
216
|
+
message: string;
|
|
217
|
+
} | {
|
|
218
|
+
type: "celebrate";
|
|
219
|
+
message?: string;
|
|
220
|
+
} | {
|
|
221
|
+
type: "end_flow";
|
|
222
|
+
status: "completed" | "abandoned";
|
|
223
|
+
message?: string;
|
|
224
|
+
};
|
|
225
|
+
interface FlowDefinition {
|
|
226
|
+
id: string;
|
|
227
|
+
title: string;
|
|
228
|
+
pageId: string;
|
|
229
|
+
goal: string;
|
|
230
|
+
audience?: string;
|
|
231
|
+
introMessage?: string;
|
|
232
|
+
phrases?: string[];
|
|
233
|
+
steps: FlowCommand[];
|
|
234
|
+
/**
|
|
235
|
+
* Optional cross-site continuation steps executed by the extension on external pages.
|
|
236
|
+
* Each step targets a page the SaaS does not control (e.g. stripe.com, meta.com).
|
|
237
|
+
*/
|
|
238
|
+
crossSiteSteps?: CrossSiteFlowStep[];
|
|
239
|
+
/**
|
|
240
|
+
* External hostnames this flow may navigate to.
|
|
241
|
+
* Must be a subset of the tenant's allowedExternalHosts.
|
|
242
|
+
*/
|
|
243
|
+
externalHosts?: string[];
|
|
244
|
+
/**
|
|
245
|
+
* The surface this flow is pinned to. Drives cross-surface `flow:handoff`
|
|
246
|
+
* routing — if the visitor's current surface != `surface` (and `surface`
|
|
247
|
+
* is not "both"), the broker emits a handoff so the other surface's bee
|
|
248
|
+
* can pick the flow up. Defaults to `"web"` at the DB layer.
|
|
249
|
+
*/
|
|
250
|
+
surface?: "web" | "desktop" | "both";
|
|
251
|
+
}
|
|
252
|
+
interface SessionState {
|
|
253
|
+
id: string;
|
|
254
|
+
visitorId: string;
|
|
255
|
+
pageId: string;
|
|
256
|
+
flowId?: string;
|
|
257
|
+
currentStepIndex: number;
|
|
258
|
+
status: "idle" | "active" | "completed" | "abandoned";
|
|
259
|
+
startedAt: string;
|
|
260
|
+
updatedAt: string;
|
|
261
|
+
/** Present when session is linked to a CRM contact (e.g. admin session detail). */
|
|
262
|
+
contactId?: string | null;
|
|
263
|
+
}
|
|
264
|
+
interface IntentMatch {
|
|
265
|
+
flowId: string | null;
|
|
266
|
+
confidence: number;
|
|
267
|
+
message: string;
|
|
268
|
+
/**
|
|
269
|
+
* Surface the matched flow is pinned to, or undefined when no flow matched.
|
|
270
|
+
* Used by the route to decide whether to emit a `flow:handoff` envelope on
|
|
271
|
+
* the bridge. The literal union mirrors `FlowDefinition.surface` — the
|
|
272
|
+
* runtime emitter still tolerates unknown strings (it no-ops outside this
|
|
273
|
+
* union), but the type narrowing prevents accidental writes of values like
|
|
274
|
+
* `"mobile"` or `"extension"` typechecking silently.
|
|
275
|
+
*/
|
|
276
|
+
flowSurface?: "web" | "desktop" | "both";
|
|
277
|
+
/** Present only in dev/debug mode — stripped before client delivery in production. */
|
|
278
|
+
_debug?: {
|
|
279
|
+
flowScore: number;
|
|
280
|
+
journeyScore: number;
|
|
281
|
+
pageCtxScore: number;
|
|
282
|
+
frictionPenalty: number;
|
|
283
|
+
fusedScore: number;
|
|
284
|
+
tier: "high" | "medium" | "low" | "none";
|
|
285
|
+
method: "fusion" | "phrase" | "none";
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Discriminated union of known event metadata shapes.
|
|
290
|
+
* The catch-all `Record<string, unknown>` arm preserves forward-compatibility
|
|
291
|
+
* for unknown event types — all existing callers that pass untyped objects
|
|
292
|
+
* remain valid.
|
|
293
|
+
*/
|
|
294
|
+
type EventMetadata = {
|
|
295
|
+
eventType: "page_identified";
|
|
296
|
+
title?: string;
|
|
297
|
+
url?: string;
|
|
298
|
+
referrer?: string;
|
|
299
|
+
} | {
|
|
300
|
+
eventType: "element_clicked";
|
|
301
|
+
kibeeId?: string;
|
|
302
|
+
selector?: string;
|
|
303
|
+
label?: string;
|
|
304
|
+
/** X / Y relative to viewport as 0–1 fractions */
|
|
305
|
+
relX?: number;
|
|
306
|
+
relY?: number;
|
|
307
|
+
} | {
|
|
308
|
+
eventType: "scroll_depth";
|
|
309
|
+
/** 0–1 fraction of page scrolled when threshold was crossed */
|
|
310
|
+
depth: number;
|
|
311
|
+
/** Milliseconds since page load when the threshold was first crossed */
|
|
312
|
+
dwellMs: number;
|
|
313
|
+
} | {
|
|
314
|
+
eventType: "bee_dismissed";
|
|
315
|
+
flowId?: string;
|
|
316
|
+
stepIndex?: number;
|
|
317
|
+
reason?: "manual" | "timeout" | "page_nav";
|
|
318
|
+
} | {
|
|
319
|
+
eventType: "flow_step_completed";
|
|
320
|
+
flowId: string;
|
|
321
|
+
stepIndex: number;
|
|
322
|
+
dwellMs?: number;
|
|
323
|
+
} | {
|
|
324
|
+
eventType: "intent_submitted";
|
|
325
|
+
input: string;
|
|
326
|
+
resolvedFlowId?: string;
|
|
327
|
+
confidence?: number;
|
|
328
|
+
} | {
|
|
329
|
+
eventType: "pairing_started";
|
|
330
|
+
/** Public tenant ID of the SaaS that initiated pairing */
|
|
331
|
+
tenantPublicId: string;
|
|
332
|
+
/** Hostname of the SaaS page where pairing was established */
|
|
333
|
+
originHost: string;
|
|
334
|
+
/** Shared session ID adopted for the pairing */
|
|
335
|
+
sessionId: string;
|
|
336
|
+
} | {
|
|
337
|
+
eventType: "pairing_ended";
|
|
338
|
+
reason: "tab_closed" | "tab_navigated" | "ttl_expired" | "user_request" | "session_expired";
|
|
339
|
+
/** Number of cross-site steps completed before pairing ended */
|
|
340
|
+
stepsCompleted: number;
|
|
341
|
+
} | {
|
|
342
|
+
eventType: "cross_site_step_completed";
|
|
343
|
+
/** Hostname where the step was executed, e.g. "stripe.com" */
|
|
344
|
+
externalHost: string;
|
|
345
|
+
stepIndex: number;
|
|
346
|
+
flowId: string;
|
|
347
|
+
dwellMs?: number;
|
|
348
|
+
} | Record<string, unknown>;
|
|
349
|
+
interface AnalyticsEvent {
|
|
350
|
+
type: string;
|
|
351
|
+
pageId: string;
|
|
352
|
+
timestamp: string;
|
|
353
|
+
visitorId?: string;
|
|
354
|
+
sessionId?: string;
|
|
355
|
+
flowId?: string;
|
|
356
|
+
targetId?: string;
|
|
357
|
+
metadata?: EventMetadata;
|
|
358
|
+
}
|
|
359
|
+
interface StartSessionRequest {
|
|
360
|
+
visitorId: string;
|
|
361
|
+
pageId: string;
|
|
362
|
+
flowId?: string;
|
|
363
|
+
}
|
|
364
|
+
interface ResolveIntentRequest {
|
|
365
|
+
input: string;
|
|
366
|
+
pageId: string;
|
|
367
|
+
visibleTargets: VisibleTarget[];
|
|
368
|
+
/** Optional: passed through to inference_outcomes for outcome tracking */
|
|
369
|
+
sessionId?: string;
|
|
370
|
+
/**
|
|
371
|
+
* Optional: stable visitor identifier shared across surfaces. Required for
|
|
372
|
+
* cross-surface `flow:handoff` emission. When omitted, no handoff is emitted
|
|
373
|
+
* (back-compat with older SDKs that haven't been updated for Sprint 4).
|
|
374
|
+
*/
|
|
375
|
+
visitorId?: string;
|
|
376
|
+
/**
|
|
377
|
+
* Optional: the surface the request originated from ("web" | "desktop" |
|
|
378
|
+
* "extension"). Required for cross-surface `flow:handoff` emission. When
|
|
379
|
+
* omitted, no handoff is emitted.
|
|
380
|
+
*/
|
|
381
|
+
currentSource?: "web" | "desktop" | "extension";
|
|
382
|
+
}
|
|
383
|
+
interface RecoveryRequest {
|
|
384
|
+
pageId: string;
|
|
385
|
+
target: TargetRef;
|
|
386
|
+
visibleTargets: VisibleTarget[];
|
|
387
|
+
}
|
|
388
|
+
interface RecoveryResponse {
|
|
389
|
+
target: TargetRef | null;
|
|
390
|
+
confidence: number;
|
|
391
|
+
message: string;
|
|
392
|
+
}
|
|
393
|
+
interface TrackEventRequest {
|
|
394
|
+
event: AnalyticsEvent;
|
|
395
|
+
}
|
|
396
|
+
type DockPositionPreset = "bottom-right" | "bottom-left" | "top-right" | "top-left";
|
|
397
|
+
interface DockInlineAnchor {
|
|
398
|
+
/** CSS selector or HTMLElement for the container to render inside */
|
|
399
|
+
container: string | HTMLElement;
|
|
400
|
+
/** Alignment within container */
|
|
401
|
+
align?: "left" | "center" | "right";
|
|
402
|
+
}
|
|
403
|
+
type DockPositionConfig = DockPositionPreset | {
|
|
404
|
+
preset: DockPositionPreset;
|
|
405
|
+
offsetX?: number;
|
|
406
|
+
offsetY?: number;
|
|
407
|
+
} | {
|
|
408
|
+
custom: {
|
|
409
|
+
x: number;
|
|
410
|
+
y: number;
|
|
411
|
+
};
|
|
412
|
+
} | {
|
|
413
|
+
inline: DockInlineAnchor;
|
|
414
|
+
};
|
|
415
|
+
interface AdminSessionSummary {
|
|
416
|
+
id: string;
|
|
417
|
+
pageId: string;
|
|
418
|
+
flowId?: string;
|
|
419
|
+
status: SessionState["status"];
|
|
420
|
+
startedAt: string;
|
|
421
|
+
updatedAt: string;
|
|
422
|
+
eventCount: number;
|
|
423
|
+
}
|
|
424
|
+
/** Who produced a message in the chat thread.
|
|
425
|
+
* - `customer`: visitor's own input (echoed in their panel, primary in admin)
|
|
426
|
+
* - `agent`: human support agent
|
|
427
|
+
* - `ai`: KiBee bee's freeform reply (Claude Haiku) or matched flow message
|
|
428
|
+
* - `system`: thread-level annotation (escalations, take-overs, releases)
|
|
429
|
+
*/
|
|
430
|
+
type ChatSender = "agent" | "customer" | "ai" | "system";
|
|
431
|
+
/** Whether the conversation is currently driven by the AI or a human agent.
|
|
432
|
+
* Set per-session; flips on take-over / release. The visitor SDK uses this
|
|
433
|
+
* to hide its "talk to a human" chip when an agent is already on. */
|
|
434
|
+
type ChatMode = "ai" | "human";
|
|
435
|
+
interface ChatMessage {
|
|
436
|
+
id: string;
|
|
437
|
+
sessionId: string;
|
|
438
|
+
sender: ChatSender;
|
|
439
|
+
text: string;
|
|
440
|
+
timestamp: string;
|
|
441
|
+
}
|
|
442
|
+
interface VisitorPollResponse {
|
|
443
|
+
messages: ChatMessage[];
|
|
444
|
+
mode: ChatMode;
|
|
445
|
+
/** True when an agent has taken over (assigned_agent_id IS NOT NULL). */
|
|
446
|
+
hasAgent: boolean;
|
|
447
|
+
/** Page-level friction score (0-100), used by the SDK to surface the
|
|
448
|
+
* proactive "want a guided tour?" prompt. */
|
|
449
|
+
frictionScore: number;
|
|
450
|
+
/** The session's last_message_at — clients echo it back as `?since=` on
|
|
451
|
+
* the next poll. */
|
|
452
|
+
lastMessageAt: string | null;
|
|
453
|
+
}
|
|
454
|
+
interface MessageTemplate {
|
|
455
|
+
id: string;
|
|
456
|
+
label: string;
|
|
457
|
+
body: string;
|
|
458
|
+
kind: "greeting" | "ack" | "handoff" | "custom";
|
|
459
|
+
createdAt: string;
|
|
460
|
+
updatedAt: string;
|
|
461
|
+
}
|
|
462
|
+
interface PushFlowRequest {
|
|
463
|
+
flowId: string;
|
|
464
|
+
/** Optional cross-site continuation steps, executed by the extension on external pages */
|
|
465
|
+
crossSiteSteps?: CrossSiteFlowStep[];
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* A flow step that executes on an external page not controlled by the SaaS.
|
|
469
|
+
* Must use textHints only — kibeeId and selector are unavailable on third-party pages.
|
|
470
|
+
*/
|
|
471
|
+
interface CrossSiteFlowStep {
|
|
472
|
+
/** Hostname the step executes on, e.g. "stripe.com" */
|
|
473
|
+
externalHost: string;
|
|
474
|
+
/** Path glob pattern, e.g. "/dashboard/apikeys*" — matches any path if absent */
|
|
475
|
+
pathPattern?: string;
|
|
476
|
+
/** Message shown to user before they navigate to the external page */
|
|
477
|
+
navigationMessage?: string;
|
|
478
|
+
/** The flow command to execute. Target must use textHints only. */
|
|
479
|
+
command: {
|
|
480
|
+
type: FlowCommand["type"];
|
|
481
|
+
message?: string;
|
|
482
|
+
/** textHints only — kibeeId and selector are disallowed for cross-site steps */
|
|
483
|
+
target?: {
|
|
484
|
+
textHints: string[];
|
|
485
|
+
};
|
|
486
|
+
timeoutMs?: number;
|
|
487
|
+
status?: "completed" | "abandoned";
|
|
488
|
+
variant?: HighlightVariant;
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
/** An item in the cross-site flow queue delivered to the extension via polling */
|
|
492
|
+
interface CrossSiteFlowQueueItem {
|
|
493
|
+
flowId: string;
|
|
494
|
+
flowTitle: string;
|
|
495
|
+
crossSiteSteps: CrossSiteFlowStep[];
|
|
496
|
+
/** Unix ms — item expires if not picked up by the extension */
|
|
497
|
+
expiresAt: number;
|
|
498
|
+
}
|
|
499
|
+
/** Sent by the extension content script to the embedded SDK page to initiate pairing */
|
|
500
|
+
interface KiBeePairRequest {
|
|
501
|
+
type: "KIBEE_PAIR_REQUEST";
|
|
502
|
+
/** chrome.runtime.id of the extension */
|
|
503
|
+
extensionId: string;
|
|
504
|
+
/** Manifest version string of the extension */
|
|
505
|
+
version: string;
|
|
506
|
+
}
|
|
507
|
+
/** Sent by the embedded SDK back to the extension content script to accept pairing */
|
|
508
|
+
interface KiBeePairAccept {
|
|
509
|
+
type: "KIBEE_PAIR_ACCEPT";
|
|
510
|
+
/** Public tenant identifier (same as websiteId) */
|
|
511
|
+
tenantPublicId: string;
|
|
512
|
+
/**
|
|
513
|
+
* The SaaS session ID — extension adopts this for all subordinate API calls.
|
|
514
|
+
* Analytics for both surfaces land in one session timeline.
|
|
515
|
+
*/
|
|
516
|
+
sessionId: string;
|
|
517
|
+
/** Domains the extension may activate on in subordinate mode, server-enforced by the API */
|
|
518
|
+
allowedExternalHosts: string[];
|
|
519
|
+
/** Pre-queued cross-site flows to execute on allowed external hosts */
|
|
520
|
+
flowQueue: CrossSiteFlowQueueItem[];
|
|
521
|
+
/** Pairing validity window in milliseconds, e.g. 1_800_000 (30 min) */
|
|
522
|
+
ttlMs: number;
|
|
523
|
+
/**
|
|
524
|
+
* Short-lived server-issued credential for the extension to authenticate
|
|
525
|
+
* subordinate polling requests. Scoped to this session only.
|
|
526
|
+
*/
|
|
527
|
+
pairingToken: string;
|
|
528
|
+
}
|
|
529
|
+
/** Sent by the extension content script to the embedded SDK to reject pairing */
|
|
530
|
+
interface KiBeePairReject {
|
|
531
|
+
type: "KIBEE_PAIR_REJECT";
|
|
532
|
+
reason: string;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Pairing state persisted in chrome.storage.local under key "kibee_pairing".
|
|
536
|
+
* Cleared on unpair. extensionVisitorId is NEVER overwritten by pairing.
|
|
537
|
+
*/
|
|
538
|
+
interface PairingState {
|
|
539
|
+
tenantPublicId: string;
|
|
540
|
+
/** The SaaS session ID shared for this pairing — used for all subordinate API calls */
|
|
541
|
+
sessionId: string;
|
|
542
|
+
/** Hostname of the SaaS page where the handshake started, e.g. "acme.com" */
|
|
543
|
+
originHostname: string;
|
|
544
|
+
/** Chrome tab ID where the handshake started — monitored for close/navigate-away */
|
|
545
|
+
originTabId: number;
|
|
546
|
+
/** Domains the extension may operate on in subordinate mode */
|
|
547
|
+
allowedExternalHosts: string[];
|
|
548
|
+
/** Cross-site flow steps cached from the last poll response */
|
|
549
|
+
flowQueue: CrossSiteFlowQueueItem[];
|
|
550
|
+
/** Short-lived token for authenticating subordinate polling requests */
|
|
551
|
+
pairingToken: string;
|
|
552
|
+
/** Unix ms when pairing was established */
|
|
553
|
+
pairedAt: number;
|
|
554
|
+
/** How long the pairing is valid in milliseconds */
|
|
555
|
+
ttlMs: number;
|
|
556
|
+
/**
|
|
557
|
+
* Index of the cross-site flow step currently executing.
|
|
558
|
+
* null = idle (no step in progress).
|
|
559
|
+
* Used to decide immediate vs deferred unpair when origin tab closes.
|
|
560
|
+
*/
|
|
561
|
+
activeFlowStepIndex: number | null;
|
|
562
|
+
/**
|
|
563
|
+
* Set to true when origin tab closes while a step is in progress.
|
|
564
|
+
* Content script detects this after step completion and clears pairing.
|
|
565
|
+
*/
|
|
566
|
+
pendingUnpair: boolean;
|
|
567
|
+
/**
|
|
568
|
+
* The extension's own permanent visitor ID.
|
|
569
|
+
* Preserved independently of pairing — NEVER replaced by the SaaS visitor ID.
|
|
570
|
+
* Used for event attribution even in subordinate mode.
|
|
571
|
+
*/
|
|
572
|
+
extensionVisitorId: string;
|
|
573
|
+
}
|
|
574
|
+
interface PushTargetsRequest {
|
|
575
|
+
targets: TargetRef[];
|
|
576
|
+
highlight?: HighlightVariant;
|
|
577
|
+
}
|
|
578
|
+
interface WidgetConfig {
|
|
579
|
+
position: DockPositionConfig;
|
|
580
|
+
size: number;
|
|
581
|
+
theme: {
|
|
582
|
+
primary: string;
|
|
583
|
+
tooltipBg: string;
|
|
584
|
+
tooltipColor: string;
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
export { type AdminSessionSummary, type AnalyticsEvent, BUDDY_TRANSITIONS, type BridgeClaims, type BridgeEnvelope, type BridgeEventType, type BuddyState, type ChatMessage, type ChatMode, type ChatSender, type CrossSiteFlowQueueItem, type CrossSiteFlowStep, type DockInlineAnchor, type DockPositionConfig, type DockPositionPreset, type EventMetadata, type FlowCommand, type FlowDefinition, type FlowMoveOptions, type HighlightVariant, type IdentityRequest, type IdentityResponse, type IntentMatch, type KiBeePairAccept, type KiBeePairReject, type KiBeePairRequest, type MessageTemplate, type PairingState, type PushFlowRequest, type PushTargetsRequest, type RecoveryRequest, type RecoveryResponse, type RegisteredTarget, type ResolveIntentRequest, type SessionState, type StartSessionRequest, type SurfaceId, type TargetRef, type TrackEventRequest, type VisibleTarget, type VisitorIdentity, type VisitorPollResponse, type WidgetConfig, canTransition, isBridgeEnvelope };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
BUDDY_TRANSITIONS: () => BUDDY_TRANSITIONS,
|
|
24
|
+
canTransition: () => canTransition,
|
|
25
|
+
isBridgeEnvelope: () => isBridgeEnvelope
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
|
|
29
|
+
// src/bridge.ts
|
|
30
|
+
var SURFACE_IDS = /* @__PURE__ */ new Set(["web", "extension", "desktop"]);
|
|
31
|
+
var BRIDGE_TARGETS = /* @__PURE__ */ new Set([
|
|
32
|
+
"web",
|
|
33
|
+
"extension",
|
|
34
|
+
"desktop",
|
|
35
|
+
"broadcast"
|
|
36
|
+
]);
|
|
37
|
+
var BRIDGE_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
38
|
+
"presence:hello",
|
|
39
|
+
"presence:bye",
|
|
40
|
+
"flow:handoff",
|
|
41
|
+
"flow:resume",
|
|
42
|
+
"pointer:show",
|
|
43
|
+
"memory:share",
|
|
44
|
+
"voice:state",
|
|
45
|
+
"capture:promote",
|
|
46
|
+
"tenant:attach",
|
|
47
|
+
"tenant:detach"
|
|
48
|
+
]);
|
|
49
|
+
function isBridgeEnvelope(value) {
|
|
50
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const e = value;
|
|
54
|
+
const isStringOrNull = (v) => v === null || typeof v === "string";
|
|
55
|
+
return e.v === 1 && typeof e.source === "string" && SURFACE_IDS.has(e.source) && typeof e.target === "string" && BRIDGE_TARGETS.has(e.target) && isStringOrNull(e.tenantId) && isStringOrNull(e.workspaceId) && typeof e.visitorId === "string" && isStringOrNull(e.sessionId) && typeof e.type === "string" && BRIDGE_EVENT_TYPES.has(e.type) && typeof e.ts === "number" && Number.isFinite(e.ts) && "payload" in e;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/buddy.ts
|
|
59
|
+
var BUDDY_TRANSITIONS = {
|
|
60
|
+
ambient: ["listening", "actionRing"],
|
|
61
|
+
listening: ["thinking", "ambient"],
|
|
62
|
+
thinking: ["speaking", "ambient"],
|
|
63
|
+
speaking: ["pointing", "followUp", "ambient"],
|
|
64
|
+
pointing: ["followUp", "ambient"],
|
|
65
|
+
followUp: ["ambient", "listening"],
|
|
66
|
+
actionRing: ["ambient", "listening"]
|
|
67
|
+
};
|
|
68
|
+
function canTransition(from, to) {
|
|
69
|
+
return BUDDY_TRANSITIONS[from].includes(to);
|
|
70
|
+
}
|
|
71
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
72
|
+
0 && (module.exports = {
|
|
73
|
+
BUDDY_TRANSITIONS,
|
|
74
|
+
canTransition,
|
|
75
|
+
isBridgeEnvelope
|
|
76
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/bridge.ts
|
|
2
|
+
var SURFACE_IDS = /* @__PURE__ */ new Set(["web", "extension", "desktop"]);
|
|
3
|
+
var BRIDGE_TARGETS = /* @__PURE__ */ new Set([
|
|
4
|
+
"web",
|
|
5
|
+
"extension",
|
|
6
|
+
"desktop",
|
|
7
|
+
"broadcast"
|
|
8
|
+
]);
|
|
9
|
+
var BRIDGE_EVENT_TYPES = /* @__PURE__ */ new Set([
|
|
10
|
+
"presence:hello",
|
|
11
|
+
"presence:bye",
|
|
12
|
+
"flow:handoff",
|
|
13
|
+
"flow:resume",
|
|
14
|
+
"pointer:show",
|
|
15
|
+
"memory:share",
|
|
16
|
+
"voice:state",
|
|
17
|
+
"capture:promote",
|
|
18
|
+
"tenant:attach",
|
|
19
|
+
"tenant:detach"
|
|
20
|
+
]);
|
|
21
|
+
function isBridgeEnvelope(value) {
|
|
22
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const e = value;
|
|
26
|
+
const isStringOrNull = (v) => v === null || typeof v === "string";
|
|
27
|
+
return e.v === 1 && typeof e.source === "string" && SURFACE_IDS.has(e.source) && typeof e.target === "string" && BRIDGE_TARGETS.has(e.target) && isStringOrNull(e.tenantId) && isStringOrNull(e.workspaceId) && typeof e.visitorId === "string" && isStringOrNull(e.sessionId) && typeof e.type === "string" && BRIDGE_EVENT_TYPES.has(e.type) && typeof e.ts === "number" && Number.isFinite(e.ts) && "payload" in e;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/buddy.ts
|
|
31
|
+
var BUDDY_TRANSITIONS = {
|
|
32
|
+
ambient: ["listening", "actionRing"],
|
|
33
|
+
listening: ["thinking", "ambient"],
|
|
34
|
+
thinking: ["speaking", "ambient"],
|
|
35
|
+
speaking: ["pointing", "followUp", "ambient"],
|
|
36
|
+
pointing: ["followUp", "ambient"],
|
|
37
|
+
followUp: ["ambient", "listening"],
|
|
38
|
+
actionRing: ["ambient", "listening"]
|
|
39
|
+
};
|
|
40
|
+
function canTransition(from, to) {
|
|
41
|
+
return BUDDY_TRANSITIONS[from].includes(to);
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
BUDDY_TRANSITIONS,
|
|
45
|
+
canTransition,
|
|
46
|
+
isBridgeEnvelope
|
|
47
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kibee/contracts",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"main": "./dist/index.js",
|
|
5
|
+
"module": "./dist/index.mjs",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": ["dist"],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean --tsconfig tsconfig.build.json",
|
|
17
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"tsup": "^8.5.1"
|
|
21
|
+
}
|
|
22
|
+
}
|