@robosystems/core 0.3.0

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 (249) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +252 -0
  3. package/actions/entity-actions.d.ts +8 -0
  4. package/actions/entity-actions.js +16 -0
  5. package/actions/graph-actions.d.ts +3 -0
  6. package/actions/graph-actions.js +13 -0
  7. package/auth-components/AppSwitcher.d.ts +6 -0
  8. package/auth-components/AppSwitcher.js +28 -0
  9. package/auth-components/AuthGuard.d.ts +7 -0
  10. package/auth-components/AuthGuard.js +31 -0
  11. package/auth-components/AuthProvider.d.ts +9 -0
  12. package/auth-components/AuthProvider.js +565 -0
  13. package/auth-components/SessionWarningDialog.d.ts +1 -0
  14. package/auth-components/SessionWarningDialog.js +51 -0
  15. package/auth-components/SignInForm.d.ts +20 -0
  16. package/auth-components/SignInForm.js +139 -0
  17. package/auth-components/SignUpForm.d.ts +15 -0
  18. package/auth-components/SignUpForm.js +167 -0
  19. package/auth-components/TurnstileWidget.d.ts +99 -0
  20. package/auth-components/TurnstileWidget.js +224 -0
  21. package/auth-components/index.d.ts +6 -0
  22. package/auth-components/index.js +6 -0
  23. package/auth-core/cleanup.d.ts +44 -0
  24. package/auth-core/cleanup.js +157 -0
  25. package/auth-core/client.d.ts +121 -0
  26. package/auth-core/client.js +767 -0
  27. package/auth-core/config.d.ts +19 -0
  28. package/auth-core/config.js +56 -0
  29. package/auth-core/hooks.d.ts +19 -0
  30. package/auth-core/hooks.js +63 -0
  31. package/auth-core/index.d.ts +6 -0
  32. package/auth-core/index.js +6 -0
  33. package/auth-core/sso.d.ts +42 -0
  34. package/auth-core/sso.js +281 -0
  35. package/auth-core/token-storage.d.ts +58 -0
  36. package/auth-core/token-storage.js +177 -0
  37. package/auth-core/types.d.ts +145 -0
  38. package/auth-core/types.js +1 -0
  39. package/components/EntitySelector.d.ts +44 -0
  40. package/components/EntitySelector.js +64 -0
  41. package/components/EntitySelectorCore.d.ts +45 -0
  42. package/components/EntitySelectorCore.js +67 -0
  43. package/components/GraphSelectorCore.d.ts +21 -0
  44. package/components/GraphSelectorCore.js +39 -0
  45. package/components/PageLayout.d.ts +8 -0
  46. package/components/PageLayout.js +5 -0
  47. package/components/RepositoryGuard.d.ts +68 -0
  48. package/components/RepositoryGuard.js +91 -0
  49. package/components/console/ConsoleContent.d.ts +4 -0
  50. package/components/console/ConsoleContent.js +612 -0
  51. package/components/console/ConsoleMarkdown.d.ts +11 -0
  52. package/components/console/ConsoleMarkdown.js +49 -0
  53. package/components/console/ProgressiveText.d.ts +6 -0
  54. package/components/console/ProgressiveText.js +21 -0
  55. package/components/console/graphAwareConfig.d.ts +70 -0
  56. package/components/console/graphAwareConfig.js +411 -0
  57. package/components/console/index.d.ts +6 -0
  58. package/components/console/index.js +4 -0
  59. package/components/console/types.d.ts +84 -0
  60. package/components/console/types.js +1 -0
  61. package/components/graph-filters.d.ts +75 -0
  62. package/components/graph-filters.js +111 -0
  63. package/components/index.d.ts +10 -0
  64. package/components/index.js +9 -0
  65. package/components/repositories/ActiveSubscriptions.d.ts +26 -0
  66. package/components/repositories/ActiveSubscriptions.js +103 -0
  67. package/components/repositories/BrowseRepositories.d.ts +11 -0
  68. package/components/repositories/BrowseRepositories.js +184 -0
  69. package/components/repositories/index.d.ts +2 -0
  70. package/components/repositories/index.js +2 -0
  71. package/components/search/SearchContent.d.ts +4 -0
  72. package/components/search/SearchContent.js +168 -0
  73. package/components/search/index.d.ts +2 -0
  74. package/components/search/index.js +1 -0
  75. package/components/search/types.d.ts +15 -0
  76. package/components/search/types.js +1 -0
  77. package/contexts/entity-context.d.ts +28 -0
  78. package/contexts/entity-context.js +89 -0
  79. package/contexts/graph-context.d.ts +27 -0
  80. package/contexts/graph-context.js +128 -0
  81. package/contexts/index.d.ts +5 -0
  82. package/contexts/index.js +5 -0
  83. package/contexts/org-context.d.ts +25 -0
  84. package/contexts/org-context.js +64 -0
  85. package/contexts/service-offerings-context.d.ts +45 -0
  86. package/contexts/service-offerings-context.js +98 -0
  87. package/contexts/sidebar-context.d.ts +18 -0
  88. package/contexts/sidebar-context.js +44 -0
  89. package/hooks/index.d.ts +6 -0
  90. package/hooks/index.js +6 -0
  91. package/hooks/use-api-error.d.ts +3 -0
  92. package/hooks/use-api-error.js +24 -0
  93. package/hooks/use-media-query.d.ts +1 -0
  94. package/hooks/use-media-query.js +21 -0
  95. package/hooks/use-streaming-query.d.ts +22 -0
  96. package/hooks/use-streaming-query.js +142 -0
  97. package/hooks/use-toast.d.ts +37 -0
  98. package/hooks/use-toast.js +117 -0
  99. package/hooks/use-user-limits.d.ts +12 -0
  100. package/hooks/use-user-limits.js +73 -0
  101. package/hooks/use-user.d.ts +11 -0
  102. package/hooks/use-user.js +39 -0
  103. package/index.d.ts +29 -0
  104. package/index.js +77 -0
  105. package/lib/entity-cookie.d.ts +10 -0
  106. package/lib/entity-cookie.js +38 -0
  107. package/lib/graph-cookie.d.ts +11 -0
  108. package/lib/graph-cookie.js +62 -0
  109. package/lib/graph-tiers.d.ts +41 -0
  110. package/lib/graph-tiers.js +107 -0
  111. package/lib/index.d.ts +3 -0
  112. package/lib/index.js +3 -0
  113. package/lib/sidebar-cookie.d.ts +11 -0
  114. package/lib/sidebar-cookie.js +42 -0
  115. package/library/colors.d.ts +4 -0
  116. package/library/colors.js +41 -0
  117. package/library/components/ClassificationPicker.d.ts +8 -0
  118. package/library/components/ClassificationPicker.js +55 -0
  119. package/library/components/ElementBrowser.d.ts +11 -0
  120. package/library/components/ElementBrowser.js +106 -0
  121. package/library/components/ElementDetail.d.ts +7 -0
  122. package/library/components/ElementDetail.js +97 -0
  123. package/library/components/LibraryHierarchy.d.ts +13 -0
  124. package/library/components/LibraryHierarchy.js +380 -0
  125. package/library/components/TaxonomySidebar.d.ts +6 -0
  126. package/library/components/TaxonomySidebar.js +45 -0
  127. package/library/index.d.ts +8 -0
  128. package/library/index.js +7 -0
  129. package/package.json +37 -0
  130. package/research/CoverageCard.d.ts +12 -0
  131. package/research/CoverageCard.js +15 -0
  132. package/research/CoverageGrid.d.ts +6 -0
  133. package/research/CoverageGrid.js +9 -0
  134. package/research/CoverageHistory.d.ts +5 -0
  135. package/research/CoverageHistory.js +7 -0
  136. package/research/ResearchArticle.d.ts +15 -0
  137. package/research/ResearchArticle.js +26 -0
  138. package/research/catalog.d.ts +14 -0
  139. package/research/catalog.js +42 -0
  140. package/research/index.d.ts +6 -0
  141. package/research/index.js +9 -0
  142. package/research/types.d.ts +38 -0
  143. package/research/types.js +4 -0
  144. package/task-monitoring/hooks.d.ts +26 -0
  145. package/task-monitoring/hooks.js +126 -0
  146. package/task-monitoring/index.d.ts +5 -0
  147. package/task-monitoring/index.js +7 -0
  148. package/task-monitoring/operationErrors.d.ts +82 -0
  149. package/task-monitoring/operationErrors.js +251 -0
  150. package/task-monitoring/operationHooks.d.ts +117 -0
  151. package/task-monitoring/operationHooks.js +536 -0
  152. package/task-monitoring/operationMonitor.d.ts +78 -0
  153. package/task-monitoring/operationMonitor.js +200 -0
  154. package/task-monitoring/operationTypes.d.ts +236 -0
  155. package/task-monitoring/operationTypes.js +60 -0
  156. package/task-monitoring/taskMonitor.d.ts +14 -0
  157. package/task-monitoring/taskMonitor.js +132 -0
  158. package/task-monitoring/types.d.ts +31 -0
  159. package/task-monitoring/types.js +1 -0
  160. package/theme/flowbite-theme.d.ts +758 -0
  161. package/theme/flowbite-theme.js +765 -0
  162. package/theme/index.d.ts +1 -0
  163. package/theme/index.js +1 -0
  164. package/types/entity.d.ts +19 -0
  165. package/types/index.d.ts +2 -0
  166. package/types/index.js +1 -0
  167. package/types/user.d.ts +6 -0
  168. package/ui-components/ConfirmModal.d.ts +41 -0
  169. package/ui-components/ConfirmModal.js +19 -0
  170. package/ui-components/EmptyState.d.ts +22 -0
  171. package/ui-components/EmptyState.js +10 -0
  172. package/ui-components/LoadingState.d.ts +27 -0
  173. package/ui-components/LoadingState.js +12 -0
  174. package/ui-components/Logo.d.ts +28 -0
  175. package/ui-components/Logo.js +95 -0
  176. package/ui-components/Spinner.d.ts +37 -0
  177. package/ui-components/Spinner.js +48 -0
  178. package/ui-components/StatCard.d.ts +21 -0
  179. package/ui-components/StatCard.js +10 -0
  180. package/ui-components/api-keys/ApiKeyDisplay.d.ts +13 -0
  181. package/ui-components/api-keys/ApiKeyDisplay.js +7 -0
  182. package/ui-components/api-keys/ApiKeyTable.d.ts +9 -0
  183. package/ui-components/api-keys/ApiKeyTable.js +17 -0
  184. package/ui-components/api-keys/ApiKeysCard.d.ts +6 -0
  185. package/ui-components/api-keys/ApiKeysCard.js +97 -0
  186. package/ui-components/api-keys/CreateApiKeyModal.d.ts +11 -0
  187. package/ui-components/api-keys/CreateApiKeyModal.js +47 -0
  188. package/ui-components/api-keys/SecureApiKeyField.d.ts +13 -0
  189. package/ui-components/api-keys/SecureApiKeyField.js +64 -0
  190. package/ui-components/api-keys/index.d.ts +5 -0
  191. package/ui-components/api-keys/index.js +5 -0
  192. package/ui-components/chat/ChatHeader.d.ts +12 -0
  193. package/ui-components/chat/ChatHeader.js +5 -0
  194. package/ui-components/chat/ChatInputArea.d.ts +16 -0
  195. package/ui-components/chat/ChatInputArea.js +9 -0
  196. package/ui-components/chat/ChatMessage.d.ts +7 -0
  197. package/ui-components/chat/ChatMessage.js +24 -0
  198. package/ui-components/chat/DeepResearchToggle.d.ts +8 -0
  199. package/ui-components/chat/DeepResearchToggle.js +13 -0
  200. package/ui-components/chat/index.d.ts +9 -0
  201. package/ui-components/chat/index.js +8 -0
  202. package/ui-components/chat/types.d.ts +23 -0
  203. package/ui-components/chat/types.js +51 -0
  204. package/ui-components/forms/PasswordRequirements.d.ts +10 -0
  205. package/ui-components/forms/PasswordRequirements.js +15 -0
  206. package/ui-components/forms/SettingsCard.d.ts +11 -0
  207. package/ui-components/forms/SettingsCard.js +5 -0
  208. package/ui-components/forms/SettingsFormField.d.ts +18 -0
  209. package/ui-components/forms/SettingsFormField.js +17 -0
  210. package/ui-components/forms/StatusAlert.d.ts +8 -0
  211. package/ui-components/forms/StatusAlert.js +7 -0
  212. package/ui-components/forms/index.d.ts +4 -0
  213. package/ui-components/forms/index.js +4 -0
  214. package/ui-components/index.d.ts +13 -0
  215. package/ui-components/index.js +18 -0
  216. package/ui-components/layout/CoreNavbar.d.ts +14 -0
  217. package/ui-components/layout/CoreNavbar.js +53 -0
  218. package/ui-components/layout/CoreSidebar.d.ts +28 -0
  219. package/ui-components/layout/CoreSidebar.js +62 -0
  220. package/ui-components/layout/LandingFooter.d.ts +28 -0
  221. package/ui-components/layout/LandingFooter.js +34 -0
  222. package/ui-components/layout/PageContainer.d.ts +8 -0
  223. package/ui-components/layout/PageContainer.js +17 -0
  224. package/ui-components/layout/PageHeader.d.ts +23 -0
  225. package/ui-components/layout/PageHeader.js +12 -0
  226. package/ui-components/layout/SettingsContainer.d.ts +10 -0
  227. package/ui-components/layout/SettingsContainer.js +9 -0
  228. package/ui-components/layout/ThemeToggle.d.ts +4 -0
  229. package/ui-components/layout/ThemeToggle.js +6 -0
  230. package/ui-components/layout/index.d.ts +7 -0
  231. package/ui-components/layout/index.js +7 -0
  232. package/ui-components/settings/GeneralInformationCard.d.ts +12 -0
  233. package/ui-components/settings/GeneralInformationCard.js +72 -0
  234. package/ui-components/settings/PasswordInformationCard.d.ts +10 -0
  235. package/ui-components/settings/PasswordInformationCard.js +167 -0
  236. package/ui-components/settings/SettingsPageHeader.d.ts +7 -0
  237. package/ui-components/settings/SettingsPageHeader.js +6 -0
  238. package/ui-components/settings/index.d.ts +3 -0
  239. package/ui-components/settings/index.js +3 -0
  240. package/ui-components/support/SupportModal.d.ts +15 -0
  241. package/ui-components/support/SupportModal.js +74 -0
  242. package/ui-components/support/index.d.ts +2 -0
  243. package/ui-components/support/index.js +1 -0
  244. package/ui-components/types/index.d.ts +39 -0
  245. package/ui-components/types/index.js +1 -0
  246. package/utils/index.d.ts +31 -0
  247. package/utils/index.js +38 -0
  248. package/utils/turnstile-config.d.ts +11 -0
  249. package/utils/turnstile-config.js +19 -0
