@memberjunction/ng-conversations 6.1.0-edge.6 → 6.1.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.
Files changed (34) hide show
  1. package/dist/lib/components/dialogs/input-dialog.component.d.ts.map +1 -1
  2. package/dist/lib/components/dialogs/input-dialog.component.js +3 -3
  3. package/dist/lib/components/dialogs/input-dialog.component.js.map +1 -1
  4. package/dist/lib/components/message/message-input.component.js +4 -4
  5. package/dist/lib/components/message/message-input.component.js.map +1 -1
  6. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts +1 -1
  7. package/dist/lib/components/realtime/realtime-activity-rail.component.d.ts.map +1 -1
  8. package/dist/lib/components/realtime/realtime-activity-rail.component.js +2 -2
  9. package/dist/lib/components/realtime/realtime-activity-rail.component.js.map +1 -1
  10. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts +16 -1
  11. package/dist/lib/components/realtime/realtime-agent-picker.component.d.ts.map +1 -1
  12. package/dist/lib/components/realtime/realtime-agent-picker.component.js +39 -7
  13. package/dist/lib/components/realtime/realtime-agent-picker.component.js.map +1 -1
  14. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts +2 -2
  15. package/dist/lib/components/realtime/realtime-delegation-card.component.d.ts.map +1 -1
  16. package/dist/lib/components/realtime/realtime-delegation-card.component.js +159 -107
  17. package/dist/lib/components/realtime/realtime-delegation-card.component.js.map +1 -1
  18. package/dist/lib/components/realtime/realtime-session-state.d.ts +9 -4
  19. package/dist/lib/components/realtime/realtime-session-state.d.ts.map +1 -1
  20. package/dist/lib/components/realtime/realtime-session-state.js +95 -19
  21. package/dist/lib/components/realtime/realtime-session-state.js.map +1 -1
  22. package/dist/lib/services/delegation-result-parser.d.ts +5 -0
  23. package/dist/lib/services/delegation-result-parser.d.ts.map +1 -1
  24. package/dist/lib/services/delegation-result-parser.js +12 -0
  25. package/dist/lib/services/delegation-result-parser.js.map +1 -1
  26. package/dist/lib/services/realtime-session-review.service.d.ts +31 -1
  27. package/dist/lib/services/realtime-session-review.service.d.ts.map +1 -1
  28. package/dist/lib/services/realtime-session-review.service.js +63 -8
  29. package/dist/lib/services/realtime-session-review.service.js.map +1 -1
  30. package/dist/lib/services/realtime-session.service.d.ts +15 -8
  31. package/dist/lib/services/realtime-session.service.d.ts.map +1 -1
  32. package/dist/lib/services/realtime-session.service.js +62 -14
  33. package/dist/lib/services/realtime-session.service.js.map +1 -1
  34. package/package.json +31 -31
@@ -6,7 +6,7 @@ import { AIEngineBase } from '@memberjunction/ai-engine-base';
6
6
  import { MJGlobal } from '@memberjunction/global';
7
7
  import { BaseRealtimeClient, LoadAssemblyAIRealtimeClient, LoadElevenLabsRealtimeClient, LoadGeminiRealtimeClient, LoadHuggingFaceRealtimeClient, LoadOpenAIRealtimeClient, LoadxAIRealtimeClient } from '@memberjunction/ai-realtime-client';
8
8
  import { BuildNarrationInstructions } from './narration-template';
9
- import { ParseDelegationResultJson } from './delegation-result-parser';
9
+ import { ParseDelegationResultJson, FormatToolName } from './delegation-result-parser';
10
10
  import { BaseRealtimeChannelClient } from '../components/realtime/channels/base-realtime-channel-client';
11
11
  import { RealtimeAudioRecorder } from './realtime-audio-recorder';
12
12
  import * as i0 from "@angular/core";
