@blocklet/aigne-hub 0.6.10 → 0.6.13
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.
|
@@ -5,16 +5,16 @@ const immer_1 = require("immer");
|
|
|
5
5
|
const nanoid_1 = require("nanoid");
|
|
6
6
|
const react_1 = require("react");
|
|
7
7
|
const nextId = () => (0, nanoid_1.nanoid)(16);
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const DEFAULT_STORAGE_KEY = 'aigne-hub-conversation-history';
|
|
9
|
+
const DEFAULT_SESSION_STORAGE_KEY = 'aigne-hub-conversation-session';
|
|
10
10
|
const MAX_CACHED_MESSAGES = 5; // Limit cached messages to reduce storage usage
|
|
11
11
|
// Load messages from localStorage/sessionStorage
|
|
12
|
-
const loadMessages = async () => {
|
|
12
|
+
const loadMessages = async (storageKey, sessionStorageKey) => {
|
|
13
13
|
try {
|
|
14
14
|
// Try localStorage first, then sessionStorage as fallback
|
|
15
|
-
let cached = localStorage.getItem(
|
|
15
|
+
let cached = localStorage.getItem(storageKey);
|
|
16
16
|
if (!cached) {
|
|
17
|
-
cached = sessionStorage.getItem(
|
|
17
|
+
cached = sessionStorage.getItem(sessionStorageKey);
|
|
18
18
|
}
|
|
19
19
|
if (cached) {
|
|
20
20
|
const parsed = JSON.parse(cached);
|
|
@@ -32,7 +32,7 @@ const loadMessages = async () => {
|
|
|
32
32
|
return [];
|
|
33
33
|
};
|
|
34
34
|
// Save messages to localStorage
|
|
35
|
-
const saveMessages = async (messages) => {
|
|
35
|
+
const saveMessages = async (messages, storageKey, sessionStorageKey) => {
|
|
36
36
|
try {
|
|
37
37
|
// Only save completed messages (no loading state)
|
|
38
38
|
const toSave = messages
|
|
@@ -69,15 +69,15 @@ const saveMessages = async (messages) => {
|
|
|
69
69
|
});
|
|
70
70
|
// Try to save to localStorage, fallback to sessionStorage if quota exceeded
|
|
71
71
|
try {
|
|
72
|
-
localStorage.setItem(
|
|
72
|
+
localStorage.setItem(storageKey, JSON.stringify(toSave));
|
|
73
73
|
// Clear sessionStorage if localStorage succeeded
|
|
74
|
-
sessionStorage.removeItem(
|
|
74
|
+
sessionStorage.removeItem(sessionStorageKey);
|
|
75
75
|
}
|
|
76
76
|
catch (storageError) {
|
|
77
77
|
if (storageError instanceof Error && storageError.name === 'QuotaExceededError') {
|
|
78
78
|
// Fallback to sessionStorage
|
|
79
79
|
try {
|
|
80
|
-
sessionStorage.setItem(
|
|
80
|
+
sessionStorage.setItem(sessionStorageKey, JSON.stringify(toSave));
|
|
81
81
|
}
|
|
82
82
|
catch (sessionError) {
|
|
83
83
|
console.warn('Failed to save to sessionStorage:', sessionError);
|
|
@@ -92,15 +92,54 @@ const saveMessages = async (messages) => {
|
|
|
92
92
|
console.warn('Failed to save conversation history:', error);
|
|
93
93
|
}
|
|
94
94
|
};
|
|
95
|
-
function useConversation({ scrollToBottom, textCompletions, imageGenerations, enableCache = true, }) {
|
|
95
|
+
function useConversation({ scrollToBottom, textCompletions, imageGenerations, enableCache = true, storageKeyPrefix, }) {
|
|
96
96
|
const [messages, setMessages] = (0, react_1.useState)([]);
|
|
97
97
|
const [isInitialLoad, setIsInitialLoad] = (0, react_1.useState)(true);
|
|
98
98
|
const [isLoadingHistory, setIsLoadingHistory] = (0, react_1.useState)(enableCache);
|
|
99
|
-
//
|
|
99
|
+
// Use user-specific storage keys if prefix provided
|
|
100
|
+
const STORAGE_KEY = storageKeyPrefix ? `${storageKeyPrefix}-conversation-history` : DEFAULT_STORAGE_KEY;
|
|
101
|
+
const SESSION_STORAGE_KEY = storageKeyPrefix
|
|
102
|
+
? `${storageKeyPrefix}-conversation-session`
|
|
103
|
+
: DEFAULT_SESSION_STORAGE_KEY;
|
|
104
|
+
// Load messages from cache (runs on mount and when STORAGE_KEY changes)
|
|
100
105
|
(0, react_1.useEffect)(() => {
|
|
101
|
-
if (enableCache
|
|
102
|
-
|
|
103
|
-
|
|
106
|
+
if (!enableCache) {
|
|
107
|
+
setMessages([
|
|
108
|
+
{ id: nextId(), response: 'Hi, I am AIGNE Hub! How can I assist you today?', timestamp: Date.now() },
|
|
109
|
+
]);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
setIsLoadingHistory(true);
|
|
113
|
+
setIsInitialLoad(true);
|
|
114
|
+
// Load from storage
|
|
115
|
+
loadMessages(STORAGE_KEY, SESSION_STORAGE_KEY).then((loadedMessages) => {
|
|
116
|
+
// If no messages loaded from new key, try to migrate from old key (one-time migration)
|
|
117
|
+
if (loadedMessages.length === 0 && storageKeyPrefix) {
|
|
118
|
+
// Try loading from old keys
|
|
119
|
+
loadMessages(DEFAULT_STORAGE_KEY, DEFAULT_SESSION_STORAGE_KEY).then((oldMessages) => {
|
|
120
|
+
if (oldMessages.length > 0) {
|
|
121
|
+
// eslint-disable-next-line no-console
|
|
122
|
+
console.log('Migrating conversation history from old storage key to user-specific key');
|
|
123
|
+
setMessages(oldMessages);
|
|
124
|
+
// Save to new key
|
|
125
|
+
saveMessages(oldMessages, STORAGE_KEY, SESSION_STORAGE_KEY).catch((error) => {
|
|
126
|
+
console.warn('Failed to migrate messages:', error);
|
|
127
|
+
});
|
|
128
|
+
// Clean up old keys after successful migration
|
|
129
|
+
localStorage.removeItem(DEFAULT_STORAGE_KEY);
|
|
130
|
+
sessionStorage.removeItem(DEFAULT_SESSION_STORAGE_KEY);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// No old data either, show welcome message
|
|
134
|
+
setMessages([
|
|
135
|
+
{ id: nextId(), response: 'Hi, I am AIGNE Hub! How can I assist you today?', timestamp: Date.now() },
|
|
136
|
+
]);
|
|
137
|
+
}
|
|
138
|
+
setIsLoadingHistory(false);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
// Messages loaded from new key, or no migration needed
|
|
104
143
|
if (loadedMessages.length === 0) {
|
|
105
144
|
setMessages([
|
|
106
145
|
{ id: nextId(), response: 'Hi, I am AIGNE Hub! How can I assist you today?', timestamp: Date.now() },
|
|
@@ -110,15 +149,9 @@ function useConversation({ scrollToBottom, textCompletions, imageGenerations, en
|
|
|
110
149
|
setMessages(loadedMessages);
|
|
111
150
|
}
|
|
112
151
|
setIsLoadingHistory(false);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
setMessages([
|
|
117
|
-
{ id: nextId(), response: 'Hi, I am AIGNE Hub! How can I assist you today?', timestamp: Date.now() },
|
|
118
|
-
]);
|
|
119
|
-
setIsLoadingHistory(false);
|
|
120
|
-
}
|
|
121
|
-
}, [enableCache, isLoadingHistory]);
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}, [enableCache, STORAGE_KEY, SESSION_STORAGE_KEY, storageKeyPrefix]);
|
|
122
155
|
// Scroll to bottom on initial load
|
|
123
156
|
(0, react_1.useEffect)(() => {
|
|
124
157
|
if (isInitialLoad && messages.length > 0 && !isLoadingHistory) {
|
|
@@ -133,14 +166,14 @@ function useConversation({ scrollToBottom, textCompletions, imageGenerations, en
|
|
|
133
166
|
(0, react_1.useEffect)(() => {
|
|
134
167
|
if (enableCache && messages.length > 0) {
|
|
135
168
|
const timeoutId = setTimeout(() => {
|
|
136
|
-
saveMessages(messages).catch((error) => {
|
|
169
|
+
saveMessages(messages, STORAGE_KEY, SESSION_STORAGE_KEY).catch((error) => {
|
|
137
170
|
console.error('❌ Failed to save messages:', error);
|
|
138
171
|
});
|
|
139
172
|
}, 1000); // Delay save by 1 second to avoid saving during streaming
|
|
140
173
|
return () => clearTimeout(timeoutId);
|
|
141
174
|
}
|
|
142
175
|
return () => { };
|
|
143
|
-
}, [messages, enableCache]);
|
|
176
|
+
}, [messages, enableCache, STORAGE_KEY, SESSION_STORAGE_KEY]);
|
|
144
177
|
const add = (0, react_1.useCallback)(async (prompt, meta) => {
|
|
145
178
|
const id = nextId();
|
|
146
179
|
const timestamp = Date.now();
|
|
@@ -248,7 +281,7 @@ function useConversation({ scrollToBottom, textCompletions, imageGenerations, en
|
|
|
248
281
|
localStorage.removeItem(STORAGE_KEY);
|
|
249
282
|
sessionStorage.removeItem(SESSION_STORAGE_KEY);
|
|
250
283
|
}
|
|
251
|
-
}, [enableCache]);
|
|
284
|
+
}, [enableCache, STORAGE_KEY, SESSION_STORAGE_KEY]);
|
|
252
285
|
return {
|
|
253
286
|
messages,
|
|
254
287
|
add,
|
|
@@ -2,16 +2,16 @@ import { produce } from 'immer';
|
|
|
2
2
|
import { nanoid } from 'nanoid';
|
|
3
3
|
import { useCallback, useEffect, useState } from 'react';
|
|
4
4
|
const nextId = () => nanoid(16);
|
|
5
|
-
const
|
|
6
|
-
const
|
|
5
|
+
const DEFAULT_STORAGE_KEY = 'aigne-hub-conversation-history';
|
|
6
|
+
const DEFAULT_SESSION_STORAGE_KEY = 'aigne-hub-conversation-session';
|
|
7
7
|
const MAX_CACHED_MESSAGES = 5; // Limit cached messages to reduce storage usage
|
|
8
8
|
// Load messages from localStorage/sessionStorage
|
|
9
|
-
const loadMessages = async () => {
|
|
9
|
+
const loadMessages = async (storageKey, sessionStorageKey) => {
|
|
10
10
|
try {
|
|
11
11
|
// Try localStorage first, then sessionStorage as fallback
|
|
12
|
-
let cached = localStorage.getItem(
|
|
12
|
+
let cached = localStorage.getItem(storageKey);
|
|
13
13
|
if (!cached) {
|
|
14
|
-
cached = sessionStorage.getItem(
|
|
14
|
+
cached = sessionStorage.getItem(sessionStorageKey);
|
|
15
15
|
}
|
|
16
16
|
if (cached) {
|
|
17
17
|
const parsed = JSON.parse(cached);
|
|
@@ -29,7 +29,7 @@ const loadMessages = async () => {
|
|
|
29
29
|
return [];
|
|
30
30
|
};
|
|
31
31
|
// Save messages to localStorage
|
|
32
|
-
const saveMessages = async (messages) => {
|
|
32
|
+
const saveMessages = async (messages, storageKey, sessionStorageKey) => {
|
|
33
33
|
try {
|
|
34
34
|
// Only save completed messages (no loading state)
|
|
35
35
|
const toSave = messages
|
|
@@ -66,15 +66,15 @@ const saveMessages = async (messages) => {
|
|
|
66
66
|
});
|
|
67
67
|
// Try to save to localStorage, fallback to sessionStorage if quota exceeded
|
|
68
68
|
try {
|
|
69
|
-
localStorage.setItem(
|
|
69
|
+
localStorage.setItem(storageKey, JSON.stringify(toSave));
|
|
70
70
|
// Clear sessionStorage if localStorage succeeded
|
|
71
|
-
sessionStorage.removeItem(
|
|
71
|
+
sessionStorage.removeItem(sessionStorageKey);
|
|
72
72
|
}
|
|
73
73
|
catch (storageError) {
|
|
74
74
|
if (storageError instanceof Error && storageError.name === 'QuotaExceededError') {
|
|
75
75
|
// Fallback to sessionStorage
|
|
76
76
|
try {
|
|
77
|
-
sessionStorage.setItem(
|
|
77
|
+
sessionStorage.setItem(sessionStorageKey, JSON.stringify(toSave));
|
|
78
78
|
}
|
|
79
79
|
catch (sessionError) {
|
|
80
80
|
console.warn('Failed to save to sessionStorage:', sessionError);
|
|
@@ -89,15 +89,54 @@ const saveMessages = async (messages) => {
|
|
|
89
89
|
console.warn('Failed to save conversation history:', error);
|
|
90
90
|
}
|
|
91
91
|
};
|
|
92
|
-
export default function useConversation({ scrollToBottom, textCompletions, imageGenerations, enableCache = true, }) {
|
|
92
|
+
export default function useConversation({ scrollToBottom, textCompletions, imageGenerations, enableCache = true, storageKeyPrefix, }) {
|
|
93
93
|
const [messages, setMessages] = useState([]);
|
|
94
94
|
const [isInitialLoad, setIsInitialLoad] = useState(true);
|
|
95
95
|
const [isLoadingHistory, setIsLoadingHistory] = useState(enableCache);
|
|
96
|
-
//
|
|
96
|
+
// Use user-specific storage keys if prefix provided
|
|
97
|
+
const STORAGE_KEY = storageKeyPrefix ? `${storageKeyPrefix}-conversation-history` : DEFAULT_STORAGE_KEY;
|
|
98
|
+
const SESSION_STORAGE_KEY = storageKeyPrefix
|
|
99
|
+
? `${storageKeyPrefix}-conversation-session`
|
|
100
|
+
: DEFAULT_SESSION_STORAGE_KEY;
|
|
101
|
+
// Load messages from cache (runs on mount and when STORAGE_KEY changes)
|
|
97
102
|
useEffect(() => {
|
|
98
|
-
if (enableCache
|
|
99
|
-
|
|
100
|
-
|
|
103
|
+
if (!enableCache) {
|
|
104
|
+
setMessages([
|
|
105
|
+
{ id: nextId(), response: 'Hi, I am AIGNE Hub! How can I assist you today?', timestamp: Date.now() },
|
|
106
|
+
]);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
setIsLoadingHistory(true);
|
|
110
|
+
setIsInitialLoad(true);
|
|
111
|
+
// Load from storage
|
|
112
|
+
loadMessages(STORAGE_KEY, SESSION_STORAGE_KEY).then((loadedMessages) => {
|
|
113
|
+
// If no messages loaded from new key, try to migrate from old key (one-time migration)
|
|
114
|
+
if (loadedMessages.length === 0 && storageKeyPrefix) {
|
|
115
|
+
// Try loading from old keys
|
|
116
|
+
loadMessages(DEFAULT_STORAGE_KEY, DEFAULT_SESSION_STORAGE_KEY).then((oldMessages) => {
|
|
117
|
+
if (oldMessages.length > 0) {
|
|
118
|
+
// eslint-disable-next-line no-console
|
|
119
|
+
console.log('Migrating conversation history from old storage key to user-specific key');
|
|
120
|
+
setMessages(oldMessages);
|
|
121
|
+
// Save to new key
|
|
122
|
+
saveMessages(oldMessages, STORAGE_KEY, SESSION_STORAGE_KEY).catch((error) => {
|
|
123
|
+
console.warn('Failed to migrate messages:', error);
|
|
124
|
+
});
|
|
125
|
+
// Clean up old keys after successful migration
|
|
126
|
+
localStorage.removeItem(DEFAULT_STORAGE_KEY);
|
|
127
|
+
sessionStorage.removeItem(DEFAULT_SESSION_STORAGE_KEY);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
// No old data either, show welcome message
|
|
131
|
+
setMessages([
|
|
132
|
+
{ id: nextId(), response: 'Hi, I am AIGNE Hub! How can I assist you today?', timestamp: Date.now() },
|
|
133
|
+
]);
|
|
134
|
+
}
|
|
135
|
+
setIsLoadingHistory(false);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
// Messages loaded from new key, or no migration needed
|
|
101
140
|
if (loadedMessages.length === 0) {
|
|
102
141
|
setMessages([
|
|
103
142
|
{ id: nextId(), response: 'Hi, I am AIGNE Hub! How can I assist you today?', timestamp: Date.now() },
|
|
@@ -107,15 +146,9 @@ export default function useConversation({ scrollToBottom, textCompletions, image
|
|
|
107
146
|
setMessages(loadedMessages);
|
|
108
147
|
}
|
|
109
148
|
setIsLoadingHistory(false);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
setMessages([
|
|
114
|
-
{ id: nextId(), response: 'Hi, I am AIGNE Hub! How can I assist you today?', timestamp: Date.now() },
|
|
115
|
-
]);
|
|
116
|
-
setIsLoadingHistory(false);
|
|
117
|
-
}
|
|
118
|
-
}, [enableCache, isLoadingHistory]);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}, [enableCache, STORAGE_KEY, SESSION_STORAGE_KEY, storageKeyPrefix]);
|
|
119
152
|
// Scroll to bottom on initial load
|
|
120
153
|
useEffect(() => {
|
|
121
154
|
if (isInitialLoad && messages.length > 0 && !isLoadingHistory) {
|
|
@@ -130,14 +163,14 @@ export default function useConversation({ scrollToBottom, textCompletions, image
|
|
|
130
163
|
useEffect(() => {
|
|
131
164
|
if (enableCache && messages.length > 0) {
|
|
132
165
|
const timeoutId = setTimeout(() => {
|
|
133
|
-
saveMessages(messages).catch((error) => {
|
|
166
|
+
saveMessages(messages, STORAGE_KEY, SESSION_STORAGE_KEY).catch((error) => {
|
|
134
167
|
console.error('❌ Failed to save messages:', error);
|
|
135
168
|
});
|
|
136
169
|
}, 1000); // Delay save by 1 second to avoid saving during streaming
|
|
137
170
|
return () => clearTimeout(timeoutId);
|
|
138
171
|
}
|
|
139
172
|
return () => { };
|
|
140
|
-
}, [messages, enableCache]);
|
|
173
|
+
}, [messages, enableCache, STORAGE_KEY, SESSION_STORAGE_KEY]);
|
|
141
174
|
const add = useCallback(async (prompt, meta) => {
|
|
142
175
|
const id = nextId();
|
|
143
176
|
const timestamp = Date.now();
|
|
@@ -245,7 +278,7 @@ export default function useConversation({ scrollToBottom, textCompletions, image
|
|
|
245
278
|
localStorage.removeItem(STORAGE_KEY);
|
|
246
279
|
sessionStorage.removeItem(SESSION_STORAGE_KEY);
|
|
247
280
|
}
|
|
248
|
-
}, [enableCache]);
|
|
281
|
+
}, [enableCache, STORAGE_KEY, SESSION_STORAGE_KEY]);
|
|
249
282
|
return {
|
|
250
283
|
messages,
|
|
251
284
|
add,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { getWallet } from '@blocklet/sdk/lib/wallet';
|
|
1
2
|
import type { BytesType } from '@ocap/util';
|
|
2
3
|
import type { NextFunction, Request, Response } from 'express';
|
|
3
|
-
export declare const wallet:
|
|
4
|
+
export declare const wallet: ReturnType<typeof getWallet>;
|
|
4
5
|
export declare const ensureAdmin: (req: Request & {
|
|
5
6
|
user?: import("@blocklet/sdk/lib/util/login").SessionUser;
|
|
6
7
|
}, res: Response, next: NextFunction) => Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ChatCompletionMessageParam } from 'openai/resources/index';
|
|
2
2
|
import type { MessageItem, VideoResponse } from './conversation';
|
|
3
|
-
export default function useConversation({ scrollToBottom, textCompletions, imageGenerations, enableCache, }: {
|
|
3
|
+
export default function useConversation({ scrollToBottom, textCompletions, imageGenerations, enableCache, storageKeyPrefix, }: {
|
|
4
4
|
scrollToBottom?: (options?: {
|
|
5
5
|
force?: boolean;
|
|
6
6
|
}) => void;
|
|
@@ -28,6 +28,7 @@ export default function useConversation({ scrollToBottom, textCompletions, image
|
|
|
28
28
|
url: string;
|
|
29
29
|
}[]>;
|
|
30
30
|
enableCache?: boolean;
|
|
31
|
+
storageKeyPrefix?: string;
|
|
31
32
|
}): {
|
|
32
33
|
messages: MessageItem[];
|
|
33
34
|
add: (prompt: string | ChatCompletionMessageParam[], meta?: any) => Promise<{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/aigne-hub",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.13",
|
|
4
4
|
"description": "The react.js component library for AIGNE Hub",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -100,12 +100,12 @@
|
|
|
100
100
|
"react": "^18.2.0"
|
|
101
101
|
},
|
|
102
102
|
"dependencies": {
|
|
103
|
-
"@arcblock/did": "^1.27.
|
|
103
|
+
"@arcblock/did": "^1.27.10",
|
|
104
104
|
"@arcblock/ux": "^3.2.6",
|
|
105
105
|
"@blocklet/error": "0.3.2",
|
|
106
|
-
"@blocklet/logger": "
|
|
107
|
-
"@blocklet/payment-js": "^1.22.
|
|
108
|
-
"@blocklet/sdk": "
|
|
106
|
+
"@blocklet/logger": "1.17.3-beta-20251118-061144-335cd35d",
|
|
107
|
+
"@blocklet/payment-js": "^1.22.15",
|
|
108
|
+
"@blocklet/sdk": "1.17.3-beta-20251118-061144-335cd35d",
|
|
109
109
|
"@emotion/css": "^11.13.5",
|
|
110
110
|
"@emotion/react": "^11.14.0",
|
|
111
111
|
"@emotion/styled": "^11.14.1",
|
|
@@ -113,8 +113,8 @@
|
|
|
113
113
|
"@mui/lab": "^7.0.0-beta.14",
|
|
114
114
|
"@mui/material": "^7.2.0",
|
|
115
115
|
"@mui/system": "^7.2.0",
|
|
116
|
-
"@ocap/mcrypto": "^1.27.
|
|
117
|
-
"@ocap/util": "^1.27.
|
|
116
|
+
"@ocap/mcrypto": "^1.27.10",
|
|
117
|
+
"@ocap/util": "^1.27.10",
|
|
118
118
|
"@types/express": "^5.0.3",
|
|
119
119
|
"ahooks": "^3.8.1",
|
|
120
120
|
"axios": "^1.7.4",
|