@ai-matrx/chat 0.4.2 → 0.4.8

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 (144) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/dist/agent-copy/RichCopySplit.d.ts +17 -0
  3. package/dist/agent-copy/RichCopySplit.js +34 -0
  4. package/dist/agents/components/agent-widgets/chat-assistant/AssistantMessageCard.js +1 -1
  5. package/dist/agents/components/chat/ConversationRecordsChip.js +1 -1
  6. package/dist/agents/components/context-items/bodies/WorkingDocumentBody.d.ts +5 -2
  7. package/dist/agents/components/context-items/bodies/WorkingDocumentBody.js +6 -1
  8. package/dist/agents/components/context-policies-display/ContextValueBody.js +1 -1
  9. package/dist/agents/components/context-preview/ContextCompareView.js +1 -1
  10. package/dist/agents/components/custom-agent/CustomAgentWindow.js +1 -1
  11. package/dist/agents/components/inputs/smart-input/AgentTextarea.d.ts +6 -1
  12. package/dist/agents/components/inputs/smart-input/AgentTextarea.js +2 -2
  13. package/dist/agents/components/inputs/smart-input/ComposerToolsNotice.d.ts +1 -0
  14. package/dist/agents/components/inputs/smart-input/ComposerToolsNotice.js +5 -0
  15. package/dist/agents/components/inputs/smart-input/ConversationContextRail.d.ts +5 -1
  16. package/dist/agents/components/inputs/smart-input/ConversationContextRail.js +6 -1
  17. package/dist/agents/components/inputs/smart-input/InboxQueueStrip.d.ts +6 -1
  18. package/dist/agents/components/inputs/smart-input/InboxQueueStrip.js +6 -1
  19. package/dist/agents/components/inputs/smart-input/InputActionButtons.js +8 -6
  20. package/dist/agents/components/inputs/smart-input/SmartInputFileDropTarget.d.ts +5 -1
  21. package/dist/agents/components/inputs/smart-input/SmartInputFileDropTarget.js +8 -1
  22. package/dist/agents/components/inputs/smart-input/composer/ComposerAgentPill.js +2 -2
  23. package/dist/agents/components/inputs/smart-input/composer/ComposerChipsRow.d.ts +5 -2
  24. package/dist/agents/components/inputs/smart-input/composer/ComposerChipsRow.js +6 -1
  25. package/dist/agents/components/inputs/smart-input/composer/ComposerMetaRow.d.ts +6 -8
  26. package/dist/agents/components/inputs/smart-input/composer/ComposerMetaRow.js +13 -1
  27. package/dist/agents/components/inputs/smart-input/composer/useOutputShapeCatalog.d.ts +1 -1
  28. package/dist/agents/components/inputs/smart-input/composer/useOutputShapeCatalog.js +1 -1
  29. package/dist/agents/components/live-run/LiveRunDisplay.js +1 -1
  30. package/dist/agents/components/live-run/RunSetDisplay.js +1 -1
  31. package/dist/agents/components/memory/components/AgentMemoryAllView.js +1 -1
  32. package/dist/agents/components/messages-display/assistant/AgentAssistantMessage.d.ts +1 -0
  33. package/dist/agents/components/messages-display/assistant/AgentAssistantMessage.js +4 -3
  34. package/dist/agents/components/messages-display/assistant/AgentEmptyMessageDisplay.js +1 -1
  35. package/dist/agents/components/messages-display/assistant/AssistantMessageFooter.d.ts +2 -2
  36. package/dist/agents/components/messages-display/assistant/AssistantMessageFooter.js +4 -7
  37. package/dist/agents/components/messages-display/assistant/InPlaceAnswerEditor.js +2 -2
  38. package/dist/agents/components/messages-display/citations/MessageSourcesRow.js +1 -1
  39. package/dist/agents/components/messages-display/rich-document/chat-message-source.d.ts +2 -0
  40. package/dist/agents/components/messages-display/rich-document/chat-message-source.js +41 -0
  41. package/dist/agents/components/messages-display/rich-document/chatMessageActions.d.ts +31 -0
  42. package/dist/agents/components/messages-display/rich-document/chatMessageActions.js +39 -0
  43. package/dist/agents/components/messages-display/user/AgentUserMessage.d.ts +1 -0
  44. package/dist/agents/components/messages-display/user/AgentUserMessage.js +7 -4
  45. package/dist/agents/components/messages-display/user/CollabNoteMessage.js +1 -1
  46. package/dist/agents/components/messages-display/user/UserActionBar.js +49 -39
  47. package/dist/agents/components/working-document/WorkingDocumentEditor.d.ts +1 -1
  48. package/dist/agents/components/working-document/WorkingDocumentPanel.js +2 -1
  49. package/dist/agents/identity/run-tier-store.js +3 -0
  50. package/dist/agents/redux/agent-definition/cache-bust-middleware.js +2 -0
  51. package/dist/agents/redux/agent-settings/agentSettingsSlice.d.ts +0 -4
  52. package/dist/agents/redux/agent-settings/agentSettingsSlice.js +12 -5
  53. package/dist/agents/redux/execution-system/host-conversations/host-conversation.thunks.d.ts +4 -1
  54. package/dist/agents/redux/execution-system/host-conversations/host-conversation.thunks.js +45 -0
  55. package/dist/agents/redux/execution-system/inbox/inbox-turn-end.middleware.js +2 -1
  56. package/dist/agents/redux/execution-system/instance-ui-state/run-configuration-persist.js +2 -0
  57. package/dist/agents/redux/execution-system/messages/messages.selectors.js +1 -1
  58. package/dist/agents/redux/execution-system/thunks/execute-instance.thunk.js +6 -0
  59. package/dist/agents/redux/execution-system/thunks/process-stream.js +25 -12
  60. package/dist/agents/redux/execution-system/thunks/run-headless-agent-json.d.ts +2 -0
  61. package/dist/agents/redux/execution-system/thunks/run-headless-agent-json.js +25 -4
  62. package/dist/agents/redux/execution-system/utils/assemble-cx-content-blocks.js +2 -1
  63. package/dist/agents/redux/execution-system/utils/inbound-render-block.d.ts +8 -0
  64. package/dist/agents/redux/execution-system/utils/inbound-render-block.js +17 -2
  65. package/dist/agents/redux/execution-system/utils/normalize-content-blocks.js +1 -1
  66. package/dist/agents/redux/execution-system/utils/progress-data-block.d.ts +11 -0
  67. package/dist/agents/redux/execution-system/utils/progress-data-block.js +37 -0
  68. package/dist/agents/redux/execution-system/utils/stream-block-accumulator.js +10 -8
  69. package/dist/agents/redux/mcp/mcp.slice.js +15 -7
  70. package/dist/agents/redux/tools/tools.thunks.js +3 -0
  71. package/dist/agents/runtime-reconnect/ServerOperationBanner.d.ts +6 -1
  72. package/dist/agents/runtime-reconnect/ServerOperationBanner.js +6 -1
  73. package/dist/agents/runtime-reconnect/reconnect-server-operation.thunk.js +10 -6
  74. package/dist/agents/ui-first-tools/ui/ApprovalCard.js +1 -1
  75. package/dist/agents/ui-first-tools/ui/AskCard.js +1 -1
  76. package/dist/agents/ui-first-tools/ui/lists/TaskPanel.js +1 -1
  77. package/dist/conversation/hooks/useDomCapturePrint.js +1 -1
  78. package/dist/conversation/utils/markdown-print.js +1 -1
  79. package/dist/cx-chat/components/messages/AssistantMessage.js +3 -5
  80. package/dist/cx-conversation/AssistantMessage.js +3 -5
  81. package/dist/host/app-data-slots.d.ts +85 -0
  82. package/dist/host/app-data-slots.js +42 -0
  83. package/dist/host/bare-host-chrome.js +1 -0
  84. package/dist/host/defaults/prefs.d.ts +19 -0
  85. package/dist/host/defaults/prefs.js +52 -0
  86. package/dist/host/defaults/workspace-gate.js +2 -1
  87. package/dist/host/index.d.ts +1 -1
  88. package/dist/host/index.js +2 -1
  89. package/dist/host/react.js +16 -1
  90. package/dist/host/source.d.ts +21 -0
  91. package/dist/host/ui-slots.d.ts +1 -23
  92. package/dist/host/ui-slots.js +0 -34
  93. package/dist/public-chat/components/PublicMessageOptionsMenu.js +2 -1
  94. package/dist/surfaces/redux/surfaceConfigSlice.js +2 -0
  95. package/dist/surfaces/redux/userStateSlice.js +3 -1
  96. package/dist/surfaces/runtime/agent-offer.js +1 -1
  97. package/dist/surfaces/runtime/surface-writeback.js +1 -1
  98. package/dist/tool-call-visualization/db-renderer/fetchToolRendererRow.js +2 -0
  99. package/dist/tool-call-visualization/renderers/agent-call/AgentCallInline.js +1 -1
  100. package/dist/tool-call-visualization/renderers/agent-call/CollabCallCard.js +1 -1
  101. package/dist/tool-call-visualization/renderers/fs/FsInline.js +1 -1
  102. package/dist/tool-call-visualization/renderers/random-wheel/RandomWheelInline.js +1 -1
  103. package/dist/tool-call-visualization/renderers/research/ResearchOverlay.js +4 -4
  104. package/dist/tool-call-visualization/renderers/research/SubagentReportBlock.js +2 -2
  105. package/dist/tool-call-visualization/renderers/scrape/ScrapeOverlay.js +1 -1
  106. package/dist/tool-call-visualization/renderers/search/SearchInline.js +1 -1
  107. package/dist/tool-call-visualization/renderers/search/SearchOverlay.js +1 -1
  108. package/dist/tool-call-visualization/renderers/sql/SqlInline.js +1 -1
  109. package/dist/tool-call-visualization/result-fields/KeyValueGrid.js +1 -1
  110. package/dist/tool-call-visualization/result-fields/ResultMarkdown.js +1 -1
  111. package/dist/tool-call-visualization/result-fields/ResultValue.js +1 -1
  112. package/dist/tool-call-visualization/surface-write/SurfaceWriteDiff.js +1 -1
  113. package/dist/ui/AudioOutputBlockSkeleton.d.ts +17 -0
  114. package/dist/ui/AudioOutputBlockSkeleton.js +78 -0
  115. package/dist/ui/chat-protocol-from-stream.d.ts +60 -0
  116. package/dist/ui/chat-protocol-from-stream.js +135 -0
  117. package/dist/ui/markdown-stream/EnhancedChatMarkdown.d.ts +59 -0
  118. package/dist/ui/markdown-stream/EnhancedChatMarkdown.js +1108 -0
  119. package/dist/ui/markdown-stream/MarkdownStream.d.ts +88 -0
  120. package/dist/ui/markdown-stream/MarkdownStream.js +14 -0
  121. package/dist/ui/markdown-stream/MarkdownStreamImpl.d.ts +4 -0
  122. package/dist/ui/markdown-stream/MarkdownStreamImpl.js +86 -0
  123. package/dist/ui/markdown-stream/StreamAwareChatMarkdown.d.ts +58 -0
  124. package/dist/ui/markdown-stream/StreamAwareChatMarkdown.js +294 -0
  125. package/dist/ui/markdown-stream/internal-handlers/AgentCallChildTrace.d.ts +22 -0
  126. package/dist/ui/markdown-stream/internal-handlers/AgentCallChildTrace.js +128 -0
  127. package/dist/ui/markdown-stream/internal-handlers/InlineAssistantError.d.ts +3 -0
  128. package/dist/ui/markdown-stream/internal-handlers/InlineAssistantError.js +26 -0
  129. package/dist/ui/markdown-stream/internal-handlers/InlineThinkingSlot.d.ts +14 -0
  130. package/dist/ui/markdown-stream/internal-handlers/InlineThinkingSlot.js +23 -0
  131. package/dist/ui/markdown-stream/internal-handlers/ToolHandlers.d.ts +42 -0
  132. package/dist/ui/markdown-stream/internal-handlers/ToolHandlers.js +109 -0
  133. package/dist/ui/markdown-stream/useBoundAgentOutputSchema.d.ts +2 -0
  134. package/dist/ui/markdown-stream/useBoundAgentOutputSchema.js +33 -0
  135. package/dist/window-panels/windows/agents/AgentAssistantMarkdownDebugWindow.js +1 -1
  136. package/package.json +10 -8
  137. package/dist/host/content-ir-slots.d.ts +0 -235
  138. package/dist/host/content-ir-slots.js +0 -135
  139. package/dist/host/markdown-slots.d.ts +0 -53
  140. package/dist/host/markdown-slots.js +0 -32
  141. package/dist/host/rich-document-slots.d.ts +0 -123
  142. package/dist/host/rich-document-slots.js +0 -36
  143. package/dist/utils/content-ir/report-kind-at-raw-renderer.d.ts +0 -19
  144. package/dist/utils/content-ir/report-kind-at-raw-renderer.js +0 -32
