@adminide-stack/yantra-mobile 12.0.52-alpha.0 → 12.0.52-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/CustomDrawer.js +1 -38
- package/lib/components/CustomDrawer.js.map +1 -1
- package/lib/components/KeyboardComposerDock.js +4 -3
- package/lib/components/KeyboardComposerDock.js.map +1 -1
- package/lib/compute.js +58 -1
- package/lib/compute.js.map +1 -1
- package/lib/features/apps/AppsCatalog.js +9 -0
- package/lib/features/apps/AppsCatalog.js.map +1 -1
- package/lib/features/apps/mobileAppCatalog.js +10 -0
- package/lib/features/apps/mobileAppCatalog.js.map +1 -1
- package/lib/features/attachments/buildGatewayMedia.js +22 -15
- package/lib/features/attachments/buildGatewayMedia.js.map +1 -1
- package/lib/features/attachments/uploadChatAttachments.js +6 -4
- package/lib/features/attachments/uploadChatAttachments.js.map +1 -1
- package/lib/features/attachments/useImageAttachments.js +63 -17
- package/lib/features/attachments/useImageAttachments.js.map +1 -1
- package/lib/features/chat/AskUserCard.js +244 -121
- package/lib/features/chat/AskUserCard.js.map +1 -1
- package/lib/features/chat/ChatTranscript.js +206 -130
- package/lib/features/chat/ChatTranscript.js.map +1 -1
- package/lib/features/chat/askUser.js +111 -15
- package/lib/features/chat/askUser.js.map +1 -1
- package/lib/features/chat/streamingMarkdown.js +7 -0
- package/lib/features/chat/streamingMarkdown.js.map +1 -0
- package/lib/features/chat/transcriptGroups.js +29 -0
- package/lib/features/chat/transcriptGroups.js.map +1 -0
- package/lib/features/messaging/nativeChatRegistry.js +7 -0
- package/lib/features/messaging/nativeChatRegistry.js.map +1 -0
- package/lib/features/messaging/useChatViewer.js +32 -0
- package/lib/features/messaging/useChatViewer.js.map +1 -0
- package/lib/hooks/mintSurfaceSystemToken.js +28 -14
- package/lib/hooks/mintSurfaceSystemToken.js.map +1 -1
- package/lib/hooks/systemTokenJwt.js +75 -0
- package/lib/hooks/systemTokenJwt.js.map +1 -0
- package/lib/hooks/useCdecliAutoConnect.js +116 -138
- package/lib/hooks/useCdecliAutoConnect.js.map +1 -1
- package/lib/hooks/useChatApi.js +43 -17
- package/lib/hooks/useChatApi.js.map +1 -1
- package/lib/hooks/useChatStream.js +61 -13
- package/lib/hooks/useChatStream.js.map +1 -1
- package/lib/hooks/useObtainSystemToken.js +121 -36
- package/lib/hooks/useObtainSystemToken.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/routes.json +53 -0
- package/lib/screens/Chat/index.js +25 -6
- package/lib/screens/Chat/index.js.map +1 -1
- package/lib/screens/ChatNative/index.js +69 -0
- package/lib/screens/ChatNative/index.js.map +1 -0
- package/lib/screens/Home/HomeScreen.js +21 -6
- package/lib/screens/Home/HomeScreen.js.map +1 -1
- package/lib/screens/Home/components/ChatHistoryLanding.js +46 -16
- package/lib/screens/Home/components/ChatHistoryLanding.js.map +1 -1
- package/lib/utils/authUserDisplay.js +37 -0
- package/lib/utils/authUserDisplay.js.map +1 -0
- package/package.json +3 -3
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {jsx,jsxs}from'react/jsx-runtime';import
|
|
1
|
+
import {jsx,jsxs}from'react/jsx-runtime';import {useRef,useMemo,useCallback,useEffect,memo}from'react';import {View,StyleSheet,FlatList,Platform,Pressable}from'react-native';import {dismissKeyboard}from'../../utils/keyboardController.js';import {useKeyboardLiftHeight}from'../../components/KeyboardComposerDock.js';import Markdown from'react-native-markdown-display';import {shouldRenderUserTranscriptTurn,displayUserMessageText}from'../attachments/displayUserMessageText.js';import {MessageAttachmentPreviews}from'../attachments/MessageAttachmentPreviews.js';import {ToolTimeline}from'./ToolTimeline.js';import {parseToolActivity}from'./toolActivity.js';import {parseAskUser,displayAskUserAssistantText,stripAskUser}from'./askUser.js';import {collapseDuplicateUserRows,groupConsecutiveRoleRows}from'./transcriptGroups.js';import {closeOpenMarkdownFences}from'./streamingMarkdown.js';var __defProp = Object.defineProperty;
|
|
2
2
|
var __defProps = Object.defineProperties;
|
|
3
3
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
@@ -23,41 +23,68 @@ function ChatTranscript({
|
|
|
23
23
|
streamingContent,
|
|
24
24
|
renderMessageActions,
|
|
25
25
|
listContentStyle,
|
|
26
|
-
isDark = false
|
|
27
|
-
onAskUserAnswer,
|
|
28
|
-
sending = false
|
|
26
|
+
isDark = false
|
|
29
27
|
}) {
|
|
30
28
|
const listRef = useRef(null);
|
|
31
29
|
const stickToBottomRef = useRef(true);
|
|
32
30
|
const isProgrammaticScrollRef = useRef(false);
|
|
33
31
|
const ignoreScrollUntilRef = useRef(0);
|
|
34
32
|
const keyboardHeight = useKeyboardLiftHeight();
|
|
35
|
-
const historyRows = useMemo(() =>
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
const historyRows = useMemo(() => {
|
|
34
|
+
const rows2 = [];
|
|
35
|
+
messages.forEach((msg, index) => {
|
|
36
|
+
var _a, _b, _c, _d;
|
|
37
|
+
if (msg.role === "user") {
|
|
38
|
+
if (shouldRenderUserTranscriptTurn(msg.content, msg.attachments)) {
|
|
39
|
+
rows2.push(__spreadProps(__spreadValues({}, msg), {
|
|
40
|
+
streaming: false
|
|
41
|
+
}));
|
|
42
|
+
}
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (msg.role !== "assistant") {
|
|
46
|
+
rows2.push(__spreadProps(__spreadValues({}, msg), {
|
|
47
|
+
streaming: false
|
|
48
|
+
}));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const askAnswered = Boolean(parseAskUser(msg.content)) && messages.slice(index + 1).some((m) => m.role === "user");
|
|
52
|
+
const visible = displayAskUserAssistantText(msg.content, askAnswered).trim();
|
|
53
|
+
const tools = parseToolActivity(stripAskUser(msg.content), false);
|
|
54
|
+
const hasAsk = Boolean(parseAskUser(msg.content));
|
|
55
|
+
if (hasAsk && !visible && tools.steps.length === 0 && !((_b = (_a = msg.attachments) == null ? void 0 : _a.length) != null ? _b : 0)) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (!hasAsk) {
|
|
59
|
+
const leftover = stripAskUser(msg.content).trim();
|
|
60
|
+
if (!leftover && !((_d = (_c = msg.attachments) == null ? void 0 : _c.length) != null ? _d : 0)) return;
|
|
61
|
+
}
|
|
62
|
+
rows2.push(__spreadProps(__spreadValues({}, msg), {
|
|
63
|
+
streaming: false,
|
|
64
|
+
askAnswered
|
|
65
|
+
}));
|
|
66
|
+
});
|
|
67
|
+
return rows2;
|
|
68
|
+
}, [messages]);
|
|
38
69
|
const rows = useMemo(() => {
|
|
39
|
-
const
|
|
40
|
-
const
|
|
70
|
+
const history = collapseDuplicateUserRows(historyRows);
|
|
71
|
+
const rawStream = streamingContent != null ? streamingContent : "";
|
|
72
|
+
const last = history[history.length - 1];
|
|
73
|
+
const streamAskAnswered = (last == null ? void 0 : last.role) === "user" && Boolean(parseAskUser(rawStream));
|
|
74
|
+
const streamProse = displayAskUserAssistantText(rawStream, streamAskAnswered).trim();
|
|
75
|
+
const streamTools = parseToolActivity(stripAskUser(rawStream), true);
|
|
76
|
+
if (!streamProse && streamTools.steps.length === 0) return history;
|
|
77
|
+
return [...history, {
|
|
41
78
|
id: "__streaming__",
|
|
42
79
|
role: "assistant",
|
|
43
|
-
content:
|
|
44
|
-
streaming: true
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (withStream[i].role === "assistant" && withStream[i].content.includes(pending.requestId)) {
|
|
50
|
-
const next = [...withStream];
|
|
51
|
-
next[i] = __spreadProps(__spreadValues({}, next[i]), {
|
|
52
|
-
askUser: pending
|
|
53
|
-
});
|
|
54
|
-
return next;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return withStream;
|
|
58
|
-
}, [historyRows, streamingContent, onAskUserAnswer]);
|
|
80
|
+
content: rawStream,
|
|
81
|
+
streaming: true,
|
|
82
|
+
askAnswered: streamAskAnswered
|
|
83
|
+
}];
|
|
84
|
+
}, [historyRows, streamingContent]);
|
|
85
|
+
const groups = useMemo(() => groupConsecutiveRoleRows(rows), [rows]);
|
|
59
86
|
const scrollToLatest = useCallback((animated) => {
|
|
60
|
-
if (
|
|
87
|
+
if (groups.length === 0) return;
|
|
61
88
|
isProgrammaticScrollRef.current = true;
|
|
62
89
|
stickToBottomRef.current = true;
|
|
63
90
|
const list = listRef.current;
|
|
@@ -69,12 +96,12 @@ function ChatTranscript({
|
|
|
69
96
|
offset: Number.MAX_SAFE_INTEGER,
|
|
70
97
|
animated
|
|
71
98
|
});
|
|
72
|
-
}, [
|
|
99
|
+
}, [groups.length]);
|
|
73
100
|
useEffect(() => {
|
|
74
|
-
if (
|
|
101
|
+
if (groups.length === 0 || !stickToBottomRef.current) return void 0;
|
|
75
102
|
const t = setTimeout(() => scrollToLatest(false), 0);
|
|
76
103
|
return () => clearTimeout(t);
|
|
77
|
-
}, [
|
|
104
|
+
}, [groups.length, streamingContent == null ? void 0 : streamingContent.length, scrollToLatest]);
|
|
78
105
|
useEffect(() => {
|
|
79
106
|
if (keyboardHeight <= 0) return void 0;
|
|
80
107
|
stickToBottomRef.current = true;
|
|
@@ -109,109 +136,52 @@ function ChatTranscript({
|
|
|
109
136
|
if (!stickToBottomRef.current) return;
|
|
110
137
|
scrollToLatest(false);
|
|
111
138
|
}, [scrollToLatest]);
|
|
112
|
-
const [dismissedAsk, setDismissedAsk] = React.useState(null);
|
|
113
139
|
const renderItem = useCallback(({
|
|
114
140
|
item
|
|
115
|
-
}) => /* @__PURE__ */ jsx(
|
|
116
|
-
return /* @__PURE__ */ jsx(View, { style: styles.list, children: /* @__PURE__ */ jsx(FlatList, { ref: listRef, data:
|
|
141
|
+
}) => /* @__PURE__ */ jsx(TranscriptGroupView, { group: item, isDark, renderMessageActions }), [isDark, renderMessageActions]);
|
|
142
|
+
return /* @__PURE__ */ jsx(View, { style: styles.list, children: /* @__PURE__ */ jsx(FlatList, { ref: listRef, data: groups, keyExtractor: (item) => item.id, renderItem, extraData: streamingContent, initialNumToRender: 12, maxToRenderPerBatch: 8, updateCellsBatchingPeriod: 50, windowSize: 7, onScroll: handleScroll, onContentSizeChange: handleContentSizeChange, onLayout: () => {
|
|
117
143
|
if (stickToBottomRef.current) scrollToLatest(false);
|
|
118
144
|
}, scrollEventThrottle: 16, keyboardShouldPersistTaps: "handled", keyboardDismissMode: Platform.OS === "ios" ? "interactive" : "on-drag", automaticallyAdjustKeyboardInsets: false, automaticallyAdjustContentInsets: false, contentInsetAdjustmentBehavior: "never", contentContainerStyle: [styles.listContent, listContentStyle, styles.listContentFill], style: styles.list }) });
|
|
119
145
|
}
|
|
120
|
-
const
|
|
121
|
-
|
|
146
|
+
const TranscriptGroupView = memo(function TranscriptGroupView2({
|
|
147
|
+
group,
|
|
122
148
|
isDark,
|
|
123
|
-
renderMessageActions
|
|
124
|
-
askUserDismissed,
|
|
125
|
-
onAskUserAnswer,
|
|
126
|
-
onAskUserDismiss,
|
|
127
|
-
sending
|
|
149
|
+
renderMessageActions
|
|
128
150
|
}) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return /* @__PURE__ */ jsxs(Pressable, { style: styles.userCol, onPress: dismissKeyboard, accessible: false, children: [
|
|
141
|
-
attachments.length > 0 ? /* @__PURE__ */ jsx(MessageAttachmentPreviews, { attachments, align: "end", isDark }) : null,
|
|
142
|
-
text ? /* @__PURE__ */ jsx(View, { style: styles.userBubble, children: /* @__PURE__ */ jsx(Text, { style: styles.userText, children: text }) }) : null
|
|
143
|
-
] });
|
|
151
|
+
if (group.role === "user") {
|
|
152
|
+
return /* @__PURE__ */ jsx(Pressable, { style: styles.userCol, onPress: dismissKeyboard, accessible: false, children: group.items.map((item, index) => {
|
|
153
|
+
var _a;
|
|
154
|
+
const attachments = (_a = item.attachments) != null ? _a : [];
|
|
155
|
+
const text = displayUserMessageText(item.content);
|
|
156
|
+
if (!text && attachments.length === 0) return null;
|
|
157
|
+
return /* @__PURE__ */ jsxs(View, { style: [styles.userTurn, index > 0 && styles.userFollow], children: [
|
|
158
|
+
attachments.length > 0 ? /* @__PURE__ */ jsx(MessageAttachmentPreviews, { attachments, align: "end", isDark }) : null,
|
|
159
|
+
text ? /* @__PURE__ */ jsx(View, { style: styles.userBubble, children: /* @__PURE__ */ jsx(Markdown, { style: USER_MARKDOWN, children: text }) }) : null
|
|
160
|
+
] }, item.id);
|
|
161
|
+
}) });
|
|
144
162
|
}
|
|
145
163
|
const markdownColor = isDark ? "#e2e8f0" : "#111827";
|
|
146
164
|
const codeBg = isDark ? "#1e293b" : "#f3f4f6";
|
|
147
|
-
|
|
165
|
+
const last = group.items[group.items.length - 1];
|
|
166
|
+
return /* @__PURE__ */ jsx(View, { style: styles.assistantGroup, children: group.items.map((item, index) => /* @__PURE__ */ jsx(AssistantTurnView, { item, isDark, markdownColor, codeBg, tightTop: index > 0, renderMessageActions: item.streaming || item !== last ? void 0 : renderMessageActions }, item.id)) });
|
|
167
|
+
});
|
|
168
|
+
const AssistantTurnView = memo(function AssistantTurnView2({
|
|
169
|
+
item,
|
|
170
|
+
isDark,
|
|
171
|
+
markdownColor,
|
|
172
|
+
codeBg,
|
|
173
|
+
tightTop,
|
|
174
|
+
renderMessageActions
|
|
175
|
+
}) {
|
|
176
|
+
var _a;
|
|
177
|
+
const attachments = (_a = item.attachments) != null ? _a : [];
|
|
178
|
+
const stripped = stripAskUser(item.content);
|
|
179
|
+
const toolActivity = parseToolActivity(stripped, !!item.streaming);
|
|
180
|
+
const text = parseToolActivity(displayAskUserAssistantText(item.content, !!item.askAnswered), !!item.streaming).text;
|
|
181
|
+
return /* @__PURE__ */ jsxs(Pressable, { style: [styles.assistantCol, tightTop && styles.assistantColTight], onPress: dismissKeyboard, accessible: false, children: [
|
|
148
182
|
attachments.length > 0 ? /* @__PURE__ */ jsx(MessageAttachmentPreviews, { attachments, align: "start", isDark }) : null,
|
|
149
183
|
toolActivity.steps.length > 0 ? /* @__PURE__ */ jsx(ToolTimeline, { steps: toolActivity.steps, active: !!item.streaming, isDark }) : null,
|
|
150
|
-
|
|
151
|
-
onAskUserDismiss == null ? void 0 : onAskUserDismiss(askUser.requestId);
|
|
152
|
-
onAskUserAnswer(formatted);
|
|
153
|
-
}, onDismiss: () => onAskUserDismiss == null ? void 0 : onAskUserDismiss(askUser.requestId) }) : null,
|
|
154
|
-
text ? item.streaming ? /* @__PURE__ */ jsx(Text, { style: [styles.assistantStreamText, {
|
|
155
|
-
color: markdownColor
|
|
156
|
-
}], children: text }) : /* @__PURE__ */ jsx(Markdown, { style: {
|
|
157
|
-
body: {
|
|
158
|
-
color: markdownColor,
|
|
159
|
-
fontSize: 15,
|
|
160
|
-
lineHeight: 22
|
|
161
|
-
},
|
|
162
|
-
heading1: {
|
|
163
|
-
fontSize: 18,
|
|
164
|
-
fontWeight: "700",
|
|
165
|
-
marginTop: 12,
|
|
166
|
-
marginBottom: 4,
|
|
167
|
-
color: markdownColor
|
|
168
|
-
},
|
|
169
|
-
heading2: {
|
|
170
|
-
fontSize: 16,
|
|
171
|
-
fontWeight: "700",
|
|
172
|
-
marginTop: 10,
|
|
173
|
-
marginBottom: 4,
|
|
174
|
-
color: markdownColor
|
|
175
|
-
},
|
|
176
|
-
heading3: {
|
|
177
|
-
fontSize: 15,
|
|
178
|
-
fontWeight: "600",
|
|
179
|
-
marginTop: 8,
|
|
180
|
-
marginBottom: 4,
|
|
181
|
-
color: markdownColor
|
|
182
|
-
},
|
|
183
|
-
strong: {
|
|
184
|
-
fontWeight: "700"
|
|
185
|
-
},
|
|
186
|
-
paragraph: {
|
|
187
|
-
marginTop: 4,
|
|
188
|
-
marginBottom: 4
|
|
189
|
-
},
|
|
190
|
-
list_item: {
|
|
191
|
-
marginVertical: 2
|
|
192
|
-
},
|
|
193
|
-
bullet_list: {
|
|
194
|
-
marginVertical: 4
|
|
195
|
-
},
|
|
196
|
-
ordered_list: {
|
|
197
|
-
marginVertical: 4
|
|
198
|
-
},
|
|
199
|
-
code_inline: {
|
|
200
|
-
backgroundColor: codeBg,
|
|
201
|
-
paddingHorizontal: 4,
|
|
202
|
-
borderRadius: 4,
|
|
203
|
-
fontSize: 14,
|
|
204
|
-
color: markdownColor
|
|
205
|
-
},
|
|
206
|
-
code_block: {
|
|
207
|
-
backgroundColor: codeBg,
|
|
208
|
-
padding: 12,
|
|
209
|
-
borderRadius: 8,
|
|
210
|
-
marginVertical: 8,
|
|
211
|
-
fontSize: 14,
|
|
212
|
-
color: markdownColor
|
|
213
|
-
}
|
|
214
|
-
}, children: text }) : null,
|
|
184
|
+
text ? /* @__PURE__ */ jsx(Markdown, { style: assistantMarkdownStyle(markdownColor, codeBg), children: item.streaming ? closeOpenMarkdownFences(text) : text }) : null,
|
|
215
185
|
renderMessageActions ? renderMessageActions({
|
|
216
186
|
id: item.id,
|
|
217
187
|
role: "assistant",
|
|
@@ -219,6 +189,107 @@ const TranscriptRowView = memo(function TranscriptRowView2({
|
|
|
219
189
|
}) : null
|
|
220
190
|
] });
|
|
221
191
|
});
|
|
192
|
+
const USER_MARKDOWN = {
|
|
193
|
+
body: {
|
|
194
|
+
color: "#ffffff",
|
|
195
|
+
fontSize: 15,
|
|
196
|
+
lineHeight: 22
|
|
197
|
+
},
|
|
198
|
+
paragraph: {
|
|
199
|
+
marginTop: 4,
|
|
200
|
+
marginBottom: 4,
|
|
201
|
+
color: "#ffffff"
|
|
202
|
+
},
|
|
203
|
+
strong: {
|
|
204
|
+
fontWeight: "700",
|
|
205
|
+
color: "#ffffff"
|
|
206
|
+
},
|
|
207
|
+
em: {
|
|
208
|
+
color: "#ffffff"
|
|
209
|
+
},
|
|
210
|
+
text: {
|
|
211
|
+
color: "#ffffff"
|
|
212
|
+
},
|
|
213
|
+
bullet_list: {
|
|
214
|
+
marginVertical: 4
|
|
215
|
+
},
|
|
216
|
+
ordered_list: {
|
|
217
|
+
marginVertical: 4
|
|
218
|
+
},
|
|
219
|
+
list_item: {
|
|
220
|
+
marginVertical: 2,
|
|
221
|
+
color: "#ffffff"
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
function assistantMarkdownStyle(markdownColor, codeBg) {
|
|
225
|
+
return {
|
|
226
|
+
body: {
|
|
227
|
+
color: markdownColor,
|
|
228
|
+
fontSize: 15,
|
|
229
|
+
lineHeight: 22
|
|
230
|
+
},
|
|
231
|
+
heading1: {
|
|
232
|
+
fontSize: 18,
|
|
233
|
+
fontWeight: "700",
|
|
234
|
+
marginTop: 12,
|
|
235
|
+
marginBottom: 4,
|
|
236
|
+
color: markdownColor
|
|
237
|
+
},
|
|
238
|
+
heading2: {
|
|
239
|
+
fontSize: 16,
|
|
240
|
+
fontWeight: "700",
|
|
241
|
+
marginTop: 10,
|
|
242
|
+
marginBottom: 4,
|
|
243
|
+
color: markdownColor
|
|
244
|
+
},
|
|
245
|
+
heading3: {
|
|
246
|
+
fontSize: 15,
|
|
247
|
+
fontWeight: "600",
|
|
248
|
+
marginTop: 8,
|
|
249
|
+
marginBottom: 4,
|
|
250
|
+
color: markdownColor
|
|
251
|
+
},
|
|
252
|
+
strong: {
|
|
253
|
+
fontWeight: "700"
|
|
254
|
+
},
|
|
255
|
+
paragraph: {
|
|
256
|
+
marginTop: 4,
|
|
257
|
+
marginBottom: 4
|
|
258
|
+
},
|
|
259
|
+
list_item: {
|
|
260
|
+
marginVertical: 2
|
|
261
|
+
},
|
|
262
|
+
bullet_list: {
|
|
263
|
+
marginVertical: 4
|
|
264
|
+
},
|
|
265
|
+
ordered_list: {
|
|
266
|
+
marginVertical: 4
|
|
267
|
+
},
|
|
268
|
+
code_inline: {
|
|
269
|
+
backgroundColor: codeBg,
|
|
270
|
+
paddingHorizontal: 4,
|
|
271
|
+
borderRadius: 4,
|
|
272
|
+
fontSize: 14,
|
|
273
|
+
color: markdownColor
|
|
274
|
+
},
|
|
275
|
+
code_block: {
|
|
276
|
+
backgroundColor: codeBg,
|
|
277
|
+
padding: 12,
|
|
278
|
+
borderRadius: 8,
|
|
279
|
+
marginVertical: 8,
|
|
280
|
+
fontSize: 14,
|
|
281
|
+
color: markdownColor
|
|
282
|
+
},
|
|
283
|
+
fence: {
|
|
284
|
+
backgroundColor: codeBg,
|
|
285
|
+
padding: 12,
|
|
286
|
+
borderRadius: 8,
|
|
287
|
+
marginVertical: 8,
|
|
288
|
+
fontSize: 14,
|
|
289
|
+
color: markdownColor
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
}
|
|
222
293
|
const styles = StyleSheet.create({
|
|
223
294
|
list: {
|
|
224
295
|
flex: 1
|
|
@@ -235,19 +306,25 @@ const styles = StyleSheet.create({
|
|
|
235
306
|
userCol: {
|
|
236
307
|
width: "100%",
|
|
237
308
|
alignItems: "flex-end",
|
|
238
|
-
marginBottom:
|
|
309
|
+
marginBottom: 12,
|
|
239
310
|
paddingHorizontal: 4
|
|
240
311
|
},
|
|
312
|
+
userTurn: {
|
|
313
|
+
maxWidth: "92%",
|
|
314
|
+
alignItems: "flex-end"
|
|
315
|
+
},
|
|
316
|
+
userFollow: {
|
|
317
|
+
marginTop: 4
|
|
318
|
+
},
|
|
241
319
|
userBubble: {
|
|
242
320
|
backgroundColor: USER_BUBBLE_BG,
|
|
243
321
|
borderRadius: 16,
|
|
244
|
-
|
|
245
|
-
|
|
322
|
+
paddingHorizontal: 12,
|
|
323
|
+
paddingVertical: 8
|
|
246
324
|
},
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
lineHeight: 22
|
|
325
|
+
assistantGroup: {
|
|
326
|
+
width: "100%",
|
|
327
|
+
marginBottom: 4
|
|
251
328
|
},
|
|
252
329
|
assistantCol: {
|
|
253
330
|
width: "100%",
|
|
@@ -255,8 +332,7 @@ const styles = StyleSheet.create({
|
|
|
255
332
|
marginBottom: 8,
|
|
256
333
|
paddingHorizontal: 4
|
|
257
334
|
},
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
lineHeight: 22
|
|
335
|
+
assistantColTight: {
|
|
336
|
+
marginTop: -4
|
|
261
337
|
}
|
|
262
338
|
});export{ChatTranscript};//# sourceMappingURL=ChatTranscript.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatTranscript.js","sources":["../../../src/features/chat/ChatTranscript.tsx"],"sourcesContent":["/**\n * Chat thread list that can show attachment previews.\n *\n * `@messenger-box/platform-mobile` PlanModeView maps each row to GiftedChat\n * `{ text }` only, so an image send becomes the gateway caption\n * \"Attached: IMG_0005.jpg\" with no thumbnail. This list keeps streaming\n * markdown for the assistant and draws Manus-style previews on the user side.\n *\n * Rows stay oldest → newest (same as web). A previous `inverted` FlatList\n * reversed that order on device. The composer dock already lifts with the\n * keyboard; this list just fills the leftover space and pins to the latest\n * turn.\n */\nimport React, { memo, useCallback, useEffect, useMemo, useRef } from 'react';\nimport { FlatList, Platform, Pressable, StyleSheet, Text, View, type StyleProp, type ViewStyle } from 'react-native';\nimport { dismissKeyboard } from '../../utils/keyboardController';\nimport { useKeyboardLiftHeight } from '../../components/KeyboardComposerDock';\nimport Markdown from 'react-native-markdown-display';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\nimport { displayUserMessageText, shouldRenderUserTranscriptTurn } from '../attachments/displayUserMessageText';\nimport { MessageAttachmentPreviews } from '../attachments/MessageAttachmentPreviews';\nimport { AskUserCard } from './AskUserCard';\nimport { ToolTimeline } from './ToolTimeline';\nimport { parseToolActivity } from './toolActivity';\nimport { pendingAskUser, stripAskUser, type AskUserPayload } from './askUser';\n\nexport type TranscriptMessage = {\n id: string;\n role: string;\n content: string;\n attachments?: MessageAttachment[];\n};\n\ntype TranscriptRow = TranscriptMessage & { streaming?: boolean; askUser?: AskUserPayload };\n\nconst USER_BUBBLE_BG = '#2563eb';\n\nexport function ChatTranscript({\n messages,\n streamingContent,\n renderMessageActions,\n listContentStyle,\n isDark = false,\n onAskUserAnswer,\n sending = false,\n}: {\n messages: TranscriptMessage[];\n streamingContent?: string;\n renderMessageActions?: (message: { id: string; role: string; content: string }) => React.ReactNode;\n listContentStyle?: StyleProp<ViewStyle>;\n isDark?: boolean;\n /**\n * Send the card's formatted answer as an ordinary user message. That send is\n * what releases cdecli's parked turn — without it the agent waits forever.\n * Omit to render questions as plain (stripped) text.\n */\n onAskUserAnswer?: (formatted: string) => void;\n /** A turn is in flight: the card stays visible but is not actionable. */\n sending?: boolean;\n}) {\n const listRef = useRef<FlatList<TranscriptRow>>(null);\n const stickToBottomRef = useRef(true);\n const isProgrammaticScrollRef = useRef(false);\n const ignoreScrollUntilRef = useRef(0);\n const keyboardHeight = useKeyboardLiftHeight();\n\n const historyRows = useMemo<TranscriptRow[]>(\n () =>\n messages\n .filter((msg) => msg.role !== 'user' || shouldRenderUserTranscriptTurn(msg.content, msg.attachments))\n .map((msg) => ({ ...msg, streaming: false })),\n [messages],\n );\n\n const rows = useMemo<TranscriptRow[]>(() => {\n const stream = streamingContent?.trim();\n const withStream = stream\n ? [\n ...historyRows,\n {\n id: '__streaming__',\n role: 'assistant',\n content: stream,\n streaming: true,\n },\n ]\n : historyRows;\n\n // Only the LAST unanswered question is actionable, and only the row that\n // carries it renders the card — so a card from earlier in the thread\n // never reappears, and answering makes it disappear on the next turn\n // (pendingAskUser stops at the first user message it meets).\n const pending = onAskUserAnswer ? pendingAskUser(withStream) : null;\n if (!pending) return withStream;\n for (let i = withStream.length - 1; i >= 0; i--) {\n if (withStream[i].role === 'assistant' && withStream[i].content.includes(pending.requestId)) {\n const next = [...withStream];\n next[i] = { ...next[i], askUser: pending };\n return next;\n }\n }\n return withStream;\n }, [historyRows, streamingContent, onAskUserAnswer]);\n\n const scrollToLatest = useCallback(\n (animated: boolean) => {\n if (rows.length === 0) return;\n isProgrammaticScrollRef.current = true;\n stickToBottomRef.current = true;\n const list = listRef.current;\n if (!list) return;\n list.scrollToEnd({ animated });\n // Tall bubbles: scrollToEnd can stop at the start of the last cell.\n list.scrollToOffset({ offset: Number.MAX_SAFE_INTEGER, animated });\n },\n [rows.length],\n );\n\n useEffect(() => {\n if (rows.length === 0 || !stickToBottomRef.current) return undefined;\n const t = setTimeout(() => scrollToLatest(false), 0);\n return () => clearTimeout(t);\n }, [rows.length, streamingContent?.length, scrollToLatest]);\n\n // Spacer and list height update on the same keyboard frame. Scroll only\n // after that shrink, or we stay on the top of a long turn (image 1).\n useEffect(() => {\n if (keyboardHeight <= 0) return undefined;\n stickToBottomRef.current = true;\n ignoreScrollUntilRef.current = Date.now() + 400;\n const frame = requestAnimationFrame(() => scrollToLatest(false));\n const afterLayout = setTimeout(() => scrollToLatest(false), 64);\n const afterKeyboard = setTimeout(() => scrollToLatest(false), 280);\n return () => {\n cancelAnimationFrame(frame);\n clearTimeout(afterLayout);\n clearTimeout(afterKeyboard);\n };\n }, [keyboardHeight, scrollToLatest]);\n\n const handleScroll = useCallback(\n (e: {\n nativeEvent: {\n contentOffset: { y: number };\n contentSize: { height: number };\n layoutMeasurement: { height: number };\n };\n }) => {\n if (Date.now() < ignoreScrollUntilRef.current) {\n stickToBottomRef.current = true;\n return;\n }\n const { contentOffset, contentSize, layoutMeasurement } = e.nativeEvent;\n const nearLatest = contentOffset.y + layoutMeasurement.height >= contentSize.height - 80;\n if (!isProgrammaticScrollRef.current) {\n stickToBottomRef.current = nearLatest;\n } else if (nearLatest) {\n isProgrammaticScrollRef.current = false;\n }\n },\n [],\n );\n\n const handleContentSizeChange = useCallback(() => {\n if (!stickToBottomRef.current) return;\n scrollToLatest(false);\n }, [scrollToLatest]);\n\n const [dismissedAsk, setDismissedAsk] = React.useState<string | null>(null);\n\n const renderItem = useCallback(\n ({ item }: { item: TranscriptRow }) => (\n <TranscriptRowView\n item={item}\n isDark={isDark}\n renderMessageActions={item.streaming ? undefined : renderMessageActions}\n askUserDismissed={dismissedAsk}\n onAskUserAnswer={onAskUserAnswer}\n onAskUserDismiss={setDismissedAsk}\n sending={sending}\n />\n ),\n [isDark, renderMessageActions, dismissedAsk, onAskUserAnswer, sending],\n );\n\n return (\n <View style={styles.list}>\n <FlatList\n ref={listRef}\n data={rows}\n keyExtractor={(item) => item.id}\n renderItem={renderItem}\n extraData={streamingContent}\n initialNumToRender={12}\n maxToRenderPerBatch={8}\n updateCellsBatchingPeriod={50}\n windowSize={7}\n onScroll={handleScroll}\n onContentSizeChange={handleContentSizeChange}\n onLayout={() => {\n if (stickToBottomRef.current) scrollToLatest(false);\n }}\n scrollEventThrottle={16}\n keyboardShouldPersistTaps=\"handled\"\n keyboardDismissMode={Platform.OS === 'ios' ? 'interactive' : 'on-drag'}\n automaticallyAdjustKeyboardInsets={false}\n automaticallyAdjustContentInsets={false}\n contentInsetAdjustmentBehavior=\"never\"\n contentContainerStyle={[styles.listContent, listContentStyle, styles.listContentFill]}\n style={styles.list}\n />\n </View>\n );\n}\n\nconst TranscriptRowView = memo(function TranscriptRowView({\n item,\n isDark,\n renderMessageActions,\n askUserDismissed,\n onAskUserAnswer,\n onAskUserDismiss,\n sending,\n}: {\n item: TranscriptRow;\n isDark: boolean;\n renderMessageActions?: (message: { id: string; role: string; content: string }) => React.ReactNode;\n askUserDismissed?: string | null;\n onAskUserAnswer?: (formatted: string) => void;\n onAskUserDismiss?: (requestId: string) => void;\n sending?: boolean;\n}) {\n const isUser = item.role === 'user';\n const attachments = item.attachments ?? [];\n // The marker is STRIPPED, never used to hide the message: cdecli emits it\n // mid-turn and streams its reply into the same message once the answer\n // releases the parked run, so dropping the message would swallow that reply.\n // Order matters: pull the ASK_USER block out first (it can contain an em\n // dash and a `⚙` line right above it), then lift the agent's narrated\n // `⚙ ToolSearch` rows out of what remains. What is left is the real answer.\n const assistantRaw = isUser ? '' : stripAskUser(item.content);\n const toolActivity = isUser ? { steps: [], text: '' } : parseToolActivity(assistantRaw, !!item.streaming);\n const text = isUser ? displayUserMessageText(item.content, attachments) : toolActivity.text;\n const askUser = !isUser && item.askUser && item.askUser.requestId !== askUserDismissed ? item.askUser : null;\n\n if (isUser) {\n return (\n <Pressable style={styles.userCol} onPress={dismissKeyboard} accessible={false}>\n {attachments.length > 0 ? (\n <MessageAttachmentPreviews attachments={attachments} align=\"end\" isDark={isDark} />\n ) : null}\n {text ? (\n <View style={styles.userBubble}>\n <Text style={styles.userText}>{text}</Text>\n </View>\n ) : null}\n </Pressable>\n );\n }\n\n const markdownColor = isDark ? '#e2e8f0' : '#111827';\n const codeBg = isDark ? '#1e293b' : '#f3f4f6';\n\n return (\n <Pressable style={styles.assistantCol} onPress={dismissKeyboard} accessible={false}>\n {attachments.length > 0 ? (\n <MessageAttachmentPreviews attachments={attachments} align=\"start\" isDark={isDark} />\n ) : null}\n {toolActivity.steps.length > 0 ? (\n <ToolTimeline steps={toolActivity.steps} active={!!item.streaming} isDark={isDark} />\n ) : null}\n {askUser && onAskUserAnswer ? (\n <AskUserCard\n payload={askUser}\n isDark={isDark}\n disabled={!!sending}\n onAnswer={(formatted) => {\n onAskUserDismiss?.(askUser.requestId);\n onAskUserAnswer(formatted);\n }}\n onDismiss={() => onAskUserDismiss?.(askUser.requestId)}\n />\n ) : null}\n {text ? (\n item.streaming ? (\n <Text style={[styles.assistantStreamText, { color: markdownColor }]}>{text}</Text>\n ) : (\n <Markdown\n style={{\n body: { color: markdownColor, fontSize: 15, lineHeight: 22 },\n heading1: {\n fontSize: 18,\n fontWeight: '700',\n marginTop: 12,\n marginBottom: 4,\n color: markdownColor,\n },\n heading2: {\n fontSize: 16,\n fontWeight: '700',\n marginTop: 10,\n marginBottom: 4,\n color: markdownColor,\n },\n heading3: {\n fontSize: 15,\n fontWeight: '600',\n marginTop: 8,\n marginBottom: 4,\n color: markdownColor,\n },\n strong: { fontWeight: '700' },\n paragraph: { marginTop: 4, marginBottom: 4 },\n list_item: { marginVertical: 2 },\n bullet_list: { marginVertical: 4 },\n ordered_list: { marginVertical: 4 },\n code_inline: {\n backgroundColor: codeBg,\n paddingHorizontal: 4,\n borderRadius: 4,\n fontSize: 14,\n color: markdownColor,\n },\n code_block: {\n backgroundColor: codeBg,\n padding: 12,\n borderRadius: 8,\n marginVertical: 8,\n fontSize: 14,\n color: markdownColor,\n },\n }}\n >\n {text}\n </Markdown>\n )\n ) : null}\n {renderMessageActions\n ? renderMessageActions({ id: item.id, role: 'assistant', content: item.content })\n : null}\n </Pressable>\n );\n});\n\nconst styles = StyleSheet.create({\n list: {\n flex: 1,\n },\n listContent: {\n paddingTop: 8,\n paddingBottom: 8,\n paddingHorizontal: 8,\n },\n listContentFill: {\n flexGrow: 1,\n justifyContent: 'flex-end',\n },\n userCol: {\n width: '100%',\n alignItems: 'flex-end',\n marginBottom: 8,\n paddingHorizontal: 4,\n },\n userBubble: {\n backgroundColor: USER_BUBBLE_BG,\n borderRadius: 16,\n padding: 12,\n maxWidth: '92%',\n },\n userText: {\n color: '#ffffff',\n fontSize: 15,\n lineHeight: 22,\n },\n assistantCol: {\n width: '100%',\n alignItems: 'flex-start',\n marginBottom: 8,\n paddingHorizontal: 4,\n },\n assistantStreamText: {\n fontSize: 15,\n lineHeight: 22,\n },\n});\n"],"names":["TranscriptRowView"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ChatTranscript.js","sources":["../../../src/features/chat/ChatTranscript.tsx"],"sourcesContent":["/**\n * Chat thread list that can show attachment previews.\n *\n * `@messenger-box/platform-mobile` PlanModeView maps each row to GiftedChat\n * `{ text }` only, so an image send becomes the gateway caption\n * \"Attached: IMG_0005.jpg\" with no thumbnail. This list keeps streaming\n * markdown for the assistant and draws Manus-style previews on the user side.\n *\n * Rows stay oldest → newest (same as web). A previous `inverted` FlatList\n * reversed that order on device. The composer dock already lifts with the\n * keyboard; this list just fills the leftover space and pins to the latest\n * turn.\n */\nimport React, { memo, useCallback, useEffect, useMemo, useRef } from 'react';\nimport { FlatList, Platform, Pressable, StyleSheet, View, type StyleProp, type ViewStyle } from 'react-native';\nimport { dismissKeyboard } from '../../utils/keyboardController';\nimport { useKeyboardLiftHeight } from '../../components/KeyboardComposerDock';\nimport Markdown from 'react-native-markdown-display';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\nimport { displayUserMessageText, shouldRenderUserTranscriptTurn } from '../attachments/displayUserMessageText';\nimport { MessageAttachmentPreviews } from '../attachments/MessageAttachmentPreviews';\nimport { ToolTimeline } from './ToolTimeline';\nimport { parseToolActivity } from './toolActivity';\nimport { parseAskUser, stripAskUser, displayAskUserAssistantText } from './askUser';\nimport { collapseDuplicateUserRows, groupConsecutiveRoleRows, type RoleGroup } from './transcriptGroups';\nimport { closeOpenMarkdownFences } from './streamingMarkdown';\n\nexport type TranscriptMessage = {\n id: string;\n role: string;\n content: string;\n attachments?: MessageAttachment[];\n};\n\ntype TranscriptRow = TranscriptMessage & { streaming?: boolean; askAnswered?: boolean };\ntype TranscriptGroup = RoleGroup<TranscriptRow>;\n\nconst USER_BUBBLE_BG = '#2563eb';\n\nexport function ChatTranscript({\n messages,\n streamingContent,\n renderMessageActions,\n listContentStyle,\n isDark = false,\n}: {\n messages: TranscriptMessage[];\n streamingContent?: string;\n renderMessageActions?: (message: { id: string; role: string; content: string }) => React.ReactNode;\n listContentStyle?: StyleProp<ViewStyle>;\n isDark?: boolean;\n}) {\n const listRef = useRef<FlatList<TranscriptGroup>>(null);\n const stickToBottomRef = useRef(true);\n const isProgrammaticScrollRef = useRef(false);\n const ignoreScrollUntilRef = useRef(0);\n const keyboardHeight = useKeyboardLiftHeight();\n\n const historyRows = useMemo<TranscriptRow[]>(() => {\n const rows: TranscriptRow[] = [];\n messages.forEach((msg, index) => {\n if (msg.role === 'user') {\n if (shouldRenderUserTranscriptTurn(msg.content, msg.attachments)) {\n rows.push({ ...msg, streaming: false });\n }\n return;\n }\n if (msg.role !== 'assistant') {\n rows.push({ ...msg, streaming: false });\n return;\n }\n const askAnswered =\n Boolean(parseAskUser(msg.content)) && messages.slice(index + 1).some((m) => m.role === 'user');\n const visible = displayAskUserAssistantText(msg.content, askAnswered).trim();\n const tools = parseToolActivity(stripAskUser(msg.content), false);\n const hasAsk = Boolean(parseAskUser(msg.content));\n if (hasAsk && !visible && tools.steps.length === 0 && !(msg.attachments?.length ?? 0)) {\n return;\n }\n if (!hasAsk) {\n const leftover = stripAskUser(msg.content).trim();\n if (!leftover && !(msg.attachments?.length ?? 0)) return;\n }\n rows.push({ ...msg, streaming: false, askAnswered });\n });\n return rows;\n }, [messages]);\n\n const rows = useMemo<TranscriptRow[]>(() => {\n const history = collapseDuplicateUserRows(historyRows);\n const rawStream = streamingContent ?? '';\n const last = history[history.length - 1];\n const streamAskAnswered = last?.role === 'user' && Boolean(parseAskUser(rawStream));\n const streamProse = displayAskUserAssistantText(rawStream, streamAskAnswered).trim();\n const streamTools = parseToolActivity(stripAskUser(rawStream), true);\n if (!streamProse && streamTools.steps.length === 0) return history;\n return [\n ...history,\n {\n id: '__streaming__',\n role: 'assistant',\n content: rawStream,\n streaming: true,\n askAnswered: streamAskAnswered,\n },\n ];\n }, [historyRows, streamingContent]);\n\n const groups = useMemo(() => groupConsecutiveRoleRows(rows), [rows]);\n\n const scrollToLatest = useCallback(\n (animated: boolean) => {\n if (groups.length === 0) return;\n isProgrammaticScrollRef.current = true;\n stickToBottomRef.current = true;\n const list = listRef.current;\n if (!list) return;\n list.scrollToEnd({ animated });\n // Tall bubbles: scrollToEnd can stop at the start of the last cell.\n list.scrollToOffset({ offset: Number.MAX_SAFE_INTEGER, animated });\n },\n [groups.length],\n );\n\n useEffect(() => {\n if (groups.length === 0 || !stickToBottomRef.current) return undefined;\n const t = setTimeout(() => scrollToLatest(false), 0);\n return () => clearTimeout(t);\n }, [groups.length, streamingContent?.length, scrollToLatest]);\n\n // Spacer and list height update on the same keyboard frame. Scroll only\n // after that shrink, or we stay on the top of a long turn (image 1).\n useEffect(() => {\n if (keyboardHeight <= 0) return undefined;\n stickToBottomRef.current = true;\n ignoreScrollUntilRef.current = Date.now() + 400;\n const frame = requestAnimationFrame(() => scrollToLatest(false));\n const afterLayout = setTimeout(() => scrollToLatest(false), 64);\n const afterKeyboard = setTimeout(() => scrollToLatest(false), 280);\n return () => {\n cancelAnimationFrame(frame);\n clearTimeout(afterLayout);\n clearTimeout(afterKeyboard);\n };\n }, [keyboardHeight, scrollToLatest]);\n\n const handleScroll = useCallback(\n (e: {\n nativeEvent: {\n contentOffset: { y: number };\n contentSize: { height: number };\n layoutMeasurement: { height: number };\n };\n }) => {\n if (Date.now() < ignoreScrollUntilRef.current) {\n stickToBottomRef.current = true;\n return;\n }\n const { contentOffset, contentSize, layoutMeasurement } = e.nativeEvent;\n const nearLatest = contentOffset.y + layoutMeasurement.height >= contentSize.height - 80;\n if (!isProgrammaticScrollRef.current) {\n stickToBottomRef.current = nearLatest;\n } else if (nearLatest) {\n isProgrammaticScrollRef.current = false;\n }\n },\n [],\n );\n\n const handleContentSizeChange = useCallback(() => {\n if (!stickToBottomRef.current) return;\n scrollToLatest(false);\n }, [scrollToLatest]);\n\n const renderItem = useCallback(\n ({ item }: { item: TranscriptGroup }) => (\n <TranscriptGroupView group={item} isDark={isDark} renderMessageActions={renderMessageActions} />\n ),\n [isDark, renderMessageActions],\n );\n\n return (\n <View style={styles.list}>\n <FlatList\n ref={listRef}\n data={groups}\n keyExtractor={(item) => item.id}\n renderItem={renderItem}\n extraData={streamingContent}\n initialNumToRender={12}\n maxToRenderPerBatch={8}\n updateCellsBatchingPeriod={50}\n windowSize={7}\n onScroll={handleScroll}\n onContentSizeChange={handleContentSizeChange}\n onLayout={() => {\n if (stickToBottomRef.current) scrollToLatest(false);\n }}\n scrollEventThrottle={16}\n keyboardShouldPersistTaps=\"handled\"\n keyboardDismissMode={Platform.OS === 'ios' ? 'interactive' : 'on-drag'}\n automaticallyAdjustKeyboardInsets={false}\n automaticallyAdjustContentInsets={false}\n contentInsetAdjustmentBehavior=\"never\"\n contentContainerStyle={[styles.listContent, listContentStyle, styles.listContentFill]}\n style={styles.list}\n />\n </View>\n );\n}\n\nconst TranscriptGroupView = memo(function TranscriptGroupView({\n group,\n isDark,\n renderMessageActions,\n}: {\n group: TranscriptGroup;\n isDark: boolean;\n renderMessageActions?: (message: { id: string; role: string; content: string }) => React.ReactNode;\n}) {\n if (group.role === 'user') {\n return (\n <Pressable style={styles.userCol} onPress={dismissKeyboard} accessible={false}>\n {group.items.map((item, index) => {\n const attachments = item.attachments ?? [];\n const text = displayUserMessageText(item.content, attachments);\n if (!text && attachments.length === 0) return null;\n return (\n <View key={item.id} style={[styles.userTurn, index > 0 && styles.userFollow]}>\n {attachments.length > 0 ? (\n <MessageAttachmentPreviews attachments={attachments} align=\"end\" isDark={isDark} />\n ) : null}\n {text ? (\n <View style={styles.userBubble}>\n <Markdown style={USER_MARKDOWN}>{text}</Markdown>\n </View>\n ) : null}\n </View>\n );\n })}\n </Pressable>\n );\n }\n\n const markdownColor = isDark ? '#e2e8f0' : '#111827';\n const codeBg = isDark ? '#1e293b' : '#f3f4f6';\n const last = group.items[group.items.length - 1];\n\n return (\n <View style={styles.assistantGroup}>\n {group.items.map((item, index) => (\n <AssistantTurnView\n key={item.id}\n item={item}\n isDark={isDark}\n markdownColor={markdownColor}\n codeBg={codeBg}\n tightTop={index > 0}\n renderMessageActions={item.streaming || item !== last ? undefined : renderMessageActions}\n />\n ))}\n </View>\n );\n});\n\nconst AssistantTurnView = memo(function AssistantTurnView({\n item,\n isDark,\n markdownColor,\n codeBg,\n tightTop,\n renderMessageActions,\n}: {\n item: TranscriptRow;\n isDark: boolean;\n markdownColor: string;\n codeBg: string;\n tightTop: boolean;\n renderMessageActions?: (message: { id: string; role: string; content: string }) => React.ReactNode;\n}) {\n const attachments = item.attachments ?? [];\n const stripped = stripAskUser(item.content);\n const toolActivity = parseToolActivity(stripped, !!item.streaming);\n const text = parseToolActivity(\n displayAskUserAssistantText(item.content, !!item.askAnswered),\n !!item.streaming,\n ).text;\n\n return (\n <Pressable\n style={[styles.assistantCol, tightTop && styles.assistantColTight]}\n onPress={dismissKeyboard}\n accessible={false}\n >\n {attachments.length > 0 ? (\n <MessageAttachmentPreviews attachments={attachments} align=\"start\" isDark={isDark} />\n ) : null}\n {toolActivity.steps.length > 0 ? (\n <ToolTimeline steps={toolActivity.steps} active={!!item.streaming} isDark={isDark} />\n ) : null}\n {text ? (\n <Markdown style={assistantMarkdownStyle(markdownColor, codeBg)}>\n {item.streaming ? closeOpenMarkdownFences(text) : text}\n </Markdown>\n ) : null}\n {renderMessageActions\n ? renderMessageActions({ id: item.id, role: 'assistant', content: item.content })\n : null}\n </Pressable>\n );\n});\n\nconst USER_MARKDOWN = {\n body: { color: '#ffffff', fontSize: 15, lineHeight: 22 },\n paragraph: { marginTop: 4, marginBottom: 4, color: '#ffffff' },\n strong: { fontWeight: '700' as const, color: '#ffffff' },\n em: { color: '#ffffff' },\n text: { color: '#ffffff' },\n bullet_list: { marginVertical: 4 },\n ordered_list: { marginVertical: 4 },\n list_item: { marginVertical: 2, color: '#ffffff' },\n};\n\nfunction assistantMarkdownStyle(markdownColor: string, codeBg: string) {\n return {\n body: { color: markdownColor, fontSize: 15, lineHeight: 22 },\n heading1: {\n fontSize: 18,\n fontWeight: '700' as const,\n marginTop: 12,\n marginBottom: 4,\n color: markdownColor,\n },\n heading2: {\n fontSize: 16,\n fontWeight: '700' as const,\n marginTop: 10,\n marginBottom: 4,\n color: markdownColor,\n },\n heading3: {\n fontSize: 15,\n fontWeight: '600' as const,\n marginTop: 8,\n marginBottom: 4,\n color: markdownColor,\n },\n strong: { fontWeight: '700' as const },\n paragraph: { marginTop: 4, marginBottom: 4 },\n list_item: { marginVertical: 2 },\n bullet_list: { marginVertical: 4 },\n ordered_list: { marginVertical: 4 },\n code_inline: {\n backgroundColor: codeBg,\n paddingHorizontal: 4,\n borderRadius: 4,\n fontSize: 14,\n color: markdownColor,\n },\n code_block: {\n backgroundColor: codeBg,\n padding: 12,\n borderRadius: 8,\n marginVertical: 8,\n fontSize: 14,\n color: markdownColor,\n },\n fence: {\n backgroundColor: codeBg,\n padding: 12,\n borderRadius: 8,\n marginVertical: 8,\n fontSize: 14,\n color: markdownColor,\n },\n };\n}\n\nconst styles = StyleSheet.create({\n list: {\n flex: 1,\n },\n listContent: {\n paddingTop: 8,\n paddingBottom: 8,\n paddingHorizontal: 8,\n },\n listContentFill: {\n flexGrow: 1,\n justifyContent: 'flex-end',\n },\n userCol: {\n width: '100%',\n alignItems: 'flex-end',\n marginBottom: 12,\n paddingHorizontal: 4,\n },\n userTurn: {\n maxWidth: '92%',\n alignItems: 'flex-end',\n },\n userFollow: {\n marginTop: 4,\n },\n userBubble: {\n backgroundColor: USER_BUBBLE_BG,\n borderRadius: 16,\n paddingHorizontal: 12,\n paddingVertical: 8,\n },\n assistantGroup: {\n width: '100%',\n marginBottom: 4,\n },\n assistantCol: {\n width: '100%',\n alignItems: 'flex-start',\n marginBottom: 8,\n paddingHorizontal: 4,\n },\n assistantColTight: {\n marginTop: -4,\n },\n});\n"],"names":["rows","TranscriptGroupView","AssistantTurnView"],"mappings":"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"}
|