@adminide-stack/yantra-mobile 12.0.141-alpha.1 → 12.0.141
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/features/agent-chat/NativeAgentChat.js +21 -4
- package/lib/features/agent-chat/NativeAgentChat.js.map +1 -1
- package/lib/features/chat/ApprovalCard.js +353 -0
- package/lib/features/chat/ApprovalCard.js.map +1 -0
- package/lib/features/chat/AskUserCard.js +9 -2
- package/lib/features/chat/AskUserCard.js.map +1 -1
- package/lib/features/chat/askUser.js +25 -3
- package/lib/features/chat/askUser.js.map +1 -1
- package/lib/features/chat/queuedFollowUpRows.js +13 -0
- package/lib/features/chat/queuedFollowUpRows.js.map +1 -0
- package/lib/features/devices/bodyComposition.js +116 -0
- package/lib/features/devices/bodyComposition.js.map +1 -0
- package/lib/features/devices/readings.js.map +1 -1
- package/lib/features/devices/session.js +22 -2
- package/lib/features/devices/session.js.map +1 -1
- package/lib/features/discover/DiscoverArticle.js +105 -92
- package/lib/features/discover/DiscoverArticle.js.map +1 -1
- package/lib/features/discover/DiscoverFeed.js +97 -48
- package/lib/features/discover/DiscoverFeed.js.map +1 -1
- package/lib/features/discover/DiscoverFollowUp.js +135 -0
- package/lib/features/discover/DiscoverFollowUp.js.map +1 -0
- package/lib/features/discover/DiscoverSidebar.js +555 -0
- package/lib/features/discover/DiscoverSidebar.js.map +1 -0
- package/lib/features/discover/DiscoverSkeletons.js +123 -0
- package/lib/features/discover/DiscoverSkeletons.js.map +1 -0
- package/lib/features/discover/DiscoverStoryCards.js +193 -87
- package/lib/features/discover/DiscoverStoryCards.js.map +1 -1
- package/lib/features/discover/followUpQuery.js +42 -0
- package/lib/features/discover/followUpQuery.js.map +1 -0
- package/lib/features/discover/markets.js +37 -0
- package/lib/features/discover/markets.js.map +1 -0
- package/lib/features/discover/useDiscoverSidebar.js +148 -0
- package/lib/features/discover/useDiscoverSidebar.js.map +1 -0
- package/lib/features/discover/weather.js +42 -0
- package/lib/features/discover/weather.js.map +1 -0
- package/lib/features/expenses/ExpensesAgentChatPane.js +1 -1
- package/lib/features/expenses/ExpensesAgentChatPane.js.map +1 -1
- package/lib/features/inbox/InboxAgentChatPane.js +1 -1
- package/lib/features/inbox/InboxAgentChatPane.js.map +1 -1
- package/lib/features/job-search/JobSearchAgentChatPane.js +1 -0
- package/lib/features/job-search/JobSearchAgentChatPane.js.map +1 -1
- package/lib/features/local-services/LocalServicesAgentChatPane.js +1 -1
- package/lib/features/local-services/LocalServicesAgentChatPane.js.map +1 -1
- package/lib/features/movies/MoviesAgentChatPane.js +1 -1
- package/lib/features/movies/MoviesAgentChatPane.js.map +1 -1
- package/lib/features/notion/NotionBlockSheets.js +206 -0
- package/lib/features/notion/NotionBlockSheets.js.map +1 -0
- package/lib/features/notion/NotionBlockView.js +36 -0
- package/lib/features/notion/NotionBlockView.js.map +1 -0
- package/lib/features/notion/NotionCommentsSheet.js +461 -0
- package/lib/features/notion/NotionCommentsSheet.js.map +1 -0
- package/lib/features/notion/NotionConnectionsSheet.js +244 -0
- package/lib/features/notion/NotionConnectionsSheet.js.map +1 -0
- package/lib/features/notion/NotionHistorySheet.js +439 -0
- package/lib/features/notion/NotionHistorySheet.js.map +1 -0
- package/lib/features/notion/NotionMediaBlocks.js +803 -0
- package/lib/features/notion/NotionMediaBlocks.js.map +1 -0
- package/lib/features/notion/NotionMentionSheet.js +279 -0
- package/lib/features/notion/NotionMentionSheet.js.map +1 -0
- package/lib/features/notion/NotionPageMenu.js +585 -0
- package/lib/features/notion/NotionPageMenu.js.map +1 -0
- package/lib/features/notion/NotionPageTree.js +220 -0
- package/lib/features/notion/NotionPageTree.js.map +1 -0
- package/lib/features/notion/NotionPageView.js +1253 -152
- package/lib/features/notion/NotionPageView.js.map +1 -1
- package/lib/features/notion/NotionShareSheet.js +606 -0
- package/lib/features/notion/NotionShareSheet.js.map +1 -0
- package/lib/features/notion/NotionSheets.js +87 -15
- package/lib/features/notion/NotionSheets.js.map +1 -1
- package/lib/features/notion/NotionSidebarSections.js +492 -0
- package/lib/features/notion/NotionSidebarSections.js.map +1 -0
- package/lib/features/notion/NotionWorkspaceAdmin.js +659 -0
- package/lib/features/notion/NotionWorkspaceAdmin.js.map +1 -0
- package/lib/features/notion/NotionWorkspaceView.js +257 -45
- package/lib/features/notion/NotionWorkspaceView.js.map +1 -1
- package/lib/features/notion/database/DatabaseCells.js +554 -0
- package/lib/features/notion/database/DatabaseCells.js.map +1 -0
- package/lib/features/notion/database/DatabaseDateLayouts.js +792 -0
- package/lib/features/notion/database/DatabaseDateLayouts.js.map +1 -0
- package/lib/features/notion/database/DatabaseLayouts.js +461 -0
- package/lib/features/notion/database/DatabaseLayouts.js.map +1 -0
- package/lib/features/notion/database/DatabaseSheets.js +791 -0
- package/lib/features/notion/database/DatabaseSheets.js.map +1 -0
- package/lib/features/notion/database/NotionDatabaseView.js +817 -0
- package/lib/features/notion/database/NotionDatabaseView.js.map +1 -0
- package/lib/features/notion/database/RowPropertiesPanel.js +162 -0
- package/lib/features/notion/database/RowPropertiesPanel.js.map +1 -0
- package/lib/features/notion/database/chartData.js +89 -0
- package/lib/features/notion/database/chartData.js.map +1 -0
- package/lib/features/notion/database/chartView.js +112 -0
- package/lib/features/notion/database/chartView.js.map +1 -0
- package/lib/features/notion/database/connectorButton.js +33 -0
- package/lib/features/notion/database/connectorButton.js.map +1 -0
- package/lib/features/notion/database/databaseCalc.js +208 -0
- package/lib/features/notion/database/databaseCalc.js.map +1 -0
- package/lib/features/notion/database/databaseCalendar.js +157 -0
- package/lib/features/notion/database/databaseCalendar.js.map +1 -0
- package/lib/features/notion/database/databaseCsv.js +98 -0
- package/lib/features/notion/database/databaseCsv.js.map +1 -0
- package/lib/features/notion/database/databaseCsvActions.js +58 -0
- package/lib/features/notion/database/databaseCsvActions.js.map +1 -0
- package/lib/features/notion/database/databaseFilter.js +473 -0
- package/lib/features/notion/database/databaseFilter.js.map +1 -0
- package/lib/features/notion/database/databaseFormula.js +1072 -0
- package/lib/features/notion/database/databaseFormula.js.map +1 -0
- package/lib/features/notion/database/databaseGroup.js +151 -0
- package/lib/features/notion/database/databaseGroup.js.map +1 -0
- package/lib/features/notion/database/databaseRollup.js +58 -0
- package/lib/features/notion/database/databaseRollup.js.map +1 -0
- package/lib/features/notion/database/databaseTimeline.js +156 -0
- package/lib/features/notion/database/databaseTimeline.js.map +1 -0
- package/lib/features/notion/database/databaseView.js +1188 -0
- package/lib/features/notion/database/databaseView.js.map +1 -0
- package/lib/features/notion/database/databaseViews.js +310 -0
- package/lib/features/notion/database/databaseViews.js.map +1 -0
- package/lib/features/notion/database/relationSource.js +92 -0
- package/lib/features/notion/database/relationSource.js.map +1 -0
- package/lib/features/notion/database/uniqueId.js +17 -0
- package/lib/features/notion/database/uniqueId.js.map +1 -0
- package/lib/features/notion/database/useNotionDatabase.js +617 -0
- package/lib/features/notion/database/useNotionDatabase.js.map +1 -0
- package/lib/features/notion/notionAgentRunStatus.js +39 -0
- package/lib/features/notion/notionAgentRunStatus.js.map +1 -0
- package/lib/features/notion/notionCodeLanguages.js +112 -0
- package/lib/features/notion/notionCodeLanguages.js.map +1 -0
- package/lib/features/notion/notionComments.js +86 -0
- package/lib/features/notion/notionComments.js.map +1 -0
- package/lib/features/notion/notionConnections.js +74 -0
- package/lib/features/notion/notionConnections.js.map +1 -0
- package/lib/features/notion/notionDocuments.js +453 -1
- package/lib/features/notion/notionDocuments.js.map +1 -1
- package/lib/features/notion/notionEditorModel.js +142 -7
- package/lib/features/notion/notionEditorModel.js.map +1 -1
- package/lib/features/notion/notionMarkdownShortcuts.js +51 -0
- package/lib/features/notion/notionMarkdownShortcuts.js.map +1 -0
- package/lib/features/notion/notionMedia.js +119 -0
- package/lib/features/notion/notionMedia.js.map +1 -0
- package/lib/features/notion/notionMentionDate.js +32 -0
- package/lib/features/notion/notionMentionDate.js.map +1 -0
- package/lib/features/notion/notionMentionOptions.js +162 -0
- package/lib/features/notion/notionMentionOptions.js.map +1 -0
- package/lib/features/notion/notionNotesAgent.js +445 -0
- package/lib/features/notion/notionNotesAgent.js.map +1 -0
- package/lib/features/notion/notionPageAccess.js +168 -0
- package/lib/features/notion/notionPageAccess.js.map +1 -0
- package/lib/features/notion/notionPageActions.js +138 -0
- package/lib/features/notion/notionPageActions.js.map +1 -0
- package/lib/features/notion/notionPageHistory.js +154 -0
- package/lib/features/notion/notionPageHistory.js.map +1 -0
- package/lib/features/notion/notionPageKinds.js +200 -0
- package/lib/features/notion/notionPageKinds.js.map +1 -0
- package/lib/features/notion/notionRecents.js +48 -0
- package/lib/features/notion/notionRecents.js.map +1 -0
- package/lib/features/notion/notionRichText.js +177 -0
- package/lib/features/notion/notionRichText.js.map +1 -0
- package/lib/features/notion/notionRichTitle.js +336 -0
- package/lib/features/notion/notionRichTitle.js.map +1 -0
- package/lib/features/notion/useNotionWorkspace.js +272 -13
- package/lib/features/notion/useNotionWorkspace.js.map +1 -1
- package/lib/features/notion/usePageActions.js +155 -0
- package/lib/features/notion/usePageActions.js.map +1 -0
- package/lib/features/resume/ResumeAgentChatPane.js +1 -1
- package/lib/features/resume/ResumeAgentChatPane.js.map +1 -1
- package/lib/features/shopping/ShoppingAgentChatPane.js +1 -1
- package/lib/features/shopping/ShoppingAgentChatPane.js.map +1 -1
- package/lib/features/study/StudyAgentChatPane.js +1 -1
- package/lib/features/study/StudyAgentChatPane.js.map +1 -1
- package/lib/features/travel/TravelAgentChatPane.js +1 -1
- package/lib/features/travel/TravelAgentChatPane.js.map +1 -1
- package/lib/features/webbuilder/WebBuilderExperience.js +40 -8
- package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -1
- package/lib/features/webbuilder/buildFragments.js +1 -1
- package/lib/features/webbuilder/buildFragments.js.map +1 -1
- package/lib/features/webbuilder/codeFiles.js +302 -0
- package/lib/features/webbuilder/codeFiles.js.map +1 -0
- package/lib/features/webbuilder/codeHighlight.js +209 -0
- package/lib/features/webbuilder/codeHighlight.js.map +1 -0
- package/lib/features/webbuilder/components/CodeView.js +682 -52
- package/lib/features/webbuilder/components/CodeView.js.map +1 -1
- package/lib/features/webbuilder/components/PreviewScreen.js +59 -38
- package/lib/features/webbuilder/components/PreviewScreen.js.map +1 -1
- package/lib/features/webbuilder/components/ProjectChat.js +3 -3
- package/lib/features/webbuilder/components/ProjectChat.js.map +1 -1
- package/lib/features/webbuilder/stepLabels.js +68 -0
- package/lib/features/webbuilder/stepLabels.js.map +1 -0
- package/lib/hooks/useHostChatSteering.js +45 -0
- package/lib/hooks/useHostChatSteering.js.map +1 -0
- package/lib/screens/Chat/index.js +2 -12
- package/lib/screens/Chat/index.js.map +1 -1
- package/lib/screens/Devices/index.js +205 -3
- package/lib/screens/Devices/index.js.map +1 -1
- package/lib/screens/ExpensesNative/useExpensesHostChat.js +25 -5
- package/lib/screens/ExpensesNative/useExpensesHostChat.js.map +1 -1
- package/lib/screens/InboxNative/useInboxHostChat.js +25 -5
- package/lib/screens/InboxNative/useInboxHostChat.js.map +1 -1
- package/lib/screens/JobSearchNative/useJobSearchHostChat.js +25 -5
- package/lib/screens/JobSearchNative/useJobSearchHostChat.js.map +1 -1
- package/lib/screens/LocalServicesNative/useLocalServicesHostChat.js +25 -5
- package/lib/screens/LocalServicesNative/useLocalServicesHostChat.js.map +1 -1
- package/lib/screens/MoviesNative/useMoviesHostChat.js +25 -5
- package/lib/screens/MoviesNative/useMoviesHostChat.js.map +1 -1
- package/lib/screens/NotionPage/index.js +2 -2
- package/lib/screens/NotionPage/index.js.map +1 -1
- package/lib/screens/ResumeNative/useResumeHostChat.js +25 -5
- package/lib/screens/ResumeNative/useResumeHostChat.js.map +1 -1
- package/lib/screens/ShoppingNative/useShoppingHostChat.js +25 -5
- package/lib/screens/ShoppingNative/useShoppingHostChat.js.map +1 -1
- package/lib/screens/StudyNative/useStudyHostChat.js +25 -5
- package/lib/screens/StudyNative/useStudyHostChat.js.map +1 -1
- package/lib/screens/TravelNative/useTravelHostChat.js +25 -5
- package/lib/screens/TravelNative/useTravelHostChat.js.map +1 -1
- package/lib/screens/WebBuilderNative/codeWorkspaceApi.js +222 -0
- package/lib/screens/WebBuilderNative/codeWorkspaceApi.js.map +1 -0
- package/lib/screens/WebBuilderNative/index.js +1 -1
- package/lib/screens/WebBuilderNative/index.js.map +1 -1
- package/lib/screens/WebBuilderNative/sandboxProxyApi.js +126 -4
- package/lib/screens/WebBuilderNative/sandboxProxyApi.js.map +1 -1
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js +120 -11
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApprovalCard.js","sources":["../../../src/features/chat/ApprovalCard.tsx"],"sourcesContent":["/**\n * <ApprovalCard> — the agent's action gate asking permission, as a touch card.\n *\n * Phone twin of the web ApprovalPromptCard: what the action will do and its\n * consequence, Allow once as the main action, Allow for this chat, the Always\n * allow choices, Don't allow, and a line to say what to change instead. Every\n * choice answers with the option's own label — the reply the gate parked on —\n * so this card and the plain question card are interchangeable. No dismiss:\n * closing it would leave the agent waiting, so \"Don't allow\" is the way to say no.\n */\nimport React, { memo, useMemo, useState } from 'react';\nimport { Image, Pressable, StyleSheet, Text, TextInput, View } from 'react-native';\nimport {\n formatAskUserAnswers,\n type ApprovalCategory,\n type ApprovalDetails,\n type ApprovalMedia,\n type AskUserOption,\n type AskUserQuestion,\n} from './askUser';\n\ntype Tone = 'neutral' | 'blue' | 'amber' | 'red';\n\nconst CATEGORY: Record<ApprovalCategory, { label: string; glyph: string; tone: Tone }> = {\n send: { label: 'Sends as you', glyph: '➤', tone: 'blue' },\n spend: { label: 'Spends money', glyph: '$', tone: 'amber' },\n book: { label: 'Books for you', glyph: '✓', tone: 'blue' },\n contact: { label: 'Reaches someone', glyph: '✆', tone: 'blue' },\n share: { label: 'Shares outside', glyph: '↗', tone: 'blue' },\n delete: { label: 'Cannot be undone', glyph: '✕', tone: 'red' },\n change: { label: 'Makes a change', glyph: '✎', tone: 'neutral' },\n};\n\nconst TONE_COLOR: Record<Tone, { light: string; dark: string }> = {\n neutral: { light: '#6b7280', dark: '#94a3b8' },\n blue: { light: '#2563eb', dark: '#60a5fa' },\n amber: { light: '#b45309', dark: '#fbbf24' },\n red: { light: '#dc2626', dark: '#f87171' },\n};\n\nconst ACCENT = '#2563eb';\n\nfunction optionRole(label: string): 'once' | 'chat' | 'always' | 'deny' | 'other' {\n const l = label.trim().toLowerCase();\n if (l === 'allow once') return 'once';\n if (l === 'allow for this chat') return 'chat';\n if (l.startsWith('always allow')) return 'always';\n if (l === \"don't allow\" || l === 'do not allow' || l === 'deny') return 'deny';\n return 'other';\n}\n\n/** The gate writes the question as `<what>? <Summary>`; show the two apart. */\nexport function splitTitle(title: string, summary?: string): { heading: string; summary: string } {\n const s = summary?.trim() ?? '';\n if (!s) return { heading: title, summary: '' };\n const capitalised = s.charAt(0).toUpperCase() + s.slice(1);\n for (const tail of [capitalised, s]) {\n if (title.endsWith(tail)) {\n const head = title.slice(0, title.length - tail.length).trim();\n if (head) return { heading: head, summary: capitalised };\n }\n }\n return { heading: title, summary: title.includes(s) ? '' : capitalised };\n}\n\nfunction MediaPreview({ media }: { media: ApprovalMedia[] }) {\n const [failed, setFailed] = useState<Record<string, true>>({});\n // Video has no inline player here; its poster is the link, so only photos preview.\n const shown = media.filter((m) => m.kind === 'image' && !failed[m.url]).slice(0, 4);\n if (shown.length === 0) return null;\n const single = shown.length === 1;\n return (\n <View style={styles.mediaRow}>\n {shown.map((m) => (\n <Image\n key={m.url}\n source={{ uri: m.url }}\n accessibilityLabel=\"Photo to post\"\n onError={() => setFailed((f) => ({ ...f, [m.url]: true }))}\n style={single ? styles.mediaSingle : styles.mediaTile}\n />\n ))}\n </View>\n );\n}\n\nexport const ApprovalCard = memo(function ApprovalCard({\n question,\n isDark = false,\n disabled = false,\n onAnswer,\n}: {\n question: AskUserQuestion & { approval: ApprovalDetails };\n isDark?: boolean;\n disabled?: boolean;\n onAnswer: (formatted: string) => void;\n}) {\n const [draft, setDraft] = useState('');\n const { approval } = question;\n const category = CATEGORY[approval.category] ?? CATEGORY.change;\n const toneColor = TONE_COLOR[category.tone][isDark ? 'dark' : 'light'];\n const categoryLabel =\n approval.category === 'share' && approval.media && approval.media.length > 0\n ? 'Posts publicly'\n : category.label;\n const { heading, summary } = useMemo(\n () => splitTitle(question.title, approval.summary),\n [question.title, approval.summary],\n );\n const groups = useMemo(() => {\n const out = { primary: [] as AskUserOption[], always: [] as AskUserOption[], deny: [] as AskUserOption[] };\n for (const o of question.options ?? []) {\n const role = optionRole(o.label);\n if (role === 'always') out.always.push(o);\n else if (role === 'deny') out.deny.push(o);\n else out.primary.push(o);\n }\n return out;\n }, [question.options]);\n\n const palette = {\n card: isDark ? '#111827' : '#ffffff',\n border: isDark ? '#1f2937' : '#e5e7eb',\n title: isDark ? '#f1f5f9' : '#111827',\n muted: isDark ? '#94a3b8' : '#6b7280',\n field: isDark ? '#0b1220' : '#f9fafb',\n };\n\n const answer = (value: string) => {\n const text = value.trim();\n if (!text || disabled) return;\n onAnswer(formatAskUserAnswers([question], { [question.id]: text }));\n };\n\n return (\n <View\n accessibilityRole=\"summary\"\n accessibilityLabel={`Approval: ${heading}`}\n style={[styles.card, { backgroundColor: palette.card, borderColor: palette.border }]}\n >\n <View style={styles.head}>\n <View style={[styles.tile, { backgroundColor: `${toneColor}1f` }]}>\n <Text style={[styles.glyph, { color: toneColor }]}>{category.glyph}</Text>\n </View>\n <View style={styles.headBody}>\n <Text style={[styles.eyebrow, { color: toneColor }]}>{categoryLabel.toUpperCase()}</Text>\n <Text style={[styles.title, { color: palette.title }]}>{heading}</Text>\n {summary ? <Text style={[styles.summary, { color: palette.muted }]}>{summary}</Text> : null}\n {approval.media && approval.media.length > 0 ? <MediaPreview media={approval.media} /> : null}\n </View>\n </View>\n\n <View style={styles.actions}>\n {groups.primary.map((o) => {\n const primary = optionRole(o.label) === 'once';\n return (\n <Pressable\n key={o.id}\n accessibilityRole=\"button\"\n accessibilityLabel={o.detail ? `${o.label}. ${o.detail}` : o.label}\n disabled={disabled}\n onPress={() => answer(o.label)}\n style={({ pressed }) => [\n styles.button,\n primary\n ? { backgroundColor: ACCENT }\n : { backgroundColor: palette.card, borderColor: palette.border, borderWidth: 1 },\n { opacity: disabled ? 0.5 : pressed ? 0.75 : 1 },\n ]}\n >\n <Text style={[styles.buttonText, { color: primary ? '#ffffff' : palette.title }]}>\n {o.label}\n </Text>\n </Pressable>\n );\n })}\n {groups.deny.map((o) => (\n <Pressable\n key={o.id}\n accessibilityRole=\"button\"\n disabled={disabled}\n onPress={() => answer(o.label)}\n style={({ pressed }) => [\n styles.button,\n {\n borderColor: palette.border,\n borderWidth: 1,\n opacity: disabled ? 0.5 : pressed ? 0.75 : 1,\n },\n ]}\n >\n <Text style={[styles.buttonText, { color: palette.muted, fontWeight: '500' }]}>{o.label}</Text>\n </Pressable>\n ))}\n </View>\n\n {groups.always.length > 0 ? (\n <View style={styles.always}>\n {groups.always.map((o) => (\n <Pressable\n key={o.id}\n accessibilityRole=\"button\"\n accessibilityLabel={o.detail ? `${o.label}. ${o.detail}` : o.label}\n disabled={disabled}\n onPress={() => answer(o.label)}\n style={styles.alwaysBtn}\n >\n <Text style={[styles.alwaysText, { color: palette.muted }]}>↻ {o.label}</Text>\n </Pressable>\n ))}\n </View>\n ) : null}\n\n {question.allowText !== false ? (\n <View style={[styles.say, { borderTopColor: palette.border }]}>\n <TextInput\n value={draft}\n onChangeText={setDraft}\n editable={!disabled}\n placeholder=\"Or say what to change\"\n placeholderTextColor={palette.muted}\n accessibilityLabel=\"Say what to change instead\"\n returnKeyType=\"send\"\n onSubmitEditing={() => answer(draft)}\n style={[styles.input, { color: palette.title, backgroundColor: palette.field }]}\n />\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel=\"Send\"\n disabled={disabled || !draft.trim()}\n onPress={() => answer(draft)}\n style={[styles.send, { backgroundColor: draft.trim() && !disabled ? ACCENT : palette.border }]}\n >\n <Text\n style={[styles.sendGlyph, { color: draft.trim() && !disabled ? '#ffffff' : palette.muted }]}\n >\n ↑\n </Text>\n </Pressable>\n </View>\n ) : null}\n </View>\n );\n});\n\nconst styles = StyleSheet.create({\n card: { width: '100%', borderWidth: 1, borderRadius: 16, padding: 14, marginTop: 4, marginBottom: 8 },\n head: { flexDirection: 'row', gap: 12 },\n tile: { width: 32, height: 32, borderRadius: 8, alignItems: 'center', justifyContent: 'center', marginTop: 2 },\n glyph: { fontSize: 15, fontWeight: '700' },\n headBody: { flex: 1 },\n eyebrow: { fontSize: 10.5, fontWeight: '600', letterSpacing: 1.2 },\n title: { fontSize: 15.5, fontWeight: '700', lineHeight: 21, marginTop: 2 },\n summary: { fontSize: 13, lineHeight: 18, marginTop: 4 },\n mediaRow: { flexDirection: 'row', flexWrap: 'wrap', gap: 6, marginTop: 10 },\n mediaSingle: { width: 240, height: 240, borderRadius: 12 },\n mediaTile: { width: 64, height: 64, borderRadius: 10 },\n actions: { marginTop: 14, gap: 8 },\n button: { minHeight: 44, borderRadius: 12, alignItems: 'center', justifyContent: 'center', paddingHorizontal: 14 },\n buttonText: { fontSize: 14, fontWeight: '700' },\n always: { marginTop: 6, flexDirection: 'row', flexWrap: 'wrap', columnGap: 16 },\n alwaysBtn: { minHeight: 44, justifyContent: 'center' },\n alwaysText: { fontSize: 12.5, fontWeight: '500' },\n say: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: 8,\n marginTop: 4,\n paddingTop: 10,\n borderTopWidth: StyleSheet.hairlineWidth,\n },\n input: { flex: 1, minHeight: 44, borderRadius: 12, paddingHorizontal: 12, fontSize: 14 },\n send: { width: 36, height: 36, borderRadius: 18, alignItems: 'center', justifyContent: 'center' },\n sendGlyph: { fontSize: 16, fontWeight: '700' },\n});\n"],"names":["ApprovalCard","_a"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {jsxs
|
|
1
|
+
import {jsx,jsxs}from'react/jsx-runtime';import {memo,useState,useRef,useMemo,useEffect}from'react';import {View,StyleSheet,Text,Pressable,TextInput}from'react-native';import {ApprovalCard}from'./ApprovalCard.js';import {isApprovalQuestion,formatAskUserAnswers}from'./askUser.js';var __defProp = Object.defineProperty;
|
|
2
2
|
var __defProps = Object.defineProperties;
|
|
3
3
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
@@ -31,7 +31,7 @@ var __objRest = (source, exclude) => {
|
|
|
31
31
|
return target;
|
|
32
32
|
};
|
|
33
33
|
const ACCENT = "#2563eb";
|
|
34
|
-
const
|
|
34
|
+
const QuestionCard = memo(function QuestionCard2({
|
|
35
35
|
payload,
|
|
36
36
|
isDark = false,
|
|
37
37
|
disabled = false,
|
|
@@ -224,6 +224,13 @@ const AskUserCard = memo(function AskUserCard2({
|
|
|
224
224
|
] })
|
|
225
225
|
] });
|
|
226
226
|
});
|
|
227
|
+
const AskUserCard = memo(function AskUserCard2(props) {
|
|
228
|
+
const only = props.payload.questions.length === 1 ? props.payload.questions[0] : void 0;
|
|
229
|
+
if (isApprovalQuestion(only)) {
|
|
230
|
+
return /* @__PURE__ */ jsx(ApprovalCard, { question: only, isDark: props.isDark, disabled: props.disabled, onAnswer: props.onAnswer });
|
|
231
|
+
}
|
|
232
|
+
return /* @__PURE__ */ jsx(QuestionCard, __spreadValues({}, props));
|
|
233
|
+
});
|
|
227
234
|
const styles = StyleSheet.create({
|
|
228
235
|
card: {
|
|
229
236
|
width: "100%",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AskUserCard.js","sources":["../../../src/features/chat/AskUserCard.tsx"],"sourcesContent":["/**\n * <AskUserCard> — the `[ASK_USER]` clarifying question, as a touch card.\n *\n * Phone twin of the web ResponsePromptCard: Question N of M, numbered options,\n * free-text row, Skip / Previous / Next / Send. Answers still travel as one\n * formatted `**Title:** answer` message so cdecli's parked turn is released.\n *\n * The reply goes out through the ordinary send path (onAnswer -> sendMessage),\n * which is what releases cdecli's parked turn.\n */\nimport React, { memo, useEffect, useMemo, useRef, useState } from 'react';\nimport { Pressable, StyleSheet, Text, TextInput, View } from 'react-native';\nimport { formatAskUserAnswers, type AskUserPayload } from './askUser';\n\nconst ACCENT = '#2563eb';\n\nexport const AskUserCard = memo(function AskUserCard({\n payload,\n isDark = false,\n disabled = false,\n onAnswer,\n onDismiss,\n}: {\n payload: AskUserPayload;\n isDark?: boolean;\n disabled?: boolean;\n onAnswer: (formatted: string) => void;\n onDismiss: () => void;\n}) {\n const questions = payload.questions;\n const [index, setIndex] = useState(0);\n const [answers, setAnswers] = useState<Record<string, string>>({});\n const [textDraft, setTextDraft] = useState('');\n const inputRef = useRef<TextInput>(null);\n\n const total = questions.length;\n const question = questions[Math.min(index, Math.max(total - 1, 0))];\n const isLast = index >= total - 1;\n const allowText = question?.allowText !== false;\n const multiSelect = question?.multiSelect === true;\n\n const palette = useMemo(\n () => ({\n card: isDark ? '#111827' : '#ffffff',\n border: isDark ? '#1f2937' : '#e5e7eb',\n title: isDark ? '#f1f5f9' : '#111827',\n muted: isDark ? '#94a3b8' : '#6b7280',\n optionBg: isDark ? '#0b1220' : '#f9fafb',\n optionBorder: isDark ? '#243045' : '#e5e7eb',\n chip: isDark ? '#1e293b' : '#f3f4f6',\n chipOn: ACCENT,\n }),\n [isDark],\n );\n\n const selectedLabels = useMemo(() => {\n const raw = answers[question?.id ?? ''] ?? '';\n if (!raw.trim()) return [] as string[];\n if (!multiSelect) return [raw];\n return raw\n .split(',')\n .map((v) => v.trim())\n .filter(Boolean);\n }, [answers, question, multiSelect]);\n\n const lastQuestionIdRef = useRef<string | null>(null);\n useEffect(() => {\n const q = questions[index];\n if (!q || lastQuestionIdRef.current === q.id) return;\n lastQuestionIdRef.current = q.id;\n const existing = answers[q.id] ?? '';\n const parts = q.multiSelect ? existing.split(',').map((v) => v.trim()) : [existing];\n const isOptionAnswer = existing !== '' && parts.every((part) => q.options?.some((o) => o.label === part));\n setTextDraft(isOptionAnswer ? '' : existing);\n // answers omitted: re-running on every keystroke would clobber the draft.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [index, questions]);\n\n const record = (value: string, advance: boolean) => {\n if (!question) return;\n setAnswers((prev) => ({ ...prev, [question.id]: value }));\n if (!advance) return;\n if (isLast) {\n const formatted = formatAskUserAnswers(questions, { ...answers, [question.id]: value });\n if (formatted) onAnswer(formatted);\n else onDismiss();\n } else {\n setIndex((i) => i + 1);\n }\n };\n\n const chooseOption = (option: { label: string; other?: boolean }) => {\n if (!question || disabled) return;\n if (option.other) {\n inputRef.current?.focus();\n return;\n }\n if (multiSelect) {\n const next = selectedLabels.includes(option.label)\n ? selectedLabels.filter((l) => l !== option.label)\n : [...selectedLabels, option.label];\n record(next.join(', '), false);\n return;\n }\n record(option.label, true);\n };\n\n const currentAnswer = textDraft.trim() || answers[question?.id ?? ''] || '';\n\n const next = () => {\n if (disabled || !currentAnswer) return;\n record(currentAnswer, true);\n };\n\n const skip = () => {\n if (disabled || !question) return;\n setAnswers((prev) => {\n const { [question.id]: _dropped, ...rest } = prev;\n return rest;\n });\n if (isLast) {\n const { [question.id]: _dropped, ...rest } = answers;\n const formatted = formatAskUserAnswers(questions, rest);\n if (formatted) onAnswer(formatted);\n else onDismiss();\n } else {\n setIndex((i) => i + 1);\n }\n };\n\n if (!question) return null;\n\n return (\n <View style={[styles.card, { backgroundColor: palette.card, borderColor: palette.border }]}>\n <View style={styles.header}>\n <Text style={[styles.kicker, { color: palette.muted }]}>\n Question {index + 1} of {total}\n </Text>\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel=\"Dismiss\"\n hitSlop={10}\n onPress={onDismiss}\n disabled={disabled}\n style={styles.dismiss}\n >\n <Text style={[styles.dismissMark, { color: palette.muted }]}>×</Text>\n </Pressable>\n </View>\n\n {question.header ? (\n <Text style={[styles.eyebrow, { color: palette.muted }]}>{question.header.toUpperCase()}</Text>\n ) : null}\n <Text style={[styles.title, { color: palette.title }]}>{question.title}</Text>\n {multiSelect ? <Text style={[styles.hint, { color: palette.muted }]}>Pick as many as apply.</Text> : null}\n\n {(question.options ?? []).map((o, i) => {\n const active = selectedLabels.includes(o.label);\n return (\n <Pressable\n key={o.id}\n accessibilityRole=\"button\"\n accessibilityState={{ selected: active, disabled }}\n accessibilityLabel={o.detail ? `${o.label}. ${o.detail}` : o.label}\n disabled={disabled}\n onPress={() => chooseOption(o)}\n style={({ pressed }) => [\n styles.option,\n {\n backgroundColor: active ? `${ACCENT}14` : palette.optionBg,\n borderColor: active ? ACCENT : palette.optionBorder,\n opacity: pressed && !disabled ? 0.75 : 1,\n },\n ]}\n >\n <View style={[styles.indexChip, { backgroundColor: active ? ACCENT : palette.chip }]}>\n <Text style={[styles.indexChipText, { color: active ? '#ffffff' : palette.muted }]}>\n {active && multiSelect ? '✓' : String(i + 1)}\n </Text>\n </View>\n <View style={styles.optionBody}>\n <Text style={[styles.optionLabel, { color: palette.title }]}>{o.label}</Text>\n {o.detail ? (\n <Text style={[styles.optionDetail, { color: palette.muted }]}>{o.detail}</Text>\n ) : null}\n </View>\n </Pressable>\n );\n })}\n\n {allowText ? (\n <TextInput\n ref={inputRef}\n value={textDraft}\n onChangeText={setTextDraft}\n editable={!disabled}\n placeholder={question.textPlaceholder ?? 'Type your answer'}\n placeholderTextColor={palette.muted}\n returnKeyType={isLast ? 'send' : 'next'}\n onSubmitEditing={next}\n style={[\n styles.input,\n {\n backgroundColor: palette.optionBg,\n borderColor: palette.optionBorder,\n color: palette.title,\n },\n ]}\n />\n ) : null}\n\n <View style={styles.actions}>\n {index > 0 ? (\n <Pressable\n accessibilityRole=\"button\"\n onPress={() => {\n if (question && textDraft.trim()) record(textDraft.trim(), false);\n setIndex((i) => i - 1);\n }}\n disabled={disabled}\n style={styles.skip}\n >\n <Text style={[styles.skipText, { color: palette.muted }]}>Previous</Text>\n </Pressable>\n ) : (\n <View />\n )}\n <View style={styles.dots} pointerEvents=\"none\">\n {total > 1\n ? questions.map((q, i) => (\n <View\n key={q.id}\n style={[\n styles.dot,\n i === index ? styles.dotOn : { backgroundColor: palette.optionBorder },\n ]}\n />\n ))\n : null}\n </View>\n <View style={styles.actionRight}>\n <Pressable accessibilityRole=\"button\" onPress={skip} disabled={disabled} style={styles.skip}>\n <Text style={[styles.skipText, { color: palette.muted }]}>Skip</Text>\n </Pressable>\n <Pressable\n accessibilityRole=\"button\"\n accessibilityState={{ disabled: disabled || !currentAnswer }}\n onPress={next}\n disabled={disabled || !currentAnswer}\n style={[\n styles.send,\n { backgroundColor: currentAnswer && !disabled ? ACCENT : palette.optionBorder },\n ]}\n >\n <Text\n style={[styles.sendText, { color: currentAnswer && !disabled ? '#ffffff' : palette.muted }]}\n >\n {isLast ? 'Send' : 'Next'}\n </Text>\n </Pressable>\n </View>\n </View>\n </View>\n );\n});\n\nconst styles = StyleSheet.create({\n card: {\n width: '100%',\n borderWidth: 1,\n borderRadius: 16,\n padding: 14,\n marginTop: 4,\n marginBottom: 8,\n },\n header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' },\n kicker: { fontSize: 10.5, fontWeight: '600', letterSpacing: 1.2, textTransform: 'uppercase' },\n dismiss: { padding: 4, minWidth: 32, minHeight: 32, alignItems: 'center', justifyContent: 'center' },\n dismissMark: { fontSize: 22, lineHeight: 24, fontWeight: '400' },\n eyebrow: { fontSize: 11, fontWeight: '600', letterSpacing: 1, marginTop: 6 },\n title: { fontSize: 15.5, fontWeight: '700', lineHeight: 21, marginTop: 4, marginBottom: 4 },\n hint: { fontSize: 12, marginBottom: 6 },\n option: {\n flexDirection: 'row',\n alignItems: 'center',\n borderWidth: 1,\n borderRadius: 12,\n paddingHorizontal: 10,\n paddingVertical: 10,\n marginTop: 6,\n minHeight: 44,\n gap: 10,\n },\n indexChip: {\n width: 24,\n height: 24,\n borderRadius: 6,\n alignItems: 'center',\n justifyContent: 'center',\n },\n indexChipText: { fontSize: 11, fontWeight: '700' },\n optionBody: { flex: 1 },\n optionLabel: { fontSize: 13.5, fontWeight: '600' },\n optionDetail: { fontSize: 12, marginTop: 2, lineHeight: 16 },\n input: {\n borderWidth: 1,\n borderRadius: 12,\n paddingHorizontal: 12,\n paddingVertical: 10,\n marginTop: 10,\n fontSize: 14,\n minHeight: 44,\n },\n actions: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginTop: 8,\n gap: 8,\n },\n dots: { flexDirection: 'row', alignItems: 'center', gap: 5, flex: 1, justifyContent: 'center' },\n dot: { width: 6, height: 6, borderRadius: 3 },\n dotOn: { width: 16, backgroundColor: ACCENT },\n actionRight: { flexDirection: 'row', alignItems: 'center' },\n skip: { paddingHorizontal: 12, paddingVertical: 10, minHeight: 44, justifyContent: 'center' },\n skipText: { fontSize: 13, fontWeight: '600' },\n send: {\n paddingHorizontal: 16,\n paddingVertical: 10,\n borderRadius: 12,\n minHeight: 44,\n justifyContent: 'center',\n },\n sendText: { fontSize: 14, fontWeight: '700' },\n});\n"],"names":["AskUserCard","_a","_b","next"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AskUserCard.js","sources":["../../../src/features/chat/AskUserCard.tsx"],"sourcesContent":["/**\n * <AskUserCard> — the `[ASK_USER]` clarifying question, as a touch card.\n *\n * Phone twin of the web ResponsePromptCard: Question N of M, numbered options,\n * free-text row, Skip / Previous / Next / Send. Answers still travel as one\n * formatted `**Title:** answer` message so cdecli's parked turn is released.\n *\n * The reply goes out through the ordinary send path (onAnswer -> sendMessage),\n * which is what releases cdecli's parked turn.\n */\nimport React, { memo, useEffect, useMemo, useRef, useState } from 'react';\nimport { Pressable, StyleSheet, Text, TextInput, View } from 'react-native';\nimport { ApprovalCard } from './ApprovalCard';\nimport { formatAskUserAnswers, isApprovalQuestion, type AskUserPayload } from './askUser';\n\nconst ACCENT = '#2563eb';\n\nconst QuestionCard = memo(function QuestionCard({\n payload,\n isDark = false,\n disabled = false,\n onAnswer,\n onDismiss,\n}: {\n payload: AskUserPayload;\n isDark?: boolean;\n disabled?: boolean;\n onAnswer: (formatted: string) => void;\n onDismiss: () => void;\n}) {\n const questions = payload.questions;\n const [index, setIndex] = useState(0);\n const [answers, setAnswers] = useState<Record<string, string>>({});\n const [textDraft, setTextDraft] = useState('');\n const inputRef = useRef<TextInput>(null);\n\n const total = questions.length;\n const question = questions[Math.min(index, Math.max(total - 1, 0))];\n const isLast = index >= total - 1;\n const allowText = question?.allowText !== false;\n const multiSelect = question?.multiSelect === true;\n\n const palette = useMemo(\n () => ({\n card: isDark ? '#111827' : '#ffffff',\n border: isDark ? '#1f2937' : '#e5e7eb',\n title: isDark ? '#f1f5f9' : '#111827',\n muted: isDark ? '#94a3b8' : '#6b7280',\n optionBg: isDark ? '#0b1220' : '#f9fafb',\n optionBorder: isDark ? '#243045' : '#e5e7eb',\n chip: isDark ? '#1e293b' : '#f3f4f6',\n chipOn: ACCENT,\n }),\n [isDark],\n );\n\n const selectedLabels = useMemo(() => {\n const raw = answers[question?.id ?? ''] ?? '';\n if (!raw.trim()) return [] as string[];\n if (!multiSelect) return [raw];\n return raw\n .split(',')\n .map((v) => v.trim())\n .filter(Boolean);\n }, [answers, question, multiSelect]);\n\n const lastQuestionIdRef = useRef<string | null>(null);\n useEffect(() => {\n const q = questions[index];\n if (!q || lastQuestionIdRef.current === q.id) return;\n lastQuestionIdRef.current = q.id;\n const existing = answers[q.id] ?? '';\n const parts = q.multiSelect ? existing.split(',').map((v) => v.trim()) : [existing];\n const isOptionAnswer = existing !== '' && parts.every((part) => q.options?.some((o) => o.label === part));\n setTextDraft(isOptionAnswer ? '' : existing);\n // answers omitted: re-running on every keystroke would clobber the draft.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [index, questions]);\n\n const record = (value: string, advance: boolean) => {\n if (!question) return;\n setAnswers((prev) => ({ ...prev, [question.id]: value }));\n if (!advance) return;\n if (isLast) {\n const formatted = formatAskUserAnswers(questions, { ...answers, [question.id]: value });\n if (formatted) onAnswer(formatted);\n else onDismiss();\n } else {\n setIndex((i) => i + 1);\n }\n };\n\n const chooseOption = (option: { label: string; other?: boolean }) => {\n if (!question || disabled) return;\n if (option.other) {\n inputRef.current?.focus();\n return;\n }\n if (multiSelect) {\n const next = selectedLabels.includes(option.label)\n ? selectedLabels.filter((l) => l !== option.label)\n : [...selectedLabels, option.label];\n record(next.join(', '), false);\n return;\n }\n record(option.label, true);\n };\n\n const currentAnswer = textDraft.trim() || answers[question?.id ?? ''] || '';\n\n const next = () => {\n if (disabled || !currentAnswer) return;\n record(currentAnswer, true);\n };\n\n const skip = () => {\n if (disabled || !question) return;\n setAnswers((prev) => {\n const { [question.id]: _dropped, ...rest } = prev;\n return rest;\n });\n if (isLast) {\n const { [question.id]: _dropped, ...rest } = answers;\n const formatted = formatAskUserAnswers(questions, rest);\n if (formatted) onAnswer(formatted);\n else onDismiss();\n } else {\n setIndex((i) => i + 1);\n }\n };\n\n if (!question) return null;\n\n return (\n <View style={[styles.card, { backgroundColor: palette.card, borderColor: palette.border }]}>\n <View style={styles.header}>\n <Text style={[styles.kicker, { color: palette.muted }]}>\n Question {index + 1} of {total}\n </Text>\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel=\"Dismiss\"\n hitSlop={10}\n onPress={onDismiss}\n disabled={disabled}\n style={styles.dismiss}\n >\n <Text style={[styles.dismissMark, { color: palette.muted }]}>×</Text>\n </Pressable>\n </View>\n\n {question.header ? (\n <Text style={[styles.eyebrow, { color: palette.muted }]}>{question.header.toUpperCase()}</Text>\n ) : null}\n <Text style={[styles.title, { color: palette.title }]}>{question.title}</Text>\n {multiSelect ? <Text style={[styles.hint, { color: palette.muted }]}>Pick as many as apply.</Text> : null}\n\n {(question.options ?? []).map((o, i) => {\n const active = selectedLabels.includes(o.label);\n return (\n <Pressable\n key={o.id}\n accessibilityRole=\"button\"\n accessibilityState={{ selected: active, disabled }}\n accessibilityLabel={o.detail ? `${o.label}. ${o.detail}` : o.label}\n disabled={disabled}\n onPress={() => chooseOption(o)}\n style={({ pressed }) => [\n styles.option,\n {\n backgroundColor: active ? `${ACCENT}14` : palette.optionBg,\n borderColor: active ? ACCENT : palette.optionBorder,\n opacity: pressed && !disabled ? 0.75 : 1,\n },\n ]}\n >\n <View style={[styles.indexChip, { backgroundColor: active ? ACCENT : palette.chip }]}>\n <Text style={[styles.indexChipText, { color: active ? '#ffffff' : palette.muted }]}>\n {active && multiSelect ? '✓' : String(i + 1)}\n </Text>\n </View>\n <View style={styles.optionBody}>\n <Text style={[styles.optionLabel, { color: palette.title }]}>{o.label}</Text>\n {o.detail ? (\n <Text style={[styles.optionDetail, { color: palette.muted }]}>{o.detail}</Text>\n ) : null}\n </View>\n </Pressable>\n );\n })}\n\n {allowText ? (\n <TextInput\n ref={inputRef}\n value={textDraft}\n onChangeText={setTextDraft}\n editable={!disabled}\n placeholder={question.textPlaceholder ?? 'Type your answer'}\n placeholderTextColor={palette.muted}\n returnKeyType={isLast ? 'send' : 'next'}\n onSubmitEditing={next}\n style={[\n styles.input,\n {\n backgroundColor: palette.optionBg,\n borderColor: palette.optionBorder,\n color: palette.title,\n },\n ]}\n />\n ) : null}\n\n <View style={styles.actions}>\n {index > 0 ? (\n <Pressable\n accessibilityRole=\"button\"\n onPress={() => {\n if (question && textDraft.trim()) record(textDraft.trim(), false);\n setIndex((i) => i - 1);\n }}\n disabled={disabled}\n style={styles.skip}\n >\n <Text style={[styles.skipText, { color: palette.muted }]}>Previous</Text>\n </Pressable>\n ) : (\n <View />\n )}\n <View style={styles.dots} pointerEvents=\"none\">\n {total > 1\n ? questions.map((q, i) => (\n <View\n key={q.id}\n style={[\n styles.dot,\n i === index ? styles.dotOn : { backgroundColor: palette.optionBorder },\n ]}\n />\n ))\n : null}\n </View>\n <View style={styles.actionRight}>\n <Pressable accessibilityRole=\"button\" onPress={skip} disabled={disabled} style={styles.skip}>\n <Text style={[styles.skipText, { color: palette.muted }]}>Skip</Text>\n </Pressable>\n <Pressable\n accessibilityRole=\"button\"\n accessibilityState={{ disabled: disabled || !currentAnswer }}\n onPress={next}\n disabled={disabled || !currentAnswer}\n style={[\n styles.send,\n { backgroundColor: currentAnswer && !disabled ? ACCENT : palette.optionBorder },\n ]}\n >\n <Text\n style={[styles.sendText, { color: currentAnswer && !disabled ? '#ffffff' : palette.muted }]}\n >\n {isLast ? 'Send' : 'Next'}\n </Text>\n </Pressable>\n </View>\n </View>\n </View>\n );\n});\n\ntype AskUserCardProps = {\n payload: AskUserPayload;\n isDark?: boolean;\n disabled?: boolean;\n onAnswer: (formatted: string) => void;\n onDismiss: () => void;\n};\n\n/** An approval request from the action gate reads as an approval, not a quiz. */\nexport const AskUserCard = memo(function AskUserCard(props: AskUserCardProps) {\n const only = props.payload.questions.length === 1 ? props.payload.questions[0] : undefined;\n if (isApprovalQuestion(only)) {\n return (\n <ApprovalCard question={only} isDark={props.isDark} disabled={props.disabled} onAnswer={props.onAnswer} />\n );\n }\n return <QuestionCard {...props} />;\n});\n\nconst styles = StyleSheet.create({\n card: {\n width: '100%',\n borderWidth: 1,\n borderRadius: 16,\n padding: 14,\n marginTop: 4,\n marginBottom: 8,\n },\n header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between' },\n kicker: { fontSize: 10.5, fontWeight: '600', letterSpacing: 1.2, textTransform: 'uppercase' },\n dismiss: { padding: 4, minWidth: 32, minHeight: 32, alignItems: 'center', justifyContent: 'center' },\n dismissMark: { fontSize: 22, lineHeight: 24, fontWeight: '400' },\n eyebrow: { fontSize: 11, fontWeight: '600', letterSpacing: 1, marginTop: 6 },\n title: { fontSize: 15.5, fontWeight: '700', lineHeight: 21, marginTop: 4, marginBottom: 4 },\n hint: { fontSize: 12, marginBottom: 6 },\n option: {\n flexDirection: 'row',\n alignItems: 'center',\n borderWidth: 1,\n borderRadius: 12,\n paddingHorizontal: 10,\n paddingVertical: 10,\n marginTop: 6,\n minHeight: 44,\n gap: 10,\n },\n indexChip: {\n width: 24,\n height: 24,\n borderRadius: 6,\n alignItems: 'center',\n justifyContent: 'center',\n },\n indexChipText: { fontSize: 11, fontWeight: '700' },\n optionBody: { flex: 1 },\n optionLabel: { fontSize: 13.5, fontWeight: '600' },\n optionDetail: { fontSize: 12, marginTop: 2, lineHeight: 16 },\n input: {\n borderWidth: 1,\n borderRadius: 12,\n paddingHorizontal: 12,\n paddingVertical: 10,\n marginTop: 10,\n fontSize: 14,\n minHeight: 44,\n },\n actions: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginTop: 8,\n gap: 8,\n },\n dots: { flexDirection: 'row', alignItems: 'center', gap: 5, flex: 1, justifyContent: 'center' },\n dot: { width: 6, height: 6, borderRadius: 3 },\n dotOn: { width: 16, backgroundColor: ACCENT },\n actionRight: { flexDirection: 'row', alignItems: 'center' },\n skip: { paddingHorizontal: 12, paddingVertical: 10, minHeight: 44, justifyContent: 'center' },\n skipText: { fontSize: 13, fontWeight: '600' },\n send: {\n paddingHorizontal: 16,\n paddingVertical: 10,\n borderRadius: 12,\n minHeight: 44,\n justifyContent: 'center',\n },\n sendText: { fontSize: 14, fontWeight: '700' },\n});\n"],"names":["QuestionCard","_a","_b","next","AskUserCard"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAcA,MAAM,MAAS,GAAA,SAAA;AACf,MAAM,YAAA,GAAe,IAAK,CAAA,SAASA,aAAa,CAAA;AAAA,EAC9C,OAAA;AAAA,EACA,MAAS,GAAA,KAAA;AAAA,EACT,QAAW,GAAA,KAAA;AAAA,EACX,QAAA;AAAA,EACA;AACF,CAMG,EAAA;AA3BH,EAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA;AA4BE,EAAA,MAAM,YAAY,OAAQ,CAAA,SAAA;AAC1B,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,SAAS,CAAC,CAAA;AACpC,EAAA,MAAM,CAAC,OAAS,EAAA,UAAU,CAAI,GAAA,QAAA,CAAiC,EAAE,CAAA;AACjE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAS,EAAE,CAAA;AAC7C,EAAM,MAAA,QAAA,GAAW,OAAkB,IAAI,CAAA;AACvC,EAAA,MAAM,QAAQ,SAAU,CAAA,MAAA;AACxB,EAAM,MAAA,QAAA,GAAW,SAAU,CAAA,IAAA,CAAK,GAAI,CAAA,KAAA,EAAO,IAAK,CAAA,GAAA,CAAI,KAAQ,GAAA,CAAA,EAAG,CAAC,CAAC,CAAC,CAAA;AAClE,EAAM,MAAA,MAAA,GAAS,SAAS,KAAQ,GAAA,CAAA;AAChC,EAAM,MAAA,SAAA,GAAA,CAAY,qCAAU,SAAc,MAAA,KAAA;AAC1C,EAAM,MAAA,WAAA,GAAA,CAAc,qCAAU,WAAgB,MAAA,IAAA;AAC9C,EAAM,MAAA,OAAA,GAAU,QAAQ,OAAO;AAAA,IAC7B,IAAA,EAAM,SAAS,SAAY,GAAA,SAAA;AAAA,IAC3B,MAAA,EAAQ,SAAS,SAAY,GAAA,SAAA;AAAA,IAC7B,KAAA,EAAO,SAAS,SAAY,GAAA,SAAA;AAAA,IAC5B,KAAA,EAAO,SAAS,SAAY,GAAA,SAAA;AAAA,IAC5B,QAAA,EAAU,SAAS,SAAY,GAAA,SAAA;AAAA,IAC/B,YAAA,EAAc,SAAS,SAAY,GAAA,SAAA;AAAA,IACnC,IAAA,EAAM,SAAS,SAAY,GAAA,SAAA;AAAA,IAC3B,MAAQ,EAAA;AAAA,GACV,CAAA,EAAI,CAAC,MAAM,CAAC,CAAA;AACZ,EAAM,MAAA,cAAA,GAAiB,QAAQ,MAAM;AAhDvC,IAAA,IAAAC,GAAAC,EAAAA,GAAAA;AAiDI,IAAM,MAAA,GAAA,GAAA,CAAMA,GAAA,GAAA,OAAA,CAAA,CAAQD,GAAA,GAAA,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAU,EAAV,KAAA,IAAA,GAAAA,GAAgB,GAAA,EAAE,CAA1B,KAAA,IAAA,GAAAC,GAA+B,GAAA,EAAA;AAC3C,IAAA,IAAI,CAAC,GAAA,CAAI,IAAK,EAAA,SAAU,EAAC;AACzB,IAAA,IAAI,CAAC,WAAA,EAAoB,OAAA,CAAC,GAAG,CAAA;AAC7B,IAAO,OAAA,GAAA,CAAI,KAAM,CAAA,GAAG,CAAE,CAAA,GAAA,CAAI,CAAK,CAAA,KAAA,CAAA,CAAE,IAAK,EAAC,CAAE,CAAA,MAAA,CAAO,OAAO,CAAA;AAAA,GACtD,EAAA,CAAC,OAAS,EAAA,QAAA,EAAU,WAAW,CAAC,CAAA;AACnC,EAAM,MAAA,iBAAA,GAAoB,OAAsB,IAAI,CAAA;AACpD,EAAA,SAAA,CAAU,MAAM;AAvDlB,IAAAD,IAAAA,GAAAA;AAwDI,IAAM,MAAA,CAAA,GAAI,UAAU,KAAK,CAAA;AACzB,IAAA,IAAI,CAAC,CAAA,IAAK,iBAAkB,CAAA,OAAA,KAAY,EAAE,EAAI,EAAA;AAC9C,IAAA,iBAAA,CAAkB,UAAU,CAAE,CAAA,EAAA;AAC9B,IAAA,MAAM,YAAWA,GAAA,GAAA,OAAA,CAAQ,EAAE,EAAE,CAAA,KAAZ,OAAAA,GAAiB,GAAA,EAAA;AAClC,IAAA,MAAM,KAAQ,GAAA,CAAA,CAAE,WAAc,GAAA,QAAA,CAAS,MAAM,GAAG,CAAA,CAAE,GAAI,CAAA,CAAA,CAAA,KAAK,CAAE,CAAA,IAAA,EAAM,CAAA,GAAI,CAAC,QAAQ,CAAA;AAChF,IAAA,MAAM,cAAiB,GAAA,QAAA,KAAa,EAAM,IAAA,KAAA,CAAM,MAAM,CAAK,IAAA,KAAA;AA7D/D,MAAAA,IAAAA,GAAAA;AA6DkE,MAAAA,OAAAA,CAAAA,GAAAA,GAAA,EAAE,OAAF,KAAA,IAAA,GAAA,MAAA,GAAAA,IAAW,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,KAAU,KAAA,IAAA,CAAA;AAAA,KAAK,CAAA;AACpG,IAAa,YAAA,CAAA,cAAA,GAAiB,KAAK,QAAQ,CAAA;AAAA,GAG1C,EAAA,CAAC,KAAO,EAAA,SAAS,CAAC,CAAA;AACrB,EAAM,MAAA,MAAA,GAAS,CAAC,KAAA,EAAe,OAAqB,KAAA;AAClD,IAAA,IAAI,CAAC,QAAU,EAAA;AACf,IAAW,UAAA,CAAA,CAAA,IAAA,KAAS,iCACf,IADe,CAAA,EAAA;AAAA,MAElB,CAAC,QAAS,CAAA,EAAE,GAAG;AAAA,KACf,CAAA,CAAA;AACF,IAAA,IAAI,CAAC,OAAS,EAAA;AACd,IAAA,IAAI,MAAQ,EAAA;AACV,MAAA,MAAM,SAAY,GAAA,oBAAA,CAAqB,SAAW,EAAA,aAAA,CAAA,cAAA,CAAA,EAAA,EAC7C,OAD6C,CAAA,EAAA;AAAA,QAEhD,CAAC,QAAS,CAAA,EAAE,GAAG;AAAA,OAChB,CAAA,CAAA;AACD,MAAI,IAAA,SAAA,WAAoB,SAAS,CAAA;AAAA,WAAiB,SAAA,EAAA;AAAA,KAC7C,MAAA;AACL,MAAS,QAAA,CAAA,CAAA,CAAA,KAAK,IAAI,CAAC,CAAA;AAAA;AACrB,GACF;AACA,EAAM,MAAA,YAAA,GAAe,CAAC,MAGhB,KAAA;AAtFR,IAAAA,IAAAA,GAAAA;AAuFI,IAAI,IAAA,CAAC,YAAY,QAAU,EAAA;AAC3B,IAAA,IAAI,OAAO,KAAO,EAAA;AAChB,MAAA,CAAAA,GAAA,GAAA,QAAA,CAAS,OAAT,KAAA,IAAA,GAAA,MAAA,GAAAA,GAAkB,CAAA,KAAA,EAAA;AAClB,MAAA;AAAA;AAEF,IAAA,IAAI,WAAa,EAAA;AACf,MAAA,MAAME,QAAO,cAAe,CAAA,QAAA,CAAS,MAAO,CAAA,KAAK,IAAI,cAAe,CAAA,MAAA,CAAO,CAAK,CAAA,KAAA,CAAA,KAAM,OAAO,KAAK,CAAA,GAAI,CAAC,GAAG,cAAA,EAAgB,OAAO,KAAK,CAAA;AACtI,MAAA,MAAA,CAAOA,KAAK,CAAA,IAAA,CAAK,IAAI,CAAA,EAAG,KAAK,CAAA;AAC7B,MAAA;AAAA;AAEF,IAAO,MAAA,CAAA,MAAA,CAAO,OAAO,IAAI,CAAA;AAAA,GAC3B;AACA,EAAM,MAAA,aAAA,GAAgB,UAAU,IAAK,EAAA,IAAK,SAAQ,EAAU,GAAA,QAAA,IAAA,IAAA,GAAA,MAAA,GAAA,QAAA,CAAA,EAAA,KAAV,IAAgB,GAAA,EAAA,GAAA,EAAE,CAAK,IAAA,EAAA;AACzE,EAAA,MAAM,OAAO,MAAM;AACjB,IAAI,IAAA,QAAA,IAAY,CAAC,aAAe,EAAA;AAChC,IAAA,MAAA,CAAO,eAAe,IAAI,CAAA;AAAA,GAC5B;AACA,EAAA,MAAM,OAAO,MAAM;AAxGrB,IAAAF,IAAAA,GAAAA;AAyGI,IAAI,IAAA,QAAA,IAAY,CAAC,QAAU,EAAA;AAC3B,IAAA,UAAA,CAAW,CAAQ,IAAA,KAAA;AA1GvB,MAAAA,IAAAA,GAAAA;AA2GM,MAAA,MAGIC,MAAA,IAFD,EAAA;AAAA,QA5GT,CA4GSD,GAAA,GAAA,QAAA,CAAS,EAAK,GAAA;AAAA,OA5GvB,GA8GUC,GADC,EAAA,IAAA,GAAA,SAAA,CACDA,GADC,EAAA;AAAA,QADF,SAAAD,CAAAA,GAAAA;AAAA,OAAA,CAAA;AAGH,MAAO,OAAA,IAAA;AAAA,KACR,CAAA;AACD,IAAA,IAAI,MAAQ,EAAA;AACV,MAAA,MAGIC,MAAA,OAFD,EAAA;AAAA,QAnHT,CAmHSD,GAAA,GAAA,QAAA,CAAS,EAAK,GAAA;AAAA,OAnHvB,GAqHUC,GADC,EAAA,IAAA,GAAA,SAAA,CACDA,GADC,EAAA;AAAA,QADF,SAAAD,CAAAA,GAAAA;AAAA,OAAA,CAAA;AAGH,MAAM,MAAA,SAAA,GAAY,oBAAqB,CAAA,SAAA,EAAW,IAAI,CAAA;AACtD,MAAI,IAAA,SAAA,WAAoB,SAAS,CAAA;AAAA,WAAiB,SAAA,EAAA;AAAA,KAC7C,MAAA;AACL,MAAS,QAAA,CAAA,CAAA,CAAA,KAAK,IAAI,CAAC,CAAA;AAAA;AACrB,GACF;AACA,EAAI,IAAA,CAAC,UAAiB,OAAA,IAAA;AACtB,EAAA,uBAAQ,IAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,IAAM,EAAA;AAAA,IAChC,iBAAiB,OAAQ,CAAA,IAAA;AAAA,IACzB,aAAa,OAAQ,CAAA;AAAA,GACtB,CACS,EAAA,QAAA,EAAA;AAAA,oBAAC,IAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,MAAA,CAAO,MAChB,EAAA,QAAA,EAAA;AAAA,sBAAA,IAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,MAAQ,EAAA;AAAA,QACrC,OAAO,OAAQ,CAAA;AAAA,OAChB,CAAG,EAAA,QAAA,EAAA;AAAA,QAAA,WAAA;AAAA,QACoB,KAAQ,GAAA,CAAA;AAAA,QAAE,MAAA;AAAA,QAAK;AAAA,OAC7B,EAAA,CAAA;AAAA,0BACC,SAAU,EAAA,EAAA,iBAAA,EAAkB,UAAS,kBAAmB,EAAA,SAAA,EAAU,SAAS,EAAI,EAAA,OAAA,EAAS,WAAW,QAAoB,EAAA,KAAA,EAAO,OAAO,OAClI,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAK,KAAO,EAAA,CAAC,OAAO,WAAa,EAAA;AAAA,QAC5C,OAAO,OAAQ,CAAA;AAAA,OAChB,CAAG,EAAA,QAAA,EAAA,MAAA,EAAC,CACG,EAAA;AAAA,KACJ,EAAA,CAAA;AAAA,IAEC,SAAS,MAAS,mBAAA,GAAA,CAAC,QAAK,KAAO,EAAA,CAAC,OAAO,OAAS,EAAA;AAAA,MACvD,OAAO,OAAQ,CAAA;AAAA,KAChB,CAAI,EAAA,QAAA,EAAA,QAAA,CAAS,MAAO,CAAA,WAAA,IAAc,CAAU,GAAA,IAAA;AAAA,oBACpC,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,KAAO,EAAA;AAAA,MAClC,OAAO,OAAQ,CAAA;AAAA,KAChB,CAAI,EAAA,QAAA,EAAA,QAAA,CAAS,KAAM,EAAA,CAAA;AAAA,IACX,8BAAe,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,IAAM,EAAA;AAAA,MAChD,OAAO,OAAQ,CAAA;AAAA,KAChB,CAAG,EAAA,QAAA,EAAA,wBAAA,EAAsB,CAAU,GAAA,IAAA;AAAA,IAE1B,CAAA,CAAA,EAAA,GAAA,QAAA,CAAS,YAAT,IAAoB,GAAA,EAAA,GAAA,IAAI,GAAI,CAAA,CAAC,GAAG,CAAM,KAAA;AAC9C,MAAA,MAAM,MAAS,GAAA,cAAA,CAAe,QAAS,CAAA,CAAA,CAAE,KAAK,CAAA;AAC9C,MAAA,uBAAQ,IAAA,CAAA,SAAA,EAAA,EAAqB,iBAAkB,EAAA,QAAA,EAAS,kBAAoB,EAAA;AAAA,QAC1E,QAAU,EAAA,MAAA;AAAA,QACV;AAAA,OACF,EAAG,oBAAoB,CAAE,CAAA,MAAA,GAAS,GAAG,CAAE,CAAA,KAAK,KAAK,CAAE,CAAA,MAAM,KAAK,CAAE,CAAA,KAAA,EAAO,UAAoB,OAAS,EAAA,MAAM,aAAa,CAAC,CAAA,EAAG,OAAO,CAAC;AAAA,QACjI;AAAA,OACF,KAAM,CAAC,MAAA,CAAO,MAAQ,EAAA;AAAA,QACpB,eAAiB,EAAA,MAAA,GAAS,CAAG,EAAA,MAAM,OAAO,OAAQ,CAAA,QAAA;AAAA,QAClD,WAAA,EAAa,MAAS,GAAA,MAAA,GAAS,OAAQ,CAAA,YAAA;AAAA,QACvC,OAAS,EAAA,OAAA,IAAW,CAAC,QAAA,GAAW,IAAO,GAAA;AAAA,OACxC,CACiB,EAAA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,SAAW,EAAA;AAAA,UAC9C,eAAA,EAAiB,MAAS,GAAA,MAAA,GAAS,OAAQ,CAAA;AAAA,SAC5C,CACmB,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAK,KAAO,EAAA,CAAC,OAAO,aAAe,EAAA;AAAA,UACpD,KAAA,EAAO,MAAS,GAAA,SAAA,GAAY,OAAQ,CAAA;AAAA,SACrC,GACsB,QAAU,EAAA,MAAA,IAAA,WAAA,GAAc,WAAM,MAAO,CAAA,CAAA,GAAI,CAAC,CAAA,EAC/C,CACJ,EAAA,CAAA;AAAA,wBACC,IAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,MAAA,CAAO,UAChB,EAAA,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,WAAa,EAAA;AAAA,YAClD,OAAO,OAAQ,CAAA;AAAA,WAChB,CAAI,EAAA,QAAA,EAAA,CAAA,CAAE,KAAM,EAAA,CAAA;AAAA,UACM,EAAE,MAAS,mBAAA,GAAA,CAAC,QAAK,KAAO,EAAA,CAAC,OAAO,YAAc,EAAA;AAAA,YAC/D,OAAO,OAAQ,CAAA;AAAA,WAChB,CAAA,EAAI,QAAE,EAAA,CAAA,CAAA,MAAA,EAAO,CAAU,GAAA;AAAA,SACV,EAAA;AAAA,OAAA,EAAA,EA1BK,EAAE,EA2BX,CAAA;AAAA,KACf,CAAA;AAAA,IAEQ,SAAY,mBAAA,GAAA,CAAC,SAAU,EAAA,EAAA,GAAA,EAAK,QAAU,EAAA,KAAA,EAAO,SAAW,EAAA,YAAA,EAAc,YAAc,EAAA,QAAA,EAAU,CAAC,QAAA,EAAU,WAAa,EAAA,CAAA,EAAA,GAAA,QAAA,CAAS,eAAT,KAAA,IAAA,GAAA,EAAA,GAA4B,kBAAoB,EAAA,oBAAA,EAAsB,OAAQ,CAAA,KAAA,EAAO,aAAe,EAAA,MAAA,GAAS,MAAS,GAAA,MAAA,EAAQ,eAAiB,EAAA,IAAA,EAAM,KAAO,EAAA,CAAC,OAAO,KAAO,EAAA;AAAA,MACxS,iBAAiB,OAAQ,CAAA,QAAA;AAAA,MACzB,aAAa,OAAQ,CAAA,YAAA;AAAA,MACrB,OAAO,OAAQ,CAAA;AAAA,KAChB,GAAG,CAAK,GAAA,IAAA;AAAA,oBAEA,IAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,MAAA,CAAO,OACf,EAAA,QAAA,EAAA;AAAA,MAAA,KAAA,GAAQ,oBAAK,GAAA,CAAA,SAAA,EAAA,EAAU,iBAAkB,EAAA,QAAA,EAAS,SAAS,MAAM;AAC1E,QAAI,IAAA,QAAA,IAAY,UAAU,IAAK,EAAA,SAAU,SAAU,CAAA,IAAA,IAAQ,KAAK,CAAA;AAChE,QAAS,QAAA,CAAA,CAAA,CAAA,KAAK,IAAI,CAAC,CAAA;AAAA,OACrB,EAAG,QAAoB,EAAA,KAAA,EAAO,MAAO,CAAA,IAAA,EACnB,8BAAC,IAAK,EAAA,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,QAAU,EAAA;AAAA,QAC7C,OAAO,OAAQ,CAAA;AAAA,OAChB,CAAG,EAAA,QAAA,EAAA,UAAA,EAAQ,CACA,EAAA,CAAA,uBAAgB,IAAK,EAAA,EAAA,CAAA;AAAA,sBACzB,GAAA,CAAC,QAAK,KAAO,EAAA,MAAA,CAAO,MAAM,aAAc,EAAA,MAAA,EACnC,QAAQ,EAAA,KAAA,GAAA,CAAA,GAAI,SAAU,CAAA,GAAA,CAAI,CAAC,CAAG,EAAA,CAAA,qBAAO,GAAA,CAAA,IAAA,EAAA,EAAgB,KAAO,EAAA,CAAC,OAAO,GAAK,EAAA,CAAA,KAAM,KAAQ,GAAA,MAAA,CAAO,KAAQ,GAAA;AAAA,QACjH,iBAAiB,OAAQ,CAAA;AAAA,OAC1B,CAF2D,EAAA,EAAA,CAAA,CAAE,EAE1D,CAAE,IAAI,IACF,EAAA,CAAA;AAAA,sBACC,IAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,MAAA,CAAO,WAChB,EAAA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,SAAU,EAAA,EAAA,iBAAA,EAAkB,QAAS,EAAA,OAAA,EAAS,MAAM,QAAoB,EAAA,KAAA,EAAO,MAAO,CAAA,IAAA,EACnF,QAAC,kBAAA,GAAA,CAAA,IAAA,EAAA,EAAK,KAAO,EAAA,CAAC,OAAO,QAAU,EAAA;AAAA,UAC3C,OAAO,OAAQ,CAAA;AAAA,SAChB,CAAG,EAAA,QAAA,EAAA,MAAA,EAAI,CACE,EAAA,CAAA;AAAA,wBACC,GAAA,CAAA,SAAA,EAAA,EAAU,iBAAkB,EAAA,QAAA,EAAS,kBAAoB,EAAA;AAAA,UACpE,QAAA,EAAU,YAAY,CAAC;AAAA,SACzB,EAAG,OAAS,EAAA,IAAA,EAAM,QAAU,EAAA,QAAA,IAAY,CAAC,aAAe,EAAA,KAAA,EAAO,CAAC,MAAA,CAAO,IAAM,EAAA;AAAA,UAC3E,eAAiB,EAAA,aAAA,IAAiB,CAAC,QAAA,GAAW,SAAS,OAAQ,CAAA;AAAA,SAChE,CACe,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAK,KAAO,EAAA,CAAC,OAAO,QAAU,EAAA;AAAA,UAC3C,KAAO,EAAA,aAAA,IAAiB,CAAC,QAAA,GAAW,YAAY,OAAQ,CAAA;AAAA,SACzD,CAAA,EACkB,QAAS,EAAA,MAAA,GAAA,MAAA,GAAS,QACvB,CACJ,EAAA;AAAA,OACJ,EAAA;AAAA,KACJ,EAAA;AAAA,GACJ,EAAA,CAAA;AACR,CAAC,CAAA;AAUM,MAAM,WAAc,GAAA,IAAA,CAAK,SAASG,YAAAA,CAAY,KAAyB,EAAA;AAC5E,EAAM,MAAA,IAAA,GAAO,KAAM,CAAA,OAAA,CAAQ,SAAU,CAAA,MAAA,KAAW,IAAI,KAAM,CAAA,OAAA,CAAQ,SAAU,CAAA,CAAC,CAAI,GAAA,MAAA;AACjF,EAAI,IAAA,kBAAA,CAAmB,IAAI,CAAG,EAAA;AAC5B,IAAA,uBAAQ,GAAA,CAAA,YAAA,EAAA,EAAa,QAAU,EAAA,IAAA,EAAM,MAAQ,EAAA,KAAA,CAAM,MAAQ,EAAA,QAAA,EAAU,KAAM,CAAA,QAAA,EAAU,QAAU,EAAA,KAAA,CAAM,QAAU,EAAA,CAAA;AAAA;AAEjH,EAAO,uBAAA,GAAA,CAAC,iCAAiB,KAAO,CAAA,CAAA;AAClC,CAAC;AACD,MAAM,MAAA,GAAS,WAAW,MAAO,CAAA;AAAA,EAC/B,IAAM,EAAA;AAAA,IACJ,KAAO,EAAA,MAAA;AAAA,IACP,WAAa,EAAA,CAAA;AAAA,IACb,YAAc,EAAA,EAAA;AAAA,IACd,OAAS,EAAA,EAAA;AAAA,IACT,SAAW,EAAA,CAAA;AAAA,IACX,YAAc,EAAA;AAAA,GAChB;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,aAAe,EAAA,KAAA;AAAA,IACf,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA;AAAA,GAClB;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,QAAU,EAAA,IAAA;AAAA,IACV,UAAY,EAAA,KAAA;AAAA,IACZ,aAAe,EAAA,GAAA;AAAA,IACf,aAAe,EAAA;AAAA,GACjB;AAAA,EACA,OAAS,EAAA;AAAA,IACP,OAAS,EAAA,CAAA;AAAA,IACT,QAAU,EAAA,EAAA;AAAA,IACV,SAAW,EAAA,EAAA;AAAA,IACX,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA;AAAA,GAClB;AAAA,EACA,WAAa,EAAA;AAAA,IACX,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA,EAAA;AAAA,IACZ,UAAY,EAAA;AAAA,GACd;AAAA,EACA,OAAS,EAAA;AAAA,IACP,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA,KAAA;AAAA,IACZ,aAAe,EAAA,CAAA;AAAA,IACf,SAAW,EAAA;AAAA,GACb;AAAA,EACA,KAAO,EAAA;AAAA,IACL,QAAU,EAAA,IAAA;AAAA,IACV,UAAY,EAAA,KAAA;AAAA,IACZ,UAAY,EAAA,EAAA;AAAA,IACZ,SAAW,EAAA,CAAA;AAAA,IACX,YAAc,EAAA;AAAA,GAChB;AAAA,EACA,IAAM,EAAA;AAAA,IACJ,QAAU,EAAA,EAAA;AAAA,IACV,YAAc,EAAA;AAAA,GAChB;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,aAAe,EAAA,KAAA;AAAA,IACf,UAAY,EAAA,QAAA;AAAA,IACZ,WAAa,EAAA,CAAA;AAAA,IACb,YAAc,EAAA,EAAA;AAAA,IACd,iBAAmB,EAAA,EAAA;AAAA,IACnB,eAAiB,EAAA,EAAA;AAAA,IACjB,SAAW,EAAA,CAAA;AAAA,IACX,SAAW,EAAA,EAAA;AAAA,IACX,GAAK,EAAA;AAAA,GACP;AAAA,EACA,SAAW,EAAA;AAAA,IACT,KAAO,EAAA,EAAA;AAAA,IACP,MAAQ,EAAA,EAAA;AAAA,IACR,YAAc,EAAA,CAAA;AAAA,IACd,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA;AAAA,GAClB;AAAA,EACA,aAAe,EAAA;AAAA,IACb,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA,GACd;AAAA,EACA,UAAY,EAAA;AAAA,IACV,IAAM,EAAA;AAAA,GACR;AAAA,EACA,WAAa,EAAA;AAAA,IACX,QAAU,EAAA,IAAA;AAAA,IACV,UAAY,EAAA;AAAA,GACd;AAAA,EACA,YAAc,EAAA;AAAA,IACZ,QAAU,EAAA,EAAA;AAAA,IACV,SAAW,EAAA,CAAA;AAAA,IACX,UAAY,EAAA;AAAA,GACd;AAAA,EACA,KAAO,EAAA;AAAA,IACL,WAAa,EAAA,CAAA;AAAA,IACb,YAAc,EAAA,EAAA;AAAA,IACd,iBAAmB,EAAA,EAAA;AAAA,IACnB,eAAiB,EAAA,EAAA;AAAA,IACjB,SAAW,EAAA,EAAA;AAAA,IACX,QAAU,EAAA,EAAA;AAAA,IACV,SAAW,EAAA;AAAA,GACb;AAAA,EACA,OAAS,EAAA;AAAA,IACP,aAAe,EAAA,KAAA;AAAA,IACf,UAAY,EAAA,QAAA;AAAA,IACZ,cAAgB,EAAA,eAAA;AAAA,IAChB,SAAW,EAAA,CAAA;AAAA,IACX,GAAK,EAAA;AAAA,GACP;AAAA,EACA,IAAM,EAAA;AAAA,IACJ,aAAe,EAAA,KAAA;AAAA,IACf,UAAY,EAAA,QAAA;AAAA,IACZ,GAAK,EAAA,CAAA;AAAA,IACL,IAAM,EAAA,CAAA;AAAA,IACN,cAAgB,EAAA;AAAA,GAClB;AAAA,EACA,GAAK,EAAA;AAAA,IACH,KAAO,EAAA,CAAA;AAAA,IACP,MAAQ,EAAA,CAAA;AAAA,IACR,YAAc,EAAA;AAAA,GAChB;AAAA,EACA,KAAO,EAAA;AAAA,IACL,KAAO,EAAA,EAAA;AAAA,IACP,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,WAAa,EAAA;AAAA,IACX,aAAe,EAAA,KAAA;AAAA,IACf,UAAY,EAAA;AAAA,GACd;AAAA,EACA,IAAM,EAAA;AAAA,IACJ,iBAAmB,EAAA,EAAA;AAAA,IACnB,eAAiB,EAAA,EAAA;AAAA,IACjB,SAAW,EAAA,EAAA;AAAA,IACX,cAAgB,EAAA;AAAA,GAClB;AAAA,EACA,QAAU,EAAA;AAAA,IACR,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA,GACd;AAAA,EACA,IAAM,EAAA;AAAA,IACJ,iBAAmB,EAAA,EAAA;AAAA,IACnB,eAAiB,EAAA,EAAA;AAAA,IACjB,YAAc,EAAA,EAAA;AAAA,IACd,SAAW,EAAA,EAAA;AAAA,IACX,cAAgB,EAAA;AAAA,GAClB;AAAA,EACA,QAAU,EAAA;AAAA,IACR,QAAU,EAAA,EAAA;AAAA,IACV,UAAY,EAAA;AAAA;AAEhB,CAAC,CAAA"}
|
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __spreadValues = (a, b) => {
|
|
7
|
+
for (var prop in b || (b = {}))
|
|
8
|
+
if (__hasOwnProp.call(b, prop))
|
|
9
|
+
__defNormalProp(a, prop, b[prop]);
|
|
10
|
+
if (__getOwnPropSymbols)
|
|
11
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
+
if (__propIsEnum.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
}
|
|
15
|
+
return a;
|
|
16
|
+
};
|
|
17
|
+
function isApprovalQuestion(q) {
|
|
18
|
+
return (q == null ? void 0 : q.kind) === "approval" && !!q.approval && typeof q.approval.connector === "string";
|
|
19
|
+
}
|
|
1
20
|
const MAX_ASK_USER_QUESTIONS = 4;
|
|
2
21
|
const ASK_USER_RE = /\[ASK_USER\]([\s\S]*?)\[\/ASK_USER\]/;
|
|
3
22
|
const ASK_USER_OPEN_RE = /\[ASK_USER\]/;
|
|
@@ -52,7 +71,7 @@ function normalizeQuestion(raw) {
|
|
|
52
71
|
const title = typeof q.title === "string" ? q.title : typeof q.question === "string" ? q.question : "";
|
|
53
72
|
if (!id || !title.trim()) return null;
|
|
54
73
|
const options = Array.isArray(q.options) ? q.options.filter((o) => !!o && typeof o === "object" && typeof o.id === "string" && typeof o.label === "string") : void 0;
|
|
55
|
-
return {
|
|
74
|
+
return __spreadValues({
|
|
56
75
|
id,
|
|
57
76
|
title: title.trim(),
|
|
58
77
|
header: typeof q.header === "string" ? q.header : void 0,
|
|
@@ -60,7 +79,10 @@ function normalizeQuestion(raw) {
|
|
|
60
79
|
allowText: q.allowText !== false,
|
|
61
80
|
textPlaceholder: typeof q.textPlaceholder === "string" ? q.textPlaceholder : void 0,
|
|
62
81
|
multiSelect: q.multiSelect === true
|
|
63
|
-
}
|
|
82
|
+
}, q.kind === "approval" && q.approval && typeof q.approval === "object" ? {
|
|
83
|
+
kind: "approval",
|
|
84
|
+
approval: q.approval
|
|
85
|
+
} : {});
|
|
64
86
|
}
|
|
65
87
|
function parseAskUser(raw) {
|
|
66
88
|
var _a;
|
|
@@ -140,4 +162,4 @@ function formatAskUserAnswers(questions, answers) {
|
|
|
140
162
|
const answer = (_a = answers[q.id]) == null ? void 0 : _a.trim();
|
|
141
163
|
return answer ? `**${q.title.replace(/:\s*$/, "")}:** ${answer}` : null;
|
|
142
164
|
}).filter(Boolean).join("\n\n");
|
|
143
|
-
}export{MAX_ASK_USER_QUESTIONS,displayAskUserAssistantText,formatAskUserAnswers,parseAskUser,pendingAskUser,splitAskUserParts,stripAskUser};//# sourceMappingURL=askUser.js.map
|
|
165
|
+
}export{MAX_ASK_USER_QUESTIONS,displayAskUserAssistantText,formatAskUserAnswers,isApprovalQuestion,parseAskUser,pendingAskUser,splitAskUserParts,stripAskUser};//# sourceMappingURL=askUser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"askUser.js","sources":["../../../src/features/chat/askUser.ts"],"sourcesContent":["/**\n * The `[ASK_USER]` clarifying-question protocol, mobile side (Clockbook #1643).\n *\n * cdecli emits the block itself — from Claude's AskUserQuestion and its own\n * ask_user_question tool — and PARKS the run until the answer arrives:\n *\n * [ASK_USER]{\"requestId\":\"ask-…\",\"questions\":[{\"id\":\"q1\",\"title\":\"Which\n * database?\",\"header\":\"Database\",\"options\":[{\"id\":\"o1\",\"label\":\"Postgres\",\n * \"detail\":\"…\"}],\"allowText\":true}]}[/ASK_USER]\n *\n * The reply is deliberately NOT a marker: answers are formatted into one visible\n * user message (`**Title:** answer` lines) and sent through the normal chat path,\n * so the producer needs no reply-protocol support. Only the question side is\n * structured.\n *\n * Deliberately a copy of the web's `responsePromptProtocol` rather than an\n * import — mobile is a separate bundle and shares no code with the web shell.\n * The reply side is plain text, so the two stay compatible without a shared\n * version.\n */\n\nexport interface AskUserOption {\n id: string;\n label: string;\n /** Secondary line under the label. */\n detail?: string;\n /** \"Something else\": focuses the free-text row instead of answering. */\n other?: boolean;\n}\n\nexport interface AskUserQuestion {\n id: string;\n /** Also the bold prefix of the formatted answer. */\n title: string;\n /** Short category eyebrow above the title, e.g. \"Database\". */\n header?: string;\n options?: AskUserOption[];\n /** Show the free-text row (default true). */\n allowText?: boolean;\n textPlaceholder?: string;\n /** Pick several options; the answer is sent as comma-joined labels. */\n multiSelect?: boolean;\n}\n\nexport interface AskUserPayload {\n requestId: string;\n questions: AskUserQuestion[];\n}\n\n/** Anything longer is a form, not a prompt — the web caps it the same way. */\nexport const MAX_ASK_USER_QUESTIONS = 4;\n\n// Not anchored: the channel layer may prepend a stream envelope or cost banner.\nconst ASK_USER_RE = /\\[ASK_USER\\]([\\s\\S]*?)\\[\\/ASK_USER\\]/;\nconst ASK_USER_OPEN_RE = /\\[ASK_USER\\]/;\n\nfunction unwrapJsonCandidate(inner: string): string {\n let s = inner.trim();\n const fence = /^```(?:json)?\\s*([\\s\\S]*?)\\s*```$/i.exec(s);\n if (fence) s = fence[1].trim();\n return s;\n}\n\n/** First complete `{...}` object in `s`, or null while the JSON is still streaming. */\nfunction parseJsonObject(s: string): unknown | null {\n const start = s.indexOf('{');\n if (start < 0) return null;\n let depth = 0;\n let inStr = false;\n let esc = false;\n for (let i = start; i < s.length; i++) {\n const c = s[i];\n if (inStr) {\n if (esc) {\n esc = false;\n continue;\n }\n if (c === '\\\\') {\n esc = true;\n continue;\n }\n if (c === '\"') inStr = false;\n continue;\n }\n if (c === '\"') {\n inStr = true;\n continue;\n }\n if (c === '{') depth += 1;\n else if (c === '}') {\n depth -= 1;\n if (depth === 0) {\n try {\n return JSON.parse(s.slice(start, i + 1));\n } catch {\n return null;\n }\n }\n }\n }\n return null;\n}\n\nfunction normalizeQuestion(raw: unknown): AskUserQuestion | null {\n if (!raw || typeof raw !== 'object') return null;\n const q = raw as Record<string, unknown>;\n const id = typeof q.id === 'string' ? q.id : '';\n const title = typeof q.title === 'string' ? q.title : typeof q.question === 'string' ? q.question : '';\n if (!id || !title.trim()) return null;\n const options = Array.isArray(q.options)\n ? q.options.filter(\n (o): o is AskUserOption =>\n !!o &&\n typeof o === 'object' &&\n typeof (o as AskUserOption).id === 'string' &&\n typeof (o as AskUserOption).label === 'string',\n )\n : undefined;\n return {\n id,\n title: title.trim(),\n header: typeof q.header === 'string' ? q.header : undefined,\n options,\n allowText: q.allowText !== false,\n textPlaceholder: typeof q.textPlaceholder === 'string' ? q.textPlaceholder : undefined,\n multiSelect: q.multiSelect === true,\n };\n}\n\n/** Parse an `[ASK_USER]…[/ASK_USER]` message, or null if it isn't one. */\nexport function parseAskUser(raw: string | null | undefined): AskUserPayload | null {\n if (!raw?.trim()) return null;\n const tagged = ASK_USER_RE.exec(raw) ?? (ASK_USER_OPEN_RE.test(raw) ? /\\[ASK_USER\\]([\\s\\S]*)$/.exec(raw) : null);\n if (!tagged) return null;\n const parsed = parseJsonObject(unwrapJsonCandidate(tagged[1]));\n if (!parsed || typeof parsed !== 'object') return null;\n const body = parsed as { requestId?: unknown; questions?: unknown };\n if (typeof body.requestId !== 'string' || !Array.isArray(body.questions)) return null;\n const questions = body.questions\n .map(normalizeQuestion)\n .filter((q): q is AskUserQuestion => q !== null)\n .slice(0, MAX_ASK_USER_QUESTIONS);\n return questions.length ? { requestId: body.requestId, questions } : null;\n}\n\n/**\n * Remove every `[ASK_USER]` block, leaving the rest of the message intact.\n *\n * cdecli emits the block MID-turn and keeps streaming its reply into the SAME\n * message once the answer releases the parked run, so the block and the reply it\n * was asked for share one message. Hiding the whole message — which is what a\n * naive implementation does — would swallow that reply.\n *\n * An unclosed `[ASK_USER]` (still streaming) is also stripped so the raw JSON\n * never paints in the bubble the way it does on web after `stripAskUser`.\n */\nexport function stripAskUser(raw: string | null | undefined): string {\n if (!raw) return '';\n let stripped = raw.replace(new RegExp(ASK_USER_RE.source, 'g'), '');\n stripped = stripped.replace(/\\[ASK_USER\\][\\s\\S]*$/, '');\n if (stripped === raw) return raw;\n return stripped.replace(/\\n{3,}/g, '\\n\\n').trim();\n}\n\n/**\n * Text around an `[ASK_USER]` marker. cdecli often speaks an intro *before* the\n * card (\"I'll need a couple more details…\") and streams the real reply *after*\n * the user answers. Once there is a user reply, the intro is stale.\n */\nexport function splitAskUserParts(raw: string | null | undefined): {\n before: string;\n after: string;\n hasMarker: boolean;\n} {\n if (!raw) return { before: '', after: '', hasMarker: false };\n const tagged = ASK_USER_RE.exec(raw);\n if (tagged && tagged.index !== undefined) {\n return {\n before: raw.slice(0, tagged.index).trim(),\n after: raw.slice(tagged.index + tagged[0].length).trim(),\n hasMarker: true,\n };\n }\n const open = raw.search(ASK_USER_OPEN_RE);\n if (open >= 0) {\n return { before: raw.slice(0, open).trim(), after: '', hasMarker: true };\n }\n return { before: '', after: '', hasMarker: false };\n}\n\n/**\n * Assistant prose to paint. After the user answers the card, drop the intro that\n * sat above `[ASK_USER]` so we don't re-ask for details already in the thread.\n */\nexport function displayAskUserAssistantText(raw: string | null | undefined, answered: boolean): string {\n const parts = splitAskUserParts(raw);\n if (!parts.hasMarker) return stripAskUser(raw);\n const keep = answered ? parts.after : [parts.before, parts.after].filter(Boolean).join('\\n\\n');\n return stripAskUser(keep || (answered ? '' : parts.before));\n}\n\n/**\n * The question still awaiting an answer: the last assistant block, unless the\n * user has already replied after it. Scanning backwards means a stale card from\n * earlier in the thread never reappears.\n */\nexport function pendingAskUser(messages: ReadonlyArray<{ role: string; content: string }>): AskUserPayload | null {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (msg.role === 'user') return null;\n const parsed = msg.role === 'assistant' ? parseAskUser(msg.content) : null;\n if (parsed) return answeredAnywhere(parsed, messages) ? null : parsed;\n }\n return null;\n}\n\n/**\n * An answer sent while the asking turn was still open is saved BEFORE that\n * turn's reply (which carries the question and everything after it), so \"a user\n * message after the question\" misses it. The answer names its question\n * (`**Title:** answer`), so it is found wherever it sits.\n */\nfunction answeredAnywhere(ask: AskUserPayload, messages: ReadonlyArray<{ role: string; content: string }>): boolean {\n const prefixes = ask.questions.map((q) => `**${q.title.replace(/:\\s*$/, '')}:**`);\n return messages.some((m) => m.role === 'user' && prefixes.some((prefix) => (m.content ?? '').includes(prefix)));\n}\n\n/**\n * Fold the answers into the single visible reply message:\n *\n * **Which database?:** Postgres\n *\n * Skipped questions are omitted; an empty result means \"nothing to send\", which\n * the card treats as a dismiss.\n */\nexport function formatAskUserAnswers(questions: readonly AskUserQuestion[], answers: Record<string, string>): string {\n return questions\n .map((q) => {\n const answer = answers[q.id]?.trim();\n return answer ? `**${q.title.replace(/:\\s*$/, '')}:** ${answer}` : null;\n })\n .filter(Boolean)\n .join('\\n\\n');\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"askUser.js","sources":["../../../src/features/chat/askUser.ts"],"sourcesContent":["/**\n * The `[ASK_USER]` clarifying-question protocol, mobile side (Clockbook #1643).\n *\n * cdecli emits the block itself — from Claude's AskUserQuestion and its own\n * ask_user_question tool — and PARKS the run until the answer arrives:\n *\n * [ASK_USER]{\"requestId\":\"ask-…\",\"questions\":[{\"id\":\"q1\",\"title\":\"Which\n * database?\",\"header\":\"Database\",\"options\":[{\"id\":\"o1\",\"label\":\"Postgres\",\n * \"detail\":\"…\"}],\"allowText\":true}]}[/ASK_USER]\n *\n * The reply is deliberately NOT a marker: answers are formatted into one visible\n * user message (`**Title:** answer` lines) and sent through the normal chat path,\n * so the producer needs no reply-protocol support. Only the question side is\n * structured.\n *\n * Deliberately a copy of the web's `responsePromptProtocol` rather than an\n * import — mobile is a separate bundle and shares no code with the web shell.\n * The reply side is plain text, so the two stay compatible without a shared\n * version.\n */\n\nexport interface AskUserOption {\n id: string;\n label: string;\n /** Secondary line under the label. */\n detail?: string;\n /** \"Something else\": focuses the free-text row instead of answering. */\n other?: boolean;\n}\n\nexport interface AskUserQuestion {\n id: string;\n /** Also the bold prefix of the formatted answer. */\n title: string;\n /** Short category eyebrow above the title, e.g. \"Database\". */\n header?: string;\n options?: AskUserOption[];\n /** Show the free-text row (default true). */\n allowText?: boolean;\n textPlaceholder?: string;\n /** Pick several options; the answer is sent as comma-joined labels. */\n multiSelect?: boolean;\n /** `approval` when the agent's action gate asks permission rather than clarifying. */\n kind?: 'approval';\n /** What the approval is for; present with `kind: 'approval'`. */\n approval?: ApprovalDetails;\n}\n\nexport type ApprovalCategory = 'send' | 'spend' | 'book' | 'contact' | 'share' | 'delete' | 'change';\n\nexport interface ApprovalMedia {\n url: string;\n kind: 'image' | 'video';\n}\n\n/** The action an approval question is about, as cdecli's action gate describes it. */\nexport interface ApprovalDetails {\n connector: string;\n action?: string;\n title: string;\n category: ApprovalCategory;\n summary?: string;\n count?: number;\n media?: ApprovalMedia[];\n}\n\n/** True when a question asks permission for an action. */\nexport function isApprovalQuestion(\n q: AskUserQuestion | undefined,\n): q is AskUserQuestion & { approval: ApprovalDetails } {\n return q?.kind === 'approval' && !!q.approval && typeof q.approval.connector === 'string';\n}\n\nexport interface AskUserPayload {\n requestId: string;\n questions: AskUserQuestion[];\n}\n\n/** Anything longer is a form, not a prompt — the web caps it the same way. */\nexport const MAX_ASK_USER_QUESTIONS = 4;\n\n// Not anchored: the channel layer may prepend a stream envelope or cost banner.\nconst ASK_USER_RE = /\\[ASK_USER\\]([\\s\\S]*?)\\[\\/ASK_USER\\]/;\nconst ASK_USER_OPEN_RE = /\\[ASK_USER\\]/;\n\nfunction unwrapJsonCandidate(inner: string): string {\n let s = inner.trim();\n const fence = /^```(?:json)?\\s*([\\s\\S]*?)\\s*```$/i.exec(s);\n if (fence) s = fence[1].trim();\n return s;\n}\n\n/** First complete `{...}` object in `s`, or null while the JSON is still streaming. */\nfunction parseJsonObject(s: string): unknown | null {\n const start = s.indexOf('{');\n if (start < 0) return null;\n let depth = 0;\n let inStr = false;\n let esc = false;\n for (let i = start; i < s.length; i++) {\n const c = s[i];\n if (inStr) {\n if (esc) {\n esc = false;\n continue;\n }\n if (c === '\\\\') {\n esc = true;\n continue;\n }\n if (c === '\"') inStr = false;\n continue;\n }\n if (c === '\"') {\n inStr = true;\n continue;\n }\n if (c === '{') depth += 1;\n else if (c === '}') {\n depth -= 1;\n if (depth === 0) {\n try {\n return JSON.parse(s.slice(start, i + 1));\n } catch {\n return null;\n }\n }\n }\n }\n return null;\n}\n\nfunction normalizeQuestion(raw: unknown): AskUserQuestion | null {\n if (!raw || typeof raw !== 'object') return null;\n const q = raw as Record<string, unknown>;\n const id = typeof q.id === 'string' ? q.id : '';\n const title = typeof q.title === 'string' ? q.title : typeof q.question === 'string' ? q.question : '';\n if (!id || !title.trim()) return null;\n const options = Array.isArray(q.options)\n ? q.options.filter(\n (o): o is AskUserOption =>\n !!o &&\n typeof o === 'object' &&\n typeof (o as AskUserOption).id === 'string' &&\n typeof (o as AskUserOption).label === 'string',\n )\n : undefined;\n return {\n id,\n title: title.trim(),\n header: typeof q.header === 'string' ? q.header : undefined,\n options,\n allowText: q.allowText !== false,\n textPlaceholder: typeof q.textPlaceholder === 'string' ? q.textPlaceholder : undefined,\n multiSelect: q.multiSelect === true,\n ...(q.kind === 'approval' && q.approval && typeof q.approval === 'object'\n ? { kind: 'approval' as const, approval: q.approval as ApprovalDetails }\n : {}),\n };\n}\n\n/** Parse an `[ASK_USER]…[/ASK_USER]` message, or null if it isn't one. */\nexport function parseAskUser(raw: string | null | undefined): AskUserPayload | null {\n if (!raw?.trim()) return null;\n const tagged = ASK_USER_RE.exec(raw) ?? (ASK_USER_OPEN_RE.test(raw) ? /\\[ASK_USER\\]([\\s\\S]*)$/.exec(raw) : null);\n if (!tagged) return null;\n const parsed = parseJsonObject(unwrapJsonCandidate(tagged[1]));\n if (!parsed || typeof parsed !== 'object') return null;\n const body = parsed as { requestId?: unknown; questions?: unknown };\n if (typeof body.requestId !== 'string' || !Array.isArray(body.questions)) return null;\n const questions = body.questions\n .map(normalizeQuestion)\n .filter((q): q is AskUserQuestion => q !== null)\n .slice(0, MAX_ASK_USER_QUESTIONS);\n return questions.length ? { requestId: body.requestId, questions } : null;\n}\n\n/**\n * Remove every `[ASK_USER]` block, leaving the rest of the message intact.\n *\n * cdecli emits the block MID-turn and keeps streaming its reply into the SAME\n * message once the answer releases the parked run, so the block and the reply it\n * was asked for share one message. Hiding the whole message — which is what a\n * naive implementation does — would swallow that reply.\n *\n * An unclosed `[ASK_USER]` (still streaming) is also stripped so the raw JSON\n * never paints in the bubble the way it does on web after `stripAskUser`.\n */\nexport function stripAskUser(raw: string | null | undefined): string {\n if (!raw) return '';\n let stripped = raw.replace(new RegExp(ASK_USER_RE.source, 'g'), '');\n stripped = stripped.replace(/\\[ASK_USER\\][\\s\\S]*$/, '');\n if (stripped === raw) return raw;\n return stripped.replace(/\\n{3,}/g, '\\n\\n').trim();\n}\n\n/**\n * Text around an `[ASK_USER]` marker. cdecli often speaks an intro *before* the\n * card (\"I'll need a couple more details…\") and streams the real reply *after*\n * the user answers. Once there is a user reply, the intro is stale.\n */\nexport function splitAskUserParts(raw: string | null | undefined): {\n before: string;\n after: string;\n hasMarker: boolean;\n} {\n if (!raw) return { before: '', after: '', hasMarker: false };\n const tagged = ASK_USER_RE.exec(raw);\n if (tagged && tagged.index !== undefined) {\n return {\n before: raw.slice(0, tagged.index).trim(),\n after: raw.slice(tagged.index + tagged[0].length).trim(),\n hasMarker: true,\n };\n }\n const open = raw.search(ASK_USER_OPEN_RE);\n if (open >= 0) {\n return { before: raw.slice(0, open).trim(), after: '', hasMarker: true };\n }\n return { before: '', after: '', hasMarker: false };\n}\n\n/**\n * Assistant prose to paint. After the user answers the card, drop the intro that\n * sat above `[ASK_USER]` so we don't re-ask for details already in the thread.\n */\nexport function displayAskUserAssistantText(raw: string | null | undefined, answered: boolean): string {\n const parts = splitAskUserParts(raw);\n if (!parts.hasMarker) return stripAskUser(raw);\n const keep = answered ? parts.after : [parts.before, parts.after].filter(Boolean).join('\\n\\n');\n return stripAskUser(keep || (answered ? '' : parts.before));\n}\n\n/**\n * The question still awaiting an answer: the last assistant block, unless the\n * user has already replied after it. Scanning backwards means a stale card from\n * earlier in the thread never reappears.\n */\nexport function pendingAskUser(messages: ReadonlyArray<{ role: string; content: string }>): AskUserPayload | null {\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (msg.role === 'user') return null;\n const parsed = msg.role === 'assistant' ? parseAskUser(msg.content) : null;\n if (parsed) return answeredAnywhere(parsed, messages) ? null : parsed;\n }\n return null;\n}\n\n/**\n * An answer sent while the asking turn was still open is saved BEFORE that\n * turn's reply (which carries the question and everything after it), so \"a user\n * message after the question\" misses it. The answer names its question\n * (`**Title:** answer`), so it is found wherever it sits.\n */\nfunction answeredAnywhere(ask: AskUserPayload, messages: ReadonlyArray<{ role: string; content: string }>): boolean {\n const prefixes = ask.questions.map((q) => `**${q.title.replace(/:\\s*$/, '')}:**`);\n return messages.some((m) => m.role === 'user' && prefixes.some((prefix) => (m.content ?? '').includes(prefix)));\n}\n\n/**\n * Fold the answers into the single visible reply message:\n *\n * **Which database?:** Postgres\n *\n * Skipped questions are omitted; an empty result means \"nothing to send\", which\n * the card treats as a dismiss.\n */\nexport function formatAskUserAnswers(questions: readonly AskUserQuestion[], answers: Record<string, string>): string {\n return questions\n .map((q) => {\n const answer = answers[q.id]?.trim();\n return answer ? `**${q.title.replace(/:\\s*$/, '')}:** ${answer}` : null;\n })\n .filter(Boolean)\n .join('\\n\\n');\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
function queuedFollowUpRows(messages, queued) {
|
|
2
|
+
var _a;
|
|
3
|
+
const waiting = queued.map((q) => q.text.trim());
|
|
4
|
+
const rows = /* @__PURE__ */ new Set();
|
|
5
|
+
for (let i = messages.length - 1; i >= 0 && waiting.length > 0; i -= 1) {
|
|
6
|
+
const match = messages[i].role === "user" ? waiting.indexOf(((_a = messages[i].content) != null ? _a : "").trim()) : -1;
|
|
7
|
+
if (match >= 0) {
|
|
8
|
+
rows.add(i);
|
|
9
|
+
waiting.splice(match, 1);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
return rows;
|
|
13
|
+
}export{queuedFollowUpRows};//# sourceMappingURL=queuedFollowUpRows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queuedFollowUpRows.js","sources":["../../../src/features/chat/queuedFollowUpRows.ts"],"sourcesContent":["/**\n * Where the messages queued mid-reply sit in the thread.\n *\n * A queued message is persisted as it is sent, so the next backend hydration\n * brings it into `messages` while it still waits; until the agent starts on it,\n * it belongs in the queue strip above the composer (QueuedFollowUps), not in the\n * thread above the reply it is waiting behind. The main Chat screen and every\n * surface's agent pane hide it the same way.\n *\n * Mobile twin of the web's `queuedFollowUpRows`.\n */\n\n/** Indexes of the newest user rows that are the queued messages' persisted copies. */\nexport function queuedFollowUpRows(\n messages: ReadonlyArray<{ role: string; content?: string | null }>,\n queued: ReadonlyArray<{ text: string }>,\n): Set<number> {\n const waiting = queued.map((q) => q.text.trim());\n const rows = new Set<number>();\n for (let i = messages.length - 1; i >= 0 && waiting.length > 0; i -= 1) {\n const match = messages[i].role === 'user' ? waiting.indexOf((messages[i].content ?? '').trim()) : -1;\n if (match >= 0) {\n rows.add(i);\n waiting.splice(match, 1);\n }\n }\n return rows;\n}\n"],"names":[],"mappings":"AAagB,SAAA,kBAAA,CAAmB,UAG/B,MAEa,EAAA;AAlBjB,EAAA,IAAA,EAAA;AAmBE,EAAA,MAAM,UAAU,MAAO,CAAA,GAAA,CAAI,OAAK,CAAE,CAAA,IAAA,CAAK,MAAM,CAAA;AAC7C,EAAM,MAAA,IAAA,uBAAW,GAAY,EAAA;AAC7B,EAAS,KAAA,IAAA,CAAA,GAAI,QAAS,CAAA,MAAA,GAAS,CAAG,EAAA,CAAA,IAAK,KAAK,OAAQ,CAAA,MAAA,GAAS,CAAG,EAAA,CAAA,IAAK,CAAG,EAAA;AACtE,IAAA,MAAM,QAAQ,QAAS,CAAA,CAAC,CAAE,CAAA,IAAA,KAAS,SAAS,OAAQ,CAAA,OAAA,CAAA,CAAA,CAAS,EAAS,GAAA,QAAA,CAAA,CAAC,EAAE,OAAZ,KAAA,IAAA,GAAA,EAAA,GAAuB,EAAI,EAAA,IAAA,EAAM,CAAI,GAAA,EAAA;AAClG,IAAA,IAAI,SAAS,CAAG,EAAA;AACd,MAAA,IAAA,CAAK,IAAI,CAAC,CAAA;AACV,MAAQ,OAAA,CAAA,MAAA,CAAO,OAAO,CAAC,CAAA;AAAA;AACzB;AAEF,EAAO,OAAA,IAAA;AACT"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
const WATER_FRACTION_OF_FFM = 0.72;
|
|
2
|
+
const BONE_FRACTION_OF_FFM = 0.0497;
|
|
3
|
+
const round1 = (n) => Math.round(n * 10) / 10;
|
|
4
|
+
const round2 = (n) => Math.round(n * 100) / 100;
|
|
5
|
+
function computeBodyComposition(input) {
|
|
6
|
+
const {
|
|
7
|
+
weightKg,
|
|
8
|
+
bodyFatPct,
|
|
9
|
+
heightCm,
|
|
10
|
+
age
|
|
11
|
+
} = input;
|
|
12
|
+
const male = input.sex === "male";
|
|
13
|
+
const heightM = heightCm / 100;
|
|
14
|
+
const bmi = heightM > 0 ? weightKg / (heightM * heightM) : 0;
|
|
15
|
+
const fat = Math.max(0, Math.min(75, bodyFatPct)) / 100;
|
|
16
|
+
const fatMassKg = weightKg * fat;
|
|
17
|
+
const leanMassKg = weightKg - fatMassKg;
|
|
18
|
+
const boneMassKg = leanMassKg * BONE_FRACTION_OF_FFM;
|
|
19
|
+
const muscleMassKg = leanMassKg - boneMassKg;
|
|
20
|
+
const bodyWaterKg = leanMassKg * WATER_FRACTION_OF_FFM;
|
|
21
|
+
const proteinKg = Math.max(0, leanMassKg - bodyWaterKg - boneMassKg);
|
|
22
|
+
let skeletalMuscleMassKg;
|
|
23
|
+
if (input.impedanceOhm && input.impedanceOhm > 0) {
|
|
24
|
+
const sexTerm = male ? 3.825 : 0;
|
|
25
|
+
skeletalMuscleMassKg = 0.401 * (heightCm * heightCm) / input.impedanceOhm + sexTerm - 0.071 * age + 5.102;
|
|
26
|
+
skeletalMuscleMassKg = Math.max(0, Math.min(muscleMassKg, skeletalMuscleMassKg));
|
|
27
|
+
} else {
|
|
28
|
+
skeletalMuscleMassKg = muscleMassKg * (male ? 0.68 : 0.62);
|
|
29
|
+
}
|
|
30
|
+
const bmr = Math.round(370 + 21.6 * leanMassKg);
|
|
31
|
+
const metabolicAge = estimateMetabolicAge(bmr, heightCm, male, age);
|
|
32
|
+
const visceralFat = Math.max(1, Math.min(59, Math.round(fatMassKg * (male ? 1 : 0.85) / 2.2 + age / 12 - 3)));
|
|
33
|
+
const subcutaneousFatPct = Math.max(0, bodyFatPct - visceralFat * 0.33);
|
|
34
|
+
const pct = (kg) => weightKg > 0 ? kg / weightKg * 100 : 0;
|
|
35
|
+
return {
|
|
36
|
+
bmi: round1(bmi),
|
|
37
|
+
fatMassKg: round2(fatMassKg),
|
|
38
|
+
leanMassKg: round2(leanMassKg),
|
|
39
|
+
muscleMassKg: round2(muscleMassKg),
|
|
40
|
+
musclePct: round1(pct(muscleMassKg)),
|
|
41
|
+
skeletalMuscleMassKg: round2(skeletalMuscleMassKg),
|
|
42
|
+
skeletalMusclePct: round1(pct(skeletalMuscleMassKg)),
|
|
43
|
+
boneMassKg: round2(boneMassKg),
|
|
44
|
+
bonePct: round1(pct(boneMassKg)),
|
|
45
|
+
bodyWaterKg: round2(bodyWaterKg),
|
|
46
|
+
bodyWaterPct: round1(pct(bodyWaterKg)),
|
|
47
|
+
proteinKg: round2(proteinKg),
|
|
48
|
+
proteinPct: round1(pct(proteinKg)),
|
|
49
|
+
bmr,
|
|
50
|
+
metabolicAge,
|
|
51
|
+
visceralFat,
|
|
52
|
+
subcutaneousFatPct: round1(subcutaneousFatPct)
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function compositionRows(c, units = "metric") {
|
|
56
|
+
const kg = (v) => units === "imperial" ? `${Math.round(v / 0.45359237 * 10) / 10} lb` : `${v} kg`;
|
|
57
|
+
const pct = (v) => `${v}%`;
|
|
58
|
+
return [{
|
|
59
|
+
label: "BMI",
|
|
60
|
+
value: String(c.bmi)
|
|
61
|
+
}, {
|
|
62
|
+
label: "Fat mass",
|
|
63
|
+
value: kg(c.fatMassKg)
|
|
64
|
+
}, {
|
|
65
|
+
label: "Fat-free mass",
|
|
66
|
+
value: kg(c.leanMassKg)
|
|
67
|
+
}, {
|
|
68
|
+
label: "Muscle mass",
|
|
69
|
+
value: kg(c.muscleMassKg)
|
|
70
|
+
}, {
|
|
71
|
+
label: "Muscle",
|
|
72
|
+
value: pct(c.musclePct)
|
|
73
|
+
}, {
|
|
74
|
+
label: "Skeletal muscle",
|
|
75
|
+
value: kg(c.skeletalMuscleMassKg)
|
|
76
|
+
}, {
|
|
77
|
+
label: "Bone mass",
|
|
78
|
+
value: kg(c.boneMassKg)
|
|
79
|
+
}, {
|
|
80
|
+
label: "Body water",
|
|
81
|
+
value: pct(c.bodyWaterPct)
|
|
82
|
+
}, {
|
|
83
|
+
label: "Protein",
|
|
84
|
+
value: pct(c.proteinPct)
|
|
85
|
+
}, {
|
|
86
|
+
label: "BMR",
|
|
87
|
+
value: `${c.bmr} kcal`
|
|
88
|
+
}, {
|
|
89
|
+
label: "Metabolic age",
|
|
90
|
+
value: `${c.metabolicAge} yrs`
|
|
91
|
+
}, {
|
|
92
|
+
label: "Visceral fat",
|
|
93
|
+
value: String(c.visceralFat)
|
|
94
|
+
}, {
|
|
95
|
+
label: "Subcutaneous fat",
|
|
96
|
+
value: pct(c.subcutaneousFatPct)
|
|
97
|
+
}];
|
|
98
|
+
}
|
|
99
|
+
function estimateMetabolicAge(bmr, heightCm, male, age) {
|
|
100
|
+
const ffmAt = (a) => {
|
|
101
|
+
const base = male ? 0.407 * heightCm - 15 : 0.357 * heightCm - 13;
|
|
102
|
+
const decline = a > 25 ? (a - 25) * 0.1 : 0;
|
|
103
|
+
return Math.max(20, base - decline);
|
|
104
|
+
};
|
|
105
|
+
const bmrAt = (a) => 370 + 21.6 * ffmAt(a);
|
|
106
|
+
let best = age;
|
|
107
|
+
let bestDiff = Infinity;
|
|
108
|
+
for (let a = 18; a <= 80; a++) {
|
|
109
|
+
const diff = Math.abs(bmrAt(a) - bmr);
|
|
110
|
+
if (diff < bestDiff) {
|
|
111
|
+
bestDiff = diff;
|
|
112
|
+
best = a;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return best;
|
|
116
|
+
}export{compositionRows,computeBodyComposition};//# sourceMappingURL=bodyComposition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bodyComposition.js","sources":["../../../src/features/devices/bodyComposition.ts"],"sourcesContent":["/**\n * Full body composition from a scale reading, using established published\n * formulas (not any vendor's proprietary coefficients).\n *\n * A body-fat scale measures weight and bioelectrical impedance and, from the\n * person's height/age/sex, estimates body-fat percentage. Everything else a\n * scale app shows (fat-free mass, muscle, bone, body water, protein, BMR,\n * metabolic age, visceral/subcutaneous fat) is derived from weight and body\n * fat with standard equations:\n *\n * - Fat mass / fat-free mass: definitional.\n * - Total body water: FFM is ~72% water (the standard hydration constant).\n * - Bone mineral: a small, roughly fixed fraction of fat-free mass.\n * - Muscle mass = fat-free mass minus bone mineral; protein is the dry\n * non-mineral remainder.\n * - BMR: Katch-McArdle (370 + 21.6 x FFM), which depends only on lean mass.\n * - Skeletal muscle: Janssen's impedance equation when impedance is known.\n *\n * These reproduce a RENPHO/QN scale's derived numbers closely because the scale\n * uses the same public science; the only vendor-specific step is the body-fat\n * estimate, which the device sends directly, so Yantra does not recompute it.\n */\n\nexport interface BodyCompositionInput {\n weightKg: number;\n bodyFatPct: number;\n heightCm: number;\n age: number;\n sex: 'male' | 'female' | 'unspecified';\n /** Whole-body impedance in ohms, when the scale reported it (for skeletal muscle). */\n impedanceOhm?: number;\n}\n\nexport interface BodyComposition {\n bmi: number;\n fatMassKg: number;\n /** Fat-free (lean) mass. */\n leanMassKg: number;\n muscleMassKg: number;\n musclePct: number;\n skeletalMuscleMassKg: number;\n skeletalMusclePct: number;\n boneMassKg: number;\n bonePct: number;\n bodyWaterKg: number;\n bodyWaterPct: number;\n proteinKg: number;\n proteinPct: number;\n /** Basal metabolic rate, kcal/day. */\n bmr: number;\n metabolicAge: number;\n /** Visceral fat rating (unitless, like the scale's 1-59 scale). */\n visceralFat: number;\n subcutaneousFatPct: number;\n}\n\n/** Fraction of fat-free mass that is water (standard hydration constant). */\nconst WATER_FRACTION_OF_FFM = 0.72;\n/** Fraction of fat-free mass that is bone mineral. */\nconst BONE_FRACTION_OF_FFM = 0.0497;\n\nconst round1 = (n: number) => Math.round(n * 10) / 10;\nconst round2 = (n: number) => Math.round(n * 100) / 100;\n\nexport function computeBodyComposition(input: BodyCompositionInput): BodyComposition {\n const { weightKg, bodyFatPct, heightCm, age } = input;\n const male = input.sex === 'male';\n const heightM = heightCm / 100;\n\n const bmi = heightM > 0 ? weightKg / (heightM * heightM) : 0;\n const fat = Math.max(0, Math.min(75, bodyFatPct)) / 100;\n const fatMassKg = weightKg * fat;\n const leanMassKg = weightKg - fatMassKg;\n\n const boneMassKg = leanMassKg * BONE_FRACTION_OF_FFM;\n const muscleMassKg = leanMassKg - boneMassKg;\n const bodyWaterKg = leanMassKg * WATER_FRACTION_OF_FFM;\n const proteinKg = Math.max(0, leanMassKg - bodyWaterKg - boneMassKg);\n\n // Skeletal muscle: Janssen (2000) when impedance is known, else a fraction of muscle.\n let skeletalMuscleMassKg: number;\n if (input.impedanceOhm && input.impedanceOhm > 0) {\n const sexTerm = male ? 3.825 : 0;\n skeletalMuscleMassKg =\n (0.401 * (heightCm * heightCm)) / input.impedanceOhm + sexTerm - 0.071 * age + 5.102;\n skeletalMuscleMassKg = Math.max(0, Math.min(muscleMassKg, skeletalMuscleMassKg));\n } else {\n skeletalMuscleMassKg = muscleMassKg * (male ? 0.68 : 0.62);\n }\n\n // Katch-McArdle: basal metabolic rate from lean mass.\n const bmr = Math.round(370 + 21.6 * leanMassKg);\n\n // Metabolic age: how old the person's BMR looks against the BMR a lean,\n // average person of their height would have at each age. Clamped to 18-80.\n const metabolicAge = estimateMetabolicAge(bmr, heightCm, male, age);\n\n // Visceral fat rating: rises with body-fat mass and age; a standard-style\n // index (not a clinical measure), clamped to the usual 1-59 range.\n const visceralFat = Math.max(\n 1,\n Math.min(59, Math.round((fatMassKg * (male ? 1.0 : 0.85)) / 2.2 + age / 12 - 3)),\n );\n // Subcutaneous fat is the body fat that is not visceral.\n const subcutaneousFatPct = Math.max(0, bodyFatPct - visceralFat * 0.33);\n\n const pct = (kg: number) => (weightKg > 0 ? (kg / weightKg) * 100 : 0);\n return {\n bmi: round1(bmi),\n fatMassKg: round2(fatMassKg),\n leanMassKg: round2(leanMassKg),\n muscleMassKg: round2(muscleMassKg),\n musclePct: round1(pct(muscleMassKg)),\n skeletalMuscleMassKg: round2(skeletalMuscleMassKg),\n skeletalMusclePct: round1(pct(skeletalMuscleMassKg)),\n boneMassKg: round2(boneMassKg),\n bonePct: round1(pct(boneMassKg)),\n bodyWaterKg: round2(bodyWaterKg),\n bodyWaterPct: round1(pct(bodyWaterKg)),\n proteinKg: round2(proteinKg),\n proteinPct: round1(pct(proteinKg)),\n bmr,\n metabolicAge,\n visceralFat,\n subcutaneousFatPct: round1(subcutaneousFatPct),\n };\n}\n\n/** The composition as labelled rows for a details view, in the person's units. */\nexport function compositionRows(\n c: BodyComposition,\n units: 'metric' | 'imperial' = 'metric',\n): Array<{ label: string; value: string }> {\n const kg = (v: number) =>\n units === 'imperial' ? `${Math.round((v / 0.45359237) * 10) / 10} lb` : `${v} kg`;\n const pct = (v: number) => `${v}%`;\n return [\n { label: 'BMI', value: String(c.bmi) },\n { label: 'Fat mass', value: kg(c.fatMassKg) },\n { label: 'Fat-free mass', value: kg(c.leanMassKg) },\n { label: 'Muscle mass', value: kg(c.muscleMassKg) },\n { label: 'Muscle', value: pct(c.musclePct) },\n { label: 'Skeletal muscle', value: kg(c.skeletalMuscleMassKg) },\n { label: 'Bone mass', value: kg(c.boneMassKg) },\n { label: 'Body water', value: pct(c.bodyWaterPct) },\n { label: 'Protein', value: pct(c.proteinPct) },\n { label: 'BMR', value: `${c.bmr} kcal` },\n { label: 'Metabolic age', value: `${c.metabolicAge} yrs` },\n { label: 'Visceral fat', value: String(c.visceralFat) },\n { label: 'Subcutaneous fat', value: pct(c.subcutaneousFatPct) },\n ];\n}\n\n/** Compare the person's BMR to the typical BMR by age for their height and sex. */\nfunction estimateMetabolicAge(bmr: number, heightCm: number, male: boolean, age: number): number {\n // Typical fat-free mass by age (slow decline past 25), then its Katch-McArdle BMR.\n const ffmAt = (a: number) => {\n const base = male ? 0.407 * heightCm - 15 : 0.357 * heightCm - 13;\n const decline = a > 25 ? (a - 25) * 0.1 : 0;\n return Math.max(20, base - decline);\n };\n const bmrAt = (a: number) => 370 + 21.6 * ffmAt(a);\n let best = age;\n let bestDiff = Infinity;\n for (let a = 18; a <= 80; a++) {\n const diff = Math.abs(bmrAt(a) - bmr);\n if (diff < bestDiff) {\n bestDiff = diff;\n best = a;\n }\n }\n return best;\n}\n"],"names":[],"mappings":"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"}
|