@@ -0,0 +1,88 @@
1
+ import type { AnswerEditRemarkMeta } from "../../agents/redux/execution-system/instance-resources/remarks.js";
2
+ import { TypedStreamEvent } from "@ai-matrx/rich-content/display/chat-markdown/types";
3
+ import type { ServerProcessedBlock } from "./EnhancedChatMarkdown.js";
4
+ /**
5
+ * Props for the MarkdownStream component.
6
+ * Defined here (in the shell) so consumers can import the type without
7
+ * pulling in the heavy implementation module.
8
+ */
9
+ export interface MarkdownStreamProps {
10
+ /** Markdown content to render (legacy mode) */
11
+ content?: string;
12
+ /** Stream events to process (new mode) */
13
+ events?: TypedStreamEvent[];
14
+ /** Optional task ID for streaming updates (legacy mode with Redux) */
15
+ taskId?: string;
16
+ requestId?: string;
17
+ /** Every committed row a multi-iteration turn's one render stands for (see EnhancedChatMarkdown). */
18
+ recordMessageIds?: readonly string[];
19
+ /** Inclusive/exclusive source timeline range for one live transcript segment. */
20
+ streamSlotStart?: number;
21
+ streamSlotEnd?: number;
22
+ /**
23
+ * Render ONE collaboration `agent_call` child's live blocks from `requestId`
24
+ * (the parent request it streams inside) — the call id of the owning card.
25
+ * Its blocks go through the normal BlockRenderer path, so kinds route as in
26
+ * the parent (`selectAgentCallChildSlots`; the transcript still hides them).
27
+ */
28
+ agentCallId?: string;
29
+ /** Turn ID for DB-loaded turn rendering */
30
+ turnId?: string;
31
+ /** Conversation ID for DB-loaded turn rendering */
32
+ conversationId?: string;
33
+ /**
34
+ * @deprecated No longer used — `MarkdownStream` now always renders in
35
+ * `message` mode. This prop is kept on the interface for backward
36
+ * compatibility only and is ignored. Remove from callers.
37
+ */
38
+ type?: "flashcard" | "message" | "text" | "image" | "audio" | "video" | "file" | string;
39
+ /**
40
+ * @deprecated No longer used — `MarkdownStream` now always renders as
41
+ * `assistant`. This prop is kept on the interface for backward
42
+ * compatibility only and is ignored. Remove from callers.
43
+ */
44
+ role?: "user" | "assistant" | "system" | "tool" | string;
45
+ /** Additional CSS classes */
46
+ className?: string;
47
+ /** Whether streaming is currently active */
48
+ isStreamActive?: boolean;
49
+ /** Callback for content changes */
50
+ /** See EnhancedChatMarkdown: `previousContent` is the text the edit applied to. */
51
+ onContentChange?: (newContent: string, previousContent: string, remark?: AnswerEditRemarkMeta) => void;
52
+ /**
53
+ * When false (with onContentChange), block edits are reported via onContentChange but
54
+ * the visible markdown stays tied to the `content` prop (no local edited overlay).
55
+ */
56
+ applyLocalEdits?: boolean;
57
+ /** Additional analysis data */
58
+ analysisData?: any;
59
+ /** Message ID for identification */
60
+ messageId?: string;
61
+ /** Allow full-screen editor mode */
62
+ allowFullScreenEditor?: boolean;
63
+ /** Hide the copy button */
64
+ hideCopyButton?: boolean;
65
+ /** Callback when an error event is received (new mode) */
66
+ onError?: (error: string) => void;
67
+ /** Callback when phase events are received (new mode) */
68
+ onPhaseUpdate?: (phase: string) => void;
69
+ /** Pre-processed content blocks from server/Redux (new content_block protocol). */
70
+ serverProcessedBlocks?: ServerProcessedBlock[];
71
+ /**
72
+ * Strict server-data mode — for testing/debugging only.
73
+ * When true, structured blocks will NOT fall back to client-side parsing
74
+ * if block.serverData is null. Leave false (default) for production.
75
+ */
76
+ strictServerData?: boolean;
77
+ /**
78
+ * WHO WROTE this content — "ai" (a model: answers, agent output), "other"
79
+ * (someone else: shared or public records) or "self" (the viewer). Decides
80
+ * whether remote images load by themselves (components/rich-content/prose/
81
+ * remote-image-policy.tsx, chair ruling 2026-09-25). Declare it at every
82
+ * call site — guard: components/rich-content/__tests__/image-policy-declared.test.ts.
83
+ */
84
+ imagePolicy?: "self" | "other" | "ai" | "inherit";
85
+ }
86
+ declare function MarkdownStream(props: MarkdownStreamProps): import("react").FunctionComponentElement<import("react").SuspenseProps> | null;
87
+ export { MarkdownStream };
88
+ export default MarkdownStream;
@@ -0,0 +1,14 @@
1
+ "use client";
2
+ import { createElement, lazy, Suspense, useEffect, useState } from "react";
3
+ const MarkdownStreamImpl = lazy(() => import("./MarkdownStreamImpl.js"));
4
+ function MarkdownStream(props) {
5
+ const [mounted, setMounted] = useState(false);
6
+ useEffect(() => setMounted(true), []);
7
+ if (!mounted) return null;
8
+ return createElement(Suspense, { fallback: null }, createElement(MarkdownStreamImpl, props));
9
+ }
10
+ var MarkdownStream_default = MarkdownStream;
11
+ export {
12
+ MarkdownStream,
13
+ MarkdownStream_default as default
14
+ };
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ import type { MarkdownStreamProps } from "./MarkdownStream.js";
3
+ declare const MarkdownStreamImpl: React.FC<MarkdownStreamProps>;
4
+ export default MarkdownStreamImpl;
@@ -0,0 +1,86 @@
1
+ "use client";
2
+ import { Fragment, jsx } from "react/jsx-runtime";
3
+ import { RichContentHostGate } from "@ai-matrx/rich-content/host";
4
+ import { PlainTextFallback } from "@ai-matrx/rich-content/display/chat-markdown/internal-handlers/PlainTextFallback";
5
+ import { MarkdownErrorBoundary } from "@ai-matrx/rich-content/display/chat-markdown/internal-handlers/MarkdownErrorBoundary";
6
+ import { StreamAwareChatMarkdown } from "./StreamAwareChatMarkdown.js";
7
+ import { BlockRenderingProvider } from "@ai-matrx/rich-content/display/chat-markdown/BlockRenderingContext";
8
+ import { withImagePolicy } from "@ai-matrx/rich-content/levels/prose/remote-image-policy";
9
+ const MarkdownStreamImpl = ({
10
+ content = "",
11
+ events,
12
+ taskId,
13
+ requestId,
14
+ recordMessageIds,
15
+ streamSlotStart,
16
+ streamSlotEnd,
17
+ agentCallId,
18
+ turnId,
19
+ conversationId,
20
+ type,
21
+ role,
22
+ className,
23
+ isStreamActive,
24
+ onContentChange,
25
+ applyLocalEdits,
26
+ analysisData,
27
+ messageId,
28
+ allowFullScreenEditor,
29
+ hideCopyButton,
30
+ onError,
31
+ onPhaseUpdate,
32
+ serverProcessedBlocks,
33
+ strictServerData = false,
34
+ imagePolicy
35
+ }) => {
36
+ const rendered = /* @__PURE__ */ jsx(
37
+ RichContentHostGate,
38
+ {
39
+ fallback: /* @__PURE__ */ jsx(PlainTextFallback, { content, className }),
40
+ children: /* @__PURE__ */ jsx(BlockRenderingProvider, { strictServerData, children: /* @__PURE__ */ jsx(
41
+ MarkdownErrorBoundary,
42
+ {
43
+ fallback: /* @__PURE__ */ jsx(PlainTextFallback, { content, className }),
44
+ onError: (error, errorInfo) => {
45
+ console.error(
46
+ "[MarkdownStream] Top-level error boundary caught:",
47
+ error,
48
+ errorInfo
49
+ );
50
+ },
51
+ children: /* @__PURE__ */ jsx(
52
+ StreamAwareChatMarkdown,
53
+ {
54
+ requestId,
55
+ recordMessageIds,
56
+ streamSlotStart,
57
+ streamSlotEnd,
58
+ agentCallId,
59
+ turnId,
60
+ conversationId,
61
+ content,
62
+ events,
63
+ taskId,
64
+ className,
65
+ isStreamActive,
66
+ onContentChange,
67
+ applyLocalEdits,
68
+ analysisData,
69
+ messageId,
70
+ allowFullScreenEditor,
71
+ hideCopyButton,
72
+ onError,
73
+ onPhaseUpdate,
74
+ serverProcessedBlocks
75
+ }
76
+ )
77
+ }
78
+ ) })
79
+ }
80
+ );
81
+ return /* @__PURE__ */ jsx(Fragment, { children: withImagePolicy(imagePolicy, rendered) });
82
+ };
83
+ var MarkdownStreamImpl_default = MarkdownStreamImpl;
84
+ export {
85
+ MarkdownStreamImpl_default as default
86
+ };
@@ -0,0 +1,58 @@
1
+ import React from "react";
2
+ import { ChatMarkdownDisplayProps } from "./EnhancedChatMarkdown.js";
3
+ import { TypedStreamEvent } from "@ai-matrx/rich-content/display/chat-markdown/types";
4
+ interface ProcessedBlockState {
5
+ blockId: string;
6
+ blockIndex: number;
7
+ type: string;
8
+ status: "streaming" | "complete" | "error";
9
+ content?: string | null;
10
+ data?: Record<string, unknown> | null;
11
+ metadata?: Record<string, unknown>;
12
+ }
13
+ /**
14
+ * Extended props that include stream event handling
15
+ */
16
+ export interface StreamAwareChatMarkdownProps extends Omit<ChatMarkdownDisplayProps, "content"> {
17
+ /**
18
+ * Direct content (legacy mode - used when not using events)
19
+ */
20
+ content?: string;
21
+ /** Turn ID for DB-loaded turn rendering */
22
+ turnId?: string;
23
+ /** Conversation ID for DB-loaded turn rendering */
24
+ conversationId?: string;
25
+ /**
26
+ * Array of stream events to process (new mode)
27
+ * When provided, this takes precedence over content prop
28
+ */
29
+ events?: TypedStreamEvent[];
30
+ /**
31
+ * Callback when an error event is received
32
+ */
33
+ onError?: (error: string) => void;
34
+ /**
35
+ * Callback when phase events are received
36
+ */
37
+ onPhaseUpdate?: (phase: string) => void;
38
+ /**
39
+ * Pre-processed blocks from the server (new render_block protocol).
40
+ * When present and non-empty, the component skips client-side parsing
41
+ * and renders these blocks directly.
42
+ */
43
+ serverProcessedBlocks?: ProcessedBlockState[];
44
+ }
45
+ /**
46
+ * Stream-aware wrapper for EnhancedChatMarkdown
47
+ *
48
+ * Supports two modes:
49
+ * 1. Legacy mode: Pass `content` directly (works with existing Redux/Socket.io)
50
+ * 2. Event mode: Pass `events` array (new unified API)
51
+ *
52
+ * In event mode, text and tool_call blocks are rendered in arrival order using
53
+ * buildCanonicalBlocks. This ensures tool calls appear inline at the exact
54
+ * position they were emitted relative to surrounding text — not pinned to the
55
+ * top of the message.
56
+ */
57
+ export declare const StreamAwareChatMarkdown: React.FC<StreamAwareChatMarkdownProps>;
58
+ export default StreamAwareChatMarkdown;
@@ -0,0 +1,294 @@
1
+ "use client";
2
+ import { Fragment, jsx } from "react/jsx-runtime";
3
+ import React, { useState, useEffect } from "react";
4
+ import {
5
+ EnhancedChatMarkdownInternal
6
+ } from "./EnhancedChatMarkdown.js";
7
+ import { buildCanonicalBlocks } from "../chat-protocol-from-stream.js";
8
+ import { MarkdownErrorBoundary } from "@ai-matrx/rich-content/display/chat-markdown/internal-handlers/MarkdownErrorBoundary";
9
+ import { LiveToolCallCard } from "../../tool-call-visualization/components/LiveToolCallCard.js";
10
+ import { useRetainRequestForViewer } from "../../agents/redux/execution-system/active-requests/useRetainRequestForViewer.js";
11
+ const StreamAwareChatMarkdown = ({
12
+ requestId,
13
+ recordMessageIds,
14
+ streamSlotStart,
15
+ streamSlotEnd,
16
+ agentCallId,
17
+ turnId,
18
+ conversationId,
19
+ content,
20
+ events,
21
+ onError,
22
+ onPhaseUpdate,
23
+ serverProcessedBlocks: serverBlocksProp,
24
+ taskId,
25
+ className,
26
+ isStreamActive,
27
+ onContentChange,
28
+ analysisData,
29
+ messageId,
30
+ allowFullScreenEditor,
31
+ hideCopyButton,
32
+ applyLocalEdits
33
+ }) => {
34
+ if (process.env.NODE_ENV !== "production") {
35
+ if (taskId !== void 0) {
36
+ console.warn(
37
+ "[StreamAwareChatMarkdown] `taskId` prop is a removal candidate \u2014 still in use:",
38
+ { requestId, turnId, conversationId, messageId, taskId }
39
+ );
40
+ }
41
+ }
42
+ useRetainRequestForViewer(requestId, "markdown-stream");
43
+ const [processedContent, setProcessedContent] = useState(
44
+ content || ""
45
+ );
46
+ const [hasStreamError, setHasStreamError] = useState(false);
47
+ const [canonicalBlocks, setCanonicalBlocks] = useState([]);
48
+ const [serverBlocks, setServerBlocks] = useState([]);
49
+ const serverBlockMapRef = React.useRef(
50
+ /* @__PURE__ */ new Map()
51
+ );
52
+ const isNewProtocolRef = React.useRef(false);
53
+ const onErrorRef = React.useRef(onError);
54
+ const onPhaseUpdateRef = React.useRef(onPhaseUpdate);
55
+ const lastProcessedIndexRef = React.useRef(-1);
56
+ const accumulatedContentRef = React.useRef("");
57
+ const canonicalBlocksChangedRef = React.useRef(false);
58
+ const eventsRef = React.useRef(events);
59
+ const rafIdRef = React.useRef(null);
60
+ const pendingContentUpdateRef = React.useRef(false);
61
+ const pendingCanonicalUpdateRef = React.useRef(false);
62
+ const pendingBlocksUpdateRef = React.useRef(false);
63
+ useEffect(() => {
64
+ onErrorRef.current = onError;
65
+ onPhaseUpdateRef.current = onPhaseUpdate;
66
+ }, [onError, onPhaseUpdate]);
67
+ useEffect(() => {
68
+ return () => {
69
+ if (rafIdRef.current !== null) {
70
+ cancelAnimationFrame(rafIdRef.current);
71
+ }
72
+ };
73
+ }, []);
74
+ useEffect(() => {
75
+ eventsRef.current = events;
76
+ });
77
+ useEffect(() => {
78
+ if (!events || events.length === 0) {
79
+ if (content !== void 0 && content !== accumulatedContentRef.current) {
80
+ setProcessedContent(content);
81
+ accumulatedContentRef.current = content;
82
+ lastProcessedIndexRef.current = -1;
83
+ canonicalBlocksChangedRef.current = false;
84
+ }
85
+ return;
86
+ }
87
+ if (events.length <= lastProcessedIndexRef.current) {
88
+ lastProcessedIndexRef.current = -1;
89
+ accumulatedContentRef.current = "";
90
+ canonicalBlocksChangedRef.current = false;
91
+ }
92
+ const startIndex = lastProcessedIndexRef.current + 1;
93
+ if (startIndex >= events.length) return;
94
+ let hasNewContent = false;
95
+ let hasNewCanonical = false;
96
+ let hasNewBlocks = false;
97
+ for (let i = startIndex; i < events.length; i++) {
98
+ const event = events[i];
99
+ switch (event.event) {
100
+ case "chunk": {
101
+ accumulatedContentRef.current += event.data.text;
102
+ hasNewContent = true;
103
+ canonicalBlocksChangedRef.current = true;
104
+ hasNewCanonical = true;
105
+ break;
106
+ }
107
+ case "tool_event": {
108
+ console.log(
109
+ "[STREAM] tool_event:",
110
+ JSON.stringify(event.data, null, 2)
111
+ );
112
+ canonicalBlocksChangedRef.current = true;
113
+ hasNewCanonical = true;
114
+ break;
115
+ }
116
+ case "error": {
117
+ console.log("[STREAM] error:", JSON.stringify(event.data, null, 2));
118
+ const errorMessage = event.data.user_message || event.data.message || "An error occurred";
119
+ onErrorRef.current?.(errorMessage);
120
+ setHasStreamError(true);
121
+ break;
122
+ }
123
+ case "phase": {
124
+ console.log("[STREAM] phase:", JSON.stringify(event.data, null, 2));
125
+ onPhaseUpdateRef.current?.(event.data.phase);
126
+ break;
127
+ }
128
+ case "render_block": {
129
+ console.log(
130
+ "[STREAM] render_block:",
131
+ JSON.stringify(event.data, null, 2)
132
+ );
133
+ isNewProtocolRef.current = true;
134
+ const block = event.data;
135
+ if (block.blockId !== void 0) {
136
+ serverBlockMapRef.current.set(block.blockId, {
137
+ blockId: block.blockId,
138
+ blockIndex: block.blockIndex ?? 0,
139
+ type: block.type,
140
+ status: block.status ?? "streaming",
141
+ content: block.content ?? null,
142
+ data: block.data ?? null,
143
+ metadata: block.metadata ?? {}
144
+ });
145
+ hasNewBlocks = true;
146
+ }
147
+ break;
148
+ }
149
+ case "completion":
150
+ console.log(
151
+ "[STREAM] completion:",
152
+ JSON.stringify(event.data, null, 2)
153
+ );
154
+ break;
155
+ case "heartbeat":
156
+ console.log(
157
+ "[STREAM] heartbeat:",
158
+ JSON.stringify(event.data, null, 2)
159
+ );
160
+ break;
161
+ case "data":
162
+ console.log("[STREAM] data:", JSON.stringify(event.data, null, 2));
163
+ break;
164
+ case "end":
165
+ console.log("[STREAM] end:", JSON.stringify(event.data, null, 2));
166
+ break;
167
+ default:
168
+ console.log(
169
+ "[STREAM] \u26A0\uFE0F UNKNOWN event type:",
170
+ event.event,
171
+ JSON.stringify(event.data, null, 2)
172
+ );
173
+ }
174
+ }
175
+ lastProcessedIndexRef.current = events.length - 1;
176
+ if (hasNewContent) pendingContentUpdateRef.current = true;
177
+ if (hasNewCanonical) pendingCanonicalUpdateRef.current = true;
178
+ if (hasNewBlocks) pendingBlocksUpdateRef.current = true;
179
+ if ((hasNewContent || hasNewCanonical || hasNewBlocks) && rafIdRef.current === null) {
180
+ rafIdRef.current = requestAnimationFrame(() => {
181
+ rafIdRef.current = null;
182
+ if (pendingContentUpdateRef.current) {
183
+ setProcessedContent(accumulatedContentRef.current);
184
+ pendingContentUpdateRef.current = false;
185
+ }
186
+ if (pendingCanonicalUpdateRef.current && canonicalBlocksChangedRef.current) {
187
+ const currentEvents = eventsRef.current;
188
+ if (currentEvents) {
189
+ setCanonicalBlocks(buildCanonicalBlocks(currentEvents));
190
+ }
191
+ canonicalBlocksChangedRef.current = false;
192
+ pendingCanonicalUpdateRef.current = false;
193
+ }
194
+ if (pendingBlocksUpdateRef.current) {
195
+ const blockArray = Array.from(
196
+ serverBlockMapRef.current.values()
197
+ ).sort((a, b) => a.blockIndex - b.blockIndex);
198
+ setServerBlocks(blockArray);
199
+ pendingBlocksUpdateRef.current = false;
200
+ }
201
+ });
202
+ }
203
+ }, [events, content]);
204
+ const isEventMode = events && events.length > 0;
205
+ const hasToolBlocks = isEventMode && canonicalBlocks.some((b) => b.type === "tool_call");
206
+ const effectiveServerBlocks = serverBlocksProp ?? (isNewProtocolRef.current ? serverBlocks : void 0);
207
+ if (isEventMode && hasToolBlocks) {
208
+ return /* @__PURE__ */ jsx(Fragment, { children: canonicalBlocks.map((block, index) => {
209
+ const isLastBlock = index === canonicalBlocks.length - 1;
210
+ if (block.type === "text") {
211
+ const textBlock = block;
212
+ return /* @__PURE__ */ jsx(
213
+ EnhancedChatMarkdownInternal,
214
+ {
215
+ requestId,
216
+ recordMessageIds,
217
+ streamSlotStart,
218
+ streamSlotEnd,
219
+ agentCallId,
220
+ turnId,
221
+ conversationId,
222
+ content: textBlock.content,
223
+ taskId,
224
+ className,
225
+ isStreamActive: isLastBlock ? isStreamActive : false,
226
+ onContentChange,
227
+ analysisData,
228
+ messageId,
229
+ allowFullScreenEditor,
230
+ hideCopyButton,
231
+ applyLocalEdits,
232
+ serverProcessedBlocks: isLastBlock ? effectiveServerBlocks : void 0
233
+ },
234
+ `text-${index}`
235
+ );
236
+ }
237
+ if (block.type === "tool_call") {
238
+ const toolBlock = block;
239
+ const hasContentAfter = canonicalBlocks.slice(index + 1).some(
240
+ (b) => b.type === "tool_call" || b.type === "text" && b.content.trim()
241
+ );
242
+ return /* @__PURE__ */ jsx(
243
+ MarkdownErrorBoundary,
244
+ {
245
+ fallback: null,
246
+ onError: (error) => console.error(
247
+ "[MarkdownStream] LiveToolCallCard error:",
248
+ error
249
+ ),
250
+ children: requestId ? /* @__PURE__ */ jsx(
251
+ LiveToolCallCard,
252
+ {
253
+ requestId,
254
+ callId: toolBlock.callId,
255
+ conversationId,
256
+ hasContentAfter
257
+ }
258
+ ) : null
259
+ },
260
+ `tool-${toolBlock.callId}`
261
+ );
262
+ }
263
+ return null;
264
+ }) });
265
+ }
266
+ return /* @__PURE__ */ jsx(
267
+ EnhancedChatMarkdownInternal,
268
+ {
269
+ requestId,
270
+ recordMessageIds,
271
+ streamSlotStart,
272
+ streamSlotEnd,
273
+ agentCallId,
274
+ turnId,
275
+ conversationId,
276
+ content: processedContent,
277
+ taskId,
278
+ className,
279
+ isStreamActive,
280
+ onContentChange,
281
+ analysisData,
282
+ messageId,
283
+ allowFullScreenEditor,
284
+ hideCopyButton,
285
+ applyLocalEdits,
286
+ serverProcessedBlocks: effectiveServerBlocks
287
+ }
288
+ );
289
+ };
290
+ var StreamAwareChatMarkdown_default = StreamAwareChatMarkdown;
291
+ export {
292
+ StreamAwareChatMarkdown,
293
+ StreamAwareChatMarkdown_default as default
294
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * AgentCallChildTrace — a sub-agent's thinking and tool calls, drawn in the
3
+ * transcript directly under the `agent_call` card that ran it, live AND after
4
+ * a reload (Arman, 2026-10-01: nested work is shown, never hidden inside the
5
+ * card). Items come from `utils/agent-call-trace.ts` (one list, two sources);
6
+ * each renders through the components the top level uses — `ToolCard` for a
7
+ * call (so a nested `agent_call` brings its own trace: depth by recursion) and
8
+ * the canonical reasoning renderer for thinking. The door opens the child's
9
+ * own conversation.
10
+ */
11
+ import React from "react";
12
+ import type { ToolLifecycleEntry } from "../../../agents/types/request.types.js";
13
+ import type { ToolCardProps } from "./ToolHandlers.js";
14
+ export interface AgentCallChildTraceProps {
15
+ entry: ToolLifecycleEntry;
16
+ conversationId: string;
17
+ /** Live source — the parent request whose wire carried the child. */
18
+ requestId?: string;
19
+ /** Passed in (not imported) — `ToolCard` renders this trace. */
20
+ ToolCardComponent: React.ComponentType<ToolCardProps>;
21
+ }
22
+ export declare function AgentCallChildTrace({ entry, conversationId, requestId, ToolCardComponent, }: AgentCallChildTraceProps): React.JSX.Element | null;