@blocklet/aigne-hub 0.6.10 → 0.6.11

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 STORAGE_KEY = 'aigne-hub-conversation-history';
9
- const SESSION_STORAGE_KEY = 'aigne-hub-conversation-session';
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(STORAGE_KEY);
15
+ let cached = localStorage.getItem(storageKey);
16
16
  if (!cached) {
17
- cached = sessionStorage.getItem(SESSION_STORAGE_KEY);
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(STORAGE_KEY, JSON.stringify(toSave));
72
+ localStorage.setItem(storageKey, JSON.stringify(toSave));
73
73
  // Clear sessionStorage if localStorage succeeded
74
- sessionStorage.removeItem(SESSION_STORAGE_KEY);
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(SESSION_STORAGE_KEY, JSON.stringify(toSave));
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
- // Load initial messages from cache
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 && isLoadingHistory) {
102
- loadMessages().then((loadedMessages) => {
103
- // If no messages loaded, show welcome message
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
- else if (!enableCache) {
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 STORAGE_KEY = 'aigne-hub-conversation-history';
6
- const SESSION_STORAGE_KEY = 'aigne-hub-conversation-session';
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(STORAGE_KEY);
12
+ let cached = localStorage.getItem(storageKey);
13
13
  if (!cached) {
14
- cached = sessionStorage.getItem(SESSION_STORAGE_KEY);
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(STORAGE_KEY, JSON.stringify(toSave));
69
+ localStorage.setItem(storageKey, JSON.stringify(toSave));
70
70
  // Clear sessionStorage if localStorage succeeded
71
- sessionStorage.removeItem(SESSION_STORAGE_KEY);
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(SESSION_STORAGE_KEY, JSON.stringify(toSave));
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
- // Load initial messages from cache
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 && isLoadingHistory) {
99
- loadMessages().then((loadedMessages) => {
100
- // If no messages loaded, show welcome message
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
- else if (!enableCache) {
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: import("@ocap/wallet").WalletObject<string>;
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.10",
3
+ "version": "0.6.11",
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.6",
103
+ "@arcblock/did": "^1.27.10",
104
104
  "@arcblock/ux": "^3.2.6",
105
105
  "@blocklet/error": "0.3.2",
106
- "@blocklet/logger": "^1.17.2",
107
- "@blocklet/payment-js": "^1.22.13",
108
- "@blocklet/sdk": "^1.17.2",
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.6",
117
- "@ocap/util": "^1.27.6",
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",