@robosystems/core 0.8.6 → 0.8.8
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/components/console/graphAwareConfig.d.ts +2 -2
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/ui-components/api-keys/index.d.ts +0 -2
- package/ui-components/api-keys/index.js +0 -2
- package/ui-components/layout/LandingFooter.d.ts +7 -1
- package/ui-components/layout/LandingFooter.js +16 -3
- package/ui-components/api-keys/ApiKeyTable.d.ts +0 -9
- package/ui-components/api-keys/ApiKeyTable.js +0 -17
- package/ui-components/api-keys/ApiKeysCard.d.ts +0 -11
- package/ui-components/api-keys/ApiKeysCard.js +0 -112
|
@@ -3,7 +3,7 @@ import type { ConsoleConfig, SampleQuery } from './types';
|
|
|
3
3
|
/**
|
|
4
4
|
* Graph-aware console configuration.
|
|
5
5
|
*
|
|
6
|
-
* The console's natural-language agent (the
|
|
6
|
+
* The console's natural-language agent (the Analyst Operator) and its example
|
|
7
7
|
* queries only make sense against the schema of the *selected* graph. A shared
|
|
8
8
|
* SEC repository, a RoboLedger accounting graph, a RoboInvestor portfolio
|
|
9
9
|
* graph, and a generic custom graph each expose completely different nodes —
|
|
@@ -19,7 +19,7 @@ export interface GraphExampleSet {
|
|
|
19
19
|
* builder swaps for the graph's display name when available. */
|
|
20
20
|
description: string;
|
|
21
21
|
/** Natural-language prompts shown in the USAGE section. Must be answerable by
|
|
22
|
-
* the
|
|
22
|
+
* the Analyst Operator against THIS graph's schema. */
|
|
23
23
|
naturalLanguageExamples: string[];
|
|
24
24
|
/** `/query <cypher>` one-liners shown in the USAGE section. */
|
|
25
25
|
directQueryExamples: string[];
|
package/index.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export { buildGraphAwareConsoleConfig, ConsoleContent, EXAMPLE_SETS, getGraphExa
|
|
|
14
14
|
export type { ConsoleBranding, ConsoleCommandContext, ConsoleConfig, ConsoleExtraCommand, ConsoleHeaderConfig, ConsoleMcpConfig, ConsoleWelcomeConfig, GraphExampleKind, GraphExampleSet, SampleQuery, } from './components/console';
|
|
15
15
|
export { ActiveSubscriptions, BrowseRepositories, EntitySelector, EntitySelectorCore, GraphSelectorCore, PageLayout, RepositoryGuard, SearchBar, SearchContent, SearchHitCard, SearchPagination, SearchResultsMeta, useIsRepository, type ActiveSubscriptionsProps, type BrowseRepositoriesProps, type EntityGroup, type EntityLike, type EntityRecord, type EntitySelectorProps, type GraphSelectorProps, type GraphWithEntities, type SearchBarProps, type SearchConfig, type SearchFilterConfig, type SearchHitCardProps, type SearchPaginationProps, type SearchResultsMetaProps, type SelectableEntity, } from './components';
|
|
16
16
|
export { composeFilters, excludeRepositories, excludeSubgraphs, GraphFilters, hasSchemaExtension, onlyRepositories, onlyUserGraphs, } from './components/graph-filters';
|
|
17
|
-
export { ApiKeyDisplay,
|
|
17
|
+
export { ApiKeyDisplay, BrandSpinner, categorizeError, CategoryInput, ChatHeader, ChatInputArea, ChatMessage, ConfirmModal, CoreNavbar, CoreSidebar, CreateApiKeyModal, DeepResearchToggle, EmptyState, ErrorType, GeneralInformationCard, generateMessageId, getErrorMessage, LandingFooter, LoadingState, MarkdownProse, PageContainer, PageHeader, PasswordInformationCard, PasswordRequirements, SecureApiKeyField, SettingsCard, SettingsContainer, SettingsFormField, SettingsPageHeader, Spinner, StatCard, StatusAlert, SupportModal, TagInput, ThemeToggle, } from './ui-components';
|
|
18
18
|
export type { CategoryInputProps, MarkdownProseProps, TagInputProps, } from './ui-components';
|
|
19
19
|
export type { AgentType, FooterLink, LandingFooterProps, Message, PageHeaderProps, SidebarItemData, SupportMetadata, } from './ui-components';
|
|
20
20
|
export * from './library';
|
package/index.js
CHANGED
|
@@ -35,7 +35,7 @@ export { ActiveSubscriptions, BrowseRepositories, EntitySelector, EntitySelector
|
|
|
35
35
|
// Export graph filters
|
|
36
36
|
export { composeFilters, excludeRepositories, excludeSubgraphs, GraphFilters, hasSchemaExtension, onlyRepositories, onlyUserGraphs, } from './components/graph-filters';
|
|
37
37
|
// Export app-components
|
|
38
|
-
export { ApiKeyDisplay,
|
|
38
|
+
export { ApiKeyDisplay, BrandSpinner, categorizeError, CategoryInput, ChatHeader, ChatInputArea,
|
|
39
39
|
// Chat components
|
|
40
40
|
ChatMessage, ConfirmModal, CoreNavbar, CoreSidebar, CreateApiKeyModal, DeepResearchToggle, EmptyState, ErrorType, GeneralInformationCard, generateMessageId, getErrorMessage, LandingFooter, LoadingState, MarkdownProse, PageContainer, PageHeader, PasswordInformationCard, PasswordRequirements, SecureApiKeyField, SettingsCard, SettingsContainer, SettingsFormField, SettingsPageHeader, Spinner, StatCard, StatusAlert, SupportModal, TagInput, ThemeToggle, } from './ui-components';
|
|
41
41
|
// Export library components, types, and helpers
|
package/package.json
CHANGED
|
@@ -17,6 +17,12 @@ export interface LandingFooterProps {
|
|
|
17
17
|
isOpen: boolean;
|
|
18
18
|
onClose: () => void;
|
|
19
19
|
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Where the Company column's Blog link goes. Defaults to the platform blog on
|
|
22
|
+
* robosystems.ai; an app with its own blog lane (roboledger.ai/blog since
|
|
23
|
+
* 2026-09-02) passes its own path so the footer sends readers to that lane.
|
|
24
|
+
*/
|
|
25
|
+
blogHref?: string;
|
|
20
26
|
}
|
|
21
27
|
/**
|
|
22
28
|
* The shared marketing-site footer for all three apps. The brand column, social
|
|
@@ -25,4 +31,4 @@ export interface LandingFooterProps {
|
|
|
25
31
|
* only the tagline and Product links vary and are passed in. Contact stays
|
|
26
32
|
* per-app via the `contactModal` prop.
|
|
27
33
|
*/
|
|
28
|
-
export declare function LandingFooter({ tagline, productLinks, contactModal: ContactModal, }: LandingFooterProps): import("react").JSX.Element;
|
|
34
|
+
export declare function LandingFooter({ tagline, productLinks, contactModal: ContactModal, blogHref, }: LandingFooterProps): import("react").JSX.Element;
|
|
@@ -15,20 +15,33 @@ const headingClass = 'mb-4 text-sm font-semibold tracking-wider text-gray-400 up
|
|
|
15
15
|
* only the tagline and Product links vary and are passed in. Contact stays
|
|
16
16
|
* per-app via the `contactModal` prop.
|
|
17
17
|
*/
|
|
18
|
-
export function LandingFooter({ tagline, productLinks, contactModal: ContactModal, }) {
|
|
18
|
+
export function LandingFooter({ tagline, productLinks, contactModal: ContactModal, blogHref, }) {
|
|
19
19
|
const [showContact, setShowContact] = useState(false);
|
|
20
20
|
const current = getAppConfig(CURRENT_APP);
|
|
21
21
|
const isRoboSystems = CURRENT_APP === 'robosystems';
|
|
22
|
-
// RoboSystems serves
|
|
22
|
+
// RoboSystems serves the platform blog, Privacy and Terms itself; the other
|
|
23
|
+
// apps link out to it.
|
|
23
24
|
const companyBase = isRoboSystems ? '' : getAppConfig('robosystems').url;
|
|
24
25
|
const companyLinkProps = isRoboSystems
|
|
25
26
|
? {}
|
|
26
27
|
: { target: '_blank', rel: 'noopener noreferrer' };
|
|
28
|
+
// Research lives on roboinvestor.ai (robosystems.ai redirects there since
|
|
29
|
+
// 2026-09-02), so it resolves against that app, not the platform site.
|
|
30
|
+
const isRoboInvestor = CURRENT_APP === 'roboinvestor';
|
|
31
|
+
const researchHref = isRoboInvestor
|
|
32
|
+
? '/research'
|
|
33
|
+
: `${getAppConfig('roboinvestor').url}/research`;
|
|
34
|
+
const researchLinkProps = isRoboInvestor
|
|
35
|
+
? {}
|
|
36
|
+
: { target: '_blank', rel: 'noopener noreferrer' };
|
|
37
|
+
const resolvedBlogHref = blogHref !== null && blogHref !== void 0 ? blogHref : `${companyBase}/blog`;
|
|
38
|
+
// A same-site path opens in the same tab; an external site opens in a new one.
|
|
39
|
+
const blogLinkProps = resolvedBlogHref.startsWith('/') ? {} : companyLinkProps;
|
|
27
40
|
return (_jsxs("footer", { className: "border-t border-gray-800 bg-zinc-950", children: [_jsxs("div", { className: "mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8", children: [_jsxs("div", { className: "grid gap-4 md:grid-cols-5 lg:gap-6", children: [_jsxs("div", { className: "md:col-span-2", children: [_jsxs("div", { className: "mb-4 flex items-center gap-2", children: [_jsx(Image, { src: `/images/logos/${CURRENT_APP}.png`, alt: current.displayName, width: 32, height: 32, className: "rounded-lg" }), _jsx("span", { className: "font-heading text-xl font-semibold text-white", children: current.displayName })] }), _jsx("p", { className: "mb-4 max-w-md text-sm text-gray-400", children: tagline }), _jsxs("div", { className: "flex gap-4", children: [_jsx(Link, { href: "https://github.com/RoboFinSystems", target: "_blank", rel: "noopener noreferrer", "aria-label": "RoboSystems on GitHub", className: linkClass, children: _jsx("svg", { className: "h-6 w-6", fill: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { d: "M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" }) }) }), _jsx(Link, { href: "https://x.com/robofinsystems", target: "_blank", rel: "noopener noreferrer", "aria-label": "RoboSystems on X", className: linkClass, children: _jsx("svg", { className: "h-6 w-6", fill: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { d: "M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" }) }) }), _jsx(Link, { href: "https://www.linkedin.com/company/robosystems", target: "_blank", rel: "noopener noreferrer", "aria-label": "RoboSystems on LinkedIn", className: linkClass, children: _jsx("svg", { className: "h-6 w-6", fill: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { d: "M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" }) }) }), _jsx(Link, { href: "https://www.youtube.com/@RoboSystems", target: "_blank", rel: "noopener noreferrer", "aria-label": "RoboSystems on YouTube", className: linkClass, children: _jsx("svg", { className: "h-6 w-6", fill: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { d: "M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z" }) }) })] })] }), _jsxs("div", { children: [_jsx("h3", { className: headingClass, children: "Product" }), _jsx("ul", { className: "space-y-2 text-sm", children: productLinks.map((link) => (_jsx("li", { children: _jsx(Link, { href: link.href, className: linkClass, children: link.label }) }, link.href))) })] }), _jsxs("div", { children: [_jsx("h3", { className: headingClass, children: "Applications" }), _jsx("ul", { className: "space-y-2 text-sm", children: APP_ORDER.map((app) => {
|
|
28
41
|
const cfg = getAppConfig(app);
|
|
29
42
|
const isCurrent = app === CURRENT_APP;
|
|
30
43
|
return (_jsx("li", { children: _jsx(Link, Object.assign({ href: cfg.url }, (isCurrent
|
|
31
44
|
? {}
|
|
32
45
|
: { target: '_blank', rel: 'noopener noreferrer' }), { className: linkClass, children: cfg.displayName })) }, app));
|
|
33
|
-
}) })] }), _jsxs("div", { children: [_jsx("h3", { className: headingClass, children: "Company" }), _jsxs("ul", { className: "space-y-2 text-sm", children: [_jsx("li", { children: _jsx(Link, Object.assign({ href:
|
|
46
|
+
}) })] }), _jsxs("div", { children: [_jsx("h3", { className: headingClass, children: "Company" }), _jsxs("ul", { className: "space-y-2 text-sm", children: [_jsx("li", { children: _jsx(Link, Object.assign({ href: researchHref }, researchLinkProps, { className: linkClass, children: "Research" })) }), _jsx("li", { children: _jsx(Link, { href: "https://holon.robosystems.ai", target: "_blank", rel: "noopener noreferrer", className: linkClass, children: "Holon Viewer" }) }), _jsx("li", { children: _jsx(Link, Object.assign({ href: resolvedBlogHref }, blogLinkProps, { className: linkClass, children: "Blog" })) }), _jsx("li", { children: _jsx(Link, Object.assign({ href: `${companyBase}/pages/privacy` }, companyLinkProps, { className: linkClass, children: "Privacy" })) }), _jsx("li", { children: _jsx(Link, Object.assign({ href: `${companyBase}/pages/terms` }, companyLinkProps, { className: linkClass, children: "Terms" })) }), _jsx("li", { children: _jsx(Link, { href: "https://trust.robosystems.ai", target: "_blank", rel: "noopener noreferrer", className: linkClass, children: "Trust Center" }) }), _jsx("li", { children: _jsx(Link, { href: "https://status.robosystems.ai", target: "_blank", rel: "noopener noreferrer", className: linkClass, children: "Status" }) }), ContactModal && (_jsx("li", { children: _jsx("button", { onClick: () => setShowContact(true), className: linkClass, children: "Contact" }) }))] })] })] }), _jsx("div", { className: "mt-8 border-t border-gray-800 pt-8 text-center text-sm text-gray-400", children: _jsxs("p", { children: ["\u00A9 ", new Date().getFullYear(), " RFS LLC. All rights reserved."] }) })] }), ContactModal && (_jsx(ContactModal, { isOpen: showContact, onClose: () => setShowContact(false) }))] }));
|
|
34
47
|
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import type { ApiKey } from '../types';
|
|
3
|
-
export interface ApiKeyTableProps {
|
|
4
|
-
apiKeys: ApiKey[];
|
|
5
|
-
onRevokeKey: (keyId: string) => void;
|
|
6
|
-
theme?: any;
|
|
7
|
-
formatDate?: (date: Date | string | null | undefined) => string;
|
|
8
|
-
}
|
|
9
|
-
export declare const ApiKeyTable: React.FC<ApiKeyTableProps>;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Button, Dropdown, DropdownItem, Table, TableBody, TableCell, TableHead, TableHeadCell, TableRow, } from 'flowbite-react';
|
|
3
|
-
import { HiCheckCircle, HiDotsVertical, HiExclamationCircle, HiKey, HiTrash, } from 'react-icons/hi';
|
|
4
|
-
const defaultFormatDate = (date) => {
|
|
5
|
-
if (!date)
|
|
6
|
-
return 'Never';
|
|
7
|
-
return new Date(date).toLocaleDateString('en-US', {
|
|
8
|
-
year: 'numeric',
|
|
9
|
-
month: 'short',
|
|
10
|
-
day: 'numeric',
|
|
11
|
-
});
|
|
12
|
-
};
|
|
13
|
-
export const ApiKeyTable = ({ apiKeys = [], onRevokeKey, theme, formatDate = defaultFormatDate, }) => {
|
|
14
|
-
// Defensive check to ensure apiKeys is always an array
|
|
15
|
-
const safeApiKeys = Array.isArray(apiKeys) ? apiKeys : [];
|
|
16
|
-
return (_jsx("div", { className: "overflow-x-auto", children: _jsxs(Table, { className: "table-fixed", children: [_jsxs(TableHead, { children: [_jsx(TableHeadCell, { className: "w-[40%]", children: "Name" }), _jsx(TableHeadCell, { className: "w-[15%] whitespace-nowrap", children: "Created" }), _jsx(TableHeadCell, { className: "w-[15%] whitespace-nowrap", children: "Last Used" }), _jsx(TableHeadCell, { className: "w-[15%] whitespace-nowrap", children: "Status" }), _jsx(TableHeadCell, { className: "w-[15%] text-right", children: "Actions" })] }), _jsx(TableBody, { className: "divide-y", children: safeApiKeys.map((key) => (_jsxs(TableRow, { className: "dark:border-zinc-700", children: [_jsx(TableCell, { className: "font-medium text-zinc-900 dark:text-zinc-100", children: _jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx(HiKey, { className: "h-5 w-5 shrink-0 text-zinc-600 dark:text-zinc-400" }), _jsx("span", { className: "truncate", title: key.name, children: key.name }), key.isSystem && (_jsx("span", { className: "bg-primary-100 text-primary-800 dark:bg-primary-900 dark:text-primary-300 shrink-0 rounded-full px-2.5 py-0.5 text-xs font-medium", children: "System" })), key.graphId && (_jsx("span", { className: "max-w-40 shrink-0 truncate rounded-full bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800 dark:bg-blue-900 dark:text-blue-300", title: `Scoped to graph ${key.graphId} — valid only for that graph and its subgraphs`, children: key.graphId }))] }) }), _jsx(TableCell, { className: "whitespace-nowrap text-zinc-600 dark:text-zinc-400", children: formatDate(key.createdAt) }), _jsx(TableCell, { className: "whitespace-nowrap text-zinc-600 dark:text-zinc-400", children: formatDate(key.lastUsedAt) }), _jsx(TableCell, { className: "whitespace-nowrap", children: key.isActive ? (_jsxs("div", { className: "inline-flex items-center rounded-full bg-green-100 px-2 py-0.5 text-xs font-medium text-green-800 dark:bg-green-800 dark:text-green-100", children: [_jsx(HiCheckCircle, { className: "mr-1 h-3 w-3" }), "Active"] })) : (_jsxs("div", { className: "inline-flex items-center rounded-full bg-red-100 px-2 py-0.5 text-xs font-medium text-red-800 dark:bg-red-800 dark:text-red-100", children: [_jsx(HiExclamationCircle, { className: "mr-1 h-3 w-3" }), "Revoked"] })) }), _jsx(TableCell, { className: "text-right", children: _jsx("div", { className: "inline-flex justify-end", children: _jsx(Dropdown, { theme: theme === null || theme === void 0 ? void 0 : theme.dropdown, label: "", dismissOnClick: true, renderTrigger: () => (_jsx(Button, { theme: theme === null || theme === void 0 ? void 0 : theme.button, size: "sm", pill: true, className: "bg-zinc-100 text-zinc-900 hover:bg-zinc-200 dark:bg-zinc-700 dark:text-zinc-100 dark:hover:bg-zinc-600", children: _jsx(HiDotsVertical, { className: "h-4 w-4" }) })), children: _jsx(DropdownItem, { onClick: () => onRevokeKey(key.id), disabled: !key.isActive || key.isSystem, icon: HiTrash, className: "hover:bg-zinc-100 dark:hover:bg-zinc-700", children: "Revoke" }) }) }) })] }, key.id))) })] }) }));
|
|
17
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
export interface ApiKeysCardProps {
|
|
3
|
-
theme?: any;
|
|
4
|
-
className?: string;
|
|
5
|
-
/**
|
|
6
|
-
* When set, the card links MCP users to the app's Connect page (the
|
|
7
|
-
* ready-made connector-URL flow) — e.g. "/connect" in robosystems-app.
|
|
8
|
-
*/
|
|
9
|
-
connectHref?: string;
|
|
10
|
-
}
|
|
11
|
-
export declare const ApiKeysCard: React.FC<ApiKeysCardProps>;
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import * as SDK from '@robosystems/client';
|
|
4
|
-
import { Button } from 'flowbite-react';
|
|
5
|
-
import { useContext, useEffect, useState } from 'react';
|
|
6
|
-
import { HiKey, HiPlusCircle } from 'react-icons/hi';
|
|
7
|
-
import { GraphContext } from '../../contexts';
|
|
8
|
-
import { Spinner } from '../Spinner';
|
|
9
|
-
import { SettingsCard } from '../forms/SettingsCard';
|
|
10
|
-
import { StatusAlert } from '../forms/StatusAlert';
|
|
11
|
-
import { ApiKeyTable } from './ApiKeyTable';
|
|
12
|
-
import { CreateApiKeyModal } from './CreateApiKeyModal';
|
|
13
|
-
export const ApiKeysCard = ({ theme, className = '', connectHref, }) => {
|
|
14
|
-
var _a;
|
|
15
|
-
// Read the graph context leniently: outside a GraphProvider the scope
|
|
16
|
-
// selector simply doesn't render, preserving the card's old standalone
|
|
17
|
-
// contract instead of throwing.
|
|
18
|
-
const graphContext = useContext(GraphContext);
|
|
19
|
-
const availableGraphs = (_a = graphContext === null || graphContext === void 0 ? void 0 : graphContext.state.graphs) !== null && _a !== void 0 ? _a : [];
|
|
20
|
-
const [apiKeys, setApiKeys] = useState([]);
|
|
21
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
22
|
-
const [isOpenCreateModal, setIsOpenCreateModal] = useState(false);
|
|
23
|
-
const [error, setError] = useState(null);
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
fetchApiKeys();
|
|
26
|
-
}, []);
|
|
27
|
-
const fetchApiKeys = async () => {
|
|
28
|
-
var _a;
|
|
29
|
-
setIsLoading(true);
|
|
30
|
-
setError(null);
|
|
31
|
-
try {
|
|
32
|
-
// Always use SDK
|
|
33
|
-
const response = await SDK.listUserApiKeys();
|
|
34
|
-
const sdkKeys = ((_a = response.data) === null || _a === void 0 ? void 0 : _a.api_keys) || [];
|
|
35
|
-
// Map SDK response to component format
|
|
36
|
-
const keys = sdkKeys.map((key) => {
|
|
37
|
-
var _a, _b;
|
|
38
|
-
return ({
|
|
39
|
-
id: key.id,
|
|
40
|
-
name: key.name,
|
|
41
|
-
graphId: key.graph_id,
|
|
42
|
-
createdAt: key.created_at,
|
|
43
|
-
lastUsedAt: key.last_used_at,
|
|
44
|
-
expiresAt: key.expires_at,
|
|
45
|
-
isActive: (_a = key.is_active) !== null && _a !== void 0 ? _a : true,
|
|
46
|
-
isSystem: (_b = key.is_system) !== null && _b !== void 0 ? _b : false,
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
setApiKeys(keys);
|
|
50
|
-
}
|
|
51
|
-
catch (_b) {
|
|
52
|
-
setError('Failed to load API keys. Please try again.');
|
|
53
|
-
}
|
|
54
|
-
finally {
|
|
55
|
-
setIsLoading(false);
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
const handleCreateKey = async (data) => {
|
|
59
|
-
var _a, _b;
|
|
60
|
-
// Always use SDK to create key
|
|
61
|
-
const response = await SDK.createUserApiKey({
|
|
62
|
-
body: {
|
|
63
|
-
name: data.name,
|
|
64
|
-
description: `API key for ${data.name}`,
|
|
65
|
-
graph_id: data.graphId,
|
|
66
|
-
},
|
|
67
|
-
});
|
|
68
|
-
await fetchApiKeys(); // Refresh the list
|
|
69
|
-
// Map SDK response to component format
|
|
70
|
-
const responseData = response.data;
|
|
71
|
-
const apiKeyInfo = responseData === null || responseData === void 0 ? void 0 : responseData.api_key;
|
|
72
|
-
return {
|
|
73
|
-
id: (apiKeyInfo === null || apiKeyInfo === void 0 ? void 0 : apiKeyInfo.id) || '',
|
|
74
|
-
name: (apiKeyInfo === null || apiKeyInfo === void 0 ? void 0 : apiKeyInfo.name) || data.name,
|
|
75
|
-
graphId: (_a = apiKeyInfo === null || apiKeyInfo === void 0 ? void 0 : apiKeyInfo.graph_id) !== null && _a !== void 0 ? _a : data.graphId,
|
|
76
|
-
key: (responseData === null || responseData === void 0 ? void 0 : responseData.key) || '', // The actual API key value
|
|
77
|
-
createdAt: (apiKeyInfo === null || apiKeyInfo === void 0 ? void 0 : apiKeyInfo.created_at) || new Date().toISOString(),
|
|
78
|
-
lastUsedAt: (apiKeyInfo === null || apiKeyInfo === void 0 ? void 0 : apiKeyInfo.last_used_at) || null,
|
|
79
|
-
expiresAt: null,
|
|
80
|
-
isActive: (_b = apiKeyInfo === null || apiKeyInfo === void 0 ? void 0 : apiKeyInfo.is_active) !== null && _b !== void 0 ? _b : true,
|
|
81
|
-
isSystem: false,
|
|
82
|
-
};
|
|
83
|
-
};
|
|
84
|
-
const handleRevokeKey = async (keyId) => {
|
|
85
|
-
try {
|
|
86
|
-
// Always use SDK to revoke key
|
|
87
|
-
await SDK.revokeUserApiKey({
|
|
88
|
-
path: { api_key_id: keyId },
|
|
89
|
-
});
|
|
90
|
-
await fetchApiKeys(); // Refresh the list
|
|
91
|
-
}
|
|
92
|
-
catch (_a) {
|
|
93
|
-
setError('Failed to revoke API key. Please try again.');
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
const formatDate = (date) => {
|
|
97
|
-
if (!date)
|
|
98
|
-
return 'Never';
|
|
99
|
-
return new Date(date).toLocaleDateString('en-US', {
|
|
100
|
-
year: 'numeric',
|
|
101
|
-
month: 'short',
|
|
102
|
-
day: 'numeric',
|
|
103
|
-
});
|
|
104
|
-
};
|
|
105
|
-
return (_jsxs(SettingsCard, { title: "API Keys", description: "Manage your API keys for programmatic access", icon: HiKey, theme: theme === null || theme === void 0 ? void 0 : theme.card, className: className, children: [_jsx("div", { className: "mb-4 flex items-center justify-end", children: _jsxs(Button, { theme: theme === null || theme === void 0 ? void 0 : theme.button, color: "blue", onClick: () => setIsOpenCreateModal(true), children: [_jsx(HiPlusCircle, { className: "mr-2 h-5 w-5" }), "Create API Key"] }) }), error && (_jsx(StatusAlert, { type: "error", message: error, theme: theme === null || theme === void 0 ? void 0 : theme.alert })), isLoading ? (_jsx("div", { className: "flex justify-center py-4", children: _jsx(Spinner, { size: "lg" }) })) : !Array.isArray(apiKeys) || apiKeys.length === 0 ? (_jsxs("div", { className: "rounded-lg border border-zinc-200 bg-zinc-50 p-8 text-center dark:border-zinc-700 dark:bg-zinc-800", children: [_jsx(HiKey, { className: "mx-auto mb-3 h-12 w-12 text-zinc-400" }), _jsx("h3", { className: "mb-2 text-lg font-semibold text-zinc-900 dark:text-zinc-100", children: "No API keys yet" }), _jsx("p", { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "Create an API key to access your graphs programmatically" })] })) : (_jsx(ApiKeyTable, { apiKeys: apiKeys, onRevokeKey: handleRevokeKey, theme: theme, formatDate: formatDate })), connectHref && (_jsxs("p", { className: "mt-4 text-sm text-zinc-500 dark:text-zinc-400", children: ["Connecting Claude or another MCP client? Generate a ready-made connector URL from the", ' ', _jsx("a", { href: connectHref, className: "text-primary-600 dark:text-primary-400 font-medium hover:underline", children: "Connect page" }), "."] })), _jsx(CreateApiKeyModal, { isOpen: isOpenCreateModal, onClose: () => setIsOpenCreateModal(false), onCreateKey: handleCreateKey, theme: theme, graphs: availableGraphs.map((g) => {
|
|
106
|
-
var _a;
|
|
107
|
-
return ({
|
|
108
|
-
graphId: g.graphId,
|
|
109
|
-
graphName: (_a = g.graphName) !== null && _a !== void 0 ? _a : g.graphId,
|
|
110
|
-
});
|
|
111
|
-
}) })] }));
|
|
112
|
-
};
|