@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.
Files changed (220) hide show
  1. package/lib/features/agent-chat/NativeAgentChat.js +21 -4
  2. package/lib/features/agent-chat/NativeAgentChat.js.map +1 -1
  3. package/lib/features/chat/ApprovalCard.js +353 -0
  4. package/lib/features/chat/ApprovalCard.js.map +1 -0
  5. package/lib/features/chat/AskUserCard.js +9 -2
  6. package/lib/features/chat/AskUserCard.js.map +1 -1
  7. package/lib/features/chat/askUser.js +25 -3
  8. package/lib/features/chat/askUser.js.map +1 -1
  9. package/lib/features/chat/queuedFollowUpRows.js +13 -0
  10. package/lib/features/chat/queuedFollowUpRows.js.map +1 -0
  11. package/lib/features/devices/bodyComposition.js +116 -0
  12. package/lib/features/devices/bodyComposition.js.map +1 -0
  13. package/lib/features/devices/readings.js.map +1 -1
  14. package/lib/features/devices/session.js +22 -2
  15. package/lib/features/devices/session.js.map +1 -1
  16. package/lib/features/discover/DiscoverArticle.js +105 -92
  17. package/lib/features/discover/DiscoverArticle.js.map +1 -1
  18. package/lib/features/discover/DiscoverFeed.js +97 -48
  19. package/lib/features/discover/DiscoverFeed.js.map +1 -1
  20. package/lib/features/discover/DiscoverFollowUp.js +135 -0
  21. package/lib/features/discover/DiscoverFollowUp.js.map +1 -0
  22. package/lib/features/discover/DiscoverSidebar.js +555 -0
  23. package/lib/features/discover/DiscoverSidebar.js.map +1 -0
  24. package/lib/features/discover/DiscoverSkeletons.js +123 -0
  25. package/lib/features/discover/DiscoverSkeletons.js.map +1 -0
  26. package/lib/features/discover/DiscoverStoryCards.js +193 -87
  27. package/lib/features/discover/DiscoverStoryCards.js.map +1 -1
  28. package/lib/features/discover/followUpQuery.js +42 -0
  29. package/lib/features/discover/followUpQuery.js.map +1 -0
  30. package/lib/features/discover/markets.js +37 -0
  31. package/lib/features/discover/markets.js.map +1 -0
  32. package/lib/features/discover/useDiscoverSidebar.js +148 -0
  33. package/lib/features/discover/useDiscoverSidebar.js.map +1 -0
  34. package/lib/features/discover/weather.js +42 -0
  35. package/lib/features/discover/weather.js.map +1 -0
  36. package/lib/features/expenses/ExpensesAgentChatPane.js +1 -1
  37. package/lib/features/expenses/ExpensesAgentChatPane.js.map +1 -1
  38. package/lib/features/inbox/InboxAgentChatPane.js +1 -1
  39. package/lib/features/inbox/InboxAgentChatPane.js.map +1 -1
  40. package/lib/features/job-search/JobSearchAgentChatPane.js +1 -0
  41. package/lib/features/job-search/JobSearchAgentChatPane.js.map +1 -1
  42. package/lib/features/local-services/LocalServicesAgentChatPane.js +1 -1
  43. package/lib/features/local-services/LocalServicesAgentChatPane.js.map +1 -1
  44. package/lib/features/movies/MoviesAgentChatPane.js +1 -1
  45. package/lib/features/movies/MoviesAgentChatPane.js.map +1 -1
  46. package/lib/features/notion/NotionBlockSheets.js +206 -0
  47. package/lib/features/notion/NotionBlockSheets.js.map +1 -0
  48. package/lib/features/notion/NotionBlockView.js +36 -0
  49. package/lib/features/notion/NotionBlockView.js.map +1 -0
  50. package/lib/features/notion/NotionCommentsSheet.js +461 -0
  51. package/lib/features/notion/NotionCommentsSheet.js.map +1 -0
  52. package/lib/features/notion/NotionConnectionsSheet.js +244 -0
  53. package/lib/features/notion/NotionConnectionsSheet.js.map +1 -0
  54. package/lib/features/notion/NotionHistorySheet.js +439 -0
  55. package/lib/features/notion/NotionHistorySheet.js.map +1 -0
  56. package/lib/features/notion/NotionMediaBlocks.js +803 -0
  57. package/lib/features/notion/NotionMediaBlocks.js.map +1 -0
  58. package/lib/features/notion/NotionMentionSheet.js +279 -0
  59. package/lib/features/notion/NotionMentionSheet.js.map +1 -0
  60. package/lib/features/notion/NotionPageMenu.js +585 -0
  61. package/lib/features/notion/NotionPageMenu.js.map +1 -0
  62. package/lib/features/notion/NotionPageTree.js +220 -0
  63. package/lib/features/notion/NotionPageTree.js.map +1 -0
  64. package/lib/features/notion/NotionPageView.js +1253 -152
  65. package/lib/features/notion/NotionPageView.js.map +1 -1
  66. package/lib/features/notion/NotionShareSheet.js +606 -0
  67. package/lib/features/notion/NotionShareSheet.js.map +1 -0
  68. package/lib/features/notion/NotionSheets.js +87 -15
  69. package/lib/features/notion/NotionSheets.js.map +1 -1
  70. package/lib/features/notion/NotionSidebarSections.js +492 -0
  71. package/lib/features/notion/NotionSidebarSections.js.map +1 -0
  72. package/lib/features/notion/NotionWorkspaceAdmin.js +659 -0
  73. package/lib/features/notion/NotionWorkspaceAdmin.js.map +1 -0
  74. package/lib/features/notion/NotionWorkspaceView.js +257 -45
  75. package/lib/features/notion/NotionWorkspaceView.js.map +1 -1
  76. package/lib/features/notion/database/DatabaseCells.js +554 -0
  77. package/lib/features/notion/database/DatabaseCells.js.map +1 -0
  78. package/lib/features/notion/database/DatabaseDateLayouts.js +792 -0
  79. package/lib/features/notion/database/DatabaseDateLayouts.js.map +1 -0
  80. package/lib/features/notion/database/DatabaseLayouts.js +461 -0
  81. package/lib/features/notion/database/DatabaseLayouts.js.map +1 -0
  82. package/lib/features/notion/database/DatabaseSheets.js +791 -0
  83. package/lib/features/notion/database/DatabaseSheets.js.map +1 -0
  84. package/lib/features/notion/database/NotionDatabaseView.js +817 -0
  85. package/lib/features/notion/database/NotionDatabaseView.js.map +1 -0
  86. package/lib/features/notion/database/RowPropertiesPanel.js +162 -0
  87. package/lib/features/notion/database/RowPropertiesPanel.js.map +1 -0
  88. package/lib/features/notion/database/chartData.js +89 -0
  89. package/lib/features/notion/database/chartData.js.map +1 -0
  90. package/lib/features/notion/database/chartView.js +112 -0
  91. package/lib/features/notion/database/chartView.js.map +1 -0
  92. package/lib/features/notion/database/connectorButton.js +33 -0
  93. package/lib/features/notion/database/connectorButton.js.map +1 -0
  94. package/lib/features/notion/database/databaseCalc.js +208 -0
  95. package/lib/features/notion/database/databaseCalc.js.map +1 -0
  96. package/lib/features/notion/database/databaseCalendar.js +157 -0
  97. package/lib/features/notion/database/databaseCalendar.js.map +1 -0
  98. package/lib/features/notion/database/databaseCsv.js +98 -0
  99. package/lib/features/notion/database/databaseCsv.js.map +1 -0
  100. package/lib/features/notion/database/databaseCsvActions.js +58 -0
  101. package/lib/features/notion/database/databaseCsvActions.js.map +1 -0
  102. package/lib/features/notion/database/databaseFilter.js +473 -0
  103. package/lib/features/notion/database/databaseFilter.js.map +1 -0
  104. package/lib/features/notion/database/databaseFormula.js +1072 -0
  105. package/lib/features/notion/database/databaseFormula.js.map +1 -0
  106. package/lib/features/notion/database/databaseGroup.js +151 -0
  107. package/lib/features/notion/database/databaseGroup.js.map +1 -0
  108. package/lib/features/notion/database/databaseRollup.js +58 -0
  109. package/lib/features/notion/database/databaseRollup.js.map +1 -0
  110. package/lib/features/notion/database/databaseTimeline.js +156 -0
  111. package/lib/features/notion/database/databaseTimeline.js.map +1 -0
  112. package/lib/features/notion/database/databaseView.js +1188 -0
  113. package/lib/features/notion/database/databaseView.js.map +1 -0
  114. package/lib/features/notion/database/databaseViews.js +310 -0
  115. package/lib/features/notion/database/databaseViews.js.map +1 -0
  116. package/lib/features/notion/database/relationSource.js +92 -0
  117. package/lib/features/notion/database/relationSource.js.map +1 -0
  118. package/lib/features/notion/database/uniqueId.js +17 -0
  119. package/lib/features/notion/database/uniqueId.js.map +1 -0
  120. package/lib/features/notion/database/useNotionDatabase.js +617 -0
  121. package/lib/features/notion/database/useNotionDatabase.js.map +1 -0
  122. package/lib/features/notion/notionAgentRunStatus.js +39 -0
  123. package/lib/features/notion/notionAgentRunStatus.js.map +1 -0
  124. package/lib/features/notion/notionCodeLanguages.js +112 -0
  125. package/lib/features/notion/notionCodeLanguages.js.map +1 -0
  126. package/lib/features/notion/notionComments.js +86 -0
  127. package/lib/features/notion/notionComments.js.map +1 -0
  128. package/lib/features/notion/notionConnections.js +74 -0
  129. package/lib/features/notion/notionConnections.js.map +1 -0
  130. package/lib/features/notion/notionDocuments.js +453 -1
  131. package/lib/features/notion/notionDocuments.js.map +1 -1
  132. package/lib/features/notion/notionEditorModel.js +142 -7
  133. package/lib/features/notion/notionEditorModel.js.map +1 -1
  134. package/lib/features/notion/notionMarkdownShortcuts.js +51 -0
  135. package/lib/features/notion/notionMarkdownShortcuts.js.map +1 -0
  136. package/lib/features/notion/notionMedia.js +119 -0
  137. package/lib/features/notion/notionMedia.js.map +1 -0
  138. package/lib/features/notion/notionMentionDate.js +32 -0
  139. package/lib/features/notion/notionMentionDate.js.map +1 -0
  140. package/lib/features/notion/notionMentionOptions.js +162 -0
  141. package/lib/features/notion/notionMentionOptions.js.map +1 -0
  142. package/lib/features/notion/notionNotesAgent.js +445 -0
  143. package/lib/features/notion/notionNotesAgent.js.map +1 -0
  144. package/lib/features/notion/notionPageAccess.js +168 -0
  145. package/lib/features/notion/notionPageAccess.js.map +1 -0
  146. package/lib/features/notion/notionPageActions.js +138 -0
  147. package/lib/features/notion/notionPageActions.js.map +1 -0
  148. package/lib/features/notion/notionPageHistory.js +154 -0
  149. package/lib/features/notion/notionPageHistory.js.map +1 -0
  150. package/lib/features/notion/notionPageKinds.js +200 -0
  151. package/lib/features/notion/notionPageKinds.js.map +1 -0
  152. package/lib/features/notion/notionRecents.js +48 -0
  153. package/lib/features/notion/notionRecents.js.map +1 -0
  154. package/lib/features/notion/notionRichText.js +177 -0
  155. package/lib/features/notion/notionRichText.js.map +1 -0
  156. package/lib/features/notion/notionRichTitle.js +336 -0
  157. package/lib/features/notion/notionRichTitle.js.map +1 -0
  158. package/lib/features/notion/useNotionWorkspace.js +272 -13
  159. package/lib/features/notion/useNotionWorkspace.js.map +1 -1
  160. package/lib/features/notion/usePageActions.js +155 -0
  161. package/lib/features/notion/usePageActions.js.map +1 -0
  162. package/lib/features/resume/ResumeAgentChatPane.js +1 -1
  163. package/lib/features/resume/ResumeAgentChatPane.js.map +1 -1
  164. package/lib/features/shopping/ShoppingAgentChatPane.js +1 -1
  165. package/lib/features/shopping/ShoppingAgentChatPane.js.map +1 -1
  166. package/lib/features/study/StudyAgentChatPane.js +1 -1
  167. package/lib/features/study/StudyAgentChatPane.js.map +1 -1
  168. package/lib/features/travel/TravelAgentChatPane.js +1 -1
  169. package/lib/features/travel/TravelAgentChatPane.js.map +1 -1
  170. package/lib/features/webbuilder/WebBuilderExperience.js +40 -8
  171. package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -1
  172. package/lib/features/webbuilder/buildFragments.js +1 -1
  173. package/lib/features/webbuilder/buildFragments.js.map +1 -1
  174. package/lib/features/webbuilder/codeFiles.js +302 -0
  175. package/lib/features/webbuilder/codeFiles.js.map +1 -0
  176. package/lib/features/webbuilder/codeHighlight.js +209 -0
  177. package/lib/features/webbuilder/codeHighlight.js.map +1 -0
  178. package/lib/features/webbuilder/components/CodeView.js +682 -52
  179. package/lib/features/webbuilder/components/CodeView.js.map +1 -1
  180. package/lib/features/webbuilder/components/PreviewScreen.js +59 -38
  181. package/lib/features/webbuilder/components/PreviewScreen.js.map +1 -1
  182. package/lib/features/webbuilder/components/ProjectChat.js +3 -3
  183. package/lib/features/webbuilder/components/ProjectChat.js.map +1 -1
  184. package/lib/features/webbuilder/stepLabels.js +68 -0
  185. package/lib/features/webbuilder/stepLabels.js.map +1 -0
  186. package/lib/hooks/useHostChatSteering.js +45 -0
  187. package/lib/hooks/useHostChatSteering.js.map +1 -0
  188. package/lib/screens/Chat/index.js +2 -12
  189. package/lib/screens/Chat/index.js.map +1 -1
  190. package/lib/screens/Devices/index.js +205 -3
  191. package/lib/screens/Devices/index.js.map +1 -1
  192. package/lib/screens/ExpensesNative/useExpensesHostChat.js +25 -5
  193. package/lib/screens/ExpensesNative/useExpensesHostChat.js.map +1 -1
  194. package/lib/screens/InboxNative/useInboxHostChat.js +25 -5
  195. package/lib/screens/InboxNative/useInboxHostChat.js.map +1 -1
  196. package/lib/screens/JobSearchNative/useJobSearchHostChat.js +25 -5
  197. package/lib/screens/JobSearchNative/useJobSearchHostChat.js.map +1 -1
  198. package/lib/screens/LocalServicesNative/useLocalServicesHostChat.js +25 -5
  199. package/lib/screens/LocalServicesNative/useLocalServicesHostChat.js.map +1 -1
  200. package/lib/screens/MoviesNative/useMoviesHostChat.js +25 -5
  201. package/lib/screens/MoviesNative/useMoviesHostChat.js.map +1 -1
  202. package/lib/screens/NotionPage/index.js +2 -2
  203. package/lib/screens/NotionPage/index.js.map +1 -1
  204. package/lib/screens/ResumeNative/useResumeHostChat.js +25 -5
  205. package/lib/screens/ResumeNative/useResumeHostChat.js.map +1 -1
  206. package/lib/screens/ShoppingNative/useShoppingHostChat.js +25 -5
  207. package/lib/screens/ShoppingNative/useShoppingHostChat.js.map +1 -1
  208. package/lib/screens/StudyNative/useStudyHostChat.js +25 -5
  209. package/lib/screens/StudyNative/useStudyHostChat.js.map +1 -1
  210. package/lib/screens/TravelNative/useTravelHostChat.js +25 -5
  211. package/lib/screens/TravelNative/useTravelHostChat.js.map +1 -1
  212. package/lib/screens/WebBuilderNative/codeWorkspaceApi.js +222 -0
  213. package/lib/screens/WebBuilderNative/codeWorkspaceApi.js.map +1 -0
  214. package/lib/screens/WebBuilderNative/index.js +1 -1
  215. package/lib/screens/WebBuilderNative/index.js.map +1 -1
  216. package/lib/screens/WebBuilderNative/sandboxProxyApi.js +126 -4
  217. package/lib/screens/WebBuilderNative/sandboxProxyApi.js.map +1 -1
  218. package/lib/screens/WebBuilderNative/useWebBuilderHost.js +120 -11
  219. package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -1
  220. package/package.json +4 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"followUpQuery.js","sources":["../../../src/features/discover/followUpQuery.ts"],"sourcesContent":["/**\n * The first message of a Discover \"Ask follow-up\" chat, ported from the\n * browser's `pages/discover/components/DiscoverFollowUp.tsx`. Keep the two in\n * step, so a follow-up asked in the app grounds the answer the same way.\n */\nimport type { IAccountNewsArticle } from 'common';\nimport { getStoryId } from './articleContent';\n\ntype FollowUpArticle = Pick<IAccountNewsArticle, 'id' | 'slug' | 'title' | 'summary' | 'topic' | 'sources'> & {\n sourceItems?: Array<{ name: string; url?: string | null }> | null;\n};\n\n/** The article's page on the web app: `/discover/:topic/:id`, the same path the browser cites. */\nexport function discoverArticleUrl(webOrigin: string, topic: string | null | undefined, id: string): string {\n const segment = (topic ?? '').trim() || 'top';\n return `${webOrigin.replace(/\\/+$/, '')}/discover/${segment}/${encodeURIComponent(id)}`;\n}\n\nfunction hostOf(value: string): string | undefined {\n const url = /^https?:\\/\\/([^/?#]+)/i.exec(value.trim());\n if (url) return url[1].toLowerCase().replace(/^www\\./, '');\n const candidate = value.trim().toLowerCase();\n return /^[a-z0-9.-]+\\.[a-z]{2,}$/.test(candidate) ? candidate.replace(/^www\\./, '') : undefined;\n}\n\n/** Publisher domains behind the summary — the grounding the scraped `href` used to imply. */\nexport function getSourceHosts(article: Pick<FollowUpArticle, 'sourceItems' | 'sources'>): string[] {\n const raw = [...(article.sourceItems ?? []).map((item) => item.url || item.name), ...(article.sources ?? [])];\n const hosts: string[] = [];\n for (const value of raw) {\n const host = value ? hostOf(value) : undefined;\n if (host && !hosts.includes(host)) hosts.push(host);\n }\n return hosts.slice(0, 6);\n}\n\nconst MAX_TITLE_CHARS = 60;\n\n/**\n * The follow-up chat's history title: the question, capped at a word boundary,\n * as the browser's `deriveChatTitleFromQuery` names it. Without it history\n * would label every follow-up with the same article preamble.\n */\nexport function followUpChatTitle(question: string): string {\n const cleaned = question.replace(/\\s+/g, ' ').trim();\n if (!cleaned) return 'New Chat';\n if (cleaned.length <= MAX_TITLE_CHARS) return cleaned;\n const cut = cleaned.slice(0, MAX_TITLE_CHARS);\n const lastSpace = cut.lastIndexOf(' ');\n return `${cut.slice(0, lastSpace > 24 ? lastSpace : MAX_TITLE_CHARS)}…`;\n}\n\n/**\n * Seeds the chat with the article as context so the follow-up answer is grounded.\n * `Source` is the article's page on this app, not `article.href` (the scraped\n * external URL); the publisher domains carry the real attribution.\n */\nexport function buildFollowUpQuery(article: FollowUpArticle, question: string, webOrigin: string): string {\n const parts = [\"I'm reading this news article and have a follow-up question.\", '', `Title: ${article.title}`];\n\n if (article.summary) {\n parts.push(`Summary: ${article.summary}`);\n }\n\n parts.push(`Source: ${discoverArticleUrl(webOrigin, article.topic, getStoryId(article))}`);\n\n const hosts = getSourceHosts(article);\n if (hosts.length > 0) {\n parts.push(`Reported by: ${hosts.join(', ')}`);\n }\n\n parts.push('', `Question: ${question}`);\n\n return parts.join('\\n');\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ function getYahooFinanceUrl(ticker) {
2
+ return `https://finance.yahoo.com/quote/${encodeURIComponent(ticker)}`;
3
+ }
4
+ function getStockLogoUrl(ticker) {
5
+ const normalized = ticker.trim().toUpperCase();
6
+ const base = normalized.includes("-") ? normalized.split("-")[0] : normalized;
7
+ return `https://assets.parqet.com/logos/symbol/${encodeURIComponent(base)}?format=png`;
8
+ }
9
+ function getStockInitials(name, ticker) {
10
+ const fromTicker = ticker.replace(/-.*$/, "").slice(0, 2).toUpperCase();
11
+ if (fromTicker.length >= 2) return fromTicker;
12
+ return name.split(/\s+/).slice(0, 2).map((part) => {
13
+ var _a;
14
+ return (_a = part[0]) != null ? _a : "";
15
+ }).join("").toUpperCase();
16
+ }
17
+ const TILE_HUES = [212, 168, 262, 24, 338, 192, 42, 140];
18
+ function tileHue(ticker) {
19
+ let hash = 0;
20
+ for (const char of ticker) hash = hash * 31 + char.charCodeAt(0) >>> 0;
21
+ return TILE_HUES[hash % TILE_HUES.length];
22
+ }
23
+ function formatChange(changePercent, up) {
24
+ return `${up ? "+" : "\u2212"}${changePercent.replace(/^[+\-−]\s*/, "")}`;
25
+ }
26
+ const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
27
+ function clock(at) {
28
+ const hours = at.getHours();
29
+ const minutes = String(at.getMinutes()).padStart(2, "0");
30
+ return `${hours % 12 || 12}:${minutes} ${hours < 12 ? "AM" : "PM"}`;
31
+ }
32
+ function formatUpdatedAt(iso, now = /* @__PURE__ */ new Date()) {
33
+ const at = new Date(iso);
34
+ if (Number.isNaN(at.getTime()) || at.getTime() === 0) return null;
35
+ if (at.toDateString() === now.toDateString()) return clock(at);
36
+ return `${MONTHS[at.getMonth()]} ${at.getDate()}, ${clock(at)}`;
37
+ }export{formatChange,formatUpdatedAt,getStockInitials,getStockLogoUrl,getYahooFinanceUrl,tileHue};//# sourceMappingURL=markets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markets.js","sources":["../../../src/features/discover/markets.ts"],"sourcesContent":["/**\n * Market-list helpers for the Discover side panel, ported from the browser's\n * `pages/discover/utils/stockLogo.ts` and `DiscoverSharedSidebar.tsx`.\n */\n\n/** Yahoo Finance quote page for a ticker. */\nexport function getYahooFinanceUrl(ticker: string): string {\n return `https://finance.yahoo.com/quote/${encodeURIComponent(ticker)}`;\n}\n\n/**\n * Stock logo URL (no API key). Falls back to initials in the UI on error.\n * Handles crypto pairs like BTC-USD by using the base symbol for the image.\n */\nexport function getStockLogoUrl(ticker: string): string {\n const normalized = ticker.trim().toUpperCase();\n const base = normalized.includes('-') ? normalized.split('-')[0] : normalized;\n return `https://assets.parqet.com/logos/symbol/${encodeURIComponent(base)}?format=png`;\n}\n\nexport function getStockInitials(name: string, ticker: string): string {\n const fromTicker = ticker.replace(/-.*$/, '').slice(0, 2).toUpperCase();\n if (fromTicker.length >= 2) return fromTicker;\n return name\n .split(/\\s+/)\n .slice(0, 2)\n .map((part) => part[0] ?? '')\n .join('')\n .toUpperCase();\n}\n\n// Initials tiles take one of these hues, picked by the ticker, so a company keeps its colour.\nconst TILE_HUES = [212, 168, 262, 24, 338, 192, 42, 140];\n\nexport function tileHue(ticker: string): number {\n let hash = 0;\n // eslint-disable-next-line no-bitwise\n for (const char of ticker) hash = (hash * 31 + char.charCodeAt(0)) >>> 0;\n return TILE_HUES[hash % TILE_HUES.length];\n}\n\n/** \"+35.31%\" / \"−2.10%\": the sign from the direction, with a true minus. */\nexport function formatChange(changePercent: string, up: boolean): string {\n return `${up ? '+' : '−'}${changePercent.replace(/^[+\\-−]\\s*/, '')}`;\n}\n\nconst MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n\nfunction clock(at: Date): string {\n const hours = at.getHours();\n const minutes = String(at.getMinutes()).padStart(2, '0');\n return `${hours % 12 || 12}:${minutes} ${hours < 12 ? 'AM' : 'PM'}`;\n}\n\n/** \"4:05 PM\" today, \"Oct 19, 4:05 PM\" before; null for the loading placeholder's epoch. */\nexport function formatUpdatedAt(iso: string, now: Date = new Date()): string | null {\n const at = new Date(iso);\n if (Number.isNaN(at.getTime()) || at.getTime() === 0) return null;\n if (at.toDateString() === now.toDateString()) return clock(at);\n return `${MONTHS[at.getMonth()]} ${at.getDate()}, ${clock(at)}`;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,148 @@
1
+ import {useState,useEffect,useCallback}from'react';import {useGetDiscoverSidebarQuery}from'common/graphql';import {isDeviceLocationAvailable,getDeviceLocation}from'../local-services/deviceLocation.js';import {localTemperatureUnit}from'./weather.js';var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var _a;
21
+ const DEFAULT_DISCOVER_WEATHER_LOCATION = {
22
+ location: "San Francisco, CA",
23
+ latitude: 37.7749,
24
+ longitude: -122.4194
25
+ };
26
+ const DISCOVER_SIDEBAR_PLACEHOLDER = {
27
+ meta: {
28
+ sourceUrl: "https://open-meteo.com/, https://finance.yahoo.com/",
29
+ crawledAt: (/* @__PURE__ */ new Date(0)).toISOString(),
30
+ lastUpdatedLabel: "Loading\u2026"
31
+ },
32
+ weather: {
33
+ location: "San Francisco, CA",
34
+ summary: "Loading weather\u2026",
35
+ temperature: "\u2014",
36
+ unitLabel: "F",
37
+ highLow: "\u2014",
38
+ forecast: []
39
+ },
40
+ marketOutlook: [],
41
+ trendingCompanies: [],
42
+ topGainers: []
43
+ };
44
+ function placeLabel(data) {
45
+ const parts = [data.city || data.locality, data.principalSubdivision, data.countryName].filter(Boolean);
46
+ return parts.length > 0 ? parts.join(", ") : void 0;
47
+ }
48
+ async function reverseGeocode(coords) {
49
+ const query = coords ? `latitude=${coords.latitude}&longitude=${coords.longitude}&localityLanguage=en` : "localityLanguage=en";
50
+ const controller = new AbortController();
51
+ const timer = setTimeout(() => controller.abort(), 1e4);
52
+ try {
53
+ const response = await fetch(`https://api.bigdatacloud.net/data/reverse-geocode-client?${query}`, {
54
+ signal: controller.signal
55
+ });
56
+ if (!response.ok) throw new Error(`reverse geocode ${response.status}`);
57
+ return await response.json();
58
+ } finally {
59
+ clearTimeout(timer);
60
+ }
61
+ }
62
+ async function approximateLocation() {
63
+ const data = await reverseGeocode();
64
+ const {
65
+ latitude,
66
+ longitude
67
+ } = data;
68
+ if (typeof latitude !== "number" || typeof longitude !== "number") return null;
69
+ if (latitude === 0 && longitude === 0) return null;
70
+ return {
71
+ latitude,
72
+ longitude,
73
+ location: placeLabel(data)
74
+ };
75
+ }
76
+ function useDiscoverSidebarLocation() {
77
+ const [location, setLocation] = useState(DEFAULT_DISCOVER_WEATHER_LOCATION);
78
+ useEffect(() => {
79
+ let cancelled = false;
80
+ const fromDevice = async () => {
81
+ if (!isDeviceLocationAvailable()) return null;
82
+ const coords = await getDeviceLocation().catch(() => null);
83
+ if (!coords) return null;
84
+ const data = await reverseGeocode(coords).catch(() => ({}));
85
+ return __spreadProps(__spreadValues({}, coords), {
86
+ location: placeLabel(data)
87
+ });
88
+ };
89
+ (async () => {
90
+ var _a2;
91
+ const found = (_a2 = await fromDevice()) != null ? _a2 : await approximateLocation().catch(() => null);
92
+ if (!cancelled && found) setLocation(found);
93
+ })();
94
+ return () => {
95
+ cancelled = true;
96
+ };
97
+ }, []);
98
+ return location;
99
+ }
100
+ let AsyncStorage = null;
101
+ try {
102
+ AsyncStorage = (_a = require("@react-native-async-storage/async-storage").default) != null ? _a : null;
103
+ } catch (e) {
104
+ AsyncStorage = null;
105
+ }
106
+ const UNIT_STORAGE_KEY = "yantra:discover:temperature-unit";
107
+ function useTemperatureUnit(location) {
108
+ const [picked, setPicked] = useState(null);
109
+ useEffect(() => {
110
+ let cancelled = false;
111
+ AsyncStorage == null ? void 0 : AsyncStorage.getItem(UNIT_STORAGE_KEY).then((saved) => {
112
+ if (!cancelled && (saved === "C" || saved === "F")) setPicked(saved);
113
+ }).catch(() => void 0);
114
+ return () => {
115
+ cancelled = true;
116
+ };
117
+ }, []);
118
+ const pick = useCallback((unit) => {
119
+ setPicked(unit);
120
+ AsyncStorage == null ? void 0 : AsyncStorage.setItem(UNIT_STORAGE_KEY, unit).catch(() => void 0);
121
+ }, []);
122
+ return [picked != null ? picked : localTemperatureUnit(location), pick];
123
+ }
124
+ function useDiscoverSidebar() {
125
+ var _a2;
126
+ const place = useDiscoverSidebarLocation();
127
+ const {
128
+ data,
129
+ previousData,
130
+ loading,
131
+ refetch
132
+ } = useGetDiscoverSidebarQuery({
133
+ variables: {
134
+ location: place.location,
135
+ latitude: place.latitude,
136
+ longitude: place.longitude
137
+ },
138
+ pollInterval: 6e4,
139
+ fetchPolicy: "cache-and-network"
140
+ });
141
+ const loaded = (_a2 = data == null ? void 0 : data.getDiscoverSidebar) != null ? _a2 : previousData == null ? void 0 : previousData.getDiscoverSidebar;
142
+ return {
143
+ sidebar: loaded != null ? loaded : DISCOVER_SIDEBAR_PLACEHOLDER,
144
+ pending: !loaded && loading,
145
+ place,
146
+ refetch
147
+ };
148
+ }export{DEFAULT_DISCOVER_WEATHER_LOCATION,DISCOVER_SIDEBAR_PLACEHOLDER,useDiscoverSidebar,useDiscoverSidebarLocation,useTemperatureUnit};//# sourceMappingURL=useDiscoverSidebar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDiscoverSidebar.js","sources":["../../../src/features/discover/useDiscoverSidebar.ts"],"sourcesContent":["/**\n * Data for the Discover weather and market panel, mirroring the browser's\n * `DiscoverSharedSidebar` + `useDiscoverSidebarLocation`: the same\n * `getDiscoverSidebar` query, polled each minute, for San Francisco until the\n * phone's location is known, and the °C / °F the person picked last.\n */\nimport { useCallback, useEffect, useState } from 'react';\nimport { useGetDiscoverSidebarQuery } from 'common/graphql';\nimport type { IGetDiscoverSidebarQuery } from 'common';\nimport { getDeviceLocation, isDeviceLocationAvailable } from '../local-services/deviceLocation';\nimport { localTemperatureUnit, type TemperatureUnit } from './weather';\n\nexport type DiscoverSidebarData = IGetDiscoverSidebarQuery['getDiscoverSidebar'];\nexport type DiscoverWeather = DiscoverSidebarData['weather'];\nexport type DiscoverStockItem = DiscoverSidebarData['topGainers'][number];\n\nexport interface DiscoverSidebarLocation {\n location?: string;\n latitude?: number;\n longitude?: number;\n}\n\n/** Default weather location before / without location permission (US — San Francisco). */\nexport const DEFAULT_DISCOVER_WEATHER_LOCATION: DiscoverSidebarLocation = {\n location: 'San Francisco, CA',\n latitude: 37.7749,\n longitude: -122.4194,\n};\n\n/** Loading placeholder — not fake market or weather data. */\nexport const DISCOVER_SIDEBAR_PLACEHOLDER: DiscoverSidebarData = {\n meta: {\n sourceUrl: 'https://open-meteo.com/, https://finance.yahoo.com/',\n crawledAt: new Date(0).toISOString(),\n lastUpdatedLabel: 'Loading…',\n },\n weather: {\n location: 'San Francisco, CA',\n summary: 'Loading weather…',\n temperature: '—',\n unitLabel: 'F',\n highLow: '—',\n forecast: [],\n },\n marketOutlook: [],\n trendingCompanies: [],\n topGainers: [],\n};\n\ninterface ReverseGeocodeResponse {\n latitude?: number;\n longitude?: number;\n city?: string;\n locality?: string;\n principalSubdivision?: string;\n countryName?: string;\n}\n\nfunction placeLabel(data: ReverseGeocodeResponse): string | undefined {\n const parts = [data.city || data.locality, data.principalSubdivision, data.countryName].filter(Boolean);\n return parts.length > 0 ? parts.join(', ') : undefined;\n}\n\n/**\n * The browser's reverse geocoder. Given coordinates it names them; given none it\n * places the caller by IP — a city-level fix with no permission prompt.\n */\nasync function reverseGeocode(coords?: { latitude: number; longitude: number }): Promise<ReverseGeocodeResponse> {\n const query = coords\n ? `latitude=${coords.latitude}&longitude=${coords.longitude}&localityLanguage=en`\n : 'localityLanguage=en';\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 10_000);\n try {\n const response = await fetch(`https://api.bigdatacloud.net/data/reverse-geocode-client?${query}`, {\n signal: controller.signal,\n });\n if (!response.ok) throw new Error(`reverse geocode ${response.status}`);\n return (await response.json()) as ReverseGeocodeResponse;\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** The phone's place by IP, or null when the lookup has no usable fix. */\nasync function approximateLocation(): Promise<DiscoverSidebarLocation | null> {\n const data = await reverseGeocode();\n const { latitude, longitude } = data;\n if (typeof latitude !== 'number' || typeof longitude !== 'number') return null;\n if (latitude === 0 && longitude === 0) return null;\n return { latitude, longitude, location: placeLabel(data) };\n}\n\n/**\n * San Francisco, then the phone's own place. Like the web, Discover asks for the\n * device location when it opens; where the build has no location module, or the\n * person says no, it falls back to an IP-based city.\n */\nexport function useDiscoverSidebarLocation(): DiscoverSidebarLocation {\n const [location, setLocation] = useState<DiscoverSidebarLocation>(DEFAULT_DISCOVER_WEATHER_LOCATION);\n\n useEffect(() => {\n let cancelled = false;\n\n const fromDevice = async (): Promise<DiscoverSidebarLocation | null> => {\n if (!isDeviceLocationAvailable()) return null;\n const coords = await getDeviceLocation().catch(() => null);\n if (!coords) return null;\n const data = await reverseGeocode(coords).catch(() => ({}) as ReverseGeocodeResponse);\n return { ...coords, location: placeLabel(data) };\n };\n\n (async () => {\n const found = (await fromDevice()) ?? (await approximateLocation().catch(() => null));\n if (!cancelled && found) setLocation(found);\n })();\n\n return () => {\n cancelled = true;\n };\n }, []);\n\n return location;\n}\n\ntype StorageLike = {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, value: string): Promise<void>;\n};\n\nlet AsyncStorage: StorageLike | null = null;\ntry {\n // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require\n AsyncStorage = require('@react-native-async-storage/async-storage').default ?? null;\n} catch {\n AsyncStorage = null;\n}\n\nconst UNIT_STORAGE_KEY = 'yantra:discover:temperature-unit';\n\n/** °C or °F: the one the person picked last, else the one the place reads its weather in. */\nexport function useTemperatureUnit(location: string): [TemperatureUnit, (unit: TemperatureUnit) => void] {\n const [picked, setPicked] = useState<TemperatureUnit | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n AsyncStorage?.getItem(UNIT_STORAGE_KEY)\n .then((saved) => {\n if (!cancelled && (saved === 'C' || saved === 'F')) setPicked(saved);\n })\n .catch(() => undefined);\n return () => {\n cancelled = true;\n };\n }, []);\n\n const pick = useCallback((unit: TemperatureUnit) => {\n setPicked(unit);\n AsyncStorage?.setItem(UNIT_STORAGE_KEY, unit).catch(() => undefined);\n }, []);\n\n return [picked ?? localTemperatureUnit(location), pick];\n}\n\nexport type DiscoverSidebarState = ReturnType<typeof useDiscoverSidebar>;\n\nexport function useDiscoverSidebar() {\n const place = useDiscoverSidebarLocation();\n const { data, previousData, loading, refetch } = useGetDiscoverSidebarQuery({\n variables: { location: place.location, latitude: place.latitude, longitude: place.longitude },\n pollInterval: 60_000,\n fetchPolicy: 'cache-and-network',\n });\n // The last answer stays up while the location changes, rather than flashing back to skeletons.\n const loaded = data?.getDiscoverSidebar ?? previousData?.getDiscoverSidebar;\n\n return {\n sidebar: loaded ?? DISCOVER_SIDEBAR_PLACEHOLDER,\n pending: !loaded && loading,\n place,\n refetch,\n };\n}\n"],"names":["_a"],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ const SKY_WORDS = [[/thunder|lightning/i, "storm"], [/snow|sleet|hail|\bice\b/i, "snow"], [/rain|drizzle|shower/i, "rain"], [/fog|mist|haze/i, "fog"], [/partly/i, "partly"], [/clear|sunny|fair/i, "clear"], [/cloud|overcast/i, "cloudy"]];
2
+ function skyFromSummary(summary) {
3
+ const match = SKY_WORDS.find(([pattern]) => pattern.test(summary));
4
+ return match ? match[1] : null;
5
+ }
6
+ function skyFromCondition(condition) {
7
+ if (condition === "sunny") return "clear";
8
+ if (condition === "partly_cloudy") return "partly";
9
+ return "cloudy";
10
+ }
11
+ const RAD = Math.PI / 180;
12
+ function isSunDown(latitude, longitude, at) {
13
+ const days = at.getTime() / 864e5 - 10957.5;
14
+ const meanLongitude = 280.46 + 0.9856474 * days;
15
+ const meanAnomaly = (357.528 + 0.9856003 * days) * RAD;
16
+ const eclipticLongitude = (meanLongitude + 1.915 * Math.sin(meanAnomaly) + 0.02 * Math.sin(2 * meanAnomaly)) * RAD;
17
+ const obliquity = (23.439 - 4e-7 * days) * RAD;
18
+ const declination = Math.asin(Math.sin(obliquity) * Math.sin(eclipticLongitude));
19
+ const rightAscension = Math.atan2(Math.cos(obliquity) * Math.sin(eclipticLongitude), Math.cos(eclipticLongitude));
20
+ const siderealTime = (280.46061837 + 360.98564736629 * days) * RAD;
21
+ const hourAngle = siderealTime + longitude * RAD - rightAscension;
22
+ const altitude = Math.asin(Math.sin(latitude * RAD) * Math.sin(declination) + Math.cos(latitude * RAD) * Math.cos(declination) * Math.cos(hourAngle));
23
+ return altitude < -0.833 * RAD;
24
+ }
25
+ function toDegrees(value, from, to) {
26
+ const match = /-?\d+(?:\.\d+)?/.exec(value);
27
+ if (!match) return null;
28
+ const degrees = Number(match[0]);
29
+ if (from === to) return Math.round(degrees);
30
+ return Math.round(to === "C" ? (degrees - 32) * 5 / 9 : degrees * 9 / 5 + 32);
31
+ }
32
+ function splitHighLow(value) {
33
+ const match = /H:\s*(-?\d+(?:\.\d+)?)°?\s*L:\s*(-?\d+(?:\.\d+)?)/.exec(value);
34
+ return match ? {
35
+ high: match[1],
36
+ low: match[2]
37
+ } : null;
38
+ }
39
+ const FAHRENHEIT_PLACES = /United States|Puerto Rico|Guam|Liberia|Bahamas|Belize|Cayman|Palau|, [A-Z]{2}$/;
40
+ function localTemperatureUnit(location) {
41
+ return FAHRENHEIT_PLACES.test(location.trim()) ? "F" : "C";
42
+ }export{isSunDown,localTemperatureUnit,skyFromCondition,skyFromSummary,splitHighLow,toDegrees};//# sourceMappingURL=weather.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weather.js","sources":["../../../src/features/discover/weather.ts"],"sourcesContent":["/**\n * Weather helpers for the Discover weather card, ported from the browser's\n * `pages/discover/utils/weather.ts`. Keep the two in step.\n */\n/** What the sky is doing, for the weather card's icon and tint. */\nexport type Sky = 'clear' | 'partly' | 'cloudy' | 'fog' | 'rain' | 'storm' | 'snow';\n\nexport type TemperatureUnit = 'F' | 'C';\n\n// First match wins: \"Thunderstorm with hail\" is a storm, \"Snow showers\" snow, \"Partly cloudy\" partly.\nconst SKY_WORDS: ReadonlyArray<readonly [RegExp, Sky]> = [\n [/thunder|lightning/i, 'storm'],\n [/snow|sleet|hail|\\bice\\b/i, 'snow'],\n [/rain|drizzle|shower/i, 'rain'],\n [/fog|mist|haze/i, 'fog'],\n [/partly/i, 'partly'],\n [/clear|sunny|fair/i, 'clear'],\n [/cloud|overcast/i, 'cloudy'],\n];\n\n/**\n * The sky the server's summary of the current weather names (\"Clear sky\", \"Overcast\", \"Light\n * rain\"), or null for a status line (\"Loading weather…\"). The current conditions only travel as\n * this text: the forecast's own `condition` is each whole day's, so it is not the sky right now.\n */\nexport function skyFromSummary(summary: string): Sky | null {\n const match = SKY_WORDS.find(([pattern]) => pattern.test(summary));\n return match ? match[1] : null;\n}\n\n/** A forecast day's condition (the schema has three) as a sky. */\nexport function skyFromCondition(condition: string | null | undefined): Sky {\n if (condition === 'sunny') return 'clear';\n if (condition === 'partly_cloudy') return 'partly';\n return 'cloudy';\n}\n\nconst RAD = Math.PI / 180;\n\n/**\n * Whether the sun is down at a place and moment: its altitude under -0.833° (refraction plus the\n * sun's radius), from the low-precision solar coordinates of the Astronomical Almanac, which land\n * within a minute or two of the published sunset.\n */\nexport function isSunDown(latitude: number, longitude: number, at: Date): boolean {\n const days = at.getTime() / 86_400_000 - 10_957.5; // since J2000.0 (2000-01-01 12:00 UTC)\n const meanLongitude = 280.46 + 0.9856474 * days;\n const meanAnomaly = (357.528 + 0.9856003 * days) * RAD;\n const eclipticLongitude = (meanLongitude + 1.915 * Math.sin(meanAnomaly) + 0.02 * Math.sin(2 * meanAnomaly)) * RAD;\n const obliquity = (23.439 - 0.0000004 * days) * RAD;\n const declination = Math.asin(Math.sin(obliquity) * Math.sin(eclipticLongitude));\n const rightAscension = Math.atan2(Math.cos(obliquity) * Math.sin(eclipticLongitude), Math.cos(eclipticLongitude));\n const siderealTime = (280.46061837 + 360.98564736629 * days) * RAD;\n const hourAngle = siderealTime + longitude * RAD - rightAscension;\n const altitude = Math.asin(\n Math.sin(latitude * RAD) * Math.sin(declination) +\n Math.cos(latitude * RAD) * Math.cos(declination) * Math.cos(hourAngle),\n );\n return altitude < -0.833 * RAD;\n}\n\n/**\n * A temperature the server sent (\"83°\", \"-4°\") as whole degrees in the unit asked for, or null\n * for its \"—\" placeholder.\n */\nexport function toDegrees(value: string, from: TemperatureUnit, to: TemperatureUnit): number | null {\n const match = /-?\\d+(?:\\.\\d+)?/.exec(value);\n if (!match) return null;\n const degrees = Number(match[0]);\n if (from === to) return Math.round(degrees);\n return Math.round(to === 'C' ? ((degrees - 32) * 5) / 9 : (degrees * 9) / 5 + 32);\n}\n\n/** Today's \"H: 92° L: 76°\" as its two temperatures, or null when the server sent \"—\". */\nexport function splitHighLow(value: string): { high: string; low: string } | null {\n const match = /H:\\s*(-?\\d+(?:\\.\\d+)?)°?\\s*L:\\s*(-?\\d+(?:\\.\\d+)?)/.exec(value);\n return match ? { high: match[1], low: match[2] } : null;\n}\n\n// The places that read the weather in Fahrenheit; \"San Francisco, CA\" is the default location.\nconst FAHRENHEIT_PLACES = /United States|Puerto Rico|Guam|Liberia|Bahamas|Belize|Cayman|Palau|, [A-Z]{2}$/;\n\n/** The unit a place reads its weather in, by the location label the card shows. */\nexport function localTemperatureUnit(location: string): TemperatureUnit {\n return FAHRENHEIT_PLACES.test(location.trim()) ? 'F' : 'C';\n}\n"],"names":[],"mappings":"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"}
@@ -46,5 +46,5 @@ function ExpensesAgentChatPane({
46
46
  seeded.current = null;
47
47
  lastContext.current = null;
48
48
  (_a2 = hostChat == null ? void 0 : hostChat.clear) == null ? void 0 : _a2.call(hostChat);
49
- }, busy: Boolean(hostChat == null ? void 0 : hostChat.busy), streamingContent: (_b = hostChat == null ? void 0 : hostChat.streaming) != null ? _b : null, error: (_c = hostChat == null ? void 0 : hostChat.error) != null ? _c : null, placeholder: claimMerchant ? "Ask about this expense\u2026" : "Ask about your spending\u2026", emptyTitle: claimMerchant ? `About ${claimMerchant}` : "What do you need?", emptyBody: claimMerchant ? "Ask whether it fits policy, which category it belongs in, or have it submitted for you." : "Ask where the money went, what needs approval, or have an expense filed for you.", suggestions: messages.length === 0 ? expensesAgentSuggestions(view, claimMerchant) : [], enableAttachments: true, isDark: theme.isDark, ink: theme.ink, muted: theme.muted, screen: theme.screen, border: theme.border, card: theme.card });
49
+ }, busy: Boolean(hostChat == null ? void 0 : hostChat.busy), steering: hostChat, streamingContent: (_b = hostChat == null ? void 0 : hostChat.streaming) != null ? _b : null, error: (_c = hostChat == null ? void 0 : hostChat.error) != null ? _c : null, placeholder: claimMerchant ? "Ask about this expense\u2026" : "Ask about your spending\u2026", emptyTitle: claimMerchant ? `About ${claimMerchant}` : "What do you need?", emptyBody: claimMerchant ? "Ask whether it fits policy, which category it belongs in, or have it submitted for you." : "Ask where the money went, what needs approval, or have an expense filed for you.", suggestions: messages.length === 0 ? expensesAgentSuggestions(view, claimMerchant) : [], enableAttachments: true, isDark: theme.isDark, ink: theme.ink, muted: theme.muted, screen: theme.screen, border: theme.border, card: theme.card });
50
50
  }export{ExpensesAgentChatPane};//# sourceMappingURL=ExpensesAgentChatPane.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpensesAgentChatPane.js","sources":["../../../src/features/expenses/ExpensesAgentChatPane.tsx"],"sourcesContent":["/**\n * The Yantra agent, over what is on the Expenses screen. Every turn goes to the\n * host's gateway chat (the same agent and skills as main chat, which reach the\n * yantra-expenses connector). A turn carries the expenses context line whenever\n * it changed since the thread last heard it - the first turn always, and again\n * after the person opens another claim or tab - so \"submit this\" means the\n * claim on screen.\n */\nimport React, { useEffect, useRef, useState } from 'react';\nimport { NativeAgentChat, type AgentChatMessage } from '../agent-chat';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\nimport { turnWithContext, type ExpensesView } from './expensesContext';\nimport { expensesAgentSuggestions } from './expensesPrompts';\nimport type { ExpensesTheme } from './expensesTheme';\nimport type { ExpensesHostChat } from './hostChat';\n\nconst NOT_CONNECTED = 'Yantra is not connected yet. Check the connection in Home, then send again.';\n\nexport interface ExpensesAgentSeed {\n id: string;\n text: string;\n files?: MessageAttachment[];\n}\n\nexport function ExpensesAgentChatPane({\n visible,\n onClose,\n hostChat,\n contextHeader,\n view,\n claimMerchant,\n seed,\n theme,\n}: {\n visible: boolean;\n onClose: () => void;\n hostChat?: ExpensesHostChat;\n /** The `[expenses context: …]` line for the screen as it is now. */\n contextHeader: string;\n view: ExpensesView;\n claimMerchant: string | null;\n /** A turn to send as the pane opens. */\n seed: ExpensesAgentSeed | null;\n theme: ExpensesTheme;\n}) {\n const [localMessages, setLocalMessages] = useState<AgentChatMessage[]>([]);\n const seeded = useRef<string | null>(null);\n const lastContext = useRef<string | null>(null);\n const hostMessages = hostChat?.messages ?? [];\n const messages = hostMessages.length > 0 ? hostMessages : localMessages;\n\n const send = (text: string, files?: MessageAttachment[]) => {\n const trimmed = text.trim();\n if (!trimmed && !files?.length) return;\n if (!hostChat || !hostChat.connected) {\n setLocalMessages((prev) => [\n ...prev,\n { id: `u-${Date.now()}`, role: 'user', content: trimmed },\n { id: `a-${Date.now()}`, role: 'assistant', content: hostChat?.error || NOT_CONNECTED },\n ]);\n return;\n }\n setLocalMessages([]);\n const turn = turnWithContext(trimmed, contextHeader, lastContext.current);\n lastContext.current = contextHeader;\n hostChat.send(turn, files);\n };\n\n useEffect(() => {\n if (!visible || !seed || seeded.current === seed.id) return;\n seeded.current = seed.id;\n send(seed.text, seed.files);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [visible, seed]);\n\n return (\n <NativeAgentChat\n title=\"Expenses agent\"\n visible={visible}\n onClose={onClose}\n onSwipeLeft={onClose}\n messages={messages}\n renderConnectorCard={hostChat?.renderConnectorCard}\n onSend={send}\n onClear={() => {\n setLocalMessages([]);\n seeded.current = null;\n lastContext.current = null;\n hostChat?.clear?.();\n }}\n busy={Boolean(hostChat?.busy)}\n streamingContent={hostChat?.streaming ?? null}\n error={hostChat?.error ?? null}\n placeholder={claimMerchant ? 'Ask about this expense…' : 'Ask about your spending…'}\n emptyTitle={claimMerchant ? `About ${claimMerchant}` : 'What do you need?'}\n emptyBody={\n claimMerchant\n ? 'Ask whether it fits policy, which category it belongs in, or have it submitted for you.'\n : 'Ask where the money went, what needs approval, or have an expense filed for you.'\n }\n suggestions={messages.length === 0 ? expensesAgentSuggestions(view, claimMerchant) : []}\n enableAttachments\n isDark={theme.isDark}\n ink={theme.ink}\n muted={theme.muted}\n screen={theme.screen}\n border={theme.border}\n card={theme.card}\n />\n );\n}\n"],"names":["_a"],"mappings":"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"}
