@memberjunction/conversations-runtime 6.1.4 → 6.2.0-edge.1

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 (41) hide show
  1. package/dist/ConversationsRuntime.d.ts +10 -0
  2. package/dist/ConversationsRuntime.d.ts.map +1 -1
  3. package/dist/ConversationsRuntime.js +12 -0
  4. package/dist/ConversationsRuntime.js.map +1 -1
  5. package/dist/agent-runner/ConversationAgentRunner.d.ts +27 -1
  6. package/dist/agent-runner/ConversationAgentRunner.d.ts.map +1 -1
  7. package/dist/agent-runner/ConversationAgentRunner.js +26 -3
  8. package/dist/agent-runner/ConversationAgentRunner.js.map +1 -1
  9. package/dist/default-agent/DefaultAgentResolver.d.ts +2 -0
  10. package/dist/default-agent/DefaultAgentResolver.d.ts.map +1 -1
  11. package/dist/default-agent/DefaultAgentResolver.js +5 -1
  12. package/dist/default-agent/DefaultAgentResolver.js.map +1 -1
  13. package/dist/index.d.ts +4 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +3 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/mentions/MentionAutocomplete.d.ts +178 -0
  18. package/dist/mentions/MentionAutocomplete.d.ts.map +1 -0
  19. package/dist/mentions/MentionAutocomplete.js +507 -0
  20. package/dist/mentions/MentionAutocomplete.js.map +1 -0
  21. package/dist/mentions/MentionParser.d.ts +10 -0
  22. package/dist/mentions/MentionParser.d.ts.map +1 -1
  23. package/dist/mentions/MentionParser.js +25 -5
  24. package/dist/mentions/MentionParser.js.map +1 -1
  25. package/dist/mentions/MentionSuggestion.d.ts +92 -0
  26. package/dist/mentions/MentionSuggestion.d.ts.map +1 -0
  27. package/dist/mentions/MentionSuggestion.js +19 -0
  28. package/dist/mentions/MentionSuggestion.js.map +1 -0
  29. package/dist/mentions/SkillNarrowing.d.ts +17 -0
  30. package/dist/mentions/SkillNarrowing.d.ts.map +1 -0
  31. package/dist/mentions/SkillNarrowing.js +17 -0
  32. package/dist/mentions/SkillNarrowing.js.map +1 -0
  33. package/dist/streaming/ConversationStreaming.d.ts +34 -1
  34. package/dist/streaming/ConversationStreaming.d.ts.map +1 -1
  35. package/dist/streaming/ConversationStreaming.js +58 -14
  36. package/dist/streaming/ConversationStreaming.js.map +1 -1
  37. package/dist/timeline/RealtimeSessionTimeline.d.ts +250 -0
  38. package/dist/timeline/RealtimeSessionTimeline.d.ts.map +1 -0
  39. package/dist/timeline/RealtimeSessionTimeline.js +347 -0
  40. package/dist/timeline/RealtimeSessionTimeline.js.map +1 -0
  41. package/package.json +8 -8
