@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.
- package/LICENSE +21 -0
- package/README.md +252 -0
- package/actions/entity-actions.d.ts +8 -0
- package/actions/entity-actions.js +16 -0
- package/actions/graph-actions.d.ts +3 -0
- package/actions/graph-actions.js +13 -0
- package/auth-components/AppSwitcher.d.ts +6 -0
- package/auth-components/AppSwitcher.js +28 -0
- package/auth-components/AuthGuard.d.ts +7 -0
- package/auth-components/AuthGuard.js +31 -0
- package/auth-components/AuthProvider.d.ts +9 -0
- package/auth-components/AuthProvider.js +565 -0
- package/auth-components/SessionWarningDialog.d.ts +1 -0
- package/auth-components/SessionWarningDialog.js +51 -0
- package/auth-components/SignInForm.d.ts +20 -0
- package/auth-components/SignInForm.js +139 -0
- package/auth-components/SignUpForm.d.ts +15 -0
- package/auth-components/SignUpForm.js +167 -0
- package/auth-components/TurnstileWidget.d.ts +99 -0
- package/auth-components/TurnstileWidget.js +224 -0
- package/auth-components/index.d.ts +6 -0
- package/auth-components/index.js +6 -0
- package/auth-core/cleanup.d.ts +44 -0
- package/auth-core/cleanup.js +157 -0
- package/auth-core/client.d.ts +121 -0
- package/auth-core/client.js +767 -0
- package/auth-core/config.d.ts +19 -0
- package/auth-core/config.js +56 -0
- package/auth-core/hooks.d.ts +19 -0
- package/auth-core/hooks.js +63 -0
- package/auth-core/index.d.ts +6 -0
- package/auth-core/index.js +6 -0
- package/auth-core/sso.d.ts +42 -0
- package/auth-core/sso.js +281 -0
- package/auth-core/token-storage.d.ts +58 -0
- package/auth-core/token-storage.js +177 -0
- package/auth-core/types.d.ts +145 -0
- package/auth-core/types.js +1 -0
- package/components/EntitySelector.d.ts +44 -0
- package/components/EntitySelector.js +64 -0
- package/components/EntitySelectorCore.d.ts +45 -0
- package/components/EntitySelectorCore.js +67 -0
- package/components/GraphSelectorCore.d.ts +21 -0
- package/components/GraphSelectorCore.js +39 -0
- package/components/PageLayout.d.ts +8 -0
- package/components/PageLayout.js +5 -0
- package/components/RepositoryGuard.d.ts +68 -0
- package/components/RepositoryGuard.js +91 -0
- package/components/console/ConsoleContent.d.ts +4 -0
- package/components/console/ConsoleContent.js +612 -0
- package/components/console/ConsoleMarkdown.d.ts +11 -0
- package/components/console/ConsoleMarkdown.js +49 -0
- package/components/console/ProgressiveText.d.ts +6 -0
- package/components/console/ProgressiveText.js +21 -0
- package/components/console/graphAwareConfig.d.ts +70 -0
- package/components/console/graphAwareConfig.js +411 -0
- package/components/console/index.d.ts +6 -0
- package/components/console/index.js +4 -0
- package/components/console/types.d.ts +84 -0
- package/components/console/types.js +1 -0
- package/components/graph-filters.d.ts +75 -0
- package/components/graph-filters.js +111 -0
- package/components/index.d.ts +10 -0
- package/components/index.js +9 -0
- package/components/repositories/ActiveSubscriptions.d.ts +26 -0
- package/components/repositories/ActiveSubscriptions.js +103 -0
- package/components/repositories/BrowseRepositories.d.ts +11 -0
- package/components/repositories/BrowseRepositories.js +184 -0
- package/components/repositories/index.d.ts +2 -0
- package/components/repositories/index.js +2 -0
- package/components/search/SearchContent.d.ts +4 -0
- package/components/search/SearchContent.js +168 -0
- package/components/search/index.d.ts +2 -0
- package/components/search/index.js +1 -0
- package/components/search/types.d.ts +15 -0
- package/components/search/types.js +1 -0
- package/contexts/entity-context.d.ts +28 -0
- package/contexts/entity-context.js +89 -0
- package/contexts/graph-context.d.ts +27 -0
- package/contexts/graph-context.js +128 -0
- package/contexts/index.d.ts +5 -0
- package/contexts/index.js +5 -0
- package/contexts/org-context.d.ts +25 -0
- package/contexts/org-context.js +64 -0
- package/contexts/service-offerings-context.d.ts +45 -0
- package/contexts/service-offerings-context.js +98 -0
- package/contexts/sidebar-context.d.ts +18 -0
- package/contexts/sidebar-context.js +44 -0
- package/hooks/index.d.ts +6 -0
- package/hooks/index.js +6 -0
- package/hooks/use-api-error.d.ts +3 -0
- package/hooks/use-api-error.js +24 -0
- package/hooks/use-media-query.d.ts +1 -0
- package/hooks/use-media-query.js +21 -0
- package/hooks/use-streaming-query.d.ts +22 -0
- package/hooks/use-streaming-query.js +142 -0
- package/hooks/use-toast.d.ts +37 -0
- package/hooks/use-toast.js +117 -0
- package/hooks/use-user-limits.d.ts +12 -0
- package/hooks/use-user-limits.js +73 -0
- package/hooks/use-user.d.ts +11 -0
- package/hooks/use-user.js +39 -0
- package/index.d.ts +29 -0
- package/index.js +77 -0
- package/lib/entity-cookie.d.ts +10 -0
- package/lib/entity-cookie.js +38 -0
- package/lib/graph-cookie.d.ts +11 -0
- package/lib/graph-cookie.js +62 -0
- package/lib/graph-tiers.d.ts +41 -0
- package/lib/graph-tiers.js +107 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -0
- package/lib/sidebar-cookie.d.ts +11 -0
- package/lib/sidebar-cookie.js +42 -0
- package/library/colors.d.ts +4 -0
- package/library/colors.js +41 -0
- package/library/components/ClassificationPicker.d.ts +8 -0
- package/library/components/ClassificationPicker.js +55 -0
- package/library/components/ElementBrowser.d.ts +11 -0
- package/library/components/ElementBrowser.js +106 -0
- package/library/components/ElementDetail.d.ts +7 -0
- package/library/components/ElementDetail.js +97 -0
- package/library/components/LibraryHierarchy.d.ts +13 -0
- package/library/components/LibraryHierarchy.js +380 -0
- package/library/components/TaxonomySidebar.d.ts +6 -0
- package/library/components/TaxonomySidebar.js +45 -0
- package/library/index.d.ts +8 -0
- package/library/index.js +7 -0
- package/package.json +37 -0
- package/research/CoverageCard.d.ts +12 -0
- package/research/CoverageCard.js +15 -0
- package/research/CoverageGrid.d.ts +6 -0
- package/research/CoverageGrid.js +9 -0
- package/research/CoverageHistory.d.ts +5 -0
- package/research/CoverageHistory.js +7 -0
- package/research/ResearchArticle.d.ts +15 -0
- package/research/ResearchArticle.js +26 -0
- package/research/catalog.d.ts +14 -0
- package/research/catalog.js +42 -0
- package/research/index.d.ts +6 -0
- package/research/index.js +9 -0
- package/research/types.d.ts +38 -0
- package/research/types.js +4 -0
- package/task-monitoring/hooks.d.ts +26 -0
- package/task-monitoring/hooks.js +126 -0
- package/task-monitoring/index.d.ts +5 -0
- package/task-monitoring/index.js +7 -0
- package/task-monitoring/operationErrors.d.ts +82 -0
- package/task-monitoring/operationErrors.js +251 -0
- package/task-monitoring/operationHooks.d.ts +117 -0
- package/task-monitoring/operationHooks.js +536 -0
- package/task-monitoring/operationMonitor.d.ts +78 -0
- package/task-monitoring/operationMonitor.js +200 -0
- package/task-monitoring/operationTypes.d.ts +236 -0
- package/task-monitoring/operationTypes.js +60 -0
- package/task-monitoring/taskMonitor.d.ts +14 -0
- package/task-monitoring/taskMonitor.js +132 -0
- package/task-monitoring/types.d.ts +31 -0
- package/task-monitoring/types.js +1 -0
- package/theme/flowbite-theme.d.ts +758 -0
- package/theme/flowbite-theme.js +765 -0
- package/theme/index.d.ts +1 -0
- package/theme/index.js +1 -0
- package/types/entity.d.ts +19 -0
- package/types/index.d.ts +2 -0
- package/types/index.js +1 -0
- package/types/user.d.ts +6 -0
- package/ui-components/ConfirmModal.d.ts +41 -0
- package/ui-components/ConfirmModal.js +19 -0
- package/ui-components/EmptyState.d.ts +22 -0
- package/ui-components/EmptyState.js +10 -0
- package/ui-components/LoadingState.d.ts +27 -0
- package/ui-components/LoadingState.js +12 -0
- package/ui-components/Logo.d.ts +28 -0
- package/ui-components/Logo.js +95 -0
- package/ui-components/Spinner.d.ts +37 -0
- package/ui-components/Spinner.js +48 -0
- package/ui-components/StatCard.d.ts +21 -0
- package/ui-components/StatCard.js +10 -0
- package/ui-components/api-keys/ApiKeyDisplay.d.ts +13 -0
- package/ui-components/api-keys/ApiKeyDisplay.js +7 -0
- package/ui-components/api-keys/ApiKeyTable.d.ts +9 -0
- package/ui-components/api-keys/ApiKeyTable.js +17 -0
- package/ui-components/api-keys/ApiKeysCard.d.ts +6 -0
- package/ui-components/api-keys/ApiKeysCard.js +97 -0
- package/ui-components/api-keys/CreateApiKeyModal.d.ts +11 -0
- package/ui-components/api-keys/CreateApiKeyModal.js +47 -0
- package/ui-components/api-keys/SecureApiKeyField.d.ts +13 -0
- package/ui-components/api-keys/SecureApiKeyField.js +64 -0
- package/ui-components/api-keys/index.d.ts +5 -0
- package/ui-components/api-keys/index.js +5 -0
- package/ui-components/chat/ChatHeader.d.ts +12 -0
- package/ui-components/chat/ChatHeader.js +5 -0
- package/ui-components/chat/ChatInputArea.d.ts +16 -0
- package/ui-components/chat/ChatInputArea.js +9 -0
- package/ui-components/chat/ChatMessage.d.ts +7 -0
- package/ui-components/chat/ChatMessage.js +24 -0
- package/ui-components/chat/DeepResearchToggle.d.ts +8 -0
- package/ui-components/chat/DeepResearchToggle.js +13 -0
- package/ui-components/chat/index.d.ts +9 -0
- package/ui-components/chat/index.js +8 -0
- package/ui-components/chat/types.d.ts +23 -0
- package/ui-components/chat/types.js +51 -0
- package/ui-components/forms/PasswordRequirements.d.ts +10 -0
- package/ui-components/forms/PasswordRequirements.js +15 -0
- package/ui-components/forms/SettingsCard.d.ts +11 -0
- package/ui-components/forms/SettingsCard.js +5 -0
- package/ui-components/forms/SettingsFormField.d.ts +18 -0
- package/ui-components/forms/SettingsFormField.js +17 -0
- package/ui-components/forms/StatusAlert.d.ts +8 -0
- package/ui-components/forms/StatusAlert.js +7 -0
- package/ui-components/forms/index.d.ts +4 -0
- package/ui-components/forms/index.js +4 -0
- package/ui-components/index.d.ts +13 -0
- package/ui-components/index.js +18 -0
- package/ui-components/layout/CoreNavbar.d.ts +14 -0
- package/ui-components/layout/CoreNavbar.js +53 -0
- package/ui-components/layout/CoreSidebar.d.ts +28 -0
- package/ui-components/layout/CoreSidebar.js +62 -0
- package/ui-components/layout/LandingFooter.d.ts +28 -0
- package/ui-components/layout/LandingFooter.js +34 -0
- package/ui-components/layout/PageContainer.d.ts +8 -0
- package/ui-components/layout/PageContainer.js +17 -0
- package/ui-components/layout/PageHeader.d.ts +23 -0
- package/ui-components/layout/PageHeader.js +12 -0
- package/ui-components/layout/SettingsContainer.d.ts +10 -0
- package/ui-components/layout/SettingsContainer.js +9 -0
- package/ui-components/layout/ThemeToggle.d.ts +4 -0
- package/ui-components/layout/ThemeToggle.js +6 -0
- package/ui-components/layout/index.d.ts +7 -0
- package/ui-components/layout/index.js +7 -0
- package/ui-components/settings/GeneralInformationCard.d.ts +12 -0
- package/ui-components/settings/GeneralInformationCard.js +72 -0
- package/ui-components/settings/PasswordInformationCard.d.ts +10 -0
- package/ui-components/settings/PasswordInformationCard.js +167 -0
- package/ui-components/settings/SettingsPageHeader.d.ts +7 -0
- package/ui-components/settings/SettingsPageHeader.js +6 -0
- package/ui-components/settings/index.d.ts +3 -0
- package/ui-components/settings/index.js +3 -0
- package/ui-components/support/SupportModal.d.ts +15 -0
- package/ui-components/support/SupportModal.js +74 -0
- package/ui-components/support/index.d.ts +2 -0
- package/ui-components/support/index.js +1 -0
- package/ui-components/types/index.d.ts +39 -0
- package/ui-components/types/index.js +1 -0
- package/utils/index.d.ts +31 -0
- package/utils/index.js +38 -0
- package/utils/turnstile-config.d.ts +11 -0
- package/utils/turnstile-config.js +19 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
|
+
import ReactMarkdown from 'react-markdown';
|
|
15
|
+
import remarkGfm from 'remark-gfm';
|
|
16
|
+
/**
|
|
17
|
+
* Renders a natural-language console answer as GitHub-flavored markdown, themed
|
|
18
|
+
* for the dark terminal. The backend now returns enriched markdown (### headings,
|
|
19
|
+
* **bold**, and | pipe tables); without this it rendered as raw literal text.
|
|
20
|
+
*
|
|
21
|
+
* Styling stays inside the terminal's cyan/mono aesthetic — the surrounding
|
|
22
|
+
* container supplies `font-mono text-sm`, so tables and code inherit it.
|
|
23
|
+
*/
|
|
24
|
+
export function ConsoleMarkdown({ content }) {
|
|
25
|
+
return (_jsx("div", { className: "leading-relaxed text-cyan-400", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components: {
|
|
26
|
+
h1: ({ children }) => (_jsx("h1", { className: "mt-4 mb-2 text-base font-bold text-cyan-300 first:mt-0", children: children })),
|
|
27
|
+
h2: ({ children }) => (_jsx("h2", { className: "mt-4 mb-2 text-sm font-bold text-cyan-300 first:mt-0", children: children })),
|
|
28
|
+
h3: ({ children }) => (_jsx("h3", { className: "mt-3 mb-1.5 text-sm font-semibold text-cyan-300 first:mt-0", children: children })),
|
|
29
|
+
h4: ({ children }) => (_jsx("h4", { className: "mt-3 mb-1 text-xs font-semibold tracking-wide text-cyan-300 uppercase first:mt-0", children: children })),
|
|
30
|
+
p: ({ children }) => _jsx("p", { className: "my-2 first:mt-0", children: children }),
|
|
31
|
+
strong: ({ children }) => (_jsx("strong", { className: "font-semibold text-white", children: children })),
|
|
32
|
+
em: ({ children }) => (_jsx("em", { className: "text-cyan-200 italic", children: children })),
|
|
33
|
+
a: ({ href, children }) => (_jsx("a", { href: href, target: "_blank", rel: "noopener noreferrer", className: "text-cyan-300 underline hover:text-cyan-200", children: children })),
|
|
34
|
+
ul: ({ children }) => (_jsx("ul", { className: "my-2 list-disc space-y-1 pl-5", children: children })),
|
|
35
|
+
ol: ({ children }) => (_jsx("ol", { className: "my-2 list-decimal space-y-1 pl-5", children: children })),
|
|
36
|
+
li: ({ children }) => _jsx("li", { className: "pl-1", children: children }),
|
|
37
|
+
blockquote: ({ children }) => (_jsx("blockquote", { className: "my-2 border-l-2 border-cyan-700 pl-3 text-cyan-300/80 italic", children: children })),
|
|
38
|
+
hr: () => _jsx("hr", { className: "my-3 border-gray-800" }),
|
|
39
|
+
code: (_a) => {
|
|
40
|
+
var { className, children } = _a, props = __rest(_a, ["className", "children"]);
|
|
41
|
+
return /language-/.test(className || '') ? (_jsx("code", Object.assign({ className: className }, props, { children: children }))) : (_jsx("code", Object.assign({ className: "rounded bg-gray-800 px-1 py-0.5 text-cyan-200" }, props, { children: children })));
|
|
42
|
+
},
|
|
43
|
+
pre: ({ children }) => (_jsx("pre", { className: "my-2 overflow-x-auto rounded border border-gray-800 bg-gray-900/40 p-3 text-xs text-cyan-300", children: children })),
|
|
44
|
+
table: ({ children }) => (_jsx("div", { className: "my-3 overflow-x-auto rounded border border-gray-800", children: _jsx("table", { className: "w-full border-collapse text-xs", children: children }) })),
|
|
45
|
+
thead: ({ children }) => (_jsx("thead", { className: "border-b border-gray-800 bg-gray-900", children: children })),
|
|
46
|
+
th: ({ children }) => (_jsx("th", { className: "px-3 py-2 text-left font-semibold whitespace-nowrap text-cyan-400", children: children })),
|
|
47
|
+
td: ({ children }) => (_jsx("td", { className: "border-t border-gray-900 px-3 py-2 text-gray-300", children: children })),
|
|
48
|
+
}, children: content }) }));
|
|
49
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
export function ProgressiveText({ text, onComplete, speed = 1, onUpdate, }) {
|
|
5
|
+
const [displayedText, setDisplayedText] = useState('');
|
|
6
|
+
const [currentIndex, setCurrentIndex] = useState(0);
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
if (currentIndex < text.length) {
|
|
9
|
+
const timeout = setTimeout(() => {
|
|
10
|
+
setDisplayedText(text.slice(0, currentIndex + 1));
|
|
11
|
+
setCurrentIndex(currentIndex + 1);
|
|
12
|
+
onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(); // Trigger scroll update
|
|
13
|
+
}, speed);
|
|
14
|
+
return () => clearTimeout(timeout);
|
|
15
|
+
}
|
|
16
|
+
else if (onComplete) {
|
|
17
|
+
onComplete();
|
|
18
|
+
}
|
|
19
|
+
}, [currentIndex, text, speed, onComplete, onUpdate]);
|
|
20
|
+
return _jsx("span", { children: displayedText });
|
|
21
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { GraphInfo } from '@robosystems/client';
|
|
2
|
+
import type { ConsoleConfig, SampleQuery } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Graph-aware console configuration.
|
|
5
|
+
*
|
|
6
|
+
* The console's natural-language agent (the "cypher operator") and its example
|
|
7
|
+
* queries only make sense against the schema of the *selected* graph. A shared
|
|
8
|
+
* SEC repository, a RoboLedger accounting graph, a RoboInvestor portfolio
|
|
9
|
+
* graph, and a generic custom graph each expose completely different nodes —
|
|
10
|
+
* so the welcome examples, sample queries, and MCP prompts must switch with the
|
|
11
|
+
* graph. This module holds one example set per graph kind plus a builder that
|
|
12
|
+
* merges the right set with an app's branding.
|
|
13
|
+
*/
|
|
14
|
+
export type GraphExampleKind = 'sec' | 'roboledger' | 'roboinvestor' | 'generic';
|
|
15
|
+
export interface GraphExampleSet {
|
|
16
|
+
/** Header subtitle describing what this graph is. */
|
|
17
|
+
subtitle: string;
|
|
18
|
+
/** Welcome-message description. May contain the token "your graph", which the
|
|
19
|
+
* builder swaps for the graph's display name when available. */
|
|
20
|
+
description: string;
|
|
21
|
+
/** Natural-language prompts shown in the USAGE section. Must be answerable by
|
|
22
|
+
* the cypher operator against THIS graph's schema. */
|
|
23
|
+
naturalLanguageExamples: string[];
|
|
24
|
+
/** `/query <cypher>` one-liners shown in the USAGE section. */
|
|
25
|
+
directQueryExamples: string[];
|
|
26
|
+
/** Full sample queries listed by the `/examples` command. */
|
|
27
|
+
sampleQueries: SampleQuery[];
|
|
28
|
+
/** Questions suggested after MCP setup (answered by the full MCP toolset). */
|
|
29
|
+
mcpExampleQuestions: string[];
|
|
30
|
+
}
|
|
31
|
+
export declare const EXAMPLE_SETS: Record<GraphExampleKind, GraphExampleSet>;
|
|
32
|
+
/**
|
|
33
|
+
* Classify the selected graph so the console can pick the right example set.
|
|
34
|
+
*
|
|
35
|
+
* @param preferredKind Tiebreak used only when a graph carries more than one
|
|
36
|
+
* entity extension (e.g. both roboledger and roboinvestor). Pass the app's
|
|
37
|
+
* own lens (a RoboLedger app passes 'roboledger') so a dual-extension graph
|
|
38
|
+
* shows the examples that fit the app the user is in.
|
|
39
|
+
*/
|
|
40
|
+
export declare function getGraphExampleKind(graph: GraphInfo | undefined, preferredKind?: GraphExampleKind): GraphExampleKind;
|
|
41
|
+
/** App-specific branding merged with the graph-derived example set. */
|
|
42
|
+
export interface ConsoleBranding {
|
|
43
|
+
/** Page heading, e.g. "Console" or "RoboInvestor Console". */
|
|
44
|
+
title: string;
|
|
45
|
+
/** Console name in the welcome banner, e.g. "RoboSystems Console". */
|
|
46
|
+
consoleName: string;
|
|
47
|
+
gradientFrom: string;
|
|
48
|
+
gradientTo: string;
|
|
49
|
+
/** Final welcome line, e.g. "How can I help you today?". */
|
|
50
|
+
closingMessage: string;
|
|
51
|
+
mcp: {
|
|
52
|
+
serverName: string;
|
|
53
|
+
packageName: string;
|
|
54
|
+
contextIdFallback: string;
|
|
55
|
+
};
|
|
56
|
+
/** Defaults to "Example Cypher Queries:". */
|
|
57
|
+
examplesLabel?: string;
|
|
58
|
+
/** Defaults to "No graph selected. Please select a graph first.". */
|
|
59
|
+
noSelectionError?: string;
|
|
60
|
+
/** Tiebreak for graphs carrying multiple entity extensions — see
|
|
61
|
+
* {@link getGraphExampleKind}. */
|
|
62
|
+
preferredKind?: GraphExampleKind;
|
|
63
|
+
}
|
|
64
|
+
/** Merge an app's branding with the example set for the given graph. */
|
|
65
|
+
export declare function buildGraphAwareConsoleConfig(graph: GraphInfo | undefined, branding: ConsoleBranding): ConsoleConfig;
|
|
66
|
+
/**
|
|
67
|
+
* React hook: build a console config that tracks the currently selected graph,
|
|
68
|
+
* swapping example sets when the user changes graphs.
|
|
69
|
+
*/
|
|
70
|
+
export declare function useGraphAwareConsoleConfig(branding: ConsoleBranding): ConsoleConfig;
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { useIsRepository } from '../RepositoryGuard';
|
|
4
|
+
// ── SEC shared repository (base + roboledger reporting; XBRL facts) ──────────
|
|
5
|
+
// Data: XBRL financial facts + filing narrative text for 10,000+ public
|
|
6
|
+
// companies. No prices/macro. Gotchas baked into the queries: anchor on a
|
|
7
|
+
// ticker FIRST, use Element.canonical_concept (not a single qname),
|
|
8
|
+
// has_dimensions:false for consolidated totals, duration_type for
|
|
9
|
+
// income-statement periods vs period_type:'instant' for the balance sheet.
|
|
10
|
+
const SEC_EXAMPLE_SET = {
|
|
11
|
+
subtitle: 'AI financial analyst for 10,000+ public companies',
|
|
12
|
+
description: 'Ask in plain English and an AI analyst does the work — pulling full financial statements, comparing companies side by side, computing ratios and multi-year trends, and searching filing narratives like risk factors and MD&A. Every answer comes back with the data and the Cypher behind it. The graph holds XBRL filings from over 10,000 public companies.',
|
|
13
|
+
naturalLanguageExamples: [
|
|
14
|
+
'Compare gross margin for NVIDIA, AMD, and Intel over the last three years',
|
|
15
|
+
'Show Apple’s income statement for the last three fiscal years',
|
|
16
|
+
'Break down Microsoft’s revenue by segment',
|
|
17
|
+
'Calculate Tesla’s free cash flow and current ratio for the last two fiscal years',
|
|
18
|
+
'What are the biggest risk factors in Apple’s latest 10-K?',
|
|
19
|
+
],
|
|
20
|
+
directQueryExamples: [
|
|
21
|
+
"MATCH (e:Entity {ticker: 'NVDA'}) RETURN e.name, e.cik, e.sic_description, e.fiscal_year_end",
|
|
22
|
+
"MATCH (e:Entity) WHERE e.sic_description CONTAINS 'Semiconductor' RETURN e.ticker, e.name LIMIT 20",
|
|
23
|
+
"MATCH (e:Entity {ticker: 'AAPL'})-[:ENTITY_HAS_REPORT]->(r:Report) RETURN r.form, r.fiscal_year_focus, r.filing_date ORDER BY r.filing_date DESC LIMIT 10",
|
|
24
|
+
],
|
|
25
|
+
sampleQueries: [
|
|
26
|
+
{
|
|
27
|
+
name: 'Companies by sector',
|
|
28
|
+
query: `MATCH (e:Entity)
|
|
29
|
+
WHERE e.sic_description IS NOT NULL
|
|
30
|
+
RETURN e.sic_description AS sector, count(e) AS company_count
|
|
31
|
+
ORDER BY company_count DESC
|
|
32
|
+
LIMIT 20`,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'Recent SEC filings',
|
|
36
|
+
query: `MATCH (e:Entity)-[:ENTITY_HAS_REPORT]->(r:Report)
|
|
37
|
+
RETURN e.ticker, e.name, r.form, r.fiscal_year_focus, r.filing_date
|
|
38
|
+
ORDER BY r.filing_date DESC
|
|
39
|
+
LIMIT 25`,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'NVIDIA annual revenue',
|
|
43
|
+
// canonical_concept normalizes across filers (us-gaap:Revenues vs
|
|
44
|
+
// RevenueFromContractWithCustomer…); has_dimensions:false = consolidated total.
|
|
45
|
+
query: `MATCH (e:Entity {ticker: 'NVDA'})<-[:FACT_HAS_ENTITY]-(f:Fact {has_dimensions: false})-[:FACT_HAS_ELEMENT]->(el:Element),
|
|
46
|
+
(f)-[:FACT_HAS_PERIOD]->(p:Period {duration_type: 'annual'})
|
|
47
|
+
WHERE el.canonical_concept = 'revenue' AND f.numeric_value IS NOT NULL
|
|
48
|
+
RETURN e.ticker, p.end_date, f.numeric_value AS revenue
|
|
49
|
+
ORDER BY p.end_date DESC
|
|
50
|
+
LIMIT 10`,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'NVIDIA income statement',
|
|
54
|
+
// Pull a whole statement via Structure.canonical_type. Anchor on the
|
|
55
|
+
// Entity FIRST and reach Structure LAST, or the query scans every filing.
|
|
56
|
+
query: `MATCH (e:Entity {ticker: 'NVDA'})<-[:FACT_HAS_ENTITY]-(f:Fact {has_dimensions: false})-[:FACT_HAS_ELEMENT]->(el:Element),
|
|
57
|
+
(f)-[:FACT_HAS_PERIOD]->(p:Period {duration_type: 'annual'}),
|
|
58
|
+
(fs:FactSet)-[:FACT_SET_CONTAINS_FACT]->(f),
|
|
59
|
+
(s:Structure {canonical_type: 'income_statement'})-[:STRUCTURE_HAS_FACT_SET]->(fs)
|
|
60
|
+
WHERE f.numeric_value IS NOT NULL
|
|
61
|
+
RETURN DISTINCT el.qname, f.numeric_value AS value, p.end_date
|
|
62
|
+
ORDER BY p.end_date DESC
|
|
63
|
+
LIMIT 40`,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
name: 'Apple balance sheet snapshot',
|
|
67
|
+
// Balance-sheet items are instantaneous — filter Period {period_type:'instant'}.
|
|
68
|
+
query: `MATCH (e:Entity {ticker: 'AAPL'})<-[:FACT_HAS_ENTITY]-(f:Fact {has_dimensions: false})-[:FACT_HAS_ELEMENT]->(el:Element),
|
|
69
|
+
(f)-[:FACT_HAS_PERIOD]->(p:Period {period_type: 'instant'})
|
|
70
|
+
WHERE el.canonical_concept IN ['total_assets', 'total_liabilities', 'stockholders_equity']
|
|
71
|
+
AND f.numeric_value IS NOT NULL
|
|
72
|
+
RETURN el.canonical_concept AS line_item, f.numeric_value AS value, p.end_date
|
|
73
|
+
ORDER BY p.end_date DESC, line_item
|
|
74
|
+
LIMIT 15`,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'Compare net income across mega-cap tech',
|
|
78
|
+
query: `MATCH (e:Entity)<-[:FACT_HAS_ENTITY]-(f:Fact {has_dimensions: false})-[:FACT_HAS_ELEMENT]->(el:Element),
|
|
79
|
+
(f)-[:FACT_HAS_PERIOD]->(p:Period {duration_type: 'annual'})
|
|
80
|
+
WHERE e.ticker IN ['AAPL', 'MSFT', 'GOOGL', 'NVDA', 'META']
|
|
81
|
+
AND el.canonical_concept = 'net_income'
|
|
82
|
+
AND f.numeric_value IS NOT NULL
|
|
83
|
+
RETURN e.ticker, p.end_date, f.numeric_value AS net_income
|
|
84
|
+
ORDER BY p.end_date DESC, net_income DESC
|
|
85
|
+
LIMIT 25`,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: 'NVIDIA gross margin trend',
|
|
89
|
+
// Pivot two concepts per period, then compute the ratio in Cypher.
|
|
90
|
+
query: `MATCH (e:Entity {ticker: 'NVDA'})<-[:FACT_HAS_ENTITY]-(f:Fact {has_dimensions: false})-[:FACT_HAS_ELEMENT]->(el:Element),
|
|
91
|
+
(f)-[:FACT_HAS_PERIOD]->(p:Period {duration_type: 'annual'})
|
|
92
|
+
WHERE el.canonical_concept IN ['revenue', 'gross_profit'] AND f.numeric_value IS NOT NULL
|
|
93
|
+
WITH p.end_date AS period,
|
|
94
|
+
max(CASE WHEN el.canonical_concept = 'revenue' THEN f.numeric_value END) AS revenue,
|
|
95
|
+
max(CASE WHEN el.canonical_concept = 'gross_profit' THEN f.numeric_value END) AS gross_profit
|
|
96
|
+
WHERE revenue IS NOT NULL AND gross_profit IS NOT NULL
|
|
97
|
+
RETURN period, gross_profit, revenue, gross_profit / revenue AS gross_margin
|
|
98
|
+
ORDER BY period DESC
|
|
99
|
+
LIMIT 10`,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: 'NVIDIA revenue by segment (dimensional)',
|
|
103
|
+
// has_dimensions:true exposes the segment/geography breakdowns.
|
|
104
|
+
query: `MATCH (e:Entity {ticker: 'NVDA'})<-[:FACT_HAS_ENTITY]-(f:Fact {has_dimensions: true})-[:FACT_HAS_ELEMENT]->(el:Element),
|
|
105
|
+
(f)-[:FACT_HAS_DIMENSION]->(d:Dimension),
|
|
106
|
+
(f)-[:FACT_HAS_PERIOD]->(p:Period {duration_type: 'annual'})
|
|
107
|
+
WHERE el.canonical_concept = 'revenue' AND f.numeric_value IS NOT NULL
|
|
108
|
+
RETURN d.member AS segment, f.numeric_value AS value, p.end_date
|
|
109
|
+
ORDER BY p.end_date DESC, value DESC
|
|
110
|
+
LIMIT 20`,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
mcpExampleQuestions: [
|
|
114
|
+
'Compare operating margin for NVIDIA, AMD, and Intel over five years',
|
|
115
|
+
'Summarize the key risk factors in Apple’s latest 10-K',
|
|
116
|
+
'Show Microsoft’s diluted EPS and free cash flow trend',
|
|
117
|
+
],
|
|
118
|
+
};
|
|
119
|
+
// ── RoboLedger entity graph (double-entry ledger + reporting) ────────────────
|
|
120
|
+
// Data: the general-ledger spine Transaction -> Entry -> LineItem (each
|
|
121
|
+
// LineItem posts to an Element/account), plus the XBRL reports generated from
|
|
122
|
+
// it. The one rule to remember: count/sum only LIVE rows via the materialized
|
|
123
|
+
// `is_live` boolean (Entry/LineItem/Transaction), or cancelled/replaced rows
|
|
124
|
+
// double-count.
|
|
125
|
+
const ROBOLEDGER_EXAMPLE_SET = {
|
|
126
|
+
subtitle: 'AI analyst for your accounting ledger',
|
|
127
|
+
description: 'Ask in plain English and an AI analyst queries your ledger — transactions, journal entries, the trial balance, and the financial statements built from them. Every answer comes back with the data and the Cypher behind it.',
|
|
128
|
+
naturalLanguageExamples: [
|
|
129
|
+
'Show me the trial balance',
|
|
130
|
+
'What are my largest expenses by category?',
|
|
131
|
+
'List the most recent journal entries',
|
|
132
|
+
'How much did I spend last month?',
|
|
133
|
+
],
|
|
134
|
+
directQueryExamples: [
|
|
135
|
+
'MATCH (e:Entity)-[:ENTITY_HAS_TRANSACTION]->(t:Transaction) WHERE t.is_live RETURN t.date, t.number, t.description, t.amount ORDER BY t.date DESC LIMIT 15',
|
|
136
|
+
'MATCH (en:Entry) WHERE en.is_live RETURN en.number, en.memo, en.posting_date, en.type ORDER BY en.posting_date DESC LIMIT 15',
|
|
137
|
+
'MATCH (e:Entity) RETURN e.name, e.entity_type, e.industry',
|
|
138
|
+
],
|
|
139
|
+
sampleQueries: [
|
|
140
|
+
{
|
|
141
|
+
name: 'Trial balance',
|
|
142
|
+
// Sum only live line items; each posts to an Element (account) via
|
|
143
|
+
// LINE_ITEM_RELATES_TO_ELEMENT.
|
|
144
|
+
query: `MATCH (en:Entry)-[:ENTRY_HAS_LINE_ITEM]->(li:LineItem)-[:LINE_ITEM_RELATES_TO_ELEMENT]->(el:Element)
|
|
145
|
+
WHERE li.is_live
|
|
146
|
+
RETURN el.qname AS account, el.name,
|
|
147
|
+
sum(li.debit_amount) AS total_debits,
|
|
148
|
+
sum(li.credit_amount) AS total_credits
|
|
149
|
+
ORDER BY total_debits DESC
|
|
150
|
+
LIMIT 25`,
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: 'Recent transactions',
|
|
154
|
+
query: `MATCH (e:Entity)-[:ENTITY_HAS_TRANSACTION]->(t:Transaction)
|
|
155
|
+
WHERE t.is_live
|
|
156
|
+
RETURN t.date, t.number, t.description, t.type, t.amount
|
|
157
|
+
ORDER BY t.date DESC
|
|
158
|
+
LIMIT 25`,
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: 'Recent journal entries',
|
|
162
|
+
query: `MATCH (t:Transaction)-[:TRANSACTION_HAS_ENTRY]->(en:Entry)
|
|
163
|
+
WHERE en.is_live
|
|
164
|
+
RETURN t.number AS txn, t.description, en.number AS entry, en.memo, en.posting_date, en.type
|
|
165
|
+
ORDER BY en.posting_date DESC
|
|
166
|
+
LIMIT 25`,
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: 'Expenses by category',
|
|
170
|
+
query: `MATCH (e:Entity)-[:ENTITY_HAS_TRANSACTION]->(t:Transaction)
|
|
171
|
+
WHERE t.is_live AND t.category IS NOT NULL
|
|
172
|
+
RETURN t.category, count(t) AS transactions, sum(t.amount) AS total
|
|
173
|
+
ORDER BY total DESC
|
|
174
|
+
LIMIT 20`,
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
name: 'Entry lines by account',
|
|
178
|
+
query: `MATCH (t:Transaction)-[:TRANSACTION_HAS_ENTRY]->(en:Entry)-[:ENTRY_HAS_LINE_ITEM]->(li:LineItem)-[:LINE_ITEM_RELATES_TO_ELEMENT]->(el:Element)
|
|
179
|
+
WHERE li.is_live
|
|
180
|
+
RETURN el.name AS account, count(li) AS line_items,
|
|
181
|
+
sum(li.debit_amount) AS debits, sum(li.credit_amount) AS credits
|
|
182
|
+
ORDER BY line_items DESC
|
|
183
|
+
LIMIT 15`,
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
name: 'Line items with dimensional breakdowns',
|
|
187
|
+
query: `MATCH (li:LineItem {has_dimensions: true})-[:LINE_ITEM_HAS_DIMENSION]->(d:Dimension)
|
|
188
|
+
WHERE li.is_live
|
|
189
|
+
RETURN d.axis, d.member, count(li) AS line_item_count
|
|
190
|
+
ORDER BY line_item_count DESC
|
|
191
|
+
LIMIT 15`,
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
name: 'Reports generated',
|
|
195
|
+
query: `MATCH (e:Entity)-[:ENTITY_HAS_REPORT]->(r:Report)
|
|
196
|
+
RETURN e.name, r.form, r.fiscal_year_focus, r.filing_date
|
|
197
|
+
ORDER BY r.filing_date DESC
|
|
198
|
+
LIMIT 20`,
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
mcpExampleQuestions: [
|
|
202
|
+
'Show me the trial balance for this entity',
|
|
203
|
+
'What are my largest expenses this quarter?',
|
|
204
|
+
'Summarize the most recent journal entries',
|
|
205
|
+
],
|
|
206
|
+
};
|
|
207
|
+
// ── RoboInvestor entity graph (portfolios / positions / securities) ──────────
|
|
208
|
+
// Data: Entity -> Portfolio -> Position -> Security, and Entity -> Security
|
|
209
|
+
// (issuance). Position carries cost_basis and current_value, so gains and
|
|
210
|
+
// allocation are computed in Cypher. Trade/Benchmark/MarketData exist in the
|
|
211
|
+
// schema but aren't populated yet — keep examples off them.
|
|
212
|
+
const ROBOINVESTOR_EXAMPLE_SET = {
|
|
213
|
+
subtitle: 'AI analyst for your investment portfolios',
|
|
214
|
+
description: 'Ask in plain English and an AI analyst queries your portfolios, positions, and securities — holdings, cost basis vs. current value, allocation, and unrealized gains. Every answer comes back with the data and the Cypher behind it.',
|
|
215
|
+
naturalLanguageExamples: [
|
|
216
|
+
'What is the current value of my portfolio?',
|
|
217
|
+
'Show my largest positions by market value',
|
|
218
|
+
'Which holdings have the biggest unrealized gains?',
|
|
219
|
+
'Break down my holdings by security type',
|
|
220
|
+
],
|
|
221
|
+
directQueryExamples: [
|
|
222
|
+
'MATCH (p:Portfolio) RETURN p.name, p.strategy, p.base_currency',
|
|
223
|
+
'MATCH (p:Portfolio)-[:PORTFOLIO_HAS_POSITION]->(pos:Position) RETURN p.name, count(pos) AS positions ORDER BY positions DESC',
|
|
224
|
+
'MATCH (s:Security) RETURN s.ticker, s.name, s.security_type LIMIT 20',
|
|
225
|
+
],
|
|
226
|
+
sampleQueries: [
|
|
227
|
+
{
|
|
228
|
+
name: 'Portfolio value',
|
|
229
|
+
query: `MATCH (p:Portfolio)-[:PORTFOLIO_HAS_POSITION]->(pos:Position)
|
|
230
|
+
RETURN p.name,
|
|
231
|
+
count(pos) AS positions,
|
|
232
|
+
sum(pos.cost_basis) AS total_cost,
|
|
233
|
+
sum(pos.current_value) AS total_value
|
|
234
|
+
ORDER BY total_value DESC`,
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
name: 'Holdings by current value',
|
|
238
|
+
query: `MATCH (p:Portfolio)-[:PORTFOLIO_HAS_POSITION]->(pos:Position)-[:POSITION_IN_SECURITY]->(s:Security)
|
|
239
|
+
RETURN p.name, s.ticker, s.name, pos.quantity, pos.cost_basis, pos.current_value
|
|
240
|
+
ORDER BY pos.current_value DESC
|
|
241
|
+
LIMIT 25`,
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
name: 'Unrealized gains',
|
|
245
|
+
query: `MATCH (p:Portfolio)-[:PORTFOLIO_HAS_POSITION]->(pos:Position)-[:POSITION_IN_SECURITY]->(s:Security)
|
|
246
|
+
WHERE pos.cost_basis IS NOT NULL AND pos.current_value IS NOT NULL
|
|
247
|
+
RETURN s.ticker, s.name, pos.cost_basis, pos.current_value,
|
|
248
|
+
pos.current_value - pos.cost_basis AS unrealized_gain
|
|
249
|
+
ORDER BY unrealized_gain DESC
|
|
250
|
+
LIMIT 20`,
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
name: 'Allocation by security type',
|
|
254
|
+
query: `MATCH (pos:Position)-[:POSITION_IN_SECURITY]->(s:Security)
|
|
255
|
+
RETURN s.security_type,
|
|
256
|
+
count(pos) AS positions,
|
|
257
|
+
sum(pos.current_value) AS total_value
|
|
258
|
+
ORDER BY total_value DESC`,
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
name: 'Securities issued by entity',
|
|
262
|
+
query: `MATCH (e:Entity)-[:ENTITY_ISSUES_SECURITY]->(s:Security)
|
|
263
|
+
RETURN e.name, s.ticker, s.name, s.security_type
|
|
264
|
+
ORDER BY s.ticker
|
|
265
|
+
LIMIT 25`,
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
mcpExampleQuestions: [
|
|
269
|
+
'What is the current value of my portfolio and its total cost basis?',
|
|
270
|
+
'Show my largest positions by market value',
|
|
271
|
+
'Which holdings have the biggest unrealized gains?',
|
|
272
|
+
],
|
|
273
|
+
};
|
|
274
|
+
// ── Generic custom graph (no known schema extensions) ────────────────────────
|
|
275
|
+
// No SEC/ledger/portfolio assumptions — the operator gets only the live schema
|
|
276
|
+
// and read-only Cypher, so the examples are structure-discovery oriented.
|
|
277
|
+
const GENERIC_EXAMPLE_SET = {
|
|
278
|
+
subtitle: 'AI analyst for your graph database',
|
|
279
|
+
description: 'Ask in plain English and an AI analyst explores your graph — discovering the node types, relationships, and patterns in your data, and returning the results with the Cypher behind every answer.',
|
|
280
|
+
naturalLanguageExamples: [
|
|
281
|
+
'What types of nodes are in the graph?',
|
|
282
|
+
'How are the nodes connected?',
|
|
283
|
+
'Show me a sample of the data',
|
|
284
|
+
'Which nodes have the most connections?',
|
|
285
|
+
],
|
|
286
|
+
directQueryExamples: [
|
|
287
|
+
'MATCH (n) RETURN labels(n), count(n) ORDER BY count(n) DESC',
|
|
288
|
+
'MATCH ()-[r]->() RETURN type(r), count(r) ORDER BY count(r) DESC',
|
|
289
|
+
'MATCH (n) RETURN n LIMIT 10',
|
|
290
|
+
],
|
|
291
|
+
sampleQueries: [
|
|
292
|
+
{
|
|
293
|
+
name: 'Node types',
|
|
294
|
+
query: `MATCH (n)
|
|
295
|
+
RETURN labels(n) AS label, count(n) AS count
|
|
296
|
+
ORDER BY count DESC`,
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
name: 'Relationship types',
|
|
300
|
+
query: `MATCH ()-[r]->()
|
|
301
|
+
RETURN type(r) AS relationship, count(r) AS count
|
|
302
|
+
ORDER BY count DESC`,
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
name: 'Sample nodes',
|
|
306
|
+
query: `MATCH (n)
|
|
307
|
+
RETURN n
|
|
308
|
+
LIMIT 25`,
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
name: 'Node connections',
|
|
312
|
+
query: `MATCH (a)-[r]->(b)
|
|
313
|
+
RETURN labels(a) AS from_type, type(r) AS relationship, labels(b) AS to_type, count(*) AS count
|
|
314
|
+
ORDER BY count DESC
|
|
315
|
+
LIMIT 15`,
|
|
316
|
+
},
|
|
317
|
+
],
|
|
318
|
+
mcpExampleQuestions: [
|
|
319
|
+
'What data is in my graph?',
|
|
320
|
+
'Show me the most connected nodes',
|
|
321
|
+
'Summarize the graph structure',
|
|
322
|
+
],
|
|
323
|
+
};
|
|
324
|
+
export const EXAMPLE_SETS = {
|
|
325
|
+
sec: SEC_EXAMPLE_SET,
|
|
326
|
+
roboledger: ROBOLEDGER_EXAMPLE_SET,
|
|
327
|
+
roboinvestor: ROBOINVESTOR_EXAMPLE_SET,
|
|
328
|
+
generic: GENERIC_EXAMPLE_SET,
|
|
329
|
+
};
|
|
330
|
+
/**
|
|
331
|
+
* Classify the selected graph so the console can pick the right example set.
|
|
332
|
+
*
|
|
333
|
+
* @param preferredKind Tiebreak used only when a graph carries more than one
|
|
334
|
+
* entity extension (e.g. both roboledger and roboinvestor). Pass the app's
|
|
335
|
+
* own lens (a RoboLedger app passes 'roboledger') so a dual-extension graph
|
|
336
|
+
* shows the examples that fit the app the user is in.
|
|
337
|
+
*/
|
|
338
|
+
export function getGraphExampleKind(graph, preferredKind) {
|
|
339
|
+
var _a;
|
|
340
|
+
if (!graph)
|
|
341
|
+
return preferredKind !== null && preferredKind !== void 0 ? preferredKind : 'generic';
|
|
342
|
+
if (graph.isRepository && graph.repositoryType === 'sec')
|
|
343
|
+
return 'sec';
|
|
344
|
+
const extensions = (_a = graph.schemaExtensions) !== null && _a !== void 0 ? _a : [];
|
|
345
|
+
const hasInvestor = extensions.includes('roboinvestor');
|
|
346
|
+
const hasLedger = extensions.includes('roboledger');
|
|
347
|
+
if (hasInvestor && hasLedger) {
|
|
348
|
+
return preferredKind === 'roboledger' || preferredKind === 'roboinvestor'
|
|
349
|
+
? preferredKind
|
|
350
|
+
: 'roboinvestor';
|
|
351
|
+
}
|
|
352
|
+
if (hasInvestor)
|
|
353
|
+
return 'roboinvestor';
|
|
354
|
+
if (hasLedger)
|
|
355
|
+
return 'roboledger';
|
|
356
|
+
return 'generic';
|
|
357
|
+
}
|
|
358
|
+
/** Merge an app's branding with the example set for the given graph. */
|
|
359
|
+
export function buildGraphAwareConsoleConfig(graph, branding) {
|
|
360
|
+
var _a, _b, _c;
|
|
361
|
+
const kind = getGraphExampleKind(graph, branding.preferredKind);
|
|
362
|
+
const set = EXAMPLE_SETS[kind];
|
|
363
|
+
const isRepository = (_a = graph === null || graph === void 0 ? void 0 : graph.isRepository) !== null && _a !== void 0 ? _a : false;
|
|
364
|
+
const graphName = graph === null || graph === void 0 ? void 0 : graph.graphName;
|
|
365
|
+
// Personalize the description with the graph's name where the set opts in.
|
|
366
|
+
const description = graphName && set.description.includes('your graph')
|
|
367
|
+
? set.description.replace('your graph', `"${graphName}"`)
|
|
368
|
+
: set.description;
|
|
369
|
+
return {
|
|
370
|
+
header: {
|
|
371
|
+
title: branding.title,
|
|
372
|
+
subtitle: set.subtitle,
|
|
373
|
+
gradientFrom: branding.gradientFrom,
|
|
374
|
+
gradientTo: branding.gradientTo,
|
|
375
|
+
},
|
|
376
|
+
welcome: {
|
|
377
|
+
consoleName: branding.consoleName,
|
|
378
|
+
description,
|
|
379
|
+
contextLabel: isRepository ? 'Repository' : 'Graph',
|
|
380
|
+
naturalLanguageExamples: set.naturalLanguageExamples,
|
|
381
|
+
directQueryExamples: set.directQueryExamples,
|
|
382
|
+
closingMessage: branding.closingMessage,
|
|
383
|
+
},
|
|
384
|
+
mcp: {
|
|
385
|
+
serverName: branding.mcp.serverName,
|
|
386
|
+
packageName: branding.mcp.packageName,
|
|
387
|
+
exampleQuestions: set.mcpExampleQuestions,
|
|
388
|
+
contextIdFallback: branding.mcp.contextIdFallback,
|
|
389
|
+
},
|
|
390
|
+
sampleQueries: set.sampleQueries,
|
|
391
|
+
examplesLabel: (_b = branding.examplesLabel) !== null && _b !== void 0 ? _b : 'Example Cypher Queries:',
|
|
392
|
+
noSelectionError: (_c = branding.noSelectionError) !== null && _c !== void 0 ? _c : 'No graph selected. Please select a graph first.',
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* React hook: build a console config that tracks the currently selected graph,
|
|
397
|
+
* swapping example sets when the user changes graphs.
|
|
398
|
+
*/
|
|
399
|
+
export function useGraphAwareConsoleConfig(branding) {
|
|
400
|
+
const { currentGraph } = useIsRepository();
|
|
401
|
+
return useMemo(() => buildGraphAwareConsoleConfig(currentGraph, branding),
|
|
402
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
403
|
+
[
|
|
404
|
+
currentGraph === null || currentGraph === void 0 ? void 0 : currentGraph.graphId,
|
|
405
|
+
currentGraph === null || currentGraph === void 0 ? void 0 : currentGraph.isRepository,
|
|
406
|
+
currentGraph === null || currentGraph === void 0 ? void 0 : currentGraph.repositoryType,
|
|
407
|
+
currentGraph === null || currentGraph === void 0 ? void 0 : currentGraph.schemaExtensions,
|
|
408
|
+
currentGraph === null || currentGraph === void 0 ? void 0 : currentGraph.graphName,
|
|
409
|
+
branding,
|
|
410
|
+
]);
|
|
411
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { ConsoleContent } from './ConsoleContent';
|
|
2
|
+
export { ConsoleMarkdown } from './ConsoleMarkdown';
|
|
3
|
+
export { EXAMPLE_SETS, buildGraphAwareConsoleConfig, getGraphExampleKind, useGraphAwareConsoleConfig, } from './graphAwareConfig';
|
|
4
|
+
export type { ConsoleBranding, GraphExampleKind, GraphExampleSet, } from './graphAwareConfig';
|
|
5
|
+
export { ProgressiveText } from './ProgressiveText';
|
|
6
|
+
export type { ConsoleCommandContext, ConsoleConfig, ConsoleExtraCommand, ConsoleHeaderConfig, ConsoleMcpConfig, ConsoleWelcomeConfig, SampleQuery, TerminalMessage, } from './types';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { ConsoleContent } from './ConsoleContent';
|
|
2
|
+
export { ConsoleMarkdown } from './ConsoleMarkdown';
|
|
3
|
+
export { EXAMPLE_SETS, buildGraphAwareConsoleConfig, getGraphExampleKind, useGraphAwareConsoleConfig, } from './graphAwareConfig';
|
|
4
|
+
export { ProgressiveText } from './ProgressiveText';
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export interface SampleQuery {
|
|
2
|
+
name: string;
|
|
3
|
+
query: string;
|
|
4
|
+
}
|
|
5
|
+
export interface ConsoleWelcomeConfig {
|
|
6
|
+
/** e.g. "RoboSystems Console", "RoboLedger Console" */
|
|
7
|
+
consoleName: string;
|
|
8
|
+
/** e.g. "Claude powered interactive graph database console" */
|
|
9
|
+
description: string;
|
|
10
|
+
/** Label for the context identifier: "Graph" | "Portfolio" */
|
|
11
|
+
contextLabel: string;
|
|
12
|
+
/** Example natural-language prompts shown in USAGE section */
|
|
13
|
+
naturalLanguageExamples: string[];
|
|
14
|
+
/** Example /query Cypher lines shown in USAGE section */
|
|
15
|
+
directQueryExamples: string[];
|
|
16
|
+
/** Final line of the welcome message, e.g. "How can I help you today?" */
|
|
17
|
+
closingMessage: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ConsoleHeaderConfig {
|
|
20
|
+
/** Page heading, e.g. "Console" */
|
|
21
|
+
title: string;
|
|
22
|
+
/** Subtitle below heading */
|
|
23
|
+
subtitle: string;
|
|
24
|
+
/** Tailwind gradient-from class, e.g. "from-blue-500" */
|
|
25
|
+
gradientFrom: string;
|
|
26
|
+
/** Tailwind gradient-to class, e.g. "to-purple-600" */
|
|
27
|
+
gradientTo: string;
|
|
28
|
+
}
|
|
29
|
+
export interface ConsoleMcpConfig {
|
|
30
|
+
/** MCP server name in the JSON config, e.g. "robosystems" */
|
|
31
|
+
serverName: string;
|
|
32
|
+
/** npm package name, e.g. "@robosystems/mcp" */
|
|
33
|
+
packageName: string;
|
|
34
|
+
/** Example questions shown after MCP setup */
|
|
35
|
+
exampleQuestions: string[];
|
|
36
|
+
/** Fallback text for graph ID placeholder, e.g. "your_graph_id" */
|
|
37
|
+
contextIdFallback: string;
|
|
38
|
+
}
|
|
39
|
+
export interface ConsoleCommandContext {
|
|
40
|
+
addSystemMessage: (content: string, animate?: boolean) => void;
|
|
41
|
+
addErrorMessage: (content: string) => void;
|
|
42
|
+
graphId: string | null;
|
|
43
|
+
}
|
|
44
|
+
export interface ConsoleExtraCommand {
|
|
45
|
+
/** The slash command string, e.g. "/api-keys" */
|
|
46
|
+
command: string;
|
|
47
|
+
/** Handler called when the command is invoked */
|
|
48
|
+
handler: (context: ConsoleCommandContext) => void | Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
export interface ConsoleConfig {
|
|
51
|
+
welcome: ConsoleWelcomeConfig;
|
|
52
|
+
header: ConsoleHeaderConfig;
|
|
53
|
+
mcp: ConsoleMcpConfig;
|
|
54
|
+
sampleQueries: SampleQuery[];
|
|
55
|
+
/** Label for the /examples output heading, e.g. "Example Cypher Queries:" */
|
|
56
|
+
examplesLabel: string;
|
|
57
|
+
/** Error message when no graph/portfolio is selected */
|
|
58
|
+
noSelectionError: string;
|
|
59
|
+
/** Extra slash commands beyond the built-in set */
|
|
60
|
+
extraCommands?: ConsoleExtraCommand[];
|
|
61
|
+
}
|
|
62
|
+
export interface TerminalMessage {
|
|
63
|
+
id: string;
|
|
64
|
+
type: 'system' | 'user' | 'result' | 'error';
|
|
65
|
+
content: string;
|
|
66
|
+
timestamp: Date;
|
|
67
|
+
/** Tabular result rows rendered below the message. */
|
|
68
|
+
data?: any;
|
|
69
|
+
/** Generated Cypher for a natural-language result, shown with a Run button. */
|
|
70
|
+
cypher?: string;
|
|
71
|
+
isAnimating?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Render `content` as GitHub-flavored markdown (headings, bold, tables)
|
|
74
|
+
* rather than raw monospace text. Set for natural-language answers, which the
|
|
75
|
+
* backend now returns as enriched markdown.
|
|
76
|
+
*/
|
|
77
|
+
markdown?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Query stats (e.g. "Query completed in 123ms\nRows returned: 40") shown as a
|
|
80
|
+
* muted footer below a markdown answer, kept out of `content` so its line
|
|
81
|
+
* breaks survive markdown rendering.
|
|
82
|
+
*/
|
|
83
|
+
footer?: string;
|
|
84
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|