1
+ {"version":3,"file":"ExpensesAgentChatPane.js","sources":["../../../src/features/expenses/ExpensesAgentChatPane.tsx"],"sourcesContent":["/**\n * The Yantra agent, over what is on the Expenses screen. Every turn goes to the\n * host's gateway chat (the same agent and skills as main chat, which reach the\n * yantra-expenses connector). A turn carries the expenses context line whenever\n * it changed since the thread last heard it - the first turn always, and again\n * after the person opens another claim or tab - so \"submit this\" means the\n * claim on screen.\n */\nimport React, { useEffect, useRef, useState } from 'react';\nimport { NativeAgentChat, type AgentChatMessage } from '../agent-chat';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\nimport { turnWithContext, type ExpensesView } from './expensesContext';\nimport { expensesAgentSuggestions } from './expensesPrompts';\nimport type { ExpensesTheme } from './expensesTheme';\nimport type { ExpensesHostChat } from './hostChat';\n\nconst NOT_CONNECTED = 'Yantra is not connected yet. Check the connection in Home, then send again.';\n\nexport interface ExpensesAgentSeed {\n id: string;\n text: string;\n files?: MessageAttachment[];\n}\n\nexport function ExpensesAgentChatPane({\n visible,\n onClose,\n hostChat,\n contextHeader,\n view,\n claimMerchant,\n seed,\n theme,\n}: {\n visible: boolean;\n onClose: () => void;\n hostChat?: ExpensesHostChat;\n /** The `[expenses context: …]` line for the screen as it is now. */\n contextHeader: string;\n view: ExpensesView;\n claimMerchant: string | null;\n /** A turn to send as the pane opens. */\n seed: ExpensesAgentSeed | null;\n theme: ExpensesTheme;\n}) {\n const [localMessages, setLocalMessages] = useState<AgentChatMessage[]>([]);\n const seeded = useRef<string | null>(null);\n const lastContext = useRef<string | null>(null);\n const hostMessages = hostChat?.messages ?? [];\n const messages = hostMessages.length > 0 ? hostMessages : localMessages;\n\n const send = (text: string, files?: MessageAttachment[]) => {\n const trimmed = text.trim();\n if (!trimmed && !files?.length) return;\n if (!hostChat || !hostChat.connected) {\n setLocalMessages((prev) => [\n ...prev,\n { id: `u-${Date.now()}`, role: 'user', content: trimmed },\n { id: `a-${Date.now()}`, role: 'assistant', content: hostChat?.error || NOT_CONNECTED },\n ]);\n return;\n }\n setLocalMessages([]);\n const turn = turnWithContext(trimmed, contextHeader, lastContext.current);\n lastContext.current = contextHeader;\n hostChat.send(turn, files);\n };\n\n useEffect(() => {\n if (!visible || !seed || seeded.current === seed.id) return;\n seeded.current = seed.id;\n send(seed.text, seed.files);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [visible, seed]);\n\n return (\n <NativeAgentChat\n title=\"Expenses agent\"\n visible={visible}\n onClose={onClose}\n onSwipeLeft={onClose}\n messages={messages}\n renderConnectorCard={hostChat?.renderConnectorCard}\n onSend={send}\n onClear={() => {\n setLocalMessages([]);\n seeded.current = null;\n lastContext.current = null;\n hostChat?.clear?.();\n }}\n busy={Boolean(hostChat?.busy)}\n steering={hostChat}\n streamingContent={hostChat?.streaming ?? null}\n error={hostChat?.error ?? null}\n placeholder={claimMerchant ? 'Ask about this expense…' : 'Ask about your spending…'}\n emptyTitle={claimMerchant ? `About ${claimMerchant}` : 'What do you need?'}\n emptyBody={\n claimMerchant\n ? 'Ask whether it fits policy, which category it belongs in, or have it submitted for you.'\n : 'Ask where the money went, what needs approval, or have an expense filed for you.'\n }\n suggestions={messages.length === 0 ? expensesAgentSuggestions(view, claimMerchant) : []}\n enableAttachments\n isDark={theme.isDark}\n ink={theme.ink}\n muted={theme.muted}\n screen={theme.screen}\n border={theme.border}\n card={theme.card}\n />\n );\n}\n"],"names":["_a"],"mappings":"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"}
@@ -60,5 +60,5 @@ function InboxAgentChatPane({
60
60
  setLocalMessages([]);
61
61
  seeded.current = null;
62
62
  (_a2 = hostChat == null ? void 0 : hostChat.clear) == null ? void 0 : _a2.call(hostChat);
63
- }, busy: Boolean(hostChat == null ? void 0 : hostChat.busy), streamingContent: (_b = hostChat == null ? void 0 : hostChat.streaming) != null ? _b : null, error: (_c = hostChat == null ? void 0 : hostChat.error) != null ? _c : null, placeholder: "Ask about your mail\u2026", emptyTitle: "Your inbox, triaged", emptyBody, suggestions: messages.length === 0 ? INBOX_SUGGESTIONS : [], isDark: theme.isDark, ink: theme.ink, muted: theme.muted, screen: theme.screen, border: theme.border });
63
+ }, busy: Boolean(hostChat == null ? void 0 : hostChat.busy), steering: hostChat, streamingContent: (_b = hostChat == null ? void 0 : hostChat.streaming) != null ? _b : null, error: (_c = hostChat == null ? void 0 : hostChat.error) != null ? _c : null, placeholder: "Ask about your mail\u2026", emptyTitle: "Your inbox, triaged", emptyBody, suggestions: messages.length === 0 ? INBOX_SUGGESTIONS : [], isDark: theme.isDark, ink: theme.ink, muted: theme.muted, screen: theme.screen, border: theme.border });
64
64
  }export{INBOX_SUGGESTIONS,InboxAgentChatPane};//# sourceMappingURL=InboxAgentChatPane.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InboxAgentChatPane.js","sources":["../../../src/features/inbox/InboxAgentChatPane.tsx"],"sourcesContent":["/**\n * The Yantra agent, over the mailbox on screen. Every turn goes to the host's\n * gateway chat (the same agent and skills as main chat); the first turn of a\n * thread carries the inbox context line so the agent works on this mailbox.\n */\nimport React, { useEffect, useRef, useState } from 'react';\nimport { NativeAgentChat, type AgentChatMessage, type AgentChatSuggestion } from '../agent-chat';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\nimport type { InboxHostChat } from './hostChat';\nimport { withInboxContext } from './inboxContext';\nimport type { InboxTheme } from './inboxTheme';\nimport type { MailAccount } from './types';\n\nexport const INBOX_SUGGESTIONS: AgentChatSuggestion[] = [\n {\n id: 'unread',\n label: 'Summarize my unread',\n prompt: 'Summarize my unread mail: who wrote, what they want, and what needs action from me.',\n },\n {\n id: 'needs-reply',\n label: 'What needs a reply?',\n prompt: 'Which emails in this mailbox need a reply from me? One line each, most urgent first.',\n },\n {\n id: 'draft',\n label: 'Draft my replies',\n prompt: 'Draft replies for the emails that need one, matching each sender’s tone. Show me every draft before sending anything.',\n },\n {\n id: 'zero',\n label: 'Get to inbox zero',\n prompt: 'Help me get to inbox zero: tell me what to archive, what to reply to, and what can wait.',\n },\n];\n\nconst NOT_CONNECTED = 'Yantra is not connected yet. Check the connection in Home, then send again.';\n\nexport interface InboxAgentSeed {\n id: string;\n text: string;\n}\n\nexport function InboxAgentChatPane({\n visible,\n onClose,\n hostChat,\n account,\n orgName,\n seed,\n theme,\n}: {\n visible: boolean;\n onClose: () => void;\n hostChat?: InboxHostChat;\n account: MailAccount | null;\n orgName?: string;\n /** A turn to send as the pane opens (Ask Yantra on a message). */\n seed: InboxAgentSeed | null;\n theme: InboxTheme;\n}) {\n const [localMessages, setLocalMessages] = useState<AgentChatMessage[]>([]);\n const seeded = useRef<string | null>(null);\n const hostMessages = hostChat?.messages ?? [];\n const messages = hostMessages.length > 0 ? hostMessages : localMessages;\n\n const send = (text: string, files?: MessageAttachment[]) => {\n const trimmed = text.trim();\n if (!trimmed && !files?.length) return;\n if (!hostChat || !hostChat.connected) {\n setLocalMessages((prev) => [\n ...prev,\n { id: `u-${Date.now()}`, role: 'user', content: trimmed },\n { id: `a-${Date.now()}`, role: 'assistant', content: hostChat?.error || NOT_CONNECTED },\n ]);\n return;\n }\n setLocalMessages([]);\n // A fresh thread learns which mailbox it is about; later turns go verbatim.\n const firstTurn = hostMessages.length === 0;\n hostChat.send(firstTurn ? withInboxContext(trimmed, account, orgName) : trimmed, files);\n };\n\n useEffect(() => {\n if (!visible || !seed || seeded.current === seed.id) return;\n seeded.current = seed.id;\n send(seed.text);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [visible, seed]);\n\n const emptyBody = account\n ? `Ask about ${account.email}: catch up on unread mail, find what needs a reply, or draft answers.`\n : 'Connect a mailbox and I can triage it, find what needs a reply, and draft answers.';\n\n return (\n <NativeAgentChat\n title=\"Inbox Agent\"\n visible={visible}\n onClose={onClose}\n onSwipeLeft={onClose}\n messages={messages}\n renderConnectorCard={hostChat?.renderConnectorCard}\n onSend={send}\n onClear={() => {\n setLocalMessages([]);\n seeded.current = null;\n hostChat?.clear?.();\n }}\n busy={Boolean(hostChat?.busy)}\n streamingContent={hostChat?.streaming ?? null}\n error={hostChat?.error ?? null}\n placeholder=\"Ask about your mail…\"\n emptyTitle=\"Your inbox, triaged\"\n emptyBody={emptyBody}\n suggestions={messages.length === 0 ? INBOX_SUGGESTIONS : []}\n isDark={theme.isDark}\n ink={theme.ink}\n muted={theme.muted}\n screen={theme.screen}\n border={theme.border}\n />\n );\n}\n"],"names":["_a"],"mappings":"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"}