@@ -0,0 +1,250 @@
1
+ /**
2
+ * Realtime-session timeline grouping for the standard conversation message list.
3
+ *
4
+ * `MJ: Conversation Details` rows persisted DURING a live realtime session are stamped
5
+ * with `AgentSessionID` (the transcript relay stamps every caption turn; the artifact
6
+ * junction-anchor rows are stamped too). Rendering those rows as the normal back/forth
7
+ * chat bubbles is wrong — a 40-turn voice call would flood the timeline. Instead the
8
+ * message list collapses each session's stamped rows into ONE distinct timeline element
9
+ * (a session card) at the session's chronological position, from which the user can
10
+ * reopen the session review.
11
+ *
12
+ * This module is PURE (no Angular, no entities) so the grouping pass is unit-testable:
13
+ * the source shape is a minimal structural interface that `MJConversationDetailEntity`
14
+ * satisfies via its getters.
15
+ *
16
+ * It LIVED in `ng-conversations` and was promoted here unchanged, because purity was
17
+ * never the same thing as being in the right package: the mobile thread rendered every
18
+ * stamped row as an ordinary bubble — precisely what the paragraph above calls wrong —
19
+ * while the only implementation of the rule sat behind an Angular import. Any surface
20
+ * that renders a conversation needs this, so it belongs with the engine they all share.
21
+ * `ng-conversations` re-exports it, so its own consumers are unaffected.
22
+ */
23
+ /** The minimal detail-row shape the grouping pass reads (satisfied by `MJConversationDetailEntity`). */
24
+ export interface RealtimeTimelineSourceDetail {
25
+ ID: string;
26
+ /** Stamped session id for rows persisted during a live realtime session; null for normal chat rows. */
27
+ AgentSessionID: string | null;
28
+ /** `User` | `AI` | `Error` on the entity; widened to string for structural compatibility. */
29
+ Role: string;
30
+ Message: string | null;
31
+ /** Hidden rows (system/junction-anchor details) never count as visible turns. */
32
+ HiddenToUser: boolean;
33
+ __mj_CreatedAt: Date | null;
34
+ }
35
+ /**
36
+ * One realtime session's collapsed block: everything the timeline card renders that can
37
+ * be computed from the conversation's already-loaded detail rows (no extra queries).
38
+ */
39
+ export interface RealtimeSessionTimelineGroup {
40
+ /** `MJ: AI Agent Sessions.ID` the block's rows are stamped with (original casing of the first row). */
41
+ SessionID: string;
42
+ /** Timestamp of the session's first stamped row (≈ when the session's transcript began). */
43
+ StartedAt: Date | null;
44
+ /** Timestamp of the session's last stamped row (≈ when the transcript ended). */
45
+ EndedAt: Date | null;
46
+ /** VISIBLE caption turns: non-hidden `User`/`AI` rows with text (mirrors review-mode's turn mapping). */
47
+ TurnCount: number;
48
+ /** ALL stamped rows folded into this block, hidden anchors included. */
49
+ DetailCount: number;
50
+ /** Who spoke the last visible turn (AI → `Assistant`), or null when no visible turn exists. */
51
+ LastTurnRole: 'User' | 'Assistant' | null;
52
+ /** The last visible turn's text (untruncated — the card ellipsizes), or null. */
53
+ LastTurnPreview: string | null;
54
+ }
55
+ /**
56
+ * Session-row metadata the card enriches itself with when the host has it (one batched
57
+ * `MJ: AI Agent Sessions` lookup per conversation). All-optional by design: a missing
58
+ * meta entry degrades the card to its generic label with no status chip.
59
+ */
60
+ export interface RealtimeSessionTimelineMeta {
61
+ /** `MJ: AI Agent Sessions.ID`. */
62
+ SessionID: string;
63
+ /** Denormalized agent display name from the session view (usually the co-agent). */
64
+ AgentName: string | null;
65
+ Status: 'Active' | 'Closed' | 'Idle' | null;
66
+ /** Why the session closed (`Error` | `Explicit` | `Janitor` | `Shutdown`), when closed. */
67
+ CloseReason: string | null;
68
+ ClosedAt: Date | null;
69
+ /**
70
+ * When the session row was created, which is when the call started. That is earlier than the
71
+ * first caption, so it measures the call better than the transcript does. Optional, so meta built
72
+ * before this field existed still type-checks.
73
+ */
74
+ StartedAt?: Date | null;
75
+ /** The user whose call it was (`MJ: AI Agent Sessions.UserID`). */
76
+ UserID?: string | null;
77
+ /** That user's display name (the session view's denormalized `User`). */
78
+ UserName?: string | null;
79
+ }
80
+ /** One renderable timeline entry: a normal chat message OR a collapsed session block. */
81
+ export type ConversationTimelineItem<T extends RealtimeTimelineSourceDetail> = {
82
+ Kind: 'message';
83
+ Detail: T;
84
+ } | {
85
+ Kind: 'session';
86
+ Group: RealtimeSessionTimelineGroup;
87
+ };
88
+ /**
89
+ * Builds the renderable conversation timeline from the loaded detail rows (chronological,
90
+ * as the engine returns them):
91
+ * - rows WITHOUT an `AgentSessionID` pass through unchanged, in order;
92
+ * - rows WITH one collapse into ONE session block per session id, positioned where the
93
+ * session's FIRST stamped row sits. Later stamped rows of the same session (even when
94
+ * interleaved with normal messages) fold into that same block — one element per
95
+ * session, period.
96
+ *
97
+ * Session-id comparison is case-insensitive ({@link NormalizeUUID}) so SQL Server
98
+ * (uppercase) and PostgreSQL (lowercase) ids group identically.
99
+ */
100
+ export declare function BuildConversationTimeline<T extends RealtimeTimelineSourceDetail>(details: readonly T[]): ConversationTimelineItem<T>[];
101
+ /**
102
+ * Whether a session-stamped row is a turn a person should see.
103
+ *
104
+ * Exported because a surface that expands a session card to show its transcript must select the
105
+ * same rows the card counted — a list whose length disagrees with the "12 turns" above it reads as
106
+ * a bug even when both numbers are defensible. Hidden rows are the system/junction anchors the
107
+ * relay also stamps.
108
+ *
109
+ * @param detail One stamped detail row.
110
+ */
111
+ export declare function IsVisibleRealtimeTurn(detail: RealtimeTimelineSourceDetail): boolean;
112
+ /**
113
+ * How a session card's status chip should read.
114
+ *
115
+ * `Tone` is semantic rather than a colour so each surface maps it to its own palette — the web to
116
+ * its chip modifier classes, React Native to its token set.
117
+ */
118
+ export interface RealtimeSessionStatusChip {
119
+ /** The chip text ("Live", "Ended", "Timed out", …). */
120
+ Label: string;
121
+ /** What the chip means, for styling. */
122
+ Tone: 'live' | 'idle' | 'error' | 'neutral';
123
+ }
124
+ /**
125
+ * The card's title, in the words the rest of the product uses for a realtime session ("Start a
126
+ * voice call with…", "End call"): "Voice call with Sage", or "Voice call" when the lookup did not
127
+ * name the agent.
128
+ *
129
+ * @param meta The session-row enrichment, or null when the lookup was unavailable.
130
+ */
131
+ export declare function SessionCardTitle(meta: RealtimeSessionTimelineMeta | null | undefined): string;
132
+ /**
133
+ * The card's status chip, or `null` to hide it entirely.
134
+ *
135
+ * Closed sessions show a humanized close reason, falling back to "Closed" for legacy rows that
136
+ * predate the column. No meta at all means no chip — a session whose row could not be read should
137
+ * say nothing rather than guess.
138
+ *
139
+ * @param meta The session-row enrichment, or null when the lookup was unavailable.
140
+ */
141
+ export declare function SessionCardStatusChip(meta: RealtimeSessionTimelineMeta | null | undefined): RealtimeSessionStatusChip | null;
142
+ /**
143
+ * Whether the block's start and end fall on the same calendar day.
144
+ *
145
+ * Drives the end-time format: a same-day range shows only the time on its right half, so the date
146
+ * is not repeated. An incomplete range counts as same-day, since there is no second date to show.
147
+ *
148
+ * @param group The collapsed session block.
149
+ */
150
+ export declare function SessionCardIsSameDayRange(group: RealtimeSessionTimelineGroup | null | undefined): boolean;
151
+ /**
152
+ * When the call started: the session row's creation time when the lookup supplied it, else the
153
+ * first caption's. The row is the better answer, because the transcript only begins once somebody
154
+ * speaks.
155
+ *
156
+ * @param group The collapsed session block.
157
+ * @param meta The session-row enrichment, or null when the lookup was unavailable.
158
+ */
159
+ export declare function SessionCardStartedAt(group: RealtimeSessionTimelineGroup | null | undefined, meta: RealtimeSessionTimelineMeta | null | undefined): Date | null;
160
+ /**
161
+ * How long the call lasted, as a person would say it: "Under a minute", "12 min", "1 hr 5 min".
162
+ *
163
+ * Measured from the session row's start and close when the lookup supplied them, since the
164
+ * transcript runs from the first thing said to the last and so comes up short. Otherwise it falls
165
+ * back to the transcript's own span.
166
+ *
167
+ * `null` while the call is still going (Active or Idle), and whenever there is no span to measure.
168
+ * A single caption says nothing about how long a call ran, so it gets no duration rather than a
169
+ * confident "Under a minute".
170
+ *
171
+ * @param group The collapsed session block.
172
+ * @param meta The session-row enrichment, or null when the lookup was unavailable.
173
+ */
174
+ export declare function SessionCardDurationLabel(group: RealtimeSessionTimelineGroup | null | undefined, meta: RealtimeSessionTimelineMeta | null | undefined): string | null;
175
+ /**
176
+ * The card's message count: "No messages", "1 message", "12 messages".
177
+ *
178
+ * Counts the same visible turns review mode lists ({@link IsVisibleRealtimeTurn}), so the card and
179
+ * the transcript it opens agree.
180
+ *
181
+ * @param group The collapsed session block.
182
+ */
183
+ export declare function SessionCardMessageCountLabel(group: RealtimeSessionTimelineGroup | null | undefined): string;
184
+ /**
185
+ * Who said the card's quoted line.
186
+ *
187
+ * An agent turn is labeled with the agent's name, or "Agent" when the lookup did not supply one.
188
+ * A user turn is labeled "You" on the viewer's own call and with the caller's name on anyone
189
+ * else's. When the session row doesn't say whose call it was, the label is the neutral "Caller",
190
+ * so a shared conversation never labels someone else's call as yours.
191
+ *
192
+ * `fallbackUserName` is used only when the caller passes no viewer id, and so can't tell whose
193
+ * call it was either way.
194
+ *
195
+ * @param role Who spoke the line (`RealtimeSessionTimelineGroup.LastTurnRole`).
196
+ * @param meta The session-row enrichment, or null when the lookup was unavailable.
197
+ * @param viewerUserID The signed-in user's id, or null when the caller does not know it.
198
+ * @param fallbackUserName Label for a user turn when the caller passes no viewer id.
199
+ */
200
+ export declare function SessionCardSpeakerLabel(role: RealtimeSessionTimelineGroup['LastTurnRole'], meta: RealtimeSessionTimelineMeta | null | undefined, viewerUserID: string | null | undefined, fallbackUserName?: string): string;
201
+ /**
202
+ * The `MJ: AI Agent Sessions` row shape the meta lookup reads.
203
+ *
204
+ * Deliberately structural and string-tolerant on the dates: a `simple` RunView returns ISO strings
205
+ * where an entity object would return `Date`, and both callers use `simple`.
206
+ */
207
+ export interface RealtimeSessionMetaRow {
208
+ ID: string;
209
+ /** Denormalized agent display name from the session view. */
210
+ Agent?: string | null;
211
+ Status?: 'Active' | 'Closed' | 'Idle' | null;
212
+ CloseReason?: string | null;
213
+ ClosedAt?: Date | string | null;
214
+ /** The user whose call it was. */
215
+ UserID?: string | null;
216
+ /** Denormalized display name of that user from the session view. */
217
+ User?: string | null;
218
+ /** When the row was created, which is when the call started. */
219
+ __mj_CreatedAt?: Date | string | null;
220
+ }
221
+ /**
222
+ * The columns the meta lookup needs, so both surfaces ask for the same ones.
223
+ *
224
+ * A host that trims this list gets cards missing their chips on that host only — the kind of
225
+ * divergence that is invisible until someone compares two screenshots.
226
+ */
227
+ export declare const REALTIME_SESSION_META_FIELDS: readonly string[];
228
+ /**
229
+ * The DISTINCT session ids stamped across `details`, in first-seen order.
230
+ *
231
+ * Deduped case-insensitively ({@link NormalizeUUID}) because SQL Server returns uppercase ids and
232
+ * PostgreSQL lowercase; the original casing of the first occurrence is what comes back, since that
233
+ * is what the `ID IN (…)` filter has to match.
234
+ *
235
+ * @param details The conversation's loaded detail rows.
236
+ */
237
+ export declare function CollectRealtimeSessionIDs(details: readonly RealtimeTimelineSourceDetail[]): string[];
238
+ /**
239
+ * Maps session rows to the card's meta, keyed by {@link NormalizeUUID} so lookups match however
240
+ * the database cased the id.
241
+ *
242
+ * Tolerant: an unparseable `ClosedAt` or `__mj_CreatedAt` becomes `null` rather than an Invalid
243
+ * Date, which would otherwise render as "Invalid Date" on the card.
244
+ *
245
+ * @param rows Rows from `MJ: AI Agent Sessions` (see {@link REALTIME_SESSION_META_FIELDS}).
246
+ */
247
+ export declare function MapRealtimeSessionMeta(rows: readonly RealtimeSessionMetaRow[] | null | undefined): Map<string, RealtimeSessionTimelineMeta>;
248
+ /** Looks up a session block's meta, matching however the database cased the id. */
249
+ export declare function FindRealtimeSessionMeta(metaMap: ReadonlyMap<string, RealtimeSessionTimelineMeta> | null | undefined, sessionId: string): RealtimeSessionTimelineMeta | null;
250
+ //# sourceMappingURL=RealtimeSessionTimeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RealtimeSessionTimeline.d.ts","sourceRoot":"","sources":["../../src/timeline/RealtimeSessionTimeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,347 @@
1
+ /**
2
+ * Realtime-session timeline grouping for the standard conversation message list.
3
+ *
4
+ * `MJ: Conversation Details` rows persisted DURING a live realtime session are stamped
5
+ * with `AgentSessionID` (the transcript relay stamps every caption turn; the artifact
6
+ * junction-anchor rows are stamped too). Rendering those rows as the normal back/forth
7
+ * chat bubbles is wrong — a 40-turn voice call would flood the timeline. Instead the
8
+ * message list collapses each session's stamped rows into ONE distinct timeline element
9
+ * (a session card) at the session's chronological position, from which the user can
10
+ * reopen the session review.
11
+ *
12
+ * This module is PURE (no Angular, no entities) so the grouping pass is unit-testable:
13
+ * the source shape is a minimal structural interface that `MJConversationDetailEntity`
14
+ * satisfies via its getters.
15
+ *
16
+ * It LIVED in `ng-conversations` and was promoted here unchanged, because purity was
17
+ * never the same thing as being in the right package: the mobile thread rendered every
18
+ * stamped row as an ordinary bubble — precisely what the paragraph above calls wrong —
19
+ * while the only implementation of the rule sat behind an Angular import. Any surface
20
+ * that renders a conversation needs this, so it belongs with the engine they all share.
21
+ * `ng-conversations` re-exports it, so its own consumers are unaffected.
22
+ */
23
+ import { NormalizeUUID, UUIDsEqual } from '@memberjunction/global';
24
+ /**
25
+ * Builds the renderable conversation timeline from the loaded detail rows (chronological,
26
+ * as the engine returns them):
27
+ * - rows WITHOUT an `AgentSessionID` pass through unchanged, in order;
28
+ * - rows WITH one collapse into ONE session block per session id, positioned where the
29
+ * session's FIRST stamped row sits. Later stamped rows of the same session (even when
30
+ * interleaved with normal messages) fold into that same block — one element per
31
+ * session, period.
32
+ *
33
+ * Session-id comparison is case-insensitive ({@link NormalizeUUID}) so SQL Server
34
+ * (uppercase) and PostgreSQL (lowercase) ids group identically.
35
+ */
36
+ export function BuildConversationTimeline(details) {
37
+ const items = [];
38
+ const groupsBySessionKey = new Map();
39
+ for (const detail of details) {
40
+ const sessionId = normalizeSessionId(detail.AgentSessionID);
41
+ if (!sessionId) {
42
+ items.push({ Kind: 'message', Detail: detail });
43
+ continue;
44
+ }
45
+ const key = NormalizeUUID(sessionId);
46
+ let group = groupsBySessionKey.get(key);
47
+ if (!group) {
48
+ group = createGroup(sessionId);
49
+ groupsBySessionKey.set(key, group);
50
+ items.push({ Kind: 'session', Group: group });
51
+ }
52
+ foldDetailIntoGroup(group, detail);
53
+ }
54
+ return items;
55
+ }
56
+ /** Trims the stamped session id; empty/whitespace ids are treated as unstamped. */
57
+ function normalizeSessionId(raw) {
58
+ const trimmed = raw?.trim() ?? '';
59
+ return trimmed.length > 0 ? trimmed : null;
60
+ }
61
+ /** A fresh, empty session block for the given session id. */
62
+ function createGroup(sessionId) {
63
+ return {
64
+ SessionID: sessionId,
65
+ StartedAt: null,
66
+ EndedAt: null,
67
+ TurnCount: 0,
68
+ DetailCount: 0,
69
+ LastTurnRole: null,
70
+ LastTurnPreview: null
71
+ };
72
+ }
73
+ /** Folds one stamped detail row into its session block (range, counts, last-turn preview). */
74
+ function foldDetailIntoGroup(group, detail) {
75
+ group.DetailCount++;
76
+ const at = toDate(detail.__mj_CreatedAt);
77
+ if (at) {
78
+ if (!group.StartedAt || at.getTime() < group.StartedAt.getTime()) {
79
+ group.StartedAt = at;
80
+ }
81
+ if (!group.EndedAt || at.getTime() > group.EndedAt.getTime()) {
82
+ group.EndedAt = at;
83
+ }
84
+ }
85
+ if (IsVisibleRealtimeTurn(detail)) {
86
+ group.TurnCount++;
87
+ group.LastTurnRole = detail.Role === 'AI' ? 'Assistant' : 'User';
88
+ group.LastTurnPreview = detail.Message?.trim() ?? '';
89
+ }
90
+ }
91
+ /**
92
+ * Whether a session-stamped row is a turn a person should see.
93
+ *
94
+ * Exported because a surface that expands a session card to show its transcript must select the
95
+ * same rows the card counted — a list whose length disagrees with the "12 turns" above it reads as
96
+ * a bug even when both numbers are defensible. Hidden rows are the system/junction anchors the
97
+ * relay also stamps.
98
+ *
99
+ * @param detail One stamped detail row.
100
+ */
101
+ export function IsVisibleRealtimeTurn(detail) {
102
+ const text = detail.Message?.trim() ?? '';
103
+ return !detail.HiddenToUser && text.length > 0 && (detail.Role === 'User' || detail.Role === 'AI');
104
+ }
105
+ /** Tolerant date conversion — raw cache rows can carry ISO strings instead of Dates. */
106
+ function toDate(value) {
107
+ if (value == null) {
108
+ return null;
109
+ }
110
+ const date = value instanceof Date ? value : new Date(value);
111
+ return isNaN(date.getTime()) ? null : date;
112
+ }
113
+ /**
114
+ * The card's title, in the words the rest of the product uses for a realtime session ("Start a
115
+ * voice call with…", "End call"): "Voice call with Sage", or "Voice call" when the lookup did not
116
+ * name the agent.
117
+ *
118
+ * @param meta The session-row enrichment, or null when the lookup was unavailable.
119
+ */
120
+ export function SessionCardTitle(meta) {
121
+ const agent = meta?.AgentName?.trim();
122
+ return agent ? `Voice call with ${agent}` : 'Voice call';
123
+ }
124
+ /**
125
+ * The card's status chip, or `null` to hide it entirely.
126
+ *
127
+ * Closed sessions show a humanized close reason, falling back to "Closed" for legacy rows that
128
+ * predate the column. No meta at all means no chip — a session whose row could not be read should
129
+ * say nothing rather than guess.
130
+ *
131
+ * @param meta The session-row enrichment, or null when the lookup was unavailable.
132
+ */
133
+ export function SessionCardStatusChip(meta) {
134
+ switch (meta?.Status) {
135
+ case 'Closed':
136
+ return closeReasonChip(meta.CloseReason);
137
+ case 'Active':
138
+ return { Label: 'Live', Tone: 'live' };
139
+ case 'Idle':
140
+ return { Label: 'Idle', Tone: 'idle' };
141
+ default:
142
+ return null;
143
+ }
144
+ }
145
+ /**
146
+ * Whether the block's start and end fall on the same calendar day.
147
+ *
148
+ * Drives the end-time format: a same-day range shows only the time on its right half, so the date
149
+ * is not repeated. An incomplete range counts as same-day, since there is no second date to show.
150
+ *
151
+ * @param group The collapsed session block.
152
+ */
153
+ export function SessionCardIsSameDayRange(group) {
154
+ const start = group?.StartedAt;
155
+ const end = group?.EndedAt;
156
+ if (!start || !end) {
157
+ return true;
158
+ }
159
+ return start.toDateString() === end.toDateString();
160
+ }
161
+ /**
162
+ * When the call started: the session row's creation time when the lookup supplied it, else the
163
+ * first caption's. The row is the better answer, because the transcript only begins once somebody
164
+ * speaks.
165
+ *
166
+ * @param group The collapsed session block.
167
+ * @param meta The session-row enrichment, or null when the lookup was unavailable.
168
+ */
169
+ export function SessionCardStartedAt(group, meta) {
170
+ return meta?.StartedAt ?? group?.StartedAt ?? null;
171
+ }
172
+ /**
173
+ * How long the call lasted, as a person would say it: "Under a minute", "12 min", "1 hr 5 min".
174
+ *
175
+ * Measured from the session row's start and close when the lookup supplied them, since the
176
+ * transcript runs from the first thing said to the last and so comes up short. Otherwise it falls
177
+ * back to the transcript's own span.
178
+ *
179
+ * `null` while the call is still going (Active or Idle), and whenever there is no span to measure.
180
+ * A single caption says nothing about how long a call ran, so it gets no duration rather than a
181
+ * confident "Under a minute".
182
+ *
183
+ * @param group The collapsed session block.
184
+ * @param meta The session-row enrichment, or null when the lookup was unavailable.
185
+ */
186
+ export function SessionCardDurationLabel(group, meta) {
187
+ if (meta?.Status === 'Active' || meta?.Status === 'Idle') {
188
+ return null;
189
+ }
190
+ const start = SessionCardStartedAt(group, meta);
191
+ const end = meta?.ClosedAt ?? group?.EndedAt ?? null;
192
+ if (!start || !end) {
193
+ return null;
194
+ }
195
+ const elapsedMs = end.getTime() - start.getTime();
196
+ // `> 0` rather than `<= 0` so a NaN from a bad date falls through to "no duration" too.
197
+ return elapsedMs > 0 ? formatCallDuration(elapsedMs) : null;
198
+ }
199
+ /**
200
+ * The card's message count: "No messages", "1 message", "12 messages".
201
+ *
202
+ * Counts the same visible turns review mode lists ({@link IsVisibleRealtimeTurn}), so the card and
203
+ * the transcript it opens agree.
204
+ *
205
+ * @param group The collapsed session block.
206
+ */
207
+ export function SessionCardMessageCountLabel(group) {
208
+ const count = group?.TurnCount ?? 0;
209
+ if (count === 0) {
210
+ return 'No messages';
211
+ }
212
+ return count === 1 ? '1 message' : `${count} messages`;
213
+ }
214
+ /**
215
+ * Who said the card's quoted line.
216
+ *
217
+ * An agent turn is labeled with the agent's name, or "Agent" when the lookup did not supply one.
218
+ * A user turn is labeled "You" on the viewer's own call and with the caller's name on anyone
219
+ * else's. When the session row doesn't say whose call it was, the label is the neutral "Caller",
220
+ * so a shared conversation never labels someone else's call as yours.
221
+ *
222
+ * `fallbackUserName` is used only when the caller passes no viewer id, and so can't tell whose
223
+ * call it was either way.
224
+ *
225
+ * @param role Who spoke the line (`RealtimeSessionTimelineGroup.LastTurnRole`).
226
+ * @param meta The session-row enrichment, or null when the lookup was unavailable.
227
+ * @param viewerUserID The signed-in user's id, or null when the caller does not know it.
228
+ * @param fallbackUserName Label for a user turn when the caller passes no viewer id.
229
+ */
230
+ export function SessionCardSpeakerLabel(role, meta, viewerUserID, fallbackUserName = 'You') {
231
+ if (role === 'Assistant') {
232
+ return meta?.AgentName?.trim() || 'Agent';
233
+ }
234
+ const viewerID = viewerUserID?.trim();
235
+ if (!viewerID) {
236
+ return fallbackUserName;
237
+ }
238
+ const ownerID = meta?.UserID?.trim();
239
+ if (!ownerID) {
240
+ return 'Caller';
241
+ }
242
+ if (UUIDsEqual(ownerID, viewerID)) {
243
+ return 'You';
244
+ }
245
+ // Someone else's call: their name if the row carried it.
246
+ return meta?.UserName?.trim() || 'Caller';
247
+ }
248
+ /** Formats a positive span in milliseconds for {@link SessionCardDurationLabel}. */
249
+ function formatCallDuration(elapsedMs) {
250
+ if (elapsedMs < 60_000) {
251
+ return 'Under a minute';
252
+ }
253
+ const totalMinutes = Math.round(elapsedMs / 60_000);
254
+ const hours = Math.floor(totalMinutes / 60);
255
+ const minutes = totalMinutes % 60;
256
+ if (hours === 0) {
257
+ return `${minutes} min`;
258
+ }
259
+ return minutes === 0 ? `${hours} hr` : `${hours} hr ${minutes} min`;
260
+ }
261
+ /** Maps a close reason to its chip. `Error` is the only one that reads as a failure. */
262
+ function closeReasonChip(reason) {
263
+ switch (reason) {
264
+ case 'Explicit':
265
+ return { Label: 'Ended', Tone: 'neutral' };
266
+ case 'Error':
267
+ return { Label: 'Error', Tone: 'error' };
268
+ case 'Janitor':
269
+ return { Label: 'Timed out', Tone: 'neutral' };
270
+ case 'Shutdown':
271
+ // The server restarted under the call. Worded for the person on it, who never saw a server.
272
+ return { Label: 'Interrupted', Tone: 'neutral' };
273
+ default:
274
+ return { Label: 'Closed', Tone: 'neutral' };
275
+ }
276
+ }
277
+ /**
278
+ * The columns the meta lookup needs, so both surfaces ask for the same ones.
279
+ *
280
+ * A host that trims this list gets cards missing their chips on that host only — the kind of
281
+ * divergence that is invisible until someone compares two screenshots.
282
+ */
283
+ export const REALTIME_SESSION_META_FIELDS = [
284
+ 'ID',
285
+ 'Agent',
286
+ 'Status',
287
+ 'CloseReason',
288
+ 'ClosedAt',
289
+ 'UserID',
290
+ 'User',
291
+ '__mj_CreatedAt'
292
+ ];
293
+ /**
294
+ * The DISTINCT session ids stamped across `details`, in first-seen order.
295
+ *
296
+ * Deduped case-insensitively ({@link NormalizeUUID}) because SQL Server returns uppercase ids and
297
+ * PostgreSQL lowercase; the original casing of the first occurrence is what comes back, since that
298
+ * is what the `ID IN (…)` filter has to match.
299
+ *
300
+ * @param details The conversation's loaded detail rows.
301
+ */
302
+ export function CollectRealtimeSessionIDs(details) {
303
+ const ids = [];
304
+ const seen = new Set();
305
+ for (const detail of details) {
306
+ const raw = detail.AgentSessionID?.trim() ?? '';
307
+ if (raw.length === 0) {
308
+ continue;
309
+ }
310
+ const key = NormalizeUUID(raw);
311
+ if (!seen.has(key)) {
312
+ seen.add(key);
313
+ ids.push(raw);
314
+ }
315
+ }
316
+ return ids;
317
+ }
318
+ /**
319
+ * Maps session rows to the card's meta, keyed by {@link NormalizeUUID} so lookups match however
320
+ * the database cased the id.
321
+ *
322
+ * Tolerant: an unparseable `ClosedAt` or `__mj_CreatedAt` becomes `null` rather than an Invalid
323
+ * Date, which would otherwise render as "Invalid Date" on the card.
324
+ *
325
+ * @param rows Rows from `MJ: AI Agent Sessions` (see {@link REALTIME_SESSION_META_FIELDS}).
326
+ */
327
+ export function MapRealtimeSessionMeta(rows) {
328
+ const map = new Map();
329
+ for (const row of rows ?? []) {
330
+ map.set(NormalizeUUID(row.ID), {
331
+ SessionID: row.ID,
332
+ AgentName: row.Agent ?? null,
333
+ Status: row.Status ?? null,
334
+ CloseReason: row.CloseReason ?? null,
335
+ ClosedAt: toDate(row.ClosedAt),
336
+ StartedAt: toDate(row.__mj_CreatedAt),
337
+ UserID: row.UserID ?? null,
338
+ UserName: row.User ?? null
339
+ });
340
+ }
341
+ return map;
342
+ }
343
+ /** Looks up a session block's meta, matching however the database cased the id. */
344
+ export function FindRealtimeSessionMeta(metaMap, sessionId) {
345
+ return metaMap?.get(NormalizeUUID(sessionId)) ?? null;
346
+ }
347
+ //# sourceMappingURL=RealtimeSessionTimeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RealtimeSessionTimeline.js","sourceRoot":"","sources":["../../src/timeline/RealtimeSessionTimeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAmEnE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAAqB;IAErB,MAAM,KAAK,GAAkC,EAAE,CAAC;IAChD,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAwC,CAAC;IAE3E,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,SAAS,GAAG,kBAAkB,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAC5D,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YAChD,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;YAC/B,kBAAkB,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAChD,CAAC;QACD,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,mFAAmF;AACnF,SAAS,kBAAkB,CAAC,GAAkB;IAC5C,MAAM,OAAO,GAAG,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAClC,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED,6DAA6D;AAC7D,SAAS,WAAW,CAAC,SAAiB;IACpC,OAAO;QACL,SAAS,EAAE,SAAS;QACpB,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,CAAC;QACZ,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,IAAI;QAClB,eAAe,EAAE,IAAI;KACtB,CAAC;AACJ,CAAC;AAED,8FAA8F;AAC9F,SAAS,mBAAmB,CAAC,KAAmC,EAAE,MAAoC;IACpG,KAAK,CAAC,WAAW,EAAE,CAAC;IAEpB,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IACzC,IAAI,EAAE,EAAE,CAAC;QACP,IAAI,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;YACjE,KAAK,CAAC,SAAS,GAAG,EAAE,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;YAC7D,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;IAED,IAAI,qBAAqB,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,KAAK,CAAC,SAAS,EAAE,CAAC;QAClB,KAAK,CAAC,YAAY,GAAG,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;QACjE,KAAK,CAAC,eAAe,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACvD,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAoC;IACxE,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC1C,OAAO,CAAC,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACrG,CAAC;AAED,wFAAwF;AACxF,SAAS,MAAM,CAAC,KAAuC;IACrD,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7D,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAeD;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAoD;IACnF,MAAM,KAAK,GAAG,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACtC,OAAO,KAAK,CAAC,CAAC,CAAC,mBAAmB,KAAK,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;AAC3D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAoD;IAEpD,QAAQ,IAAI,EAAE,MAAM,EAAE,CAAC;QACrB,KAAK,QAAQ;YACX,OAAO,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3C,KAAK,QAAQ;YACX,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QACzC,KAAK,MAAM;YACT,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QACzC;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,yBAAyB,CAAC,KAAsD;IAC9F,MAAM,KAAK,GAAG,KAAK,EAAE,SAAS,CAAC;IAC/B,MAAM,GAAG,GAAG,KAAK,EAAE,OAAO,CAAC;IAC3B,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC,YAAY,EAAE,KAAK,GAAG,CAAC,YAAY,EAAE,CAAC;AACrD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAsD,EACtD,IAAoD;IAEpD,OAAO,IAAI,EAAE,SAAS,IAAI,KAAK,EAAE,SAAS,IAAI,IAAI,CAAC;AACrD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,wBAAwB,CACtC,KAAsD,EACtD,IAAoD;IAEpD,IAAI,IAAI,EAAE,MAAM,KAAK,QAAQ,IAAI,IAAI,EAAE,MAAM,KAAK,MAAM,EAAE,CAAC;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,oBAAoB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,IAAI,EAAE,QAAQ,IAAI,KAAK,EAAE,OAAO,IAAI,IAAI,CAAC;IACrD,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC;IAClD,wFAAwF;IACxF,OAAO,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,4BAA4B,CAAC,KAAsD;IACjG,MAAM,KAAK,GAAG,KAAK,EAAE,SAAS,IAAI,CAAC,CAAC;IACpC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,KAAK,WAAW,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,uBAAuB,CACrC,IAAkD,EAClD,IAAoD,EACpD,YAAuC,EACvC,gBAAgB,GAAG,KAAK;IAExB,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACzB,OAAO,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC;IAC5C,CAAC;IACD,MAAM,QAAQ,GAAG,YAAY,EAAE,IAAI,EAAE,CAAC;IACtC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,IAAI,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,yDAAyD;IACzD,OAAO,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,QAAQ,CAAC;AAC5C,CAAC;AAED,oFAAoF;AACpF,SAAS,kBAAkB,CAAC,SAAiB;IAC3C,IAAI,SAAS,GAAG,MAAM,EAAE,CAAC;QACvB,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,YAAY,GAAG,EAAE,CAAC;IAClC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,OAAO,GAAG,OAAO,MAAM,CAAC;IAC1B,CAAC;IACD,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,OAAO,OAAO,MAAM,CAAC;AACtE,CAAC;AAED,wFAAwF;AACxF,SAAS,eAAe,CAAC,MAAqB;IAC5C,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,UAAU;YACb,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAC7C,KAAK,OAAO;YACV,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC3C,KAAK,SAAS;YACZ,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QACjD,KAAK,UAAU;YACb,4FAA4F;YAC5F,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QACnD;YACE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAChD,CAAC;AACH,CAAC;AAuBD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAsB;IAC7D,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,aAAa;IACb,UAAU;IACV,QAAQ;IACR,MAAM;IACN,gBAAgB;CACjB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAgD;IACxF,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAChD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,IAA0D;IAE1D,MAAM,GAAG,GAAG,IAAI,GAAG,EAAuC,CAAC;IAC3D,KAAK,MAAM,GAAG,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;QAC7B,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAC7B,SAAS,EAAE,GAAG,CAAC,EAAE;YACjB,SAAS,EAAE,GAAG,CAAC,KAAK,IAAI,IAAI;YAC5B,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,IAAI;YAC1B,WAAW,EAAE,GAAG,CAAC,WAAW,IAAI,IAAI;YACpC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC9B,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC;YACrC,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,IAAI;YAC1B,QAAQ,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI;SAC3B,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,uBAAuB,CACrC,OAA4E,EAC5E,SAAiB;IAEjB,OAAO,OAAO,EAAE,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,IAAI,IAAI,CAAC;AACxD,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@memberjunction/conversations-runtime",
3
3
  "type": "module",
