@flamingo-stack/openframe-frontend-core 0.0.193 → 0.0.194-snapshot.20260518210734

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 (30) hide show
  1. package/dist/{chunk-GMC5VU7X.cjs → chunk-IQM3G2I6.cjs} +480 -369
  2. package/dist/chunk-IQM3G2I6.cjs.map +1 -0
  3. package/dist/{chunk-E6VCRL42.js → chunk-U6AJSRJP.js} +140 -29
  4. package/dist/chunk-U6AJSRJP.js.map +1 -0
  5. package/dist/components/chat/chat-message-list.d.ts.map +1 -1
  6. package/dist/components/chat/types/message.types.d.ts +19 -0
  7. package/dist/components/chat/types/message.types.d.ts.map +1 -1
  8. package/dist/components/chat/utils/message-segment-accumulator.d.ts +16 -0
  9. package/dist/components/chat/utils/message-segment-accumulator.d.ts.map +1 -1
  10. package/dist/components/chat/utils/process-historical-messages.d.ts.map +1 -1
  11. package/dist/components/features/index.cjs +2 -2
  12. package/dist/components/features/index.js +1 -1
  13. package/dist/components/index.cjs +4 -2
  14. package/dist/components/index.cjs.map +1 -1
  15. package/dist/components/index.js +3 -1
  16. package/dist/components/navigation/index.cjs +2 -2
  17. package/dist/components/navigation/index.js +1 -1
  18. package/dist/components/ui/index.cjs +4 -2
  19. package/dist/components/ui/index.cjs.map +1 -1
  20. package/dist/components/ui/index.js +3 -1
  21. package/dist/index.cjs +4 -2
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.js +3 -1
  24. package/package.json +1 -1
  25. package/src/components/chat/chat-message-list.tsx +138 -1
  26. package/src/components/chat/types/message.types.ts +20 -0
  27. package/src/components/chat/utils/message-segment-accumulator.ts +28 -0
  28. package/src/components/chat/utils/process-historical-messages.ts +23 -5
  29. package/dist/chunk-E6VCRL42.js.map +0 -1
  30. package/dist/chunk-GMC5VU7X.cjs.map +0 -1
@@ -5521,6 +5521,28 @@ function CyclingPhrase({
5521
5521
  ] });
5522
5522
  }
5523
5523
 
5524
+ // src/components/chat/types/message.types.ts
5525
+ var MESSAGE_TYPE = {
5526
+ TEXT: "TEXT",
5527
+ THINKING: "THINKING",
5528
+ EXECUTING_TOOL: "EXECUTING_TOOL",
5529
+ EXECUTED_TOOL: "EXECUTED_TOOL",
5530
+ APPROVAL_REQUEST: "APPROVAL_REQUEST",
5531
+ APPROVAL_RESULT: "APPROVAL_RESULT",
5532
+ ERROR: "ERROR",
5533
+ MESSAGE_START: "MESSAGE_START",
5534
+ MESSAGE_END: "MESSAGE_END",
5535
+ MESSAGE_REQUEST: "MESSAGE_REQUEST",
5536
+ AI_METADATA: "AI_METADATA",
5537
+ TOKEN_USAGE: "TOKEN_USAGE",
5538
+ CONTEXT_COMPACTION_START: "CONTEXT_COMPACTION_START",
5539
+ CONTEXT_COMPACTION_END: "CONTEXT_COMPACTION_END",
5540
+ DIRECT_MESSAGE: "DIRECT_MESSAGE",
5541
+ SYSTEM: "SYSTEM",
5542
+ DIALOG_CLOSED: "DIALOG_CLOSED"
5543
+ };
5544
+ var SCROLL_ANCHOR = { TOP: "top", BOTTOM: "bottom" };
5545
+
5524
5546
  // src/components/chat/chat-message-list.tsx
5525
5547
  import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
