@blocklet/aigne-hub 0.2.15 → 0.2.17

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.
@@ -17,3 +17,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./v1"), exports);
18
18
  __exportStar(require("./v2"), exports);
19
19
  __exportStar(require("./proxy"), exports);
20
+ __exportStar(require("../user"), exports);
@@ -3,41 +3,85 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.callRemoteApi = callRemoteApi;
6
7
  exports.chatCompletionsV2 = chatCompletionsV2;
7
8
  exports.imageGenerationsV2 = imageGenerationsV2;
8
9
  exports.embeddingsV2 = embeddingsV2;
10
+ exports.getUserCreditInfo = getUserCreditInfo;
9
11
  const web_1 = require("stream/web");
10
- const component_1 = require("@blocklet/sdk/lib/component");
11
- const json_stable_stringify_1 = __importDefault(require("json-stable-stringify"));
12
+ const axios_1 = __importDefault(require("axios"));
13
+ const ufo_1 = require("ufo");
12
14
  const types_1 = require("../types");
13
- const auth_1 = require("../utils/auth");
14
15
  const event_stream_1 = require("../utils/event-stream");
16
+ const util_1 = require("../utils/util");
15
17
  const api_1 = require("./api");
16
- async function chatCompletionsV2(input, { useAIKitService, ...options } = {}) {
17
- const response = (0, api_1.catchAndRethrowUpstreamError)(useAIKitService
18
- ? (0, api_1.aiKitApi)('/api/v2/chat/completions', {
19
- responseType: 'stream',
20
- method: 'POST',
21
- data: (0, json_stable_stringify_1.default)(input),
22
- headers: {
23
- ...(0, auth_1.getRemoteComponentCallHeaders)(input, options.userDid),
24
- Accept: 'text/event-stream',
25
- 'Content-Type': 'application/json',
26
- },
27
- })
28
- : (0, component_1.call)({
29
- name: 'ai-kit',
30
- path: 'api/v2/chat/completions',
31
- data: input,
32
- responseType: 'stream',
33
- headers: { Accept: 'text/event-stream' },
34
- }));
18
+ let cachedUrl = null;
19
+ const CACHE_TTL = 30 * 60 * 1000; // 30分钟
20
+ function isCacheExpired(cacheItem) {
21
+ if (!cacheItem)
22
+ return true;
23
+ return Date.now() - cacheItem.timestamp > CACHE_TTL;
24
+ }
25
+ function getConfig() {
26
+ const baseUrl = process.env.BLOCKLET_AIGNE_API_URL;
27
+ const credentials = JSON.parse(process.env.BLOCKLET_AIGNE_API_CREDENTIAL || '{}');
28
+ const accessKey = credentials === null || credentials === void 0 ? void 0 : credentials.apiKey;
29
+ if (!baseUrl || !accessKey) {
30
+ throw new Error('Please connect to AIGNE Hub First, baseUrl or accessKey not found');
31
+ }
32
+ return { baseUrl, accessKey };
33
+ }
34
+ async function getCachedUrl(url) {
35
+ if (url !== (cachedUrl === null || cachedUrl === void 0 ? void 0 : cachedUrl.data)) {
36
+ cachedUrl = null;
37
+ }
38
+ if (isCacheExpired(cachedUrl)) {
39
+ const { baseUrl } = getConfig();
40
+ const url = await (0, util_1.getRemoteBaseUrl)(baseUrl);
41
+ cachedUrl = {
42
+ data: url,
43
+ timestamp: Date.now(),
44
+ };
45
+ }
46
+ return cachedUrl.data;
47
+ }
48
+ async function callRemoteApi(input, config, options = {}) {
49
+ const { accessKey, baseUrl } = getConfig();
50
+ const url = await getCachedUrl(baseUrl);
51
+ const headers = {
52
+ Authorization: `Bearer ${accessKey}`,
53
+ ...config.additionalHeaders,
54
+ };
55
+ if (config.isStreamEndpoint) {
56
+ headers.Accept = 'text/event-stream';
57
+ headers['Content-Type'] = 'application/json';
58
+ }
59
+ const method = config.method || 'POST';
60
+ const requestConfig = {
61
+ method,
62
+ url: (0, ufo_1.joinURL)(url, config.endpoint),
63
+ headers,
64
+ timeout: options === null || options === void 0 ? void 0 : options.timeout,
65
+ };
66
+ if (method === 'GET') {
67
+ requestConfig.params = input;
68
+ }
69
+ else {
70
+ requestConfig.data = input;
71
+ }
72
+ return (0, api_1.catchAndRethrowUpstreamError)(axios_1.default.request(requestConfig));
73
+ }
74
+ async function chatCompletionsV2(input, options = {}) {
75
+ const response = await callRemoteApi(input, {
76
+ endpoint: 'api/v2/chat/completions',
77
+ isStreamEndpoint: true,
78
+ }, options);
35
79
  if ((options === null || options === void 0 ? void 0 : options.responseType) === 'stream')
36
80
  return response;
37
81
  return new web_1.ReadableStream({
38
82
  async start(controller) {
39
83
  try {
40
- const stream = (0, event_stream_1.readableToWeb)((await response).data)
84
+ const stream = (0, event_stream_1.readableToWeb)(response.data)
41
85
  .pipeThrough(new web_1.TextDecoderStream())
42
86
  .pipeThrough(new event_stream_1.EventSourceParserStream());
43
87
  for await (const chunk of stream) {
@@ -65,37 +109,27 @@ async function chatCompletionsV2(input, { useAIKitService, ...options } = {}) {
65
109
  },
66
110
  });
67
111
  }
68
- async function imageGenerationsV2(input, { useAIKitService, ...options } = {}) {
69
- const response = await (0, api_1.catchAndRethrowUpstreamError)(useAIKitService
70
- ? api_1.aiKitApi.post('/api/v2/image/generations', input, {
71
- responseType: options.responseType,
72
- headers: { ...(0, auth_1.getRemoteComponentCallHeaders)(input, options.userDid) },
73
- })
74
- : // @ts-ignore
75
- (0, component_1.call)({
76
- name: 'ai-kit',
77
- path: '/api/v2/image/generations',
78
- data: input,
79
- responseType: options === null || options === void 0 ? void 0 : options.responseType,
80
- timeout: options === null || options === void 0 ? void 0 : options.timeout,
81
- }));
112
+ async function imageGenerationsV2(input, options = {}) {
113
+ const response = await callRemoteApi(input, {
114
+ endpoint: 'api/v2/image/generations',
115
+ }, options);
82
116
  if ((options === null || options === void 0 ? void 0 : options.responseType) === 'stream')
83
117
  return response;
84
118
  return response.data;
85
119
  }
86
- async function embeddingsV2(input, { useAIKitService, ...options } = {}) {
87
- const response = await (0, api_1.catchAndRethrowUpstreamError)(useAIKitService
88
- ? api_1.aiKitApi.post('/api/v2/embeddings', input, {
89
- responseType: options.responseType,
90
- headers: { ...(0, auth_1.getRemoteComponentCallHeaders)(input, options.userDid) },
91
- })
92
- : (0, component_1.call)({
93
- name: 'ai-kit',
94
- path: '/api/v2/embeddings',
95
- data: input,
96
- responseType: options === null || options === void 0 ? void 0 : options.responseType,
97
- }));
98
- if ((options === null || options === void 0 ? void 0 : options.responseType) === 'stream')
120
+ async function embeddingsV2(input, options = {}) {
121
+ const response = await callRemoteApi(input, {
122
+ endpoint: 'api/v2/embeddings',
123
+ }, options);
124
+ if ((options === null || options === void 0 ? void 0 : options.responseType) === 'stream') {
99
125
  return response;
126
+ }
127
+ return response.data;
128
+ }
129
+ async function getUserCreditInfo() {
130
+ const response = await callRemoteApi({}, {
131
+ endpoint: 'api/user/info',
132
+ method: 'GET',
133
+ });
100
134
  return response.data;
101
135
  }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getUserInfo = getUserInfo;
7
+ const error_1 = require("@blocklet/error");
8
+ const axios_1 = __importDefault(require("axios"));
9
+ const ufo_1 = require("ufo");
10
+ const util_1 = require("./utils/util");
11
+ async function getUserInfo({ baseUrl = '', accessKey = '', }) {
12
+ let finalBaseUrl = (0, util_1.getPrefix)();
13
+ const windowExist = typeof window !== 'undefined';
14
+ try {
15
+ if (baseUrl) {
16
+ const tmp = new URL(baseUrl);
17
+ if (!windowExist || (windowExist && tmp.origin !== window.location.origin)) {
18
+ finalBaseUrl = await (0, util_1.getRemoteBaseUrl)(baseUrl);
19
+ }
20
+ }
21
+ }
22
+ catch (err) {
23
+ console.warn('Failed to parse baseUrl:', err);
24
+ throw new Error(`Failed to parse baseUrl: ${(0, error_1.formatError)(err)}`);
25
+ }
26
+ if (!finalBaseUrl || !accessKey) {
27
+ throw new Error('baseUrl or accessKey is not set');
28
+ }
29
+ return axios_1.default
30
+ .get((0, ufo_1.joinURL)(finalBaseUrl, '/api/user/info'), {
31
+ headers: {
32
+ Authorization: `Bearer ${accessKey}`,
33
+ },
34
+ })
35
+ .then((res) => res.data);
36
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getPrefix = exports.getRemoteBaseUrl = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const ufo_1 = require("ufo");
9
+ const AIGNE_HUB_DID = 'z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ';
10
+ const getRemoteBaseUrl = async (url) => {
11
+ const tmp = new URL(url);
12
+ if (typeof window !== 'undefined' && tmp.origin === window.location.origin) {
13
+ return (0, exports.getPrefix)();
14
+ }
15
+ const scriptUrl = (0, ufo_1.joinURL)(tmp.origin, '__blocklet__.js?type=json');
16
+ const blockletInfo = await axios_1.default.get(scriptUrl).then((res) => res.data);
17
+ const componentId = ((blockletInfo === null || blockletInfo === void 0 ? void 0 : blockletInfo.componentId) || '').split('/').pop();
18
+ if (componentId === AIGNE_HUB_DID) {
19
+ return (0, ufo_1.joinURL)(tmp.origin, blockletInfo.prefix || '/');
20
+ }
21
+ const component = ((blockletInfo === null || blockletInfo === void 0 ? void 0 : blockletInfo.componentMountPoints) || []).find((x) => (x === null || x === void 0 ? void 0 : x.did) === AIGNE_HUB_DID);
22
+ return component ? (0, ufo_1.joinURL)(tmp.origin, component.mountPoint) : url;
23
+ };
24
+ exports.getRemoteBaseUrl = getRemoteBaseUrl;
25
+ const getPrefix = () => {
26
+ var _a, _b, _c, _d;
27
+ if (typeof window === 'undefined') {
28
+ return '';
29
+ }
30
+ const prefix = ((_a = window.blocklet) === null || _a === void 0 ? void 0 : _a.prefix) || '/';
31
+ const baseUrl = (_b = window.location) === null || _b === void 0 ? void 0 : _b.origin; // required when use payment feature cross origin
32
+ const componentId = (((_c = window.blocklet) === null || _c === void 0 ? void 0 : _c.componentId) || '').split('/').pop();
33
+ if (componentId === AIGNE_HUB_DID) {
34
+ return (0, ufo_1.joinURL)(baseUrl, prefix);
35
+ }
36
+ const component = (((_d = window.blocklet) === null || _d === void 0 ? void 0 : _d.componentMountPoints) || []).find((x) => (x === null || x === void 0 ? void 0 : x.did) === AIGNE_HUB_DID);
37
+ if (component) {
38
+ return (0, ufo_1.joinURL)(baseUrl, component.mountPoint);
39
+ }
40
+ return (0, ufo_1.joinURL)(baseUrl, prefix);
41
+ };
42
+ exports.getPrefix = getPrefix;
@@ -5,15 +5,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const jsx_runtime_1 = require("react/jsx-runtime");
7
7
  const context_1 = require("@arcblock/ux/lib/Locale/context");
8
+ const error_1 = require("@blocklet/error");
8
9
  const material_1 = require("@mui/material");
9
- const error_1 = require("../../api/error");
10
+ const error_2 = require("../../api/error");
10
11
  const withLocaleProvider_1 = __importDefault(require("../../utils/withLocaleProvider"));
11
12
  const button_1 = __importDefault(require("./button"));
12
13
  function CreditErrorAlert({ error, ...props }) {
13
14
  const { t } = (0, context_1.useLocaleContext)();
14
- const isCreditError = (error === null || error === void 0 ? void 0 : error.type) === error_1.CreditErrorType.NOT_ENOUGH;
15
+ const isCreditError = (error === null || error === void 0 ? void 0 : error.type) === error_2.CreditErrorType.NOT_ENOUGH;
15
16
  if (!isCreditError) {
16
- return ((0, jsx_runtime_1.jsx)(material_1.Alert, { severity: "error", ...props, children: (error === null || error === void 0 ? void 0 : error.message) || t('unknownError') }));
17
+ return ((0, jsx_runtime_1.jsx)(material_1.Alert, { severity: "error", ...props, children: (0, error_1.formatError)(error) || t('unknownError') }));
17
18
  }
18
19
  return ((0, jsx_runtime_1.jsxs)(material_1.Alert, { severity: "warning", ...props, sx: {
19
20
  px: 1,
@@ -18,7 +18,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
18
18
  return (mod && mod.__esModule) ? mod : { "default": mod };
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.FormLabel = exports.Table = exports.Switch = exports.CreditErrorAlert = exports.CreditBalance = exports.CreditButton = exports.SubscribeErrorAlert = exports.SubscribeButton = exports.Conversation = exports.ImagePreview = exports.LoadingImage = void 0;
21
+ exports.FormLabel = exports.UserCreditCard = exports.Table = exports.Switch = exports.CreditErrorAlert = exports.CreditBalance = exports.CreditButton = exports.SubscribeErrorAlert = exports.SubscribeButton = exports.Conversation = exports.ImagePreview = exports.LoadingImage = void 0;
22
22
  var loading_image_1 = require("./loading-image");
23
23
  Object.defineProperty(exports, "LoadingImage", { enumerable: true, get: function () { return __importDefault(loading_image_1).default; } });
24
24
  var image_preview_1 = require("./image-preview");
@@ -41,5 +41,7 @@ var switch_button_1 = require("./switch-button");
41
41
  Object.defineProperty(exports, "Switch", { enumerable: true, get: function () { return __importDefault(switch_button_1).default; } });
42
42
  var table_1 = require("./table");
43
43
  Object.defineProperty(exports, "Table", { enumerable: true, get: function () { return __importDefault(table_1).default; } });
44
+ var user_credit_card_1 = require("./user-credit-card");
45
+ Object.defineProperty(exports, "UserCreditCard", { enumerable: true, get: function () { return __importDefault(user_credit_card_1).default; } });
44
46
  var form_label_1 = require("./form-label");
45
47
  Object.defineProperty(exports, "FormLabel", { enumerable: true, get: function () { return __importDefault(form_label_1).default; } });
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ const context_1 = require("@arcblock/ux/lib/Locale/context");
8
+ const Toast_1 = __importDefault(require("@arcblock/ux/lib/Toast"));
9
+ const UserCard_1 = __importDefault(require("@arcblock/ux/lib/UserCard"));
10
+ const error_1 = require("@blocklet/error");
11
+ const material_1 = require("@mui/material");
12
+ const ahooks_1 = require("ahooks");
13
+ const user_1 = require("../api/user");
14
+ const util_1 = require("../utils/util");
15
+ const withLocaleProvider_1 = __importDefault(require("../utils/withLocaleProvider"));
16
+ function UserCreditCard({ baseUrl, accessKey, onSuccess = () => { }, onError = () => { }, mode = 'default', render = () => null, }) {
17
+ var _a, _b, _c, _d, _e, _f;
18
+ const { t } = (0, context_1.useLocaleContext)();
19
+ const { data: userInfoData, loading } = (0, ahooks_1.useRequest)(() => (0, user_1.getUserInfo)({ baseUrl, accessKey }), {
20
+ refreshDeps: [baseUrl, accessKey],
21
+ onError: (err) => {
22
+ Toast_1.default.error((0, error_1.formatError)(err));
23
+ onError === null || onError === void 0 ? void 0 : onError(err);
24
+ },
25
+ onSuccess: (data) => {
26
+ onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(data);
27
+ },
28
+ });
29
+ if (loading) {
30
+ return ((0, jsx_runtime_1.jsxs)(material_1.Box, { sx: { p: 2, textAlign: 'center' }, children: [(0, jsx_runtime_1.jsx)(material_1.CircularProgress, { size: 24 }), (0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", color: "text.secondary", sx: { mt: 1 }, children: t('loadingUserInfo') })] }));
31
+ }
32
+ if (!userInfoData) {
33
+ return ((0, jsx_runtime_1.jsx)(material_1.Box, { sx: { p: 2 }, children: (0, jsx_runtime_1.jsx)(material_1.Alert, { severity: "info", sx: { fontSize: '0.875rem' }, children: t('noUserData') }) }));
34
+ }
35
+ if (mode === 'custom') {
36
+ return render(userInfoData);
37
+ }
38
+ return ((0, jsx_runtime_1.jsxs)(material_1.Stack, { sx: { p: 2, border: '1px solid', borderColor: 'divider', borderRadius: 2, width: '100%' }, spacing: 2, className: "user-credit-card", children: [(0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", color: "text.secondary", children: t('username') }), (0, jsx_runtime_1.jsx)(UserCard_1.default, { user: userInfoData.user, showHoverCard: true, popupShowDid: true, sx: {
39
+ border: 'none',
40
+ p: 0,
41
+ minWidth: 0,
42
+ }, avatarProps: {
43
+ size: 24,
44
+ } })] }), (userInfoData === null || userInfoData === void 0 ? void 0 : userInfoData.enableCredit) ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", color: "text.secondary", children: t('creditBalance') }), (0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "h6", fontWeight: "bold", children: [(0, util_1.formatNumber)(((_a = userInfoData === null || userInfoData === void 0 ? void 0 : userInfoData.creditBalance) === null || _a === void 0 ? void 0 : _a.balance) || '0'), " ", (_c = (_b = userInfoData.currency) === null || _b === void 0 ? void 0 : _b.symbol) !== null && _c !== void 0 ? _c : 'AHC'] })] }), ((_d = userInfoData.creditBalance) === null || _d === void 0 ? void 0 : _d.pendingCredit) && Number(userInfoData.creditBalance.pendingCredit) > 0 && ((0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "body2", color: "text.secondary", children: t('pendingCredit') }), (0, jsx_runtime_1.jsxs)(material_1.Typography, { variant: "h6", fontWeight: "bold", sx: { color: 'error.main' }, children: [(0, util_1.formatNumber)(userInfoData.creditBalance.pendingCredit), " ", (_f = (_e = userInfoData.currency) === null || _e === void 0 ? void 0 : _e.symbol) !== null && _f !== void 0 ? _f : 'AHC'] })] })), (0, jsx_runtime_1.jsxs)(material_1.Stack, { direction: "row", spacing: 1.5, sx: { mt: 1 }, children: [(userInfoData === null || userInfoData === void 0 ? void 0 : userInfoData.paymentLink) && ((0, jsx_runtime_1.jsx)(material_1.Button, { variant: "outlined", onClick: () => {
45
+ window.open((userInfoData === null || userInfoData === void 0 ? void 0 : userInfoData.paymentLink) || '', '_blank');
46
+ }, sx: {
47
+ flex: 1,
48
+ }, children: t('recharge') })), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "text", onClick: () => {
49
+ window.open((userInfoData === null || userInfoData === void 0 ? void 0 : userInfoData.profileLink) || '', '_blank');
50
+ }, sx: {
51
+ borderColor: 'primary.main',
52
+ color: 'primary.main',
53
+ }, children: t('manage') })] })] })) : ((0, jsx_runtime_1.jsxs)(material_1.Alert, { severity: "info", sx: {
54
+ textAlign: 'left',
55
+ }, children: [t('creditNotEnabled'), (0, jsx_runtime_1.jsx)(material_1.Typography, { sx: {
56
+ display: 'inline-block',
57
+ fontSize: 'inherit',
58
+ lineHeight: 'inherit',
59
+ ml: 1,
60
+ a: {
61
+ textDecoration: 'none',
62
+ },
63
+ '& .MuiButtonBase-root': { p: 0, minWidth: 'auto' },
64
+ }, children: (0, jsx_runtime_1.jsx)(material_1.Link, { href: (userInfoData === null || userInfoData === void 0 ? void 0 : userInfoData.profileLink) || '', target: "_blank", children: t('viewProfile') }) })] }))] }));
65
+ }
66
+ exports.default = (0, withLocaleProvider_1.default)(UserCreditCard, {
67
+ translations: {
68
+ en: {
69
+ username: 'User',
70
+ creditBalance: 'Credit Balance',
71
+ pendingCredit: 'Outstanding Charges',
72
+ recharge: 'Buy Credits',
73
+ manage: 'Manage',
74
+ creditNotEnabled: 'AIGNE Hub Credit billing is not enabled. You can use AI services directly.',
75
+ loadingUserInfo: 'Loading user information...',
76
+ fetchUserInfoFailed: 'Failed to fetch user information',
77
+ unknownUser: 'Unknown User',
78
+ noUserData: 'No user data available',
79
+ retry: 'Retry',
80
+ viewProfile: 'View Profile',
81
+ },
82
+ zh: {
83
+ username: '用户',
84
+ creditBalance: '信用额度',
85
+ pendingCredit: '待结清额度',
86
+ recharge: '购买额度',
87
+ manage: '管理额度',
88
+ creditNotEnabled: 'AIGNE Hub 未启用 Credit 计费功能,您可以直接使用AI服务。',
89
+ loadingUserInfo: '正在加载用户信息...',
90
+ fetchUserInfoFailed: '获取用户信息失败',
91
+ unknownUser: '未知用户',
92
+ noUserData: '暂无用户数据',
93
+ retry: '重试',
94
+ viewProfile: '查看用户信息',
95
+ },
96
+ },
97
+ });
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.formatNumber = formatNumber;
7
+ const trimEnd_1 = __importDefault(require("lodash/trimEnd"));
8
+ const numbro_1 = __importDefault(require("numbro"));
9
+ function formatNumber(n, precision = 6, trim = true, thousandSeparated = true) {
10
+ if (!n || n === '0') {
11
+ return '0';
12
+ }
13
+ const num = (0, numbro_1.default)(n);
14
+ const options = {
15
+ thousandSeparated,
16
+ ...((precision || precision === 0) && { mantissa: precision }),
17
+ };
18
+ const result = num.format(options);
19
+ if (!trim) {
20
+ return result;
21
+ }
22
+ const [left, right] = result.split('.');
23
+ return right ? [left, (0, trimEnd_1.default)(right, '0')].filter(Boolean).join('.') : left;
24
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './v1';
2
2
  export * from './v2';
3
3
  export * from './proxy';
4
+ export * from '../user';
@@ -1,35 +1,77 @@
1
1
  import { ReadableStream, TextDecoderStream } from 'stream/web';
2
- import { call } from '@blocklet/sdk/lib/component';
3
- import stringify from 'json-stable-stringify';
2
+ import axios from 'axios';
3
+ import { joinURL } from 'ufo';
4
4
  import { isChatCompletionError, } from '../types';
5
- import { getRemoteComponentCallHeaders } from '../utils/auth';
6
5
  import { EventSourceParserStream, readableToWeb } from '../utils/event-stream';
7
- import { aiKitApi, catchAndRethrowUpstreamError } from './api';
8
- export async function chatCompletionsV2(input, { useAIKitService, ...options } = {}) {
9
- const response = catchAndRethrowUpstreamError(useAIKitService
10
- ? aiKitApi('/api/v2/chat/completions', {
11
- responseType: 'stream',
12
- method: 'POST',
13
- data: stringify(input),
14
- headers: {
15
- ...getRemoteComponentCallHeaders(input, options.userDid),
16
- Accept: 'text/event-stream',
17
- 'Content-Type': 'application/json',
18
- },
19
- })
20
- : call({
21
- name: 'ai-kit',
22
- path: 'api/v2/chat/completions',
23
- data: input,
24
- responseType: 'stream',
25
- headers: { Accept: 'text/event-stream' },
26
- }));
6
+ import { getRemoteBaseUrl } from '../utils/util';
7
+ import { catchAndRethrowUpstreamError } from './api';
8
+ let cachedUrl = null;
9
+ const CACHE_TTL = 30 * 60 * 1000; // 30分钟
10
+ function isCacheExpired(cacheItem) {
11
+ if (!cacheItem)
12
+ return true;
13
+ return Date.now() - cacheItem.timestamp > CACHE_TTL;
14
+ }
15
+ function getConfig() {
16
+ const baseUrl = process.env.BLOCKLET_AIGNE_API_URL;
17
+ const credentials = JSON.parse(process.env.BLOCKLET_AIGNE_API_CREDENTIAL || '{}');
18
+ const accessKey = credentials === null || credentials === void 0 ? void 0 : credentials.apiKey;
19
+ if (!baseUrl || !accessKey) {
20
+ throw new Error('Please connect to AIGNE Hub First, baseUrl or accessKey not found');
21
+ }
22
+ return { baseUrl, accessKey };
23
+ }
24
+ async function getCachedUrl(url) {
25
+ if (url !== (cachedUrl === null || cachedUrl === void 0 ? void 0 : cachedUrl.data)) {
26
+ cachedUrl = null;
27
+ }
28
+ if (isCacheExpired(cachedUrl)) {
29
+ const { baseUrl } = getConfig();
30
+ const url = await getRemoteBaseUrl(baseUrl);
31
+ cachedUrl = {
32
+ data: url,
33
+ timestamp: Date.now(),
34
+ };
35
+ }
36
+ return cachedUrl.data;
37
+ }
38
+ export async function callRemoteApi(input, config, options = {}) {
39
+ const { accessKey, baseUrl } = getConfig();
40
+ const url = await getCachedUrl(baseUrl);
41
+ const headers = {
42
+ Authorization: `Bearer ${accessKey}`,
43
+ ...config.additionalHeaders,
44
+ };
45
+ if (config.isStreamEndpoint) {
46
+ headers.Accept = 'text/event-stream';
47
+ headers['Content-Type'] = 'application/json';
48
+ }
49
+ const method = config.method || 'POST';
50
+ const requestConfig = {
51
+ method,
52
+ url: joinURL(url, config.endpoint),
53
+ headers,
54
+ timeout: options === null || options === void 0 ? void 0 : options.timeout,
55
+ };
56
+ if (method === 'GET') {
57
+ requestConfig.params = input;
58
+ }
59
+ else {
60
+ requestConfig.data = input;
61
+ }
62
+ return catchAndRethrowUpstreamError(axios.request(requestConfig));
63
+ }
64
+ export async function chatCompletionsV2(input, options = {}) {
65
+ const response = await callRemoteApi(input, {
66
+ endpoint: 'api/v2/chat/completions',
67
+ isStreamEndpoint: true,
68
+ }, options);
27
69
  if ((options === null || options === void 0 ? void 0 : options.responseType) === 'stream')
28
70
  return response;
29
71
  return new ReadableStream({
30
72
  async start(controller) {
31
73
  try {
32
- const stream = readableToWeb((await response).data)
74
+ const stream = readableToWeb(response.data)
33
75
  .pipeThrough(new TextDecoderStream())
34
76
  .pipeThrough(new EventSourceParserStream());
35
77
  for await (const chunk of stream) {
@@ -57,37 +99,27 @@ export async function chatCompletionsV2(input, { useAIKitService, ...options } =
57
99
  },
58
100
  });
59
101
  }
60
- export async function imageGenerationsV2(input, { useAIKitService, ...options } = {}) {
61
- const response = await catchAndRethrowUpstreamError(useAIKitService
62
- ? aiKitApi.post('/api/v2/image/generations', input, {
63
- responseType: options.responseType,
64
- headers: { ...getRemoteComponentCallHeaders(input, options.userDid) },
65
- })
66
- : // @ts-ignore
67
- call({
68
- name: 'ai-kit',
69
- path: '/api/v2/image/generations',
70
- data: input,
71
- responseType: options === null || options === void 0 ? void 0 : options.responseType,
72
- timeout: options === null || options === void 0 ? void 0 : options.timeout,
73
- }));
102
+ export async function imageGenerationsV2(input, options = {}) {
103
+ const response = await callRemoteApi(input, {
104
+ endpoint: 'api/v2/image/generations',
105
+ }, options);
74
106
  if ((options === null || options === void 0 ? void 0 : options.responseType) === 'stream')
75
107
  return response;
76
108
  return response.data;
77
109
  }
78
- export async function embeddingsV2(input, { useAIKitService, ...options } = {}) {
79
- const response = await catchAndRethrowUpstreamError(useAIKitService
80
- ? aiKitApi.post('/api/v2/embeddings', input, {
81
- responseType: options.responseType,
82
- headers: { ...getRemoteComponentCallHeaders(input, options.userDid) },
83
- })
84
- : call({
85
- name: 'ai-kit',
86
- path: '/api/v2/embeddings',
87
- data: input,
88
- responseType: options === null || options === void 0 ? void 0 : options.responseType,
89
- }));
90
- if ((options === null || options === void 0 ? void 0 : options.responseType) === 'stream')
110
+ export async function embeddingsV2(input, options = {}) {
111
+ const response = await callRemoteApi(input, {
112
+ endpoint: 'api/v2/embeddings',
113
+ }, options);
114
+ if ((options === null || options === void 0 ? void 0 : options.responseType) === 'stream') {
91
115
  return response;
116
+ }
117
+ return response.data;
118
+ }
119
+ export async function getUserCreditInfo() {
120
+ const response = await callRemoteApi({}, {
121
+ endpoint: 'api/user/info',
122
+ method: 'GET',
123
+ });
92
124
  return response.data;
93
125
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,30 @@
1
+ import { formatError } from '@blocklet/error';
2
+ import axios from 'axios';
3
+ import { joinURL } from 'ufo';
4
+ import { getPrefix, getRemoteBaseUrl } from './utils/util';
5
+ export async function getUserInfo({ baseUrl = '', accessKey = '', }) {
6
+ let finalBaseUrl = getPrefix();
7
+ const windowExist = typeof window !== 'undefined';
8
+ try {
9
+ if (baseUrl) {
10
+ const tmp = new URL(baseUrl);
11
+ if (!windowExist || (windowExist && tmp.origin !== window.location.origin)) {
12
+ finalBaseUrl = await getRemoteBaseUrl(baseUrl);
13
+ }
14
+ }
15
+ }
16
+ catch (err) {
17
+ console.warn('Failed to parse baseUrl:', err);
18
+ throw new Error(`Failed to parse baseUrl: ${formatError(err)}`);
19
+ }
20
+ if (!finalBaseUrl || !accessKey) {
21
+ throw new Error('baseUrl or accessKey is not set');
22
+ }
23
+ return axios
24
+ .get(joinURL(finalBaseUrl, '/api/user/info'), {
25
+ headers: {
26
+ Authorization: `Bearer ${accessKey}`,
27
+ },
28
+ })
29
+ .then((res) => res.data);
30
+ }
@@ -0,0 +1,34 @@
1
+ import axios from 'axios';
2
+ import { joinURL } from 'ufo';
3
+ const AIGNE_HUB_DID = 'z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ';
4
+ export const getRemoteBaseUrl = async (url) => {
5
+ const tmp = new URL(url);
6
+ if (typeof window !== 'undefined' && tmp.origin === window.location.origin) {
7
+ return getPrefix();
8
+ }
9
+ const scriptUrl = joinURL(tmp.origin, '__blocklet__.js?type=json');
10
+ const blockletInfo = await axios.get(scriptUrl).then((res) => res.data);
11
+ const componentId = ((blockletInfo === null || blockletInfo === void 0 ? void 0 : blockletInfo.componentId) || '').split('/').pop();
12
+ if (componentId === AIGNE_HUB_DID) {
13
+ return joinURL(tmp.origin, blockletInfo.prefix || '/');
14
+ }
15
+ const component = ((blockletInfo === null || blockletInfo === void 0 ? void 0 : blockletInfo.componentMountPoints) || []).find((x) => (x === null || x === void 0 ? void 0 : x.did) === AIGNE_HUB_DID);
16
+ return component ? joinURL(tmp.origin, component.mountPoint) : url;
17
+ };
18
+ export const getPrefix = () => {
19
+ var _a, _b, _c, _d;
20
+ if (typeof window === 'undefined') {
21
+ return '';
22
+ }
23
+ const prefix = ((_a = window.blocklet) === null || _a === void 0 ? void 0 : _a.prefix) || '/';
24
+ const baseUrl = (_b = window.location) === null || _b === void 0 ? void 0 : _b.origin; // required when use payment feature cross origin
25
+ const componentId = (((_c = window.blocklet) === null || _c === void 0 ? void 0 : _c.componentId) || '').split('/').pop();
26
+ if (componentId === AIGNE_HUB_DID) {
27
+ return joinURL(baseUrl, prefix);
28
+ }
29
+ const component = (((_d = window.blocklet) === null || _d === void 0 ? void 0 : _d.componentMountPoints) || []).find((x) => (x === null || x === void 0 ? void 0 : x.did) === AIGNE_HUB_DID);
30
+ if (component) {
31
+ return joinURL(baseUrl, component.mountPoint);
32
+ }
33
+ return joinURL(baseUrl, prefix);
34
+ };
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
3
+ import { formatError } from '@blocklet/error';
3
4
  import { Alert, Stack } from '@mui/material';
4
5
  import { CreditErrorType } from '../../api/error';
5
6
  import withLocaleProvider from '../../utils/withLocaleProvider';
@@ -8,7 +9,7 @@ function CreditErrorAlert({ error, ...props }) {
8
9
  const { t } = useLocaleContext();
9
10
  const isCreditError = (error === null || error === void 0 ? void 0 : error.type) === CreditErrorType.NOT_ENOUGH;
10
11
  if (!isCreditError) {
11
- return (_jsx(Alert, { severity: "error", ...props, children: (error === null || error === void 0 ? void 0 : error.message) || t('unknownError') }));
12
+ return (_jsx(Alert, { severity: "error", ...props, children: formatError(error) || t('unknownError') }));
12
13
  }
13
14
  return (_jsxs(Alert, { severity: "warning", ...props, sx: {
14
15
  px: 1,
@@ -11,4 +11,5 @@ export { default as CreditBalance } from './credit/balance';
11
11
  export { default as CreditErrorAlert } from './credit/alert';
12
12
  export { default as Switch } from './switch-button';
13
13
  export { default as Table } from './table';
14
+ export { default as UserCreditCard } from './user-credit-card';
14
15
  export { default as FormLabel } from './form-label';
@@ -0,0 +1,92 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
3
+ import Toast from '@arcblock/ux/lib/Toast';
4
+ import UserCard from '@arcblock/ux/lib/UserCard';
5
+ import { formatError } from '@blocklet/error';
6
+ import { Alert, Box, Button, CircularProgress, Link, Stack, Typography } from '@mui/material';
7
+ import { useRequest } from 'ahooks';
8
+ import { getUserInfo } from '../api/user';
9
+ import { formatNumber } from '../utils/util';
10
+ import withLocaleProvider from '../utils/withLocaleProvider';
11
+ function UserCreditCard({ baseUrl, accessKey, onSuccess = () => { }, onError = () => { }, mode = 'default', render = () => null, }) {
12
+ var _a, _b, _c, _d, _e, _f;
13
+ const { t } = useLocaleContext();
14
+ const { data: userInfoData, loading } = useRequest(() => getUserInfo({ baseUrl, accessKey }), {
15
+ refreshDeps: [baseUrl, accessKey],
16
+ onError: (err) => {
17
+ Toast.error(formatError(err));
18
+ onError === null || onError === void 0 ? void 0 : onError(err);
19
+ },
20
+ onSuccess: (data) => {
21
+ onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(data);
22
+ },
23
+ });
24
+ if (loading) {
25
+ return (_jsxs(Box, { sx: { p: 2, textAlign: 'center' }, children: [_jsx(CircularProgress, { size: 24 }), _jsx(Typography, { variant: "body2", color: "text.secondary", sx: { mt: 1 }, children: t('loadingUserInfo') })] }));
26
+ }
27
+ if (!userInfoData) {
28
+ return (_jsx(Box, { sx: { p: 2 }, children: _jsx(Alert, { severity: "info", sx: { fontSize: '0.875rem' }, children: t('noUserData') }) }));
29
+ }
30
+ if (mode === 'custom') {
31
+ return render(userInfoData);
32
+ }
33
+ return (_jsxs(Stack, { sx: { p: 2, border: '1px solid', borderColor: 'divider', borderRadius: 2, width: '100%' }, spacing: 2, className: "user-credit-card", children: [_jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", children: [_jsx(Typography, { variant: "body2", color: "text.secondary", children: t('username') }), _jsx(UserCard, { user: userInfoData.user, showHoverCard: true, popupShowDid: true, sx: {
34
+ border: 'none',
35
+ p: 0,
36
+ minWidth: 0,
37
+ }, avatarProps: {
38
+ size: 24,
39
+ } })] }), (userInfoData === null || userInfoData === void 0 ? void 0 : userInfoData.enableCredit) ? (_jsxs(_Fragment, { children: [_jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", children: [_jsx(Typography, { variant: "body2", color: "text.secondary", children: t('creditBalance') }), _jsxs(Typography, { variant: "h6", fontWeight: "bold", children: [formatNumber(((_a = userInfoData === null || userInfoData === void 0 ? void 0 : userInfoData.creditBalance) === null || _a === void 0 ? void 0 : _a.balance) || '0'), " ", (_c = (_b = userInfoData.currency) === null || _b === void 0 ? void 0 : _b.symbol) !== null && _c !== void 0 ? _c : 'AHC'] })] }), ((_d = userInfoData.creditBalance) === null || _d === void 0 ? void 0 : _d.pendingCredit) && Number(userInfoData.creditBalance.pendingCredit) > 0 && (_jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", children: [_jsx(Typography, { variant: "body2", color: "text.secondary", children: t('pendingCredit') }), _jsxs(Typography, { variant: "h6", fontWeight: "bold", sx: { color: 'error.main' }, children: [formatNumber(userInfoData.creditBalance.pendingCredit), " ", (_f = (_e = userInfoData.currency) === null || _e === void 0 ? void 0 : _e.symbol) !== null && _f !== void 0 ? _f : 'AHC'] })] })), _jsxs(Stack, { direction: "row", spacing: 1.5, sx: { mt: 1 }, children: [(userInfoData === null || userInfoData === void 0 ? void 0 : userInfoData.paymentLink) && (_jsx(Button, { variant: "outlined", onClick: () => {
40
+ window.open((userInfoData === null || userInfoData === void 0 ? void 0 : userInfoData.paymentLink) || '', '_blank');
41
+ }, sx: {
42
+ flex: 1,
43
+ }, children: t('recharge') })), _jsx(Button, { variant: "text", onClick: () => {
44
+ window.open((userInfoData === null || userInfoData === void 0 ? void 0 : userInfoData.profileLink) || '', '_blank');
45
+ }, sx: {
46
+ borderColor: 'primary.main',
47
+ color: 'primary.main',
48
+ }, children: t('manage') })] })] })) : (_jsxs(Alert, { severity: "info", sx: {
49
+ textAlign: 'left',
50
+ }, children: [t('creditNotEnabled'), _jsx(Typography, { sx: {
51
+ display: 'inline-block',
52
+ fontSize: 'inherit',
53
+ lineHeight: 'inherit',
54
+ ml: 1,
55
+ a: {
56
+ textDecoration: 'none',
57
+ },
58
+ '& .MuiButtonBase-root': { p: 0, minWidth: 'auto' },
59
+ }, children: _jsx(Link, { href: (userInfoData === null || userInfoData === void 0 ? void 0 : userInfoData.profileLink) || '', target: "_blank", children: t('viewProfile') }) })] }))] }));
60
+ }
61
+ export default withLocaleProvider(UserCreditCard, {
62
+ translations: {
63
+ en: {
64
+ username: 'User',
65
+ creditBalance: 'Credit Balance',
66
+ pendingCredit: 'Outstanding Charges',
67
+ recharge: 'Buy Credits',
68
+ manage: 'Manage',
69
+ creditNotEnabled: 'AIGNE Hub Credit billing is not enabled. You can use AI services directly.',
70
+ loadingUserInfo: 'Loading user information...',
71
+ fetchUserInfoFailed: 'Failed to fetch user information',
72
+ unknownUser: 'Unknown User',
73
+ noUserData: 'No user data available',
74
+ retry: 'Retry',
75
+ viewProfile: 'View Profile',
76
+ },
77
+ zh: {
78
+ username: '用户',
79
+ creditBalance: '信用额度',
80
+ pendingCredit: '待结清额度',
81
+ recharge: '购买额度',
82
+ manage: '管理额度',
83
+ creditNotEnabled: 'AIGNE Hub 未启用 Credit 计费功能,您可以直接使用AI服务。',
84
+ loadingUserInfo: '正在加载用户信息...',
85
+ fetchUserInfoFailed: '获取用户信息失败',
86
+ unknownUser: '未知用户',
87
+ noUserData: '暂无用户数据',
88
+ retry: '重试',
89
+ viewProfile: '查看用户信息',
90
+ },
91
+ },
92
+ });
@@ -0,0 +1,18 @@
1
+ import trimEnd from 'lodash/trimEnd';
2
+ import numbro from 'numbro';
3
+ export function formatNumber(n, precision = 6, trim = true, thousandSeparated = true) {
4
+ if (!n || n === '0') {
5
+ return '0';
6
+ }
7
+ const num = numbro(n);
8
+ const options = {
9
+ thousandSeparated,
10
+ ...((precision || precision === 0) && { mantissa: precision }),
11
+ };
12
+ const result = num.format(options);
13
+ if (!trim) {
14
+ return result;
15
+ }
16
+ const [left, right] = result.split('.');
17
+ return right ? [left, trimEnd(right, '0')].filter(Boolean).join('.') : left;
18
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './v1';
2
2
  export * from './v2';
3
3
  export * from './proxy';
4
+ export * from '../user';
@@ -2,29 +2,41 @@ import type { IncomingMessage } from 'http';
2
2
  import { ReadableStream } from 'stream/web';
3
3
  import { AxiosResponse } from 'axios';
4
4
  import { ChatCompletionError, ChatCompletionInput, ChatCompletionResponse, EmbeddingInput, EmbeddingResponse, ImageGenerationInput, ImageGenerationResponse } from '../types';
5
+ import { UserInfoResult } from '../types/user';
6
+ interface RemoteApiOptions {
7
+ responseType?: 'stream';
8
+ timeout?: number;
9
+ }
10
+ interface RemoteApiConfig {
11
+ endpoint: string;
12
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';
13
+ additionalHeaders?: Record<string, string>;
14
+ isStreamEndpoint?: boolean;
15
+ }
16
+ export declare function callRemoteApi<T = any>(input: any, config: RemoteApiConfig, options?: RemoteApiOptions): Promise<AxiosResponse<T, any>>;
5
17
  export declare function chatCompletionsV2(input: ChatCompletionInput, options?: {
6
- useAIKitService?: boolean;
7
18
  responseType?: undefined;
19
+ timeout?: number;
8
20
  }): Promise<ReadableStream<Exclude<ChatCompletionResponse, ChatCompletionError>>>;
9
21
  export declare function chatCompletionsV2(input: ChatCompletionInput, options: {
10
- useAIKitService?: boolean;
11
22
  responseType: 'stream';
23
+ timeout?: number;
12
24
  }): Promise<AxiosResponse<IncomingMessage, any>>;
13
25
  export declare function imageGenerationsV2(input: ImageGenerationInput, options?: {
14
- useAIKitService?: boolean;
15
26
  responseType?: undefined;
16
27
  timeout?: number;
17
28
  }): Promise<ImageGenerationResponse>;
18
29
  export declare function imageGenerationsV2(input: ImageGenerationInput, options: {
19
- useAIKitService?: boolean;
20
30
  responseType: 'stream';
21
31
  timeout?: number;
22
32
  }): Promise<AxiosResponse<IncomingMessage, any>>;
23
33
  export declare function embeddingsV2(input: EmbeddingInput, options?: {
24
- useAIKitService?: boolean;
25
34
  responseType?: undefined;
35
+ timeout?: number;
26
36
  }): Promise<EmbeddingResponse>;
27
37
  export declare function embeddingsV2(input: EmbeddingInput, options: {
28
- useAIKitService?: boolean;
29
38
  responseType: 'stream';
39
+ timeout?: number;
30
40
  }): Promise<AxiosResponse<IncomingMessage, any>>;
41
+ export declare function getUserCreditInfo(): Promise<UserInfoResult>;
42
+ export {};
@@ -0,0 +1,15 @@
1
+ import type { User } from '@arcblock/ux/lib/type';
2
+ import type { TPaymentCurrency } from '@blocklet/payment-js';
3
+ export interface UserInfoResult {
4
+ user: User;
5
+ enableCredit: boolean;
6
+ creditBalance: {
7
+ balance: string;
8
+ total: string;
9
+ grantCount: number;
10
+ pendingCredit: string;
11
+ } | null;
12
+ paymentLink: string | null;
13
+ currency?: TPaymentCurrency;
14
+ profileLink: string;
15
+ }
@@ -0,0 +1,5 @@
1
+ import { UserInfoResult } from './types/user';
2
+ export declare function getUserInfo({ baseUrl, accessKey, }: {
3
+ baseUrl: string;
4
+ accessKey: string;
5
+ }): Promise<UserInfoResult>;
@@ -0,0 +1,2 @@
1
+ export declare const getRemoteBaseUrl: (url: string) => Promise<string>;
2
+ export declare const getPrefix: () => string;
@@ -9,4 +9,5 @@ export { default as CreditBalance } from './credit/balance';
9
9
  export { default as CreditErrorAlert } from './credit/alert';
10
10
  export { default as Switch } from './switch-button';
11
11
  export { default as Table } from './table';
12
+ export { default as UserCreditCard } from './user-credit-card';
12
13
  export { default as FormLabel } from './form-label';
@@ -0,0 +1,11 @@
1
+ import { UserInfoResult } from '../api/types/user';
2
+ interface UserCreditCardProps {
3
+ baseUrl: string;
4
+ accessKey: string;
5
+ onSuccess?: (userInfo: UserInfoResult) => void;
6
+ onError?: (error: Error) => void;
7
+ mode?: 'default' | 'custom';
8
+ render?: (userInfo: UserInfoResult) => React.ReactNode | null;
9
+ }
10
+ declare const _default: import("react").ComponentType<UserCreditCardProps>;
11
+ export default _default;
@@ -0,0 +1 @@
1
+ export declare function formatNumber(n: number | string, precision?: number, trim?: boolean, thousandSeparated?: boolean): string | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/aigne-hub",
3
- "version": "0.2.15",
3
+ "version": "0.2.17",
4
4
  "description": "The react.js component library for AIGNE Hub",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -46,6 +46,16 @@
46
46
  "types": "./lib/types/components/*.d.ts",
47
47
  "import": "./lib/esm/components/*.js",
48
48
  "require": "./lib/cjs/components/*.js"
49
+ },
50
+ "./utils": {
51
+ "types": "./lib/types/utils/index.d.ts",
52
+ "import": "./lib/esm/utils/index.js",
53
+ "require": "./lib/cjs/utils/index.js"
54
+ },
55
+ "./utils/*": {
56
+ "types": "./lib/types/utils/*.d.ts",
57
+ "import": "./lib/esm/utils/*.js",
58
+ "require": "./lib/cjs/utils/*.js"
49
59
  }
50
60
  },
51
61
  "typesVersions": {
@@ -85,8 +95,9 @@
85
95
  "dependencies": {
86
96
  "@arcblock/did": "^1.21.0",
87
97
  "@arcblock/ux": "^3.0.33",
98
+ "@blocklet/error": "0.2.5",
88
99
  "@blocklet/logger": "^1.16.46",
89
- "@blocklet/payment-js": "^1.19.6",
100
+ "@blocklet/payment-js": "^1.19.8",
90
101
  "@blocklet/sdk": "^1.16.46",
91
102
  "@emotion/css": "^11.13.5",
92
103
  "@emotion/react": "^11.14.0",
@@ -109,6 +120,7 @@
109
120
  "json-stable-stringify": "^1.1.1",
110
121
  "lodash": "^4.17.21",
111
122
  "nanoid": "^5.0.7",
123
+ "numbro": "^2.5.0",
112
124
  "openai": "^4.56.0",
113
125
  "react-markdown": "^9.0.1",
114
126
  "react-photo-view": "^1.2.6",