4
- "version": "6.1.4",
4
+ "version": "6.2.0-edge.1",
5
5
  "description": "MemberJunction: Framework-agnostic Conversations Runtime — orchestration, mention parsing, overlay/workspace bridge, default-agent resolution, client-tool registry, sessions observability. Pure TypeScript, zero UX dependencies. Consumable from browser (Angular widget, React, Vue, etc.) or server (Node workers, CLI tools, test harnesses).",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -11,13 +11,13 @@
11
11
  "author": "MemberJunction.com",
12
12
  "license": "BUSL-1.1",
13
13
  "dependencies": {
14
- "@memberjunction/ai-agent-client": "6.1.4",
15
- "@memberjunction/ai-core-plus": "6.1.4",
16
- "@memberjunction/ai-engine-base": "6.1.4",
17
- "@memberjunction/core": "6.1.4",
18
- "@memberjunction/core-entities": "6.1.4",
19
- "@memberjunction/global": "6.1.4",
20
- "@memberjunction/graphql-dataprovider": "6.1.4",
14
+ "@memberjunction/ai-agent-client": "6.2.0-edge.1",
15
+ "@memberjunction/ai-core-plus": "6.2.0-edge.1",
16
+ "@memberjunction/ai-engine-base": "6.2.0-edge.1",
17
+ "@memberjunction/core": "6.2.0-edge.1",
18
+ "@memberjunction/core-entities": "6.2.0-edge.1",
19
+ "@memberjunction/global": "6.2.0-edge.1",
20
+ "@memberjunction/graphql-dataprovider": "6.2.0-edge.1",
21
21
  "rxjs": "^7.8.2"
22
22
  },
23
23
  "devDependencies": {