@@ -181,6 +181,10 @@ export class RealtimeSessionService {
181
181
  sessionConversationId = null;
182
182
  /** First final user utterance of the live session (the naming seed). */
183
183
  firstUserTranscript = null;
184
+ /** Buffer accumulating streaming user interim deltas into a single in-progress bubble. */
185
+ pendingUserCaption = '';
186
+ /** Whether an in-place interim user caption is currently placed in `_captions$`. */
187
+ hasActiveInterimUserCaption = false;
184
188
  /**
185
189
  * When the active/last session CREATED its conversation (started without one), the new
186
190
  * conversation's id — the host uses it to refresh the cached list, conditionally select
@@ -1299,7 +1303,7 @@ export class RealtimeSessionService {
1299
1303
  void this.handleToolCall(call);
1300
1304
  });
1301
1305
  client.OnError((error) => {
1302
- console.error('[RealtimeSession] Provider error event:', error);
1306
+ console.error('[RealtimeSession] Provider error event:', JSON.stringify(error), error);
1303
1307
  });
1304
1308
  // Usage telemetry: accumulate the driver's per-response token DELTAS and relay them to
1305
1309
  // the server (onto the co-agent AIPromptRun) debounced + once at teardown. Providers
@@ -1367,9 +1371,25 @@ export class RealtimeSessionService {
1367
1371
  // silence gap is timed where its audio really is — not inherited from the prior
1368
1372
  // turn's end. Narration interims are ephemeral and excluded (Kind guard inside).
1369
1373
  this.markTurnAudioStart(transcript.Kind);
1374
+ if (transcript.Role === 'User') {
1375
+ if (!this.hasActiveInterimUserCaption) {
1376
+ if (transcript.Text.trim().length === 0) {
1377
+ return;
1378
+ }
1379
+ this.hasActiveInterimUserCaption = true;
1380
+ this.pendingUserCaption = transcript.Text;
1381
+ this.appendCaption({ Role: 'User', Text: this.pendingUserCaption });
1382
+ }
1383
+ else {
1384
+ this.pendingUserCaption += transcript.Text;
1385
+ this.replaceLastCaption('User', this.pendingUserCaption);
1386
+ }
1387
+ }
1370
1388
  return;
1371
1389
  }
1372
1390
  if (transcript.Role === 'Assistant') {
1391
+ this.hasActiveInterimUserCaption = false;
1392
+ this.pendingUserCaption = '';
1373
1393
  if (transcript.Kind === 'narration') {
1374
1394
  this._delegationNarration$.next({ Text: transcript.Text });
1375
1395
  // Remember what was actually SAID so later updates build on it instead of repeating.
@@ -1390,11 +1410,26 @@ export class RealtimeSessionService {
1390
1410
  await this.relayTranscript('assistant', transcript.Text);
1391
1411
  }
1392
1412
  }
1413
+ else if (this.hasActiveInterimUserCaption) {
1414
+ this.hasActiveInterimUserCaption = false;
1415
+ this.pendingUserCaption = '';
1416
+ if (transcript.Text.trim().length === 0) {
1417
+ return;
1418
+ }
1419
+ this.replaceLastCaption('User', transcript.Text);
1420
+ if (this.firstUserTranscript === null) {
1421
+ this.firstUserTranscript = transcript.Text;
1422
+ }
1423
+ await this.relayTranscript('user', transcript.Text);
1424
+ }
1393
1425
  else if (transcript.ReplacesPrevious) {
1394
- // STREAMING user transcription: providers like Grok emit the growing utterance as repeated
1426
+ // STREAMING user transcription: providers like Grok and OpenAI Live emit the growing utterance as repeated
1395
1427
  // events (each the full text so far), flagging all but the first ReplacesPrevious. Update the
1396
1428
  // in-place User caption + persisted turn instead of stacking a new bubble per increment — the
1397
- // same correction semantics the assistant branch uses. (OpenAI sends one final → the else path.)
1429
+ // same correction semantics the assistant branch uses. (Classic OpenAI Realtime sends one final → the else path.)
1430
+ if (transcript.Text.trim().length === 0) {
1431
+ return;
1432
+ }
1398
1433
  this.replaceLastCaption('User', transcript.Text);
1399
1434
  await this.relayTranscript('user', transcript.Text, true);
1400
1435
  }
@@ -1488,8 +1523,9 @@ export class RealtimeSessionService {
1488
1523
  async handleToolCall(call) {
1489
1524
  const clientHandler = this.findClientToolHandler(call.ToolName);
1490
1525
  if (clientHandler) {
1491
- // Local UI tool: no server relay, no 'thinking' turn-state / narration burst these
1492
- // are fast, in-browser surface mutations (e.g. drawing on the whiteboard).
1526
+ // Local UI tool: no server relay, no 'thinking' turn-state / narration burst, and intentionally
1527
+ // NO thread card — these are fast, in-browser surface mutations (e.g. drawing on the whiteboard)
1528
+ // whose visual effects are immediately visible on the dedicated canvas/surface.
1493
1529
  const resultJson = await this.executeClientTool(clientHandler, call);
1494
1530
  this.client?.SendToolResult(call.CallID, resultJson);
1495
1531
  // Observability: record the channel tool call on the co-agent's run (run-only — NOT a chat
@@ -1511,9 +1547,19 @@ export class RealtimeSessionService {
1511
1547
  this.lastNarratedTail = '';
1512
1548
  }
1513
1549
  this.inFlightCallIds.add(call.CallID);
1550
+ if (call.ToolName !== 'invoke-target-agent') {
1551
+ // Direct action: emit synthetic progress immediately so the conversation thread
1552
+ // and activity rail render an active "working" action card while the tool executes.
1553
+ this._delegationProgress$.next({
1554
+ CallID: call.CallID,
1555
+ ToolName: call.ToolName,
1556
+ Step: 'direct_action',
1557
+ Message: `Executing ${FormatToolName(call.ToolName)}`
1558
+ });
1559
+ }
1514
1560
  try {
1515
1561
  const resultJson = await this.executeSessionTool(call.CallID, call.ToolName, call.ArgumentsJson);
1516
- this.emitDelegationResult(call.CallID, resultJson);
1562
+ this.emitDelegationResult(call.CallID, resultJson, call.ToolName);
1517
1563
  this.client?.SendToolResult(call.CallID, resultJson);
1518
1564
  }
1519
1565
  catch (error) {
@@ -1526,7 +1572,7 @@ export class RealtimeSessionService {
1526
1572
  success: false,
1527
1573
  error: error instanceof Error ? error.message : String(error)
1528
1574
  });
1529
- this.emitDelegationResult(call.CallID, errorJson);
1575
+ this.emitDelegationResult(call.CallID, errorJson, call.ToolName);
1530
1576
  this.client?.SendToolResult(call.CallID, errorJson);
1531
1577
  }
1532
1578
  }
@@ -1559,13 +1605,12 @@ export class RealtimeSessionService {
1559
1605
  /**
1560
1606
  * Emits a delegation result so the overlay's "working" card flips to a result card with real
1561
1607
  * content. Parses the broker's `{success, output, runId}` | `{success:false, error}` shape via
1562
- * {@link ParseDelegationResultJson}; if it isn't JSON, surfaces the raw string. Only delegation
1563
- * cards (created from progress events) react non-delegation tool results have no card and are
1564
- * harmlessly ignored downstream. The `runId` (the delegated `MJ: AI Agent Runs` record) rides
1565
- * along as {@link RealtimeDelegationResult.RunID} for the overlay's dev links, and any `artifacts`
1566
- * ride along as {@link RealtimeDelegationResult.Artifacts} for the surface panel's artifact tabs.
1608
+ * {@link ParseDelegationResultJson}; if it isn't JSON, surfaces the raw string. The `runId`
1609
+ * (the delegated `MJ: AI Agent Runs` record) rides along as {@link RealtimeDelegationResult.RunID}
1610
+ * for the overlay's dev links, and any `artifacts` ride along as {@link RealtimeDelegationResult.Artifacts}
1611
+ * for the surface panel's artifact tabs.
1567
1612
  */
1568
- emitDelegationResult(callId, resultJson) {
1613
+ emitDelegationResult(callId, resultJson, toolName) {
1569
1614
  // The result will be spoken next — a deferred interim update is now pointless
1570
1615
  // (this is what keeps fast agents like Sage from narrating over their own answer),
1571
1616
  // and any progress still in the PubSub pipe for this call is stale.
@@ -1580,6 +1625,7 @@ export class RealtimeSessionService {
1580
1625
  const parsed = ParseDelegationResultJson(resultJson);
1581
1626
  this._delegationResult$.next({
1582
1627
  CallID: callId,
1628
+ ToolName: toolName,
1583
1629
  Success: parsed.Success,
1584
1630
  Output: parsed.Output,
1585
1631
  RunID: parsed.RunID,
@@ -2259,6 +2305,8 @@ export class RealtimeSessionService {
2259
2305
  /** Resets reactive + internal state at the start of a session. */
2260
2306
  resetState() {
2261
2307
  this._captions$.next([]);
2308
+ this.pendingUserCaption = '';
2309
+ this.hasActiveInterimUserCaption = false;
2262
2310
  this.SetMinimized(false);
2263
2311
  this.stopSegmentFlushing();
2264
2312
  this.segmentIndex = 0;