@@ -0,0 +1,45 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Badge, Card } from 'flowbite-react';
4
+ const SECTION_ORDER = ['reporting', 'chart_of_accounts', 'schedule', 'mapping'];
5
+ const SECTION_LABELS = {
6
+ reporting: 'Reporting',
7
+ chart_of_accounts: 'Chart of Accounts',
8
+ schedule: 'Schedules',
9
+ mapping: 'Mappings',
10
+ };
11
+ export function TaxonomySidebar({ taxonomies, selectedId, onSelect, }) {
12
+ var _a;
13
+ // Group by taxonomyType, preserve SECTION_ORDER
14
+ const groups = [];
15
+ const seen = new Set();
16
+ const grouped = new Map();
17
+ for (const t of taxonomies) {
18
+ const type = (_a = t.taxonomyType) !== null && _a !== void 0 ? _a : 'reporting';
19
+ if (!grouped.has(type))
20
+ grouped.set(type, []);
21
+ grouped.get(type).push(t);
22
+ }
23
+ for (const type of SECTION_ORDER) {
24
+ if (grouped.has(type)) {
25
+ groups.push({ type, items: grouped.get(type) });
26
+ seen.add(type);
27
+ }
28
+ }
29
+ // Any remaining types not in SECTION_ORDER
30
+ for (const [type, items] of grouped) {
31
+ if (!seen.has(type))
32
+ groups.push({ type, items });
33
+ }
34
+ const showSections = groups.length > 1;
35
+ return (_jsx("aside", { className: "col-span-12 min-h-0 md:col-span-3", children: _jsxs(Card, { className: "flex h-full flex-col overflow-hidden", children: [_jsx("h2", { className: "font-heading shrink-0 text-lg font-semibold text-gray-900 dark:text-white", children: "Taxonomies" }), _jsx("div", { className: "min-h-0 flex-1 space-y-3 overflow-y-auto", children: groups.map(({ type, items }, gi) => {
36
+ var _a;
37
+ return (_jsxs("div", { children: [showSections && (_jsx("div", { className: `px-1 pb-1 text-[10px] font-semibold tracking-wider text-gray-400 uppercase dark:text-gray-500 ${gi > 0 ? 'border-t border-gray-100 pt-3 dark:border-gray-700' : ''}`, children: (_a = SECTION_LABELS[type]) !== null && _a !== void 0 ? _a : type })), _jsx("ul", { className: "space-y-1", children: items.map((t) => {
38
+ var _a, _b;
39
+ const isSelected = t.id === selectedId;
40
+ return (_jsx("li", { children: _jsxs("button", { onClick: () => onSelect(t.id), className: `w-full rounded px-3 py-2 text-left text-sm transition-colors ${isSelected
41
+ ? 'bg-primary-100 text-primary-900 dark:bg-primary-900/50 dark:text-primary-100'
42
+ : 'text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-800'}`, children: [_jsxs("div", { className: "flex items-center justify-between gap-2", children: [t.standard ? (_jsxs("span", { className: "truncate font-mono text-xs", title: `${t.standard}/${(_a = t.version) !== null && _a !== void 0 ? _a : ''}`, children: [t.standard, _jsxs("span", { className: "text-gray-400 dark:text-gray-500", children: ["/", (_b = t.version) !== null && _b !== void 0 ? _b : ''] })] })) : (_jsx("span", { className: "truncate text-xs font-medium", title: t.name, children: t.name })), t.elementCount !== null && (_jsx(Badge, { color: "gray", size: "xs", className: "shrink-0", children: t.elementCount.toLocaleString() }))] }), t.standard && (_jsx("div", { className: "truncate text-xs text-gray-500 dark:text-gray-400", title: t.name, children: t.name }))] }) }, t.id));
43
+ }) })] }, type));
44
+ }) })] }) }));
45
+ }
@@ -0,0 +1,8 @@
1
+ export { LIBRARY_GRAPH_ID, LibraryClient } from '@robosystems/client/clients';
2
+ export type { GetLibraryElementIdentifier, LibraryArc, LibraryElement, LibraryElementArc, LibraryElementClassification, LibraryElementDetail, LibraryEquivalence, LibraryLabel, LibraryReference, LibrarySearchResult, LibraryStructure, LibraryTaxonomy, LibraryTaxonomyDetail, ListLibraryElementsOptions, ListLibraryStructuresOptions, ListLibraryTaxonomyArcsOptions, ListLibraryTaxonomyArcsResult, SearchLibraryElementsOptions, } from '@robosystems/client/clients';
3
+ export { arcTypeColor, classificationColor } from './colors';
4
+ export { ClassificationPicker } from './components/ClassificationPicker';
5
+ export { ElementBrowser } from './components/ElementBrowser';
6
+ export { ElementDetail } from './components/ElementDetail';
7
+ export { LibraryHierarchy } from './components/LibraryHierarchy';
8
+ export { TaxonomySidebar } from './components/TaxonomySidebar';
@@ -0,0 +1,7 @@
1
+ export { LIBRARY_GRAPH_ID, LibraryClient } from '@robosystems/client/clients';
2
+ export { arcTypeColor, classificationColor } from './colors';
3
+ export { ClassificationPicker } from './components/ClassificationPicker';
4
+ export { ElementBrowser } from './components/ElementBrowser';
5
+ export { ElementDetail } from './components/ElementDetail';
6
+ export { LibraryHierarchy } from './components/LibraryHierarchy';
7
+ export { TaxonomySidebar } from './components/TaxonomySidebar';
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@robosystems/core",
3
+ "version": "0.3.0",
4
+ "description": "Shared RoboSystems frontend core library (auth, contexts, task monitoring, UI components) for the RoboSystems Next.js apps",
5
+ "license": "MIT",
6
+ "private": false,
7
+ "type": "module",
8
+ "main": "./index.js",
9
+ "types": "./index.d.ts",
10
+ "sideEffects": [
11
+ "./index.js"
12
+ ],
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/RoboFinSystems/robosystems-core.git"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public",
19
+ "registry": "https://registry.npmjs.org/"
20
+ },
21
+ "engines": {
22
+ "node": ">=22.0.0"
23
+ },
24
+ "dependencies": {
25
+ "react-markdown": "^10",
26
+ "remark-gfm": "^4.0.1",
27
+ "tailwind-merge": "^3"
28
+ },
29
+ "peerDependencies": {
30
+ "@robosystems/client": ">=0.3.2 <1",
31
+ "flowbite-react": "^0.12.5",
32
+ "next": ">=15 <17",
33
+ "react": ">=18 <20",
34
+ "react-dom": ">=18 <20",
35
+ "react-icons": ">=4 <6"
36
+ }
37
+ }
@@ -0,0 +1,12 @@
1
+ import type { CoverageItem } from './types';
2
+ /**
3
+ * A coverage tile: full-bleed thumbnail on top, then ticker/label, title, summary, and
4
+ * prior-report count. Self-contained (not the shared Flowbite Card) so the cover image
5
+ * sits flush at the top of every card regardless of how much text each one has — the
6
+ * shared card theme centers its content (`justify-center`), which left the covers at
7
+ * different heights across a row.
8
+ */
9
+ export declare function CoverageCard({ item, hrefBase, }: {
10
+ item: CoverageItem;
11
+ hrefBase?: string;
12
+ }): import("react").JSX.Element;
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import Link from 'next/link';
3
+ /**
4
+ * A coverage tile: full-bleed thumbnail on top, then ticker/label, title, summary, and
5
+ * prior-report count. Self-contained (not the shared Flowbite Card) so the cover image
6
+ * sits flush at the top of every card regardless of how much text each one has — the
7
+ * shared card theme centers its content (`justify-center`), which left the covers at
8
+ * different heights across a row.
9
+ */
10
+ export function CoverageCard({ item, hrefBase = '/research', }) {
11
+ var _a;
12
+ return (_jsx(Link, { href: `${hrefBase}/${item.ticker.toLowerCase()}`, className: "group block h-full", children: _jsxs("div", { className: "flex h-full flex-col overflow-hidden rounded-lg border border-gray-200 bg-white/80 shadow-lg backdrop-blur-sm transition-shadow duration-300 hover:shadow-xl dark:border-gray-700 dark:bg-zinc-950", children: [item.assets.thumbnail && (
13
+ // eslint-disable-next-line @next/next/no-img-element
14
+ _jsx("img", { src: item.assets.thumbnail, alt: item.title, className: "aspect-video w-full object-cover" })), _jsxs("div", { className: "flex flex-1 flex-col gap-2 p-5", children: [_jsxs("div", { className: "flex items-center gap-2 text-xs font-medium text-gray-500 dark:text-gray-400", children: [_jsx("span", { className: "rounded bg-cyan-500/10 px-2 py-0.5 font-semibold text-cyan-600 dark:text-cyan-400", children: item.ticker }), item.coverage_label && _jsx("span", { children: item.coverage_label }), _jsx("span", { className: "ml-auto", children: (_a = item.date) === null || _a === void 0 ? void 0 : _a.slice(0, 10) })] }), _jsx("h3", { className: "text-lg font-bold text-gray-900 group-hover:text-cyan-600 dark:text-white dark:group-hover:text-cyan-400", children: item.title }), _jsx("p", { className: "line-clamp-3 text-sm text-gray-600 dark:text-gray-300", children: item.summary }), item.history.length > 0 && (_jsxs("p", { className: "mt-auto pt-1 text-xs text-gray-400", children: ["+", item.history.length, " prior", ' ', item.history.length === 1 ? 'report' : 'reports'] }))] })] }) }));
15
+ }
@@ -0,0 +1,6 @@
1
+ import type { CoverageItem } from './types';
2
+ /** Responsive grid of coverage cards. */
3
+ export declare function CoverageGrid({ items, hrefBase, }: {
4
+ items: CoverageItem[];
5
+ hrefBase?: string;
6
+ }): import("react").JSX.Element;
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { CoverageCard } from './CoverageCard';
3
+ /** Responsive grid of coverage cards. */
4
+ export function CoverageGrid({ items, hrefBase, }) {
5
+ if (!items.length) {
6
+ return (_jsx("p", { className: "py-12 text-center text-gray-500 dark:text-gray-400", children: "No coverage yet \u2014 check back soon." }));
7
+ }
8
+ return (_jsx("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3", children: items.map((item) => (_jsx(CoverageCard, { item: item, hrefBase: hrefBase }, item.ticker))) }));
9
+ }
@@ -0,0 +1,5 @@
1
+ import type { CoverageVersion } from './types';
2
+ /** The continuing-coverage timeline: prior dated reports with links to their archived assets. */
3
+ export declare function CoverageHistory({ history }: {
4
+ history: CoverageVersion[];
5
+ }): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /** The continuing-coverage timeline: prior dated reports with links to their archived assets. */
3
+ export function CoverageHistory({ history }) {
4
+ if (!history.length)
5
+ return null;
6
+ return (_jsxs("section", { className: "mt-12 border-t border-gray-200 pt-8 dark:border-gray-800", children: [_jsx("h2", { className: "mb-4 text-xl font-bold text-gray-900 dark:text-white", children: "Coverage history" }), _jsx("ol", { className: "space-y-3", children: history.map((h) => (_jsxs("li", { className: "flex flex-col gap-1 rounded-lg border border-gray-200 p-4 sm:flex-row sm:items-center sm:gap-4 dark:border-gray-800", children: [_jsx("span", { className: "shrink-0 rounded bg-gray-100 px-2 py-0.5 text-xs font-semibold text-gray-600 dark:bg-gray-800 dark:text-gray-300", children: h.version }), _jsxs("span", { className: "flex-1 text-sm text-gray-700 dark:text-gray-200", children: [h.title || 'Prior report', h.legacy_ticker && (_jsxs("em", { className: "text-gray-400", children: [" (as ", h.legacy_ticker, ")"] }))] }), _jsxs("span", { className: "flex gap-3 text-xs", children: [(h.youtube_url || h.assets.video) && (_jsx("a", { href: h.youtube_url || h.assets.video, className: "text-cyan-600 hover:underline dark:text-cyan-400", children: "Video" })), h.assets.podcast_mp3 && (_jsx("a", { href: h.assets.podcast_mp3, className: "text-cyan-600 hover:underline dark:text-cyan-400", children: "Podcast" })), h.assets.brief && (_jsx("a", { href: h.assets.brief, className: "text-cyan-600 hover:underline dark:text-cyan-400", children: "Brief" }))] })] }, h.version))) })] }));
7
+ }
@@ -0,0 +1,15 @@
1
+ import type { CoverageItem } from './types';
2
+ /**
3
+ * The full coverage report: native video, the Q&A podcast (surfaced as a prominent
4
+ * "Listen" card right under the video), then the brief rendered from markdown (its own
5
+ * leading H1 is stripped — we render the title above it), and the continuing-coverage
6
+ * history. Works in a server component (SSR'd for SEO) or a client one.
7
+ * Styled for a dark background — render inside a dark (`bg-black`/`.dark`) container.
8
+ * The prose styling mirrors the blog article body so research reads consistently with it
9
+ * (explicit `prose-invert` + element overrides rather than `dark:prose-invert`, which the
10
+ * Tailwind v4 + typography-plugin setup in these apps does not resolve from a `.dark` class).
11
+ */
12
+ export declare function ResearchArticle({ item, briefMarkdown, }: {
13
+ item: CoverageItem;
14
+ briefMarkdown?: string;
15
+ }): import("react").JSX.Element;
@@ -0,0 +1,26 @@
1
+ import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import ReactMarkdown from 'react-markdown';
3
+ import remarkGfm from 'remark-gfm';
4
+ import { youtubeId } from './catalog';
5
+ import { CoverageHistory } from './CoverageHistory';
6
+ /**
7
+ * The full coverage report: native video, the Q&A podcast (surfaced as a prominent
8
+ * "Listen" card right under the video), then the brief rendered from markdown (its own
9
+ * leading H1 is stripped — we render the title above it), and the continuing-coverage
10
+ * history. Works in a server component (SSR'd for SEO) or a client one.
11
+ * Styled for a dark background — render inside a dark (`bg-black`/`.dark`) container.
12
+ * The prose styling mirrors the blog article body so research reads consistently with it
13
+ * (explicit `prose-invert` + element overrides rather than `dark:prose-invert`, which the
14
+ * Tailwind v4 + typography-plugin setup in these apps does not resolve from a `.dark` class).
15
+ */
16
+ export function ResearchArticle({ item, briefMarkdown, }) {
17
+ var _a;
18
+ const body = (briefMarkdown || '').replace(/^#\s.*(\r?\n)+/, '');
19
+ const ytId = youtubeId(item.youtube_url);
20
+ const podcastYtId = youtubeId(item.podcast_youtube_url);
21
+ return (_jsxs("article", { className: "mx-auto max-w-3xl", children: [_jsxs("div", { className: "mb-3 flex flex-wrap items-center gap-2 text-sm text-gray-500 dark:text-gray-400", children: [_jsxs("span", { className: "rounded bg-cyan-500/10 px-2 py-0.5 font-semibold text-cyan-600 dark:text-cyan-400", children: [item.company, " \u00B7 ", item.ticker] }), item.coverage_label && _jsx("span", { children: item.coverage_label }), _jsx("span", { children: (_a = item.date) === null || _a === void 0 ? void 0 : _a.slice(0, 10) })] }), _jsx("h1", { className: "mb-6 text-3xl font-bold text-gray-900 dark:text-white", children: item.title }), ytId ? (_jsx("div", { className: "mb-8 aspect-video w-full overflow-hidden rounded-xl bg-black", children: _jsx("iframe", { className: "h-full w-full", src: `https://www.youtube.com/embed/${ytId}`, title: item.title, loading: "lazy", allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share", allowFullScreen: true }) })) : (item.assets.video && (
22
+ // eslint-disable-next-line jsx-a11y/media-has-caption
23
+ _jsx("video", { controls: true, poster: item.assets.thumbnail, src: item.assets.video, className: "mb-8 aspect-video w-full rounded-xl bg-black" }))), (item.assets.podcast_mp3 || podcastYtId) && (_jsx("section", { className: "mb-8", children: item.assets.podcast_mp3 ? (_jsxs("div", { className: "rounded-xl border border-cyan-500/30 bg-gray-900/50 p-4", children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-3", children: [_jsx("p", { className: "text-sm font-semibold text-cyan-600 dark:text-cyan-400", children: "\uD83C\uDF99 Listen \u2014 Q&A podcast" }), podcastYtId && (_jsx("a", { href: item.podcast_youtube_url, target: "_blank", rel: "noopener noreferrer", className: "shrink-0 text-xs text-cyan-600 hover:underline dark:text-cyan-400", children: "Watch on YouTube \u2197" }))] }), _jsx("audio", { controls: true, preload: "none", src: item.assets.podcast_mp3, className: "w-full" })] })) : (
24
+ // no MP3 yet — fall back to the YouTube video player
25
+ _jsxs(_Fragment, { children: [_jsx("h2", { className: "mb-3 text-xl font-bold text-gray-900 dark:text-white", children: "Listen \u2014 Q&A podcast" }), _jsx("div", { className: "aspect-video w-full overflow-hidden rounded-xl bg-black", children: _jsx("iframe", { className: "h-full w-full", src: `https://www.youtube.com/embed/${podcastYtId}`, title: `${item.title} — Q&A podcast`, loading: "lazy", allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share", allowFullScreen: true }) })] })) })), body && (_jsx("div", { className: "prose prose-lg prose-invert prose-headings:font-heading prose-headings:font-bold prose-headings:text-white prose-p:text-gray-300 prose-p:leading-relaxed prose-a:text-cyan-400 prose-a:no-underline hover:prose-a:text-cyan-300 prose-strong:text-white prose-strong:font-semibold prose-code:text-cyan-400 prose-code:bg-gray-800 prose-code:px-2 prose-code:py-1 prose-code:rounded prose-pre:bg-gray-900 prose-pre:border prose-pre:border-gray-800 prose-blockquote:border-l-cyan-500 prose-blockquote:text-gray-400 prose-blockquote:italic prose-ul:text-gray-300 prose-ol:text-gray-300 prose-li:marker:text-cyan-500 prose-table:border-gray-700 prose-th:bg-gray-900 prose-th:text-white prose-td:text-gray-300 max-w-none", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: body }) })), _jsx(CoverageHistory, { history: item.history }), _jsxs("footer", { className: "mt-12 border-t border-gray-200 pt-6 dark:border-gray-800", children: [_jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: "Audio & music produced with ElevenLabs." }), _jsxs("a", { href: "https://elevenlabs.io/startup-grants", target: "_blank", rel: "noopener noreferrer", "aria-label": "Backed by the ElevenLabs Grants program", className: "mt-3 inline-block", children: [_jsx("img", { src: "/images/logos/elevenlabs-grants.webp", alt: "Backed by the ElevenLabs Grants program", width: 200, className: "h-auto dark:hidden" }), _jsx("img", { src: "/images/logos/elevenlabs-grants-white.webp", alt: "Backed by the ElevenLabs Grants program", width: 200, className: "hidden h-auto dark:block" })] }), _jsxs("p", { className: "mt-2 text-xs text-gray-400 dark:text-gray-500", children: ["Using ElevenLabs yourself? Our", ' ', _jsx("a", { href: "https://try.elevenlabs.io/v9z3wzm97gk3", target: "_blank", rel: "noopener noreferrer", className: "hover:underline", children: "referral link" }), ' ', "costs you nothing extra and supports this research."] })] })] }));
26
+ }
@@ -0,0 +1,14 @@
1
+ import type { Catalog, CoverageItem } from './types';
2
+ export declare const CATALOG_URL: string;
3
+ /** Fetch the full catalog. `revalidate` (seconds) drives Next ISR on the server. */
4
+ export declare function fetchCatalog(revalidate?: number): Promise<Catalog>;
5
+ /** All coverage items, newest first (the catalog is already sorted, but be defensive). */
6
+ export declare function getAllCoverage(revalidate?: number): Promise<CoverageItem[]>;
7
+ /** One company's coverage (latest + history), or null if not in the catalog. */
8
+ export declare function getCoverage(ticker: string, revalidate?: number): Promise<CoverageItem | null>;
9
+ /** Tickers for generateStaticParams(). */
10
+ export declare function getCoverageTickers(): Promise<string[]>;
11
+ /** Fetch a brief's raw markdown (rendered to HTML by ResearchArticle). */
12
+ export declare function fetchBrief(url: string, revalidate?: number): Promise<string>;
13
+ /** Extract a YouTube video id from a youtu.be / watch?v= / embed URL (or null). */
14
+ export declare function youtubeId(url?: string | null): string | null;
@@ -0,0 +1,42 @@
1
+ // Data access for the research catalog. The catalog is a single public JSON file served
2
+ // via the CloudFront CDN, produced by `just reindex` in robosystems-content-machine.
3
+ // Fetched server-side (SSG/ISR) in the public site and client-side in the logged-in app.
4
+ export const CATALOG_URL = process.env.NEXT_PUBLIC_RESEARCH_CATALOG_URL ||
5
+ 'https://assets.robosystems.ai/content/index.json';
6
+ /** Fetch the full catalog. `revalidate` (seconds) drives Next ISR on the server. */
7
+ export async function fetchCatalog(revalidate = 3600) {
8
+ const res = await fetch(CATALOG_URL, { next: { revalidate } });
9
+ if (!res.ok)
10
+ throw new Error(`Research catalog fetch failed: ${res.status}`);
11
+ return (await res.json());
12
+ }
13
+ /** All coverage items, newest first (the catalog is already sorted, but be defensive). */
14
+ export async function getAllCoverage(revalidate = 3600) {
15
+ const { items } = await fetchCatalog(revalidate);
16
+ return [...items].sort((a, b) => (b.date || '').localeCompare(a.date || ''));
17
+ }
18
+ /** One company's coverage (latest + history), or null if not in the catalog. */
19
+ export async function getCoverage(ticker, revalidate = 3600) {
20
+ const { items } = await fetchCatalog(revalidate);
21
+ const t = ticker.toUpperCase();
22
+ return items.find((i) => i.ticker.toUpperCase() === t) || null;
23
+ }
24
+ /** Tickers for generateStaticParams(). */
25
+ export async function getCoverageTickers() {
26
+ const { items } = await fetchCatalog();
27
+ return items.map((i) => i.ticker);
28
+ }
29
+ /** Fetch a brief's raw markdown (rendered to HTML by ResearchArticle). */
30
+ export async function fetchBrief(url, revalidate = 3600) {
31
+ const res = await fetch(url, { next: { revalidate } });
32
+ if (!res.ok)
33
+ throw new Error(`Brief fetch failed: ${res.status}`);
34
+ return await res.text();
35
+ }
36
+ /** Extract a YouTube video id from a youtu.be / watch?v= / embed URL (or null). */
37
+ export function youtubeId(url) {
38
+ if (!url)
39
+ return null;
40
+ const m = url.match(/(?:youtu\.be\/|[?&]v=|embed\/)([A-Za-z0-9_-]{6,})/);
41
+ return m ? m[1] : null;
42
+ }
@@ -0,0 +1,6 @@
1
+ export { CATALOG_URL, fetchBrief, fetchCatalog, getAllCoverage, getCoverage, getCoverageTickers, youtubeId, } from './catalog';
2
+ export { CoverageCard } from './CoverageCard';
3
+ export { CoverageGrid } from './CoverageGrid';
4
+ export { CoverageHistory } from './CoverageHistory';
5
+ export { ResearchArticle } from './ResearchArticle';
6
+ export * from './types';
@@ -0,0 +1,9 @@
1
+ // Research portal module — shared across robosystems-app (public/SEO) and
2
+ // roboinvestor-app (logged-in). Data layer reads the S3 catalog produced by
3
+ // robosystems-content-machine; components render the coverage + continuing-coverage thread.
4
+ export { CATALOG_URL, fetchBrief, fetchCatalog, getAllCoverage, getCoverage, getCoverageTickers, youtubeId, } from './catalog';
5
+ export { CoverageCard } from './CoverageCard';
6
+ export { CoverageGrid } from './CoverageGrid';
7
+ export { CoverageHistory } from './CoverageHistory';
8
+ export { ResearchArticle } from './ResearchArticle';
9
+ export * from './types';
@@ -0,0 +1,38 @@
1
+ export interface CoverageAssets {
2
+ video?: string;
3
+ short?: string;
4
+ podcast_mp3?: string;
5
+ podcast_mp4?: string;
6
+ brief?: string;
7
+ thumbnail?: string;
8
+ }
9
+ export interface CoverageVersion {
10
+ version: string;
11
+ date?: string;
12
+ title?: string;
13
+ legacy_ticker?: string;
14
+ youtube_url?: string;
15
+ assets: CoverageAssets;
16
+ }
17
+ export interface CoverageItem {
18
+ ticker: string;
19
+ company: string;
20
+ title: string;
21
+ summary: string;
22
+ tags: string[];
23
+ campaign?: string | null;
24
+ campaign_slug?: string | null;
25
+ coverage_label?: string | null;
26
+ date: string;
27
+ version: string;
28
+ youtube_url?: string;
29
+ short_youtube_url?: string;
30
+ podcast_youtube_url?: string;
31
+ assets: CoverageAssets;
32
+ history: CoverageVersion[];
33
+ }
34
+ export interface Catalog {
35
+ generated: string;
36
+ count: number;
37
+ items: CoverageItem[];
38
+ }
@@ -0,0 +1,4 @@
1
+ // Shared types for the equity-research catalog produced by robosystems-content-machine
2
+ // (https://assets.robosystems.ai/content/index.json). The company is the durable
3
+ // entity; each run is a dated quarterly report version (latest + history[]).
4
+ export {};
@@ -0,0 +1,26 @@
1
+ import type { TaskMonitorState } from './types';
2
+ export interface UseTaskMonitoringResult extends TaskMonitorState {
3
+ startMonitoring: (taskId: string, options?: {
4
+ maxAttempts?: number;
5
+ pollInterval?: number;
6
+ }) => Promise<any>;
7
+ cancelTask: () => Promise<void>;
8
+ reset: () => void;
9
+ }
10
+ export declare function useTaskMonitoring(): UseTaskMonitoringResult;
11
+ export declare function useEntityCreationTask(): {
12
+ createEntityWithGraph: (entityData: any) => Promise<any>;
13
+ startMonitoring: (taskId: string, options?: {
14
+ maxAttempts?: number;
15
+ pollInterval?: number;
16
+ }) => Promise<any>;
17
+ cancelTask: () => Promise<void>;
18
+ reset: () => void;
19
+ isLoading: boolean;
20
+ progress: number | null;
21
+ currentStep: string | null;
22
+ error: string | null;
23
+ taskId: string | null;
24
+ result: any | null;
25
+ };
26
+ export declare function getProgressFromStep(step?: string | null): number;
@@ -0,0 +1,126 @@
1
+ 'use client';
2
+ import * as SDK from '@robosystems/client';
3
+ import { useCallback, useEffect, useRef, useState } from 'react';
4
+ import { taskMonitor } from './taskMonitor';
5
+ export function useTaskMonitoring() {
6
+ const [state, setState] = useState({
7
+ isLoading: false,
8
+ progress: null,
9
+ currentStep: null,
10
+ error: null,
11
+ taskId: null,
12
+ result: null,
13
+ });
14
+ const currentTaskId = useRef(null);
15
+ const reset = useCallback(() => {
16
+ setState({
17
+ isLoading: false,
18
+ progress: null,
19
+ currentStep: null,
20
+ error: null,
21
+ taskId: null,
22
+ result: null,
23
+ });
24
+ currentTaskId.current = null;
25
+ }, []);
26
+ const cancelTask = useCallback(async () => {
27
+ if (currentTaskId.current) {
28
+ try {
29
+ await taskMonitor.cancelTask(currentTaskId.current);
30
+ setState((prev) => (Object.assign(Object.assign({}, prev), { isLoading: false, error: 'Task was cancelled', result: null })));
31
+ }
32
+ catch (error) {
33
+ console.error('Failed to cancel task:', error);
34
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: 'Failed to cancel task', result: null })));
35
+ }
36
+ }
37
+ }, []);
38
+ const startMonitoring = useCallback(async (taskId, options) => {
39
+ currentTaskId.current = taskId;
40
+ setState({
41
+ isLoading: true,
42
+ progress: null,
43
+ currentStep: null,
44
+ error: null,
45
+ taskId,
46
+ result: null,
47
+ });
48
+ try {
49
+ const result = await taskMonitor.pollTask({
50
+ taskId,
51
+ maxAttempts: options === null || options === void 0 ? void 0 : options.maxAttempts,
52
+ pollInterval: options === null || options === void 0 ? void 0 : options.pollInterval,
53
+ onProgress: (status) => {
54
+ setState((prev) => (Object.assign(Object.assign({}, prev), { progress: status.progress || null, currentStep: status.step || status.message || 'Processing...' })));
55
+ },
56
+ onComplete: (result) => {
57
+ setState((prev) => (Object.assign(Object.assign({}, prev), { isLoading: false, progress: 100, currentStep: 'Completed', result: result })));
58
+ },
59
+ onError: (errorMsg) => {
60
+ setState((prev) => (Object.assign(Object.assign({}, prev), { isLoading: false, error: errorMsg, result: null })));
61
+ },
62
+ });
63
+ return result.details || result;
64
+ }
65
+ catch (error) {
66
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
67
+ setState((prev) => (Object.assign(Object.assign({}, prev), { isLoading: false, error: errorMessage, result: null })));
68
+ throw error;
69
+ }
70
+ finally {
71
+ currentTaskId.current = null;
72
+ }
73
+ }, []);
74
+ // Cleanup on unmount
75
+ useEffect(() => {
76
+ return () => {
77
+ if (currentTaskId.current) {
78
+ taskMonitor.cancelTask(currentTaskId.current);
79
+ }
80
+ };
81
+ }, []);
82
+ return Object.assign(Object.assign({}, state), { startMonitoring,
83
+ cancelTask,
84
+ reset });
85
+ }
86
+ // Convenience hook for entity creation specifically
87
+ export function useEntityCreationTask() {
88
+ const taskMonitoring = useTaskMonitoring();
89
+ const createEntityWithGraph = useCallback(async (entityData) => {
90
+ try {
91
+ // Call the SDK function to create company with new graph
92
+ // Note: createCompanyWithNewGraph function does not exist in SDK
93
+ // This is a placeholder implementation
94
+ const response = await SDK.createGraph({
95
+ body: entityData,
96
+ });
97
+ const responseData = response.data;
98
+ if (!(responseData === null || responseData === void 0 ? void 0 : responseData.operationId)) {
99
+ throw new Error('No operation ID returned from company creation');
100
+ }
101
+ // Start monitoring the task
102
+ const result = await taskMonitoring.startMonitoring(responseData.operationId);
103
+ return result;
104
+ }
105
+ catch (error) {
106
+ console.error('Company creation failed:', error);
107
+ throw error;
108
+ }
109
+ }, [taskMonitoring]);
110
+ return Object.assign(Object.assign({}, taskMonitoring), { createEntityWithGraph });
111
+ }
112
+ // Helper function to get progress percentage from step name
113
+ export function getProgressFromStep(step) {
114
+ if (!step)
115
+ return 0;
116
+ const stepProgress = {
117
+ initializing: 10,
118
+ checking_mode: 20,
119
+ creating_database: 40,
120
+ installing_labels: 60,
121
+ creating_company: 80,
122
+ updating_user_graph: 90,
123
+ completed: 100,
124
+ };
125
+ return stepProgress[step.toLowerCase()] || 0;
126
+ }
@@ -0,0 +1,5 @@
1
+ export * from './hooks';
2
+ export * from './taskMonitor';
3
+ export * from './types';
4
+ export * from './operationHooks';
5
+ export * from './operationMonitor';
@@ -0,0 +1,7 @@
1
+ // Legacy exports (for backward compatibility)
2
+ export * from './hooks';
3
+ export * from './taskMonitor';
4
+ export * from './types';
5
+ // New operation-based exports
6
+ export * from './operationHooks';
7
+ export * from './operationMonitor';
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Error handling for operation-based monitoring
3
+ */
4
+ export declare enum OperationErrorCode {
5
+ CONNECTION_FAILED = "CONNECTION_FAILED",
6
+ CONNECTION_LOST = "CONNECTION_LOST",
7
+ TIMEOUT = "TIMEOUT",
8
+ OPERATION_NOT_FOUND = "OPERATION_NOT_FOUND",
9
+ OPERATION_CANCELLED = "OPERATION_CANCELLED",
10
+ OPERATION_FAILED = "OPERATION_FAILED",
11
+ UNAUTHORIZED = "UNAUTHORIZED",
12
+ FORBIDDEN = "FORBIDDEN",
13
+ INSUFFICIENT_CREDITS = "INSUFFICIENT_CREDITS",
14
+ RESOURCE_NOT_FOUND = "RESOURCE_NOT_FOUND",
15
+ RESOURCE_LOCKED = "RESOURCE_LOCKED",
16
+ RESOURCE_LIMIT_EXCEEDED = "RESOURCE_LIMIT_EXCEEDED",
17
+ INVALID_INPUT = "INVALID_INPUT",
18
+ INVALID_QUERY = "INVALID_QUERY",
19
+ SCHEMA_VIOLATION = "SCHEMA_VIOLATION",
20
+ INTERNAL_ERROR = "INTERNAL_ERROR",
21
+ SERVICE_UNAVAILABLE = "SERVICE_UNAVAILABLE",
22
+ RATE_LIMITED = "RATE_LIMITED"
23
+ }
24
+ export declare class OperationError extends Error {
25
+ code: OperationErrorCode;
26
+ details?: any;
27
+ constructor(code: OperationErrorCode, message: string, details?: any);
28
+ /**
29
+ * Check if error is recoverable
30
+ */
31
+ isRecoverable(): boolean;
32
+ /**
33
+ * Check if error requires user action
34
+ */
35
+ requiresUserAction(): boolean;
36
+ /**
37
+ * Get user-friendly message
38
+ */
39
+ getUserMessage(): string;
40
+ /**
41
+ * Get recommended action for the user
42
+ */
43
+ getRecommendedAction(): string | null;
44
+ }
45
+ /**
46
+ * Parse SSE error events into OperationError
47
+ */
48
+ export declare function parseOperationError(event: any): OperationError;
49
+ /**
50
+ * Error recovery strategies
51
+ */
52
+ export declare class ErrorRecovery {
53
+ private retryCount;
54
+ private readonly maxRetries;
55
+ private readonly baseDelay;
56
+ /**
57
+ * Determine if we should retry
58
+ */
59
+ shouldRetry(operationId: string, error: OperationError): boolean;
60
+ /**
61
+ * Get retry delay with exponential backoff
62
+ */
63
+ getRetryDelay(operationId: string): number;
64
+ /**
65
+ * Reset retry count for an operation
66
+ */
67
+ reset(operationId: string): void;
68
+ /**
69
+ * Clear all retry counts
70
+ */
71
+ clear(): void;
72
+ }
73
+ /**
74
+ * Error notification helper
75
+ */
76
+ export interface ErrorNotification {
77
+ title: string;
78
+ message: string;
79
+ action?: string;
80
+ severity: 'info' | 'warning' | 'error';
81
+ }
82
+ export declare function createErrorNotification(error: OperationError): ErrorNotification;