1
+ {"version":3,"file":"InboxAgentChatPane.js","sources":["../../../src/features/inbox/InboxAgentChatPane.tsx"],"sourcesContent":["/**\n * The Yantra agent, over the mailbox on screen. Every turn goes to the host's\n * gateway chat (the same agent and skills as main chat); the first turn of a\n * thread carries the inbox context line so the agent works on this mailbox.\n */\nimport React, { useEffect, useRef, useState } from 'react';\nimport { NativeAgentChat, type AgentChatMessage, type AgentChatSuggestion } from '../agent-chat';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\nimport type { InboxHostChat } from './hostChat';\nimport { withInboxContext } from './inboxContext';\nimport type { InboxTheme } from './inboxTheme';\nimport type { MailAccount } from './types';\n\nexport const INBOX_SUGGESTIONS: AgentChatSuggestion[] = [\n {\n id: 'unread',\n label: 'Summarize my unread',\n prompt: 'Summarize my unread mail: who wrote, what they want, and what needs action from me.',\n },\n {\n id: 'needs-reply',\n label: 'What needs a reply?',\n prompt: 'Which emails in this mailbox need a reply from me? One line each, most urgent first.',\n },\n {\n id: 'draft',\n label: 'Draft my replies',\n prompt: 'Draft replies for the emails that need one, matching each sender’s tone. Show me every draft before sending anything.',\n },\n {\n id: 'zero',\n label: 'Get to inbox zero',\n prompt: 'Help me get to inbox zero: tell me what to archive, what to reply to, and what can wait.',\n },\n];\n\nconst NOT_CONNECTED = 'Yantra is not connected yet. Check the connection in Home, then send again.';\n\nexport interface InboxAgentSeed {\n id: string;\n text: string;\n}\n\nexport function InboxAgentChatPane({\n visible,\n onClose,\n hostChat,\n account,\n orgName,\n seed,\n theme,\n}: {\n visible: boolean;\n onClose: () => void;\n hostChat?: InboxHostChat;\n account: MailAccount | null;\n orgName?: string;\n /** A turn to send as the pane opens (Ask Yantra on a message). */\n seed: InboxAgentSeed | null;\n theme: InboxTheme;\n}) {\n const [localMessages, setLocalMessages] = useState<AgentChatMessage[]>([]);\n const seeded = useRef<string | null>(null);\n const hostMessages = hostChat?.messages ?? [];\n const messages = hostMessages.length > 0 ? hostMessages : localMessages;\n\n const send = (text: string, files?: MessageAttachment[]) => {\n const trimmed = text.trim();\n if (!trimmed && !files?.length) return;\n if (!hostChat || !hostChat.connected) {\n setLocalMessages((prev) => [\n ...prev,\n { id: `u-${Date.now()}`, role: 'user', content: trimmed },\n { id: `a-${Date.now()}`, role: 'assistant', content: hostChat?.error || NOT_CONNECTED },\n ]);\n return;\n }\n setLocalMessages([]);\n // A fresh thread learns which mailbox it is about; later turns go verbatim.\n const firstTurn = hostMessages.length === 0;\n hostChat.send(firstTurn ? withInboxContext(trimmed, account, orgName) : trimmed, files);\n };\n\n useEffect(() => {\n if (!visible || !seed || seeded.current === seed.id) return;\n seeded.current = seed.id;\n send(seed.text);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [visible, seed]);\n\n const emptyBody = account\n ? `Ask about ${account.email}: catch up on unread mail, find what needs a reply, or draft answers.`\n : 'Connect a mailbox and I can triage it, find what needs a reply, and draft answers.';\n\n return (\n <NativeAgentChat\n title=\"Inbox Agent\"\n visible={visible}\n onClose={onClose}\n onSwipeLeft={onClose}\n messages={messages}\n renderConnectorCard={hostChat?.renderConnectorCard}\n onSend={send}\n onClear={() => {\n setLocalMessages([]);\n seeded.current = null;\n hostChat?.clear?.();\n }}\n busy={Boolean(hostChat?.busy)}\n steering={hostChat}\n streamingContent={hostChat?.streaming ?? null}\n error={hostChat?.error ?? null}\n placeholder=\"Ask about your mail…\"\n emptyTitle=\"Your inbox, triaged\"\n emptyBody={emptyBody}\n suggestions={messages.length === 0 ? INBOX_SUGGESTIONS : []}\n isDark={theme.isDark}\n ink={theme.ink}\n muted={theme.muted}\n screen={theme.screen}\n border={theme.border}\n />\n );\n}\n"],"names":["_a"],"mappings":"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"}
@@ -253,6 +253,7 @@ function JobSearchAgentChatPane({
253
253
  },
254
254
  onClear: clearChat,
255
255
  busy: busy || Boolean(hostChat == null ? void 0 : hostChat.busy) && !nativeOwnsTurn.current && !stream,
256
+ steering: hostChat,
256
257
  streamingContent: stream != null ? stream : nativeOwnsTurn.current ? null : (_b = hostChat == null ? void 0 : hostChat.streaming) != null ? _b : null,
257
258
  error: (_c = hostChat == null ? void 0 : hostChat.error) != null ? _c : null,
258
259
  placeholder,
@@ -1 +1 @@
1
- {"version":3,"file":"JobSearchAgentChatPane.js","sources":["../../../src/features/job-search/JobSearchAgentChatPane.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';\nimport { Feather, MaterialCommunityIcons } from '@expo/vector-icons';\nimport { NativeAgentChat, type AgentChatMessage, type AgentChatSuggestion } from '../agent-chat';\nimport { delayMs, splitReplyChunks } from '../shopping/chat/streamAssistantReply';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\nimport type { JobPosting } from './types';\nimport type { ApplyFromChatResult } from './useJobSearchSession';\nimport type { JobSearchHostChat } from './hostChat';\nimport { parseJobSearchIntent, shouldUseHostLane } from './chat/widgetContent';\nimport { companyAvatarColor } from './jobSearchTheme';\n\nconst STREAM_TICK_MS = 16;\nconst CONVERSATION_REPLY =\n 'Tell me what to look for — a role, a company, a city, or remote. For example: remote senior backend engineer roles.';\n\nconst SUGGESTIONS: AgentChatSuggestion[] = [\n { id: 'find', label: 'Find roles', prompt: 'Find remote senior backend engineer roles' },\n { id: 'research', label: 'Research a company', prompt: 'Research Stripe for a senior backend role' },\n {\n id: 'analyze',\n label: 'Analyze a JD',\n prompt: 'Analyze this job description against my profile — I will paste the JD.',\n },\n {\n id: 'tailor',\n label: 'Tailor an application',\n prompt: 'Tailor my full application package for a job posting I name.',\n },\n {\n id: 'track',\n label: \"This week's pipeline\",\n prompt: 'Show my application pipeline: statuses, follow-ups, and what to apply to next.',\n },\n {\n id: 'outreach',\n label: 'Write outreach',\n prompt: 'Write a LinkedIn DM for one of my applications with a real hook.',\n },\n];\n\nexport function JobSearchAgentChatPane({\n visible,\n onClose,\n hostChat,\n applyFromChat,\n jobs,\n onViewJobs,\n onOpenJob,\n seedTurn = null,\n onClearChat,\n isDark,\n ink,\n muted,\n screen,\n border,\n card,\n accent,\n}: {\n visible: boolean;\n onClose: () => void;\n hostChat?: JobSearchHostChat;\n applyFromChat: (text: string) => Promise<ApplyFromChatResult>;\n jobs: JobPosting[];\n onViewJobs: () => void;\n onOpenJob: (job: JobPosting) => void;\n seedTurn?: {\n text: string;\n files?: MessageAttachment[];\n id?: string;\n mode?: 'send' | 'greet';\n greeting?: string;\n desk?: 'research' | 'tailor';\n } | null;\n /** Clears local + host chat and notifies parent to reset search. */\n onClearChat?: () => void;\n isDark: boolean;\n ink: string;\n muted: string;\n screen: string;\n border: string;\n card: string;\n accent: string;\n}) {\n const [localMessages, setLocalMessages] = useState<AgentChatMessage[]>([]);\n const [busy, setBusy] = useState(false);\n const [stream, setStream] = useState<string | null>(null);\n const [hitQuery, setHitQuery] = useState('');\n /** Landing chip desk: research / tailor empty state instead of a lone greeting bubble. */\n const [desk, setDesk] = useState<'default' | 'research' | 'tailor'>('default');\n const [composerSeed, setComposerSeed] = useState<string | null>(null);\n const [composerSeedKey, setComposerSeedKey] = useState(0);\n const inFlight = useRef(false);\n const seededKey = useRef<string | null>(null);\n const streamGen = useRef(0);\n const liveRef = useRef('');\n /** Native search owns the turn — ignore host busy/stream so Thinking does not reappear after results. */\n const nativeOwnsTurn = useRef(false);\n\n const hostMessages = hostChat?.messages ?? [];\n const messages = hostMessages.length > 0 ? hostMessages : localMessages;\n\n const pumpTo = async (gen: number, target: string) => {\n if (streamGen.current !== gen) return;\n let current = liveRef.current;\n if (target === current) return;\n if (!target.startsWith(current)) {\n current = '';\n liveRef.current = '';\n }\n const rest = target.slice(current.length);\n for (const chunk of splitReplyChunks(rest)) {\n if (streamGen.current !== gen) return;\n liveRef.current += chunk;\n setStream(liveRef.current);\n await delayMs(STREAM_TICK_MS);\n }\n };\n\n const summarizeJobs = (rows: JobPosting[], query: string) => {\n const q = query.trim();\n if (rows.length === 0) {\n return q\n ? `I couldn't find roles matching **${q}**. Try a broader title or drop the location.`\n : `I couldn't find roles for that request. Try a different query.`;\n }\n const header = q\n ? `I found **${rows.length} role${rows.length === 1 ? '' : 's'}** for **${q}**:`\n : `I found **${rows.length} role${rows.length === 1 ? '' : 's'}**:`;\n const preview = rows.slice(0, 3);\n const lines = preview.map((j, i) => `${i + 1}. **${j.title}** — ${j.company}${j.remote ? ' · Remote' : ''}`);\n const remaining = rows.length - preview.length;\n const parts = [header, '', ...lines];\n if (remaining > 0) parts.push('', `_+ ${remaining} more in the card below._`);\n parts.push('', 'Tap **View roles** below to browse the full list on the Jobs page.');\n return parts.join('\\n');\n };\n\n const runNativeSearch = (query: string, showLocalTurns: boolean) => {\n const gen = ++streamGen.current;\n nativeOwnsTurn.current = true;\n liveRef.current = `Searching live boards for **${query}**…`;\n setBusy(true);\n setStream(liveRef.current);\n void applyFromChat(query)\n .then(async (result) => {\n if (streamGen.current !== gen) return;\n // `in`, not `result.conversation`: without strictNullChecks a boolean\n // discriminant does not narrow the union.\n if (!('jobs' in result)) {\n if (showLocalTurns) {\n await pumpTo(gen, CONVERSATION_REPLY);\n setLocalMessages((prev) => [\n ...prev,\n { id: `a-${Date.now()}`, role: 'assistant', content: CONVERSATION_REPLY },\n ]);\n }\n setBusy(false);\n setStream(null);\n liveRef.current = '';\n return;\n }\n if (!result.error && result.jobs.length > 0) setHitQuery(result.query);\n else setHitQuery('');\n const body = result.error || summarizeJobs(result.jobs, result.query);\n await pumpTo(gen, body);\n if (streamGen.current !== gen) return;\n if (showLocalTurns) {\n setLocalMessages((prev) => [...prev, { id: `a-${Date.now()}`, role: 'assistant', content: body }]);\n }\n // Clear busy before stream so Thinking never flashes between the reply and the card.\n setBusy(false);\n setStream(null);\n liveRef.current = '';\n })\n .finally(() => {\n if (streamGen.current !== gen) return;\n nativeOwnsTurn.current = false;\n inFlight.current = false;\n setBusy(false);\n });\n };\n\n const send = (text: string, files?: MessageAttachment[]) => {\n const trimmed = text.trim();\n if (!trimmed && !files?.length) return;\n streamGen.current += 1;\n setStream(null);\n inFlight.current = true;\n const fileCount = files?.length ?? 0;\n const parsed = parseJobSearchIntent(trimmed);\n const useHost = Boolean(hostChat) && shouldUseHostLane(trimmed, fileCount);\n\n if (useHost && hostChat) {\n nativeOwnsTurn.current = false;\n if (!hostChat.connected) {\n setLocalMessages((prev) => [\n ...prev,\n { id: `u-${Date.now()}`, role: 'user', content: trimmed },\n {\n id: `a-${Date.now()}`,\n role: 'assistant',\n content:\n hostChat.error ||\n 'CDeCLI is not connected yet. Check gateway status in the header, then send again.',\n },\n ]);\n inFlight.current = false;\n return;\n }\n // Host-only: do not also run native search. Parallel lanes left Thinking/Drafting\n // on after the roles card appeared (research prompts match SEARCH_HINT via \"role\").\n hostChat.send(trimmed, files);\n inFlight.current = false;\n return;\n }\n\n setLocalMessages((prev) => [\n ...prev,\n { id: `u-${Date.now()}`, role: 'user', content: trimmed, createdAt: new Date().toISOString() },\n ]);\n if (parsed) {\n runNativeSearch(trimmed, true);\n return;\n }\n setLocalMessages((prev) => [\n ...prev,\n { id: `a-${Date.now()}`, role: 'assistant', content: CONVERSATION_REPLY },\n ]);\n inFlight.current = false;\n };\n\n const clearChat = () => {\n streamGen.current += 1;\n liveRef.current = '';\n nativeOwnsTurn.current = false;\n setStream(null);\n setBusy(false);\n inFlight.current = false;\n setLocalMessages([]);\n setHitQuery('');\n setDesk('default');\n setComposerSeed(null);\n seededKey.current = null;\n hostChat?.clear?.();\n onClearChat?.();\n };\n\n useEffect(() => {\n if (!visible || !seedTurn) return;\n const key = seedTurn.id ?? `${seedTurn.text}|${seedTurn.files?.length ?? 0}|${seedTurn.mode ?? 'send'}`;\n if (seededKey.current === key) return;\n seededKey.current = key;\n // Conversational chips (Research / Tailor): open a focused desk — do not\n // auto-send a long instruction that leaves the user on Pondering…\n if (seedTurn.mode === 'greet') {\n const kind = seedTurn.desk === 'tailor' ? 'tailor' : 'research';\n setHitQuery('');\n setBusy(false);\n setStream(null);\n setLocalMessages([]);\n setDesk(kind);\n setComposerSeed(kind === 'research' ? 'Research ' : '');\n setComposerSeedKey((n) => n + 1);\n return;\n }\n setDesk('default');\n send(seedTurn.text, seedTurn.files);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [visible, seedTurn]);\n\n const emptyTitle =\n desk === 'research' ? 'Research a company' : desk === 'tailor' ? 'Tailor an application' : 'Job hunt copilot';\n const emptyBody =\n desk === 'research'\n ? 'Name a company and the role you are targeting. I will cover culture, tech stack, live openings, and verifiable hooks.'\n : desk === 'tailor'\n ? 'Paste a JD URL or name the company + role and I will build the tailored package.'\n : 'Search live boards, tailor a resume, and track applications in one place.';\n const placeholder =\n desk === 'research'\n ? 'e.g. Stripe — senior backend'\n : desk === 'tailor'\n ? 'e.g. paste JD URL or company + role'\n : 'Find roles, tailor a JD, or ask about the pipeline…';\n const deskSuggestions: AgentChatSuggestion[] =\n desk === 'research'\n ? [\n { id: 'r-stripe', label: 'Stripe', prompt: 'Research Stripe for a senior backend engineer role' },\n { id: 'r-notion', label: 'Notion', prompt: 'Research Notion for a product engineer role' },\n { id: 'r-vercel', label: 'Vercel', prompt: 'Research Vercel for a full stack engineer role' },\n ]\n : desk === 'tailor'\n ? [\n {\n id: 't-url',\n label: 'I have a JD URL',\n prompt: 'Tailor my application — I will paste the job URL next.',\n },\n {\n id: 't-paste',\n label: 'I will paste the JD',\n prompt: 'Tailor my application — I will paste the job description next.',\n },\n ]\n : SUGGESTIONS;\n\n return (\n <NativeAgentChat\n title=\"Job Agent\"\n visible={visible}\n onClose={onClose}\n // Opens with a swipe in from the right edge, so it closes with one back out.\n onSwipeLeft={onClose}\n messages={messages}\n renderConnectorCard={hostChat?.renderConnectorCard}\n onSend={(text, files) => {\n setDesk('default');\n send(text, files);\n }}\n onClear={clearChat}\n busy={busy || (Boolean(hostChat?.busy) && !nativeOwnsTurn.current && !stream)}\n streamingContent={stream ?? (nativeOwnsTurn.current ? null : (hostChat?.streaming ?? null))}\n error={hostChat?.error ?? null}\n placeholder={placeholder}\n emptyTitle={emptyTitle}\n emptyBody={emptyBody}\n suggestions={messages.length === 0 ? deskSuggestions : []}\n composerSeed={composerSeed}\n composerSeedKey={composerSeedKey}\n onComposerSeedConsumed={() => setComposerSeed(null)}\n composerLead={\n hitQuery && jobs.length > 0 ? (\n <JobHitsCard\n jobs={jobs}\n query={hitQuery}\n onViewJobs={onViewJobs}\n onOpenJob={onOpenJob}\n ink={ink}\n muted={muted}\n border={border}\n card={card}\n accent={accent}\n />\n ) : null\n }\n isDark={isDark}\n ink={ink}\n muted={muted}\n screen={screen}\n border={border}\n />\n );\n}\n\nconst PREVIEW_LIMIT = 8;\nconst TILE_W = 112;\n\nfunction JobHitsCard({\n jobs,\n query,\n onViewJobs,\n onOpenJob,\n ink,\n muted,\n border,\n card,\n accent,\n}: {\n jobs: JobPosting[];\n query: string;\n onViewJobs: () => void;\n onOpenJob: (job: JobPosting) => void;\n ink: string;\n muted: string;\n border: string;\n card: string;\n accent: string;\n}) {\n const preview = jobs.slice(0, PREVIEW_LIMIT);\n const remaining = jobs.length - preview.length;\n const queryHint = query.trim() ? `Roles for ${query.trim()}` : 'Job results';\n\n return (\n <View style={[hitStyles.wrap, { backgroundColor: card, borderColor: border }]}>\n <Text style={[hitStyles.title, { color: ink }]} numberOfLines={1}>\n {queryHint}\n </Text>\n <Text style={[hitStyles.sub, { color: muted }]} numberOfLines={1}>\n {jobs.length} role{jobs.length === 1 ? '' : 's'}\n </Text>\n <ScrollView\n horizontal\n nestedScrollEnabled\n directionalLockEnabled\n keyboardShouldPersistTaps=\"handled\"\n showsHorizontalScrollIndicator\n bounces\n style={hitStyles.hScroll}\n contentContainerStyle={hitStyles.row}\n >\n {preview.map((job) => (\n <Pressable\n key={job.id}\n unstable_pressDelay={80}\n onPress={() => onOpenJob(job)}\n style={hitStyles.tile}\n >\n <View style={[hitStyles.avatar, { backgroundColor: companyAvatarColor(job.company) }]}>\n <MaterialCommunityIcons name=\"briefcase-outline\" size={22} color=\"#FFFFFF\" />\n </View>\n <Text style={[hitStyles.thumbTitle, { color: ink }]} numberOfLines={2}>\n {job.title}\n </Text>\n <Text style={[hitStyles.thumbMeta, { color: muted }]} numberOfLines={1}>\n {job.company}\n </Text>\n </Pressable>\n ))}\n {remaining > 0 ? (\n <Pressable\n onPress={onViewJobs}\n style={[hitStyles.more, { borderColor: border }]}\n accessibilityRole=\"button\"\n accessibilityLabel={`View ${remaining} more roles`}\n >\n <Text style={[hitStyles.moreText, { color: muted }]}>+{remaining} more</Text>\n </Pressable>\n ) : null}\n </ScrollView>\n <Pressable\n onPress={onViewJobs}\n style={[hitStyles.cta, { backgroundColor: accent }]}\n accessibilityRole=\"button\"\n accessibilityLabel=\"View roles\"\n >\n <Feather name=\"external-link\" size={12} color=\"#fff\" />\n <Text style={hitStyles.ctaText}>View roles</Text>\n </Pressable>\n </View>\n );\n}\n\nconst hitStyles = StyleSheet.create({\n wrap: {\n marginHorizontal: 12,\n marginBottom: 8,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: 8,\n padding: 10,\n gap: 4,\n },\n title: { fontSize: 12, fontWeight: '600' },\n sub: { fontSize: 11, marginBottom: 4 },\n hScroll: { flexGrow: 0 },\n row: { gap: 8, paddingBottom: 4, paddingRight: 20 },\n tile: { width: TILE_W },\n avatar: {\n width: TILE_W,\n height: 56,\n borderRadius: 6,\n alignItems: 'center',\n justifyContent: 'center',\n },\n\n thumbTitle: { marginTop: 4, fontSize: 11, fontWeight: '600', lineHeight: 14 },\n thumbMeta: { fontSize: 10, marginTop: 1 },\n more: {\n width: TILE_W,\n alignItems: 'center',\n justifyContent: 'center',\n borderWidth: 1,\n borderStyle: 'dashed',\n borderRadius: 6,\n minHeight: 70,\n },\n moreText: { fontSize: 11 },\n cta: {\n marginTop: 8,\n borderRadius: 6,\n paddingVertical: 7,\n alignItems: 'center',\n justifyContent: 'center',\n flexDirection: 'row',\n gap: 6,\n },\n ctaText: { color: '#fff', fontWeight: '600', fontSize: 11 },\n});\n"],"names":["_a","_b","_c"],"mappings":"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"}
1
+ {"version":3,"file":"JobSearchAgentChatPane.js","sources":["../../../src/features/job-search/JobSearchAgentChatPane.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';\nimport { Feather, MaterialCommunityIcons } from '@expo/vector-icons';\nimport { NativeAgentChat, type AgentChatMessage, type AgentChatSuggestion } from '../agent-chat';\nimport { delayMs, splitReplyChunks } from '../shopping/chat/streamAssistantReply';\nimport type { MessageAttachment } from '../../hooks/useChatStream';\nimport type { JobPosting } from './types';\nimport type { ApplyFromChatResult } from './useJobSearchSession';\nimport type { JobSearchHostChat } from './hostChat';\nimport { parseJobSearchIntent, shouldUseHostLane } from './chat/widgetContent';\nimport { companyAvatarColor } from './jobSearchTheme';\n\nconst STREAM_TICK_MS = 16;\nconst CONVERSATION_REPLY =\n 'Tell me what to look for — a role, a company, a city, or remote. For example: remote senior backend engineer roles.';\n\nconst SUGGESTIONS: AgentChatSuggestion[] = [\n { id: 'find', label: 'Find roles', prompt: 'Find remote senior backend engineer roles' },\n { id: 'research', label: 'Research a company', prompt: 'Research Stripe for a senior backend role' },\n {\n id: 'analyze',\n label: 'Analyze a JD',\n prompt: 'Analyze this job description against my profile — I will paste the JD.',\n },\n {\n id: 'tailor',\n label: 'Tailor an application',\n prompt: 'Tailor my full application package for a job posting I name.',\n },\n {\n id: 'track',\n label: \"This week's pipeline\",\n prompt: 'Show my application pipeline: statuses, follow-ups, and what to apply to next.',\n },\n {\n id: 'outreach',\n label: 'Write outreach',\n prompt: 'Write a LinkedIn DM for one of my applications with a real hook.',\n },\n];\n\nexport function JobSearchAgentChatPane({\n visible,\n onClose,\n hostChat,\n applyFromChat,\n jobs,\n onViewJobs,\n onOpenJob,\n seedTurn = null,\n onClearChat,\n isDark,\n ink,\n muted,\n screen,\n border,\n card,\n accent,\n}: {\n visible: boolean;\n onClose: () => void;\n hostChat?: JobSearchHostChat;\n applyFromChat: (text: string) => Promise<ApplyFromChatResult>;\n jobs: JobPosting[];\n onViewJobs: () => void;\n onOpenJob: (job: JobPosting) => void;\n seedTurn?: {\n text: string;\n files?: MessageAttachment[];\n id?: string;\n mode?: 'send' | 'greet';\n greeting?: string;\n desk?: 'research' | 'tailor';\n } | null;\n /** Clears local + host chat and notifies parent to reset search. */\n onClearChat?: () => void;\n isDark: boolean;\n ink: string;\n muted: string;\n screen: string;\n border: string;\n card: string;\n accent: string;\n}) {\n const [localMessages, setLocalMessages] = useState<AgentChatMessage[]>([]);\n const [busy, setBusy] = useState(false);\n const [stream, setStream] = useState<string | null>(null);\n const [hitQuery, setHitQuery] = useState('');\n /** Landing chip desk: research / tailor empty state instead of a lone greeting bubble. */\n const [desk, setDesk] = useState<'default' | 'research' | 'tailor'>('default');\n const [composerSeed, setComposerSeed] = useState<string | null>(null);\n const [composerSeedKey, setComposerSeedKey] = useState(0);\n const inFlight = useRef(false);\n const seededKey = useRef<string | null>(null);\n const streamGen = useRef(0);\n const liveRef = useRef('');\n /** Native search owns the turn — ignore host busy/stream so Thinking does not reappear after results. */\n const nativeOwnsTurn = useRef(false);\n\n const hostMessages = hostChat?.messages ?? [];\n const messages = hostMessages.length > 0 ? hostMessages : localMessages;\n\n const pumpTo = async (gen: number, target: string) => {\n if (streamGen.current !== gen) return;\n let current = liveRef.current;\n if (target === current) return;\n if (!target.startsWith(current)) {\n current = '';\n liveRef.current = '';\n }\n const rest = target.slice(current.length);\n for (const chunk of splitReplyChunks(rest)) {\n if (streamGen.current !== gen) return;\n liveRef.current += chunk;\n setStream(liveRef.current);\n await delayMs(STREAM_TICK_MS);\n }\n };\n\n const summarizeJobs = (rows: JobPosting[], query: string) => {\n const q = query.trim();\n if (rows.length === 0) {\n return q\n ? `I couldn't find roles matching **${q}**. Try a broader title or drop the location.`\n : `I couldn't find roles for that request. Try a different query.`;\n }\n const header = q\n ? `I found **${rows.length} role${rows.length === 1 ? '' : 's'}** for **${q}**:`\n : `I found **${rows.length} role${rows.length === 1 ? '' : 's'}**:`;\n const preview = rows.slice(0, 3);\n const lines = preview.map((j, i) => `${i + 1}. **${j.title}** — ${j.company}${j.remote ? ' · Remote' : ''}`);\n const remaining = rows.length - preview.length;\n const parts = [header, '', ...lines];\n if (remaining > 0) parts.push('', `_+ ${remaining} more in the card below._`);\n parts.push('', 'Tap **View roles** below to browse the full list on the Jobs page.');\n return parts.join('\\n');\n };\n\n const runNativeSearch = (query: string, showLocalTurns: boolean) => {\n const gen = ++streamGen.current;\n nativeOwnsTurn.current = true;\n liveRef.current = `Searching live boards for **${query}**…`;\n setBusy(true);\n setStream(liveRef.current);\n void applyFromChat(query)\n .then(async (result) => {\n if (streamGen.current !== gen) return;\n // `in`, not `result.conversation`: without strictNullChecks a boolean\n // discriminant does not narrow the union.\n if (!('jobs' in result)) {\n if (showLocalTurns) {\n await pumpTo(gen, CONVERSATION_REPLY);\n setLocalMessages((prev) => [\n ...prev,\n { id: `a-${Date.now()}`, role: 'assistant', content: CONVERSATION_REPLY },\n ]);\n }\n setBusy(false);\n setStream(null);\n liveRef.current = '';\n return;\n }\n if (!result.error && result.jobs.length > 0) setHitQuery(result.query);\n else setHitQuery('');\n const body = result.error || summarizeJobs(result.jobs, result.query);\n await pumpTo(gen, body);\n if (streamGen.current !== gen) return;\n if (showLocalTurns) {\n setLocalMessages((prev) => [...prev, { id: `a-${Date.now()}`, role: 'assistant', content: body }]);\n }\n // Clear busy before stream so Thinking never flashes between the reply and the card.\n setBusy(false);\n setStream(null);\n liveRef.current = '';\n })\n .finally(() => {\n if (streamGen.current !== gen) return;\n nativeOwnsTurn.current = false;\n inFlight.current = false;\n setBusy(false);\n });\n };\n\n const send = (text: string, files?: MessageAttachment[]) => {\n const trimmed = text.trim();\n if (!trimmed && !files?.length) return;\n streamGen.current += 1;\n setStream(null);\n inFlight.current = true;\n const fileCount = files?.length ?? 0;\n const parsed = parseJobSearchIntent(trimmed);\n const useHost = Boolean(hostChat) && shouldUseHostLane(trimmed, fileCount);\n\n if (useHost && hostChat) {\n nativeOwnsTurn.current = false;\n if (!hostChat.connected) {\n setLocalMessages((prev) => [\n ...prev,\n { id: `u-${Date.now()}`, role: 'user', content: trimmed },\n {\n id: `a-${Date.now()}`,\n role: 'assistant',\n content:\n hostChat.error ||\n 'CDeCLI is not connected yet. Check gateway status in the header, then send again.',\n },\n ]);\n inFlight.current = false;\n return;\n }\n // Host-only: do not also run native search. Parallel lanes left Thinking/Drafting\n // on after the roles card appeared (research prompts match SEARCH_HINT via \"role\").\n hostChat.send(trimmed, files);\n inFlight.current = false;\n return;\n }\n\n setLocalMessages((prev) => [\n ...prev,\n { id: `u-${Date.now()}`, role: 'user', content: trimmed, createdAt: new Date().toISOString() },\n ]);\n if (parsed) {\n runNativeSearch(trimmed, true);\n return;\n }\n setLocalMessages((prev) => [\n ...prev,\n { id: `a-${Date.now()}`, role: 'assistant', content: CONVERSATION_REPLY },\n ]);\n inFlight.current = false;\n };\n\n const clearChat = () => {\n streamGen.current += 1;\n liveRef.current = '';\n nativeOwnsTurn.current = false;\n setStream(null);\n setBusy(false);\n inFlight.current = false;\n setLocalMessages([]);\n setHitQuery('');\n setDesk('default');\n setComposerSeed(null);\n seededKey.current = null;\n hostChat?.clear?.();\n onClearChat?.();\n };\n\n useEffect(() => {\n if (!visible || !seedTurn) return;\n const key = seedTurn.id ?? `${seedTurn.text}|${seedTurn.files?.length ?? 0}|${seedTurn.mode ?? 'send'}`;\n if (seededKey.current === key) return;\n seededKey.current = key;\n // Conversational chips (Research / Tailor): open a focused desk — do not\n // auto-send a long instruction that leaves the user on Pondering…\n if (seedTurn.mode === 'greet') {\n const kind = seedTurn.desk === 'tailor' ? 'tailor' : 'research';\n setHitQuery('');\n setBusy(false);\n setStream(null);\n setLocalMessages([]);\n setDesk(kind);\n setComposerSeed(kind === 'research' ? 'Research ' : '');\n setComposerSeedKey((n) => n + 1);\n return;\n }\n setDesk('default');\n send(seedTurn.text, seedTurn.files);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [visible, seedTurn]);\n\n const emptyTitle =\n desk === 'research' ? 'Research a company' : desk === 'tailor' ? 'Tailor an application' : 'Job hunt copilot';\n const emptyBody =\n desk === 'research'\n ? 'Name a company and the role you are targeting. I will cover culture, tech stack, live openings, and verifiable hooks.'\n : desk === 'tailor'\n ? 'Paste a JD URL or name the company + role and I will build the tailored package.'\n : 'Search live boards, tailor a resume, and track applications in one place.';\n const placeholder =\n desk === 'research'\n ? 'e.g. Stripe — senior backend'\n : desk === 'tailor'\n ? 'e.g. paste JD URL or company + role'\n : 'Find roles, tailor a JD, or ask about the pipeline…';\n const deskSuggestions: AgentChatSuggestion[] =\n desk === 'research'\n ? [\n { id: 'r-stripe', label: 'Stripe', prompt: 'Research Stripe for a senior backend engineer role' },\n { id: 'r-notion', label: 'Notion', prompt: 'Research Notion for a product engineer role' },\n { id: 'r-vercel', label: 'Vercel', prompt: 'Research Vercel for a full stack engineer role' },\n ]\n : desk === 'tailor'\n ? [\n {\n id: 't-url',\n label: 'I have a JD URL',\n prompt: 'Tailor my application — I will paste the job URL next.',\n },\n {\n id: 't-paste',\n label: 'I will paste the JD',\n prompt: 'Tailor my application — I will paste the job description next.',\n },\n ]\n : SUGGESTIONS;\n\n return (\n <NativeAgentChat\n title=\"Job Agent\"\n visible={visible}\n onClose={onClose}\n // Opens with a swipe in from the right edge, so it closes with one back out.\n onSwipeLeft={onClose}\n messages={messages}\n renderConnectorCard={hostChat?.renderConnectorCard}\n onSend={(text, files) => {\n setDesk('default');\n send(text, files);\n }}\n onClear={clearChat}\n busy={busy || (Boolean(hostChat?.busy) && !nativeOwnsTurn.current && !stream)}\n steering={hostChat}\n streamingContent={stream ?? (nativeOwnsTurn.current ? null : (hostChat?.streaming ?? null))}\n error={hostChat?.error ?? null}\n placeholder={placeholder}\n emptyTitle={emptyTitle}\n emptyBody={emptyBody}\n suggestions={messages.length === 0 ? deskSuggestions : []}\n composerSeed={composerSeed}\n composerSeedKey={composerSeedKey}\n onComposerSeedConsumed={() => setComposerSeed(null)}\n composerLead={\n hitQuery && jobs.length > 0 ? (\n <JobHitsCard\n jobs={jobs}\n query={hitQuery}\n onViewJobs={onViewJobs}\n onOpenJob={onOpenJob}\n ink={ink}\n muted={muted}\n border={border}\n card={card}\n accent={accent}\n />\n ) : null\n }\n isDark={isDark}\n ink={ink}\n muted={muted}\n screen={screen}\n border={border}\n />\n );\n}\n\nconst PREVIEW_LIMIT = 8;\nconst TILE_W = 112;\n\nfunction JobHitsCard({\n jobs,\n query,\n onViewJobs,\n onOpenJob,\n ink,\n muted,\n border,\n card,\n accent,\n}: {\n jobs: JobPosting[];\n query: string;\n onViewJobs: () => void;\n onOpenJob: (job: JobPosting) => void;\n ink: string;\n muted: string;\n border: string;\n card: string;\n accent: string;\n}) {\n const preview = jobs.slice(0, PREVIEW_LIMIT);\n const remaining = jobs.length - preview.length;\n const queryHint = query.trim() ? `Roles for ${query.trim()}` : 'Job results';\n\n return (\n <View style={[hitStyles.wrap, { backgroundColor: card, borderColor: border }]}>\n <Text style={[hitStyles.title, { color: ink }]} numberOfLines={1}>\n {queryHint}\n </Text>\n <Text style={[hitStyles.sub, { color: muted }]} numberOfLines={1}>\n {jobs.length} role{jobs.length === 1 ? '' : 's'}\n </Text>\n <ScrollView\n horizontal\n nestedScrollEnabled\n directionalLockEnabled\n keyboardShouldPersistTaps=\"handled\"\n showsHorizontalScrollIndicator\n bounces\n style={hitStyles.hScroll}\n contentContainerStyle={hitStyles.row}\n >\n {preview.map((job) => (\n <Pressable\n key={job.id}\n unstable_pressDelay={80}\n onPress={() => onOpenJob(job)}\n style={hitStyles.tile}\n >\n <View style={[hitStyles.avatar, { backgroundColor: companyAvatarColor(job.company) }]}>\n <MaterialCommunityIcons name=\"briefcase-outline\" size={22} color=\"#FFFFFF\" />\n </View>\n <Text style={[hitStyles.thumbTitle, { color: ink }]} numberOfLines={2}>\n {job.title}\n </Text>\n <Text style={[hitStyles.thumbMeta, { color: muted }]} numberOfLines={1}>\n {job.company}\n </Text>\n </Pressable>\n ))}\n {remaining > 0 ? (\n <Pressable\n onPress={onViewJobs}\n style={[hitStyles.more, { borderColor: border }]}\n accessibilityRole=\"button\"\n accessibilityLabel={`View ${remaining} more roles`}\n >\n <Text style={[hitStyles.moreText, { color: muted }]}>+{remaining} more</Text>\n </Pressable>\n ) : null}\n </ScrollView>\n <Pressable\n onPress={onViewJobs}\n style={[hitStyles.cta, { backgroundColor: accent }]}\n accessibilityRole=\"button\"\n accessibilityLabel=\"View roles\"\n >\n <Feather name=\"external-link\" size={12} color=\"#fff\" />\n <Text style={hitStyles.ctaText}>View roles</Text>\n </Pressable>\n </View>\n );\n}\n\nconst hitStyles = StyleSheet.create({\n wrap: {\n marginHorizontal: 12,\n marginBottom: 8,\n borderWidth: StyleSheet.hairlineWidth,\n borderRadius: 8,\n padding: 10,\n gap: 4,\n },\n title: { fontSize: 12, fontWeight: '600' },\n sub: { fontSize: 11, marginBottom: 4 },\n hScroll: { flexGrow: 0 },\n row: { gap: 8, paddingBottom: 4, paddingRight: 20 },\n tile: { width: TILE_W },\n avatar: {\n width: TILE_W,\n height: 56,\n borderRadius: 6,\n alignItems: 'center',\n justifyContent: 'center',\n },\n\n thumbTitle: { marginTop: 4, fontSize: 11, fontWeight: '600', lineHeight: 14 },\n thumbMeta: { fontSize: 10, marginTop: 1 },\n more: {\n width: TILE_W,\n alignItems: 'center',\n justifyContent: 'center',\n borderWidth: 1,\n borderStyle: 'dashed',\n borderRadius: 6,\n minHeight: 70,\n },\n moreText: { fontSize: 11 },\n cta: {\n marginTop: 8,\n borderRadius: 6,\n paddingVertical: 7,\n alignItems: 'center',\n justifyContent: 'center',\n flexDirection: 'row',\n gap: 6,\n },\n ctaText: { color: '#fff', fontWeight: '600', fontSize: 11 },\n});\n"],"names":["_a","_b","_c"],"mappings":"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"}
@@ -109,7 +109,7 @@ function LocalServicesAgentChatPane({
109
109
  setLocalMessages([]);
110
110
  seeded.current = null;
111
111
  (_a2 = hostChat == null ? void 0 : hostChat.clear) == null ? void 0 : _a2.call(hostChat);
112
- }, busy: Boolean(hostChat == null ? void 0 : hostChat.busy), streamingContent: (_b = hostChat == null ? void 0 : hostChat.streaming) != null ? _b : null, error: (_c = hostChat == null ? void 0 : hostChat.error) != null ? _c : null, placeholder: "Ask about a job or a pro\u2026", emptyTitle: "What needs doing?", emptyBody: hasResults ? "Ask about the pros on your list: who is open, who to call first, what to ask them." : "Describe the job and where, and the agent finds the right local pro for it.", suggestions: messages.length === 0 ? agentSuggestions(hasResults) : [], beforeComposer: latest && !(hostChat == null ? void 0 : hostChat.busy) ? /* @__PURE__ */ jsx(ResultsCard, { results: latest.results, theme, onShow: () => onShowResults(latest.results) }) : null, isDark: theme.isDark, ink: theme.ink, muted: theme.muted, screen: theme.screen, border: theme.border, card: theme.card });
112
+ }, busy: Boolean(hostChat == null ? void 0 : hostChat.busy), steering: hostChat, streamingContent: (_b = hostChat == null ? void 0 : hostChat.streaming) != null ? _b : null, error: (_c = hostChat == null ? void 0 : hostChat.error) != null ? _c : null, placeholder: "Ask about a job or a pro\u2026", emptyTitle: "What needs doing?", emptyBody: hasResults ? "Ask about the pros on your list: who is open, who to call first, what to ask them." : "Describe the job and where, and the agent finds the right local pro for it.", suggestions: messages.length === 0 ? agentSuggestions(hasResults) : [], beforeComposer: latest && !(hostChat == null ? void 0 : hostChat.busy) ? /* @__PURE__ */ jsx(ResultsCard, { results: latest.results, theme, onShow: () => onShowResults(latest.results) }) : null, isDark: theme.isDark, ink: theme.ink, muted: theme.muted, screen: theme.screen, border: theme.border, card: theme.card });
113
113
  }
114
114
  const styles = StyleSheet.create({
115
115
  card: {