5526
5548
  var STREAMING_WORDS = [
@@ -5535,6 +5557,16 @@ var STREAMING_WORDS = [
5535
5557
  "Conjuring",
5536
5558
  "Riffing"
5537
5559
  ];
5560
+ function hasNonEmptyContent(content) {
5561
+ if (typeof content === "string") return content.length > 0;
5562
+ if (!Array.isArray(content)) return false;
5563
+ return content.some((s) => s.type === "text" && s.text.length > 0);
5564
+ }
5565
+ function disposeAnchorWatcher(w) {
5566
+ if (!w) return;
5567
+ w.ro.disconnect();
5568
+ clearTimeout(w.timer);
5569
+ }
5538
5570
  var ChatMessageList = forwardRef21(
5539
5571
  ({
5540
5572
  className,
@@ -5555,7 +5587,7 @@ var ChatMessageList = forwardRef21(
5555
5587
  NavLinkAnchor,
5556
5588
  ...props
5557
5589
  }, ref) => {
5558
- const { scrollRef, contentRef, scrollToBottom } = useStickToBottom({
5590
+ const { scrollRef, contentRef, scrollToBottom, stopScroll } = useStickToBottom({
5559
5591
  resize: "smooth",
5560
5592
  initial: false
5561
5593
  });
@@ -5619,6 +5651,68 @@ var ChatMessageList = forwardRef21(
5619
5651
  prependRef.current.firstMessageContent = currentFirstContent;
5620
5652
  }
5621
5653
  }, [messages, scrollRef]);
5654
+ const messageElsRef = useRef5(/* @__PURE__ */ new Map());
5655
+ const refCallbacksRef = useRef5(/* @__PURE__ */ new Map());
5656
+ const getRegisterMessageEl = (id) => {
5657
+ let cb = refCallbacksRef.current.get(id);
5658
+ if (cb) return cb;
5659
+ cb = (el) => {
5660
+ if (el) {
5661
+ messageElsRef.current.set(id, el);
5662
+ } else {
5663
+ messageElsRef.current.delete(id);
5664
+ refCallbacksRef.current.delete(id);
5665
+ }
5666
+ };
5667
+ refCallbacksRef.current.set(id, cb);
5668
+ return cb;
5669
+ };
5670
+ const scrolledIdsRef = useRef5(null);
5671
+ if (scrolledIdsRef.current === null) {
5672
+ scrolledIdsRef.current = new Set(
5673
+ messages.filter((m) => hasNonEmptyContent(m.content)).map((m) => m.id)
5674
+ );
5675
+ }
5676
+ const anchorWatcherRef = useRef5(null);
5677
+ useLayoutEffect2(() => {
5678
+ if (!autoScroll) return;
5679
+ const last = messages[messages.length - 1];
5680
+ if (!last || last.role !== "assistant" || last.scrollAnchor !== SCROLL_ANCHOR.TOP) return;
5681
+ if (!hasNonEmptyContent(last.content)) return;
5682
+ const seen = scrolledIdsRef.current;
5683
+ if (seen.has(last.id)) return;
5684
+ const node = messageElsRef.current.get(last.id);
5685
+ const container = scrollRef.current;
5686
+ if (!node || !node.isConnected || !container) return;
5687
+ seen.add(last.id);
5688
+ stopScroll();
5689
+ node.scrollIntoView({ block: "start" });
5690
+ disposeAnchorWatcher(anchorWatcherRef.current);
5691
+ const baselineScrollTop = container.scrollTop;
5692
+ const ro = new ResizeObserver(() => {
5693
+ if (!node.isConnected) {
5694
+ ro.disconnect();
5695
+ return;
5696
+ }
5697
+ if (container.scrollTop > baselineScrollTop + 200) {
5698
+ ro.disconnect();
5699
+ return;
5700
+ }
5701
+ node.scrollIntoView({ block: "start" });
5702
+ });
5703
+ ro.observe(node);
5704
+ const timer = setTimeout(() => {
5705
+ ro.disconnect();
5706
+ if (anchorWatcherRef.current?.id === last.id) {
5707
+ anchorWatcherRef.current = null;
5708
+ }
5709
+ }, 2e3);
5710
+ anchorWatcherRef.current = { id: last.id, ro, timer };
5711
+ }, [messages, autoScroll, stopScroll, scrollRef]);
5712
+ useEffect6(() => () => {
5713
+ disposeAnchorWatcher(anchorWatcherRef.current);
5714
+ anchorWatcherRef.current = null;
5715
+ }, []);
5622
5716
  useEffect6(() => {
5623
5717
  const scrollContainer = scrollRef.current;
5624
5718
  const sentinelElement = sentinelRef.current;
@@ -5686,6 +5780,7 @@ var ChatMessageList = forwardRef21(
5686
5780
  messages.map((message, index) => /* @__PURE__ */ jsx33(
5687
5781
  MemoizedChatMessageEnhanced,
5688
5782
  {
5783
+ ref: getRegisterMessageEl(message.id),
5689
5784
  role: message.role,
5690
5785
  name: message.name,
5691
5786
  content: message.content,
@@ -6924,27 +7019,6 @@ var CONNECTION_STATUS = {
6924
7019
  ERROR: "error"
6925
7020
  };
6926
7021
 
6927
- // src/components/chat/types/message.types.ts
6928
- var MESSAGE_TYPE = {
6929
- TEXT: "TEXT",
6930
- THINKING: "THINKING",
6931
- EXECUTING_TOOL: "EXECUTING_TOOL",
6932
- EXECUTED_TOOL: "EXECUTED_TOOL",
6933
- APPROVAL_REQUEST: "APPROVAL_REQUEST",
6934
- APPROVAL_RESULT: "APPROVAL_RESULT",
6935
- ERROR: "ERROR",
6936
- MESSAGE_START: "MESSAGE_START",
6937
- MESSAGE_END: "MESSAGE_END",
6938
- MESSAGE_REQUEST: "MESSAGE_REQUEST",
6939
- AI_METADATA: "AI_METADATA",
6940
- TOKEN_USAGE: "TOKEN_USAGE",
6941
- CONTEXT_COMPACTION_START: "CONTEXT_COMPACTION_START",
6942
- CONTEXT_COMPACTION_END: "CONTEXT_COMPACTION_END",
6943
- DIRECT_MESSAGE: "DIRECT_MESSAGE",
6944
- SYSTEM: "SYSTEM",
6945
- DIALOG_CLOSED: "DIALOG_CLOSED"
6946
- };
6947
-
6948
7022
  // src/components/chat/types/network.types.ts
6949
7023
  var NETWORK_CONFIG = {
6950
7024
  SHARED_CLOSE_DELAY_MS: 3e3,
@@ -7835,6 +7909,7 @@ var MessageSegmentAccumulator = class {
7835
7909
  return this.getSegments();
7836
7910
  }
7837
7911
  const toolKey = execId || `${toolData.integratedToolType}-${toolData.toolFunction}`;
7912
+ this.resolvePendingApprovalForExecution();
7838
7913
  if (toolData.type === "EXECUTING_TOOL") {
7839
7914
  this.executingTools.set(toolKey, {
7840
7915
  integratedToolType: toolData.integratedToolType,
@@ -7891,6 +7966,30 @@ var MessageSegmentAccumulator = class {
7891
7966
  });
7892
7967
  return matched;
7893
7968
  }
7969
+ /**
7970
+ * A tool only ever runs after its approval gate was granted. The legacy /
7971
+ * single `approval_request` segment carries no `toolExecutionRequestId` to
7972
+ * correlate with the execution, and an observer (e.g. a technician
7973
+ * mirroring the client chat) may never receive an `APPROVAL_RESULT` chunk —
7974
+ * only the tool's `EXECUTING_TOOL` / `EXECUTED_TOOL` events. Treat the
7975
+ * arrival of a tool execution as implicit approval of the most recent
7976
+ * still-pending gate so the card does not stay stuck `pending` in realtime.
7977
+ *
7978
+ * The agent stays paused while an approval is outstanding, so there is at
7979
+ * most one relevant gate; flipping only the latest pending one is safe and
7980
+ * monotonic (never downgrades, can't make a correct state wrong — an
7981
+ * unapproved tool cannot execute). `approval_batch` is handled separately by
7982
+ * `applyExecutionToBatch` and is intentionally left untouched here.
7983
+ */
7984
+ resolvePendingApprovalForExecution() {
7985
+ for (let i = this.segments.length - 1; i >= 0; i--) {
7986
+ const seg = this.segments[i];
7987
+ if (seg.type === "approval_request" && seg.status === "pending") {
7988
+ this.segments[i] = { ...seg, status: "approved" };
7989
+ return;
7990
+ }
7991
+ }
7992
+ }
7894
7993
  /**
7895
7994
  * Track a pending approval request
7896
7995
  */
@@ -8588,11 +8687,22 @@ function processMessageData(data, accumulator, approvalStatuses, options = {}, e
8588
8687
  }
8589
8688
  }
8590
8689
  } else {
8591
- accumulator.trackApprovalRequest(data.approvalRequestId, {
8592
- command: data.command || "",
8593
- explanation: data.explanation,
8594
- approvalType
8595
- });
8690
+ const resolvedStatus = approvalStatuses[data.approvalRequestId];
8691
+ if (resolvedStatus === "approved" || resolvedStatus === "rejected") {
8692
+ accumulator.addApprovalRequest(
8693
+ data.approvalRequestId,
8694
+ data.command || "",
8695
+ data.explanation,
8696
+ approvalType,
8697
+ resolvedStatus
8698
+ );
8699
+ } else {
8700
+ accumulator.trackApprovalRequest(data.approvalRequestId, {
8701
+ command: data.command || "",
8702
+ explanation: data.explanation,
8703
+ approvalType
8704
+ });
8705
+ }
8596
8706
  }
8597
8707
  } else {
8598
8708
  escalatedApprovals?.set(data.approvalRequestId, {
@@ -33507,6 +33617,8 @@ export {
33507
33617
  remarkCardLinks,
33508
33618
  BlockCard,
33509
33619
  MemoizedChatMessageEnhanced,
33620
+ MESSAGE_TYPE,
33621
+ SCROLL_ANCHOR,
33510
33622
  ChatMessageList,
33511
33623
  Tabs,
33512
33624
  TabsList,
@@ -33540,7 +33652,6 @@ export {
33540
33652
  AUTHOR_TYPE,
33541
33653
  APPROVAL_STATUS,
33542
33654
  CONNECTION_STATUS,
33543
- MESSAGE_TYPE,
33544
33655
  NETWORK_CONFIG,
33545
33656
  useChunkCatchup,
33546
33657
  useNatsDialogSubscription,
@@ -34008,4 +34119,4 @@ export {
34008
34119
  TMCG_SOCIAL_PLATFORMS,
34009
34120
  assets
34010
34121
  };
34011
- //# sourceMappingURL=chunk-E6VCRL42.js.map
34122
+ //# sourceMappingURL=chunk-U6AJSRJP.js.map