@sqaitech/visualizer 0.30.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +9 -0
- package/dist/es/component/blackboard/index.css +33 -0
- package/dist/es/component/blackboard/index.mjs +278 -0
- package/dist/es/component/config-selector/index.mjs +104 -0
- package/dist/es/component/context-preview/index.mjs +38 -0
- package/dist/es/component/env-config/index.mjs +112 -0
- package/dist/es/component/env-config-reminder/index.css +22 -0
- package/dist/es/component/env-config-reminder/index.mjs +28 -0
- package/dist/es/component/form-field/index.mjs +163 -0
- package/dist/es/component/history-selector/index.css +135 -0
- package/dist/es/component/history-selector/index.mjs +170 -0
- package/dist/es/component/index.mjs +1 -0
- package/dist/es/component/logo/index.css +13 -0
- package/dist/es/component/logo/index.mjs +20 -0
- package/dist/es/component/misc/index.mjs +94 -0
- package/dist/es/component/nav-actions/index.mjs +32 -0
- package/dist/es/component/nav-actions/style.css +35 -0
- package/dist/es/component/player/index.css +185 -0
- package/dist/es/component/player/index.mjs +856 -0
- package/dist/es/component/playground/index.css +431 -0
- package/dist/es/component/playground/index.mjs +8 -0
- package/dist/es/component/playground/playground-demo-ui-context.json +290 -0
- package/dist/es/component/playground-result/index.css +34 -0
- package/dist/es/component/playground-result/index.mjs +62 -0
- package/dist/es/component/prompt-input/index.css +391 -0
- package/dist/es/component/prompt-input/index.mjs +730 -0
- package/dist/es/component/service-mode-control/index.mjs +105 -0
- package/dist/es/component/shiny-text/index.css +75 -0
- package/dist/es/component/shiny-text/index.mjs +15 -0
- package/dist/es/component/universal-playground/index.css +341 -0
- package/dist/es/component/universal-playground/index.mjs +302 -0
- package/dist/es/component/universal-playground/providers/context-provider.mjs +52 -0
- package/dist/es/component/universal-playground/providers/indexeddb-storage-provider.mjs +207 -0
- package/dist/es/component/universal-playground/providers/storage-provider.mjs +210 -0
- package/dist/es/hooks/usePlaygroundExecution.mjs +180 -0
- package/dist/es/hooks/usePlaygroundState.mjs +203 -0
- package/dist/es/hooks/useSafeOverrideAIConfig.mjs +24 -0
- package/dist/es/hooks/useServerValid.mjs +30 -0
- package/dist/es/icons/avatar.mjs +28 -0
- package/dist/es/icons/close.mjs +19 -0
- package/dist/es/icons/global-perspective.mjs +16 -0
- package/dist/es/icons/history.mjs +30 -0
- package/dist/es/icons/magnifying-glass.mjs +39 -0
- package/dist/es/icons/player-setting.mjs +26 -0
- package/dist/es/icons/setting.mjs +20 -0
- package/dist/es/icons/show-marker.mjs +16 -0
- package/dist/es/index.mjs +25 -0
- package/dist/es/store/history.mjs +89 -0
- package/dist/es/store/store.mjs +186 -0
- package/dist/es/types.mjs +70 -0
- package/dist/es/utils/color.mjs +35 -0
- package/dist/es/utils/constants.mjs +99 -0
- package/dist/es/utils/index.mjs +10 -0
- package/dist/es/utils/pixi-loader.mjs +16 -0
- package/dist/es/utils/playground-utils.mjs +67 -0
- package/dist/es/utils/replay-scripts.mjs +312 -0
- package/dist/lib/component/blackboard/index.css +33 -0
- package/dist/lib/component/blackboard/index.js +321 -0
- package/dist/lib/component/config-selector/index.js +148 -0
- package/dist/lib/component/context-preview/index.js +83 -0
- package/dist/lib/component/env-config/index.js +146 -0
- package/dist/lib/component/env-config-reminder/index.css +22 -0
- package/dist/lib/component/env-config-reminder/index.js +62 -0
- package/dist/lib/component/form-field/index.js +209 -0
- package/dist/lib/component/history-selector/index.css +135 -0
- package/dist/lib/component/history-selector/index.js +216 -0
- package/dist/lib/component/index.js +60 -0
- package/dist/lib/component/logo/index.css +13 -0
- package/dist/lib/component/logo/index.js +57 -0
- package/dist/lib/component/misc/index.js +150 -0
- package/dist/lib/component/nav-actions/index.js +66 -0
- package/dist/lib/component/nav-actions/style.css +35 -0
- package/dist/lib/component/player/index.css +185 -0
- package/dist/lib/component/player/index.js +902 -0
- package/dist/lib/component/playground/index.css +431 -0
- package/dist/lib/component/playground/index.js +113 -0
- package/dist/lib/component/playground/playground-demo-ui-context.json +290 -0
- package/dist/lib/component/playground-result/index.css +34 -0
- package/dist/lib/component/playground-result/index.js +106 -0
- package/dist/lib/component/prompt-input/index.css +391 -0
- package/dist/lib/component/prompt-input/index.js +774 -0
- package/dist/lib/component/service-mode-control/index.js +139 -0
- package/dist/lib/component/shiny-text/index.css +75 -0
- package/dist/lib/component/shiny-text/index.js +49 -0
- package/dist/lib/component/universal-playground/index.css +341 -0
- package/dist/lib/component/universal-playground/index.js +350 -0
- package/dist/lib/component/universal-playground/providers/context-provider.js +95 -0
- package/dist/lib/component/universal-playground/providers/indexeddb-storage-provider.js +247 -0
- package/dist/lib/component/universal-playground/providers/storage-provider.js +268 -0
- package/dist/lib/hooks/usePlaygroundExecution.js +214 -0
- package/dist/lib/hooks/usePlaygroundState.js +237 -0
- package/dist/lib/hooks/useSafeOverrideAIConfig.js +61 -0
- package/dist/lib/hooks/useServerValid.js +64 -0
- package/dist/lib/icons/avatar.js +62 -0
- package/dist/lib/icons/close.js +53 -0
- package/dist/lib/icons/global-perspective.js +50 -0
- package/dist/lib/icons/history.js +64 -0
- package/dist/lib/icons/magnifying-glass.js +73 -0
- package/dist/lib/icons/player-setting.js +60 -0
- package/dist/lib/icons/setting.js +54 -0
- package/dist/lib/icons/show-marker.js +50 -0
- package/dist/lib/index.js +187 -0
- package/dist/lib/store/history.js +96 -0
- package/dist/lib/store/store.js +196 -0
- package/dist/lib/types.js +116 -0
- package/dist/lib/utils/color.js +75 -0
- package/dist/lib/utils/constants.js +154 -0
- package/dist/lib/utils/index.js +63 -0
- package/dist/lib/utils/pixi-loader.js +56 -0
- package/dist/lib/utils/playground-utils.js +110 -0
- package/dist/lib/utils/replay-scripts.js +355 -0
- package/dist/types/component/blackboard/index.d.ts +15 -0
- package/dist/types/component/config-selector/index.d.ts +9 -0
- package/dist/types/component/context-preview/index.d.ts +9 -0
- package/dist/types/component/env-config/index.d.ts +6 -0
- package/dist/types/component/env-config-reminder/index.d.ts +6 -0
- package/dist/types/component/form-field/index.d.ts +17 -0
- package/dist/types/component/history-selector/index.d.ts +10 -0
- package/dist/types/component/index.d.ts +1 -0
- package/dist/types/component/logo/index.d.ts +5 -0
- package/dist/types/component/misc/index.d.ts +6 -0
- package/dist/types/component/nav-actions/index.d.ts +10 -0
- package/dist/types/component/player/index.d.ts +13 -0
- package/dist/types/component/playground/index.d.ts +7 -0
- package/dist/types/component/playground-result/index.d.ts +20 -0
- package/dist/types/component/prompt-input/index.d.ts +22 -0
- package/dist/types/component/service-mode-control/index.d.ts +6 -0
- package/dist/types/component/shiny-text/index.d.ts +12 -0
- package/dist/types/component/universal-playground/index.d.ts +4 -0
- package/dist/types/component/universal-playground/providers/context-provider.d.ts +37 -0
- package/dist/types/component/universal-playground/providers/indexeddb-storage-provider.d.ts +71 -0
- package/dist/types/component/universal-playground/providers/storage-provider.d.ts +58 -0
- package/dist/types/hooks/usePlaygroundExecution.d.ts +10 -0
- package/dist/types/hooks/usePlaygroundState.d.ts +26 -0
- package/dist/types/hooks/useSafeOverrideAIConfig.d.ts +16 -0
- package/dist/types/hooks/useServerValid.d.ts +1 -0
- package/dist/types/index.d.ts +27 -0
- package/dist/types/store/history.d.ts +16 -0
- package/dist/types/store/store.d.ts +36 -0
- package/dist/types/types.d.ts +161 -0
- package/dist/types/utils/color.d.ts +4 -0
- package/dist/types/utils/constants.d.ts +74 -0
- package/dist/types/utils/index.d.ts +4 -0
- package/dist/types/utils/pixi-loader.d.ts +5 -0
- package/dist/types/utils/playground-utils.d.ts +6 -0
- package/dist/types/utils/replay-scripts.d.ts +34 -0
- package/package.json +85 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { IndexedDBStorageProvider, MemoryStorageProvider, NoOpStorageProvider } from "./indexeddb-storage-provider.mjs";
|
|
2
|
+
function _define_property(obj, key, value) {
|
|
3
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
4
|
+
value: value,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true
|
|
8
|
+
});
|
|
9
|
+
else obj[key] = value;
|
|
10
|
+
return obj;
|
|
11
|
+
}
|
|
12
|
+
class LocalStorageProvider {
|
|
13
|
+
checkStorageSpace() {
|
|
14
|
+
try {
|
|
15
|
+
const testKey = 'storage-test';
|
|
16
|
+
const testData = 'x'.repeat(102400);
|
|
17
|
+
localStorage.setItem(testKey, testData);
|
|
18
|
+
localStorage.removeItem(testKey);
|
|
19
|
+
return true;
|
|
20
|
+
} catch (e) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async saveMessages(messages) {
|
|
25
|
+
try {
|
|
26
|
+
if (!this.checkStorageSpace()) {
|
|
27
|
+
console.warn('Low storage space detected, clearing old data...');
|
|
28
|
+
await this.handleQuotaExceeded();
|
|
29
|
+
}
|
|
30
|
+
const messagesToSave = messages.slice(-this.maxStorageItems);
|
|
31
|
+
const lightMessages = messagesToSave.map((msg)=>({
|
|
32
|
+
...msg,
|
|
33
|
+
result: void 0
|
|
34
|
+
}));
|
|
35
|
+
const messageData = JSON.stringify(lightMessages);
|
|
36
|
+
localStorage.setItem(this.messagesKey, messageData);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
if (error instanceof DOMException && 'QuotaExceededError' === error.name) {
|
|
39
|
+
console.warn('LocalStorage quota exceeded, attempting to clear old data and retry...');
|
|
40
|
+
await this.handleQuotaExceeded();
|
|
41
|
+
try {
|
|
42
|
+
const recentMessages = messages.slice(-10);
|
|
43
|
+
const lightRecentMessages = recentMessages.map((msg)=>({
|
|
44
|
+
...msg,
|
|
45
|
+
result: void 0
|
|
46
|
+
}));
|
|
47
|
+
const messageData = JSON.stringify(lightRecentMessages);
|
|
48
|
+
localStorage.setItem(this.messagesKey, messageData);
|
|
49
|
+
console.info('Successfully saved recent messages after clearing storage');
|
|
50
|
+
} catch (retryError) {
|
|
51
|
+
console.error('Failed to save even after clearing storage:', retryError);
|
|
52
|
+
await this.clearMessages();
|
|
53
|
+
}
|
|
54
|
+
} else console.error('Failed to save messages to localStorage:', error);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
async loadMessages() {
|
|
58
|
+
try {
|
|
59
|
+
const stored = localStorage.getItem(this.messagesKey);
|
|
60
|
+
if (!stored) return [];
|
|
61
|
+
const messages = JSON.parse(stored);
|
|
62
|
+
const restoredMessages = await Promise.all(messages.map(async (msg)=>{
|
|
63
|
+
if ('result' === msg.type && msg.id) {
|
|
64
|
+
const resultKey = `${this.resultsKey}-${msg.id}`;
|
|
65
|
+
const storedResult = localStorage.getItem(resultKey);
|
|
66
|
+
if (storedResult) try {
|
|
67
|
+
const resultItem = JSON.parse(storedResult);
|
|
68
|
+
return {
|
|
69
|
+
...msg,
|
|
70
|
+
...resultItem
|
|
71
|
+
};
|
|
72
|
+
} catch (e) {
|
|
73
|
+
console.warn('Failed to parse stored result:', e);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return msg;
|
|
77
|
+
}));
|
|
78
|
+
return restoredMessages;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error('Failed to load messages from localStorage:', error);
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async clearMessages() {
|
|
85
|
+
try {
|
|
86
|
+
localStorage.removeItem(this.messagesKey);
|
|
87
|
+
const keys = Object.keys(localStorage);
|
|
88
|
+
keys.forEach((key)=>{
|
|
89
|
+
if (key.startsWith(this.resultsKey)) localStorage.removeItem(key);
|
|
90
|
+
});
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error('Failed to clear messages from localStorage:', error);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async saveResult(id, result) {
|
|
96
|
+
try {
|
|
97
|
+
const resultKey = `${this.resultsKey}-${id}`;
|
|
98
|
+
localStorage.setItem(resultKey, JSON.stringify(result));
|
|
99
|
+
} catch (error) {
|
|
100
|
+
if (error instanceof DOMException && 'QuotaExceededError' === error.name) {
|
|
101
|
+
console.warn('LocalStorage quota exceeded when saving result, clearing old results...');
|
|
102
|
+
await this.handleQuotaExceeded();
|
|
103
|
+
try {
|
|
104
|
+
const resultKey = `${this.resultsKey}-${id}`;
|
|
105
|
+
localStorage.setItem(resultKey, JSON.stringify(result));
|
|
106
|
+
} catch (retryError) {
|
|
107
|
+
console.error('Failed to save result even after clearing storage:', retryError);
|
|
108
|
+
}
|
|
109
|
+
} else console.error('Failed to save result to localStorage:', error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async handleQuotaExceeded() {
|
|
113
|
+
try {
|
|
114
|
+
const keys = Object.keys(localStorage);
|
|
115
|
+
const resultKeys = keys.filter((key)=>key.startsWith(this.resultsKey));
|
|
116
|
+
const keysToRemove = resultKeys.slice(0, Math.max(1, Math.floor(resultKeys.length / 2)));
|
|
117
|
+
keysToRemove.forEach((key)=>{
|
|
118
|
+
localStorage.removeItem(key);
|
|
119
|
+
});
|
|
120
|
+
console.info(`Cleared ${keysToRemove.length} old result entries to free up storage space`);
|
|
121
|
+
const playgroundKeys = keys.filter((key)=>key.includes('playground') || key.includes('agent') || key.startsWith('midscene'));
|
|
122
|
+
if (playgroundKeys.length > 10) {
|
|
123
|
+
const additionalKeysToRemove = playgroundKeys.slice(0, Math.floor(playgroundKeys.length / 3));
|
|
124
|
+
additionalKeysToRemove.forEach((key)=>{
|
|
125
|
+
if (key !== this.messagesKey) localStorage.removeItem(key);
|
|
126
|
+
});
|
|
127
|
+
console.info(`Cleared ${additionalKeysToRemove.length} additional playground-related entries`);
|
|
128
|
+
}
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error('Failed to handle quota exceeded:', error);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
constructor(namespace = 'playground'){
|
|
134
|
+
_define_property(this, "messagesKey", void 0);
|
|
135
|
+
_define_property(this, "resultsKey", void 0);
|
|
136
|
+
_define_property(this, "maxStorageItems", 50);
|
|
137
|
+
this.messagesKey = `${namespace}-messages`;
|
|
138
|
+
this.resultsKey = `${namespace}-results`;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
class storage_provider_MemoryStorageProvider {
|
|
142
|
+
async saveMessages(messages) {
|
|
143
|
+
this.messages = [
|
|
144
|
+
...messages
|
|
145
|
+
];
|
|
146
|
+
}
|
|
147
|
+
async loadMessages() {
|
|
148
|
+
return [
|
|
149
|
+
...this.messages
|
|
150
|
+
];
|
|
151
|
+
}
|
|
152
|
+
async clearMessages() {
|
|
153
|
+
this.messages = [];
|
|
154
|
+
this.results.clear();
|
|
155
|
+
}
|
|
156
|
+
async saveResult(id, result) {
|
|
157
|
+
this.results.set(id, result);
|
|
158
|
+
}
|
|
159
|
+
constructor(){
|
|
160
|
+
_define_property(this, "messages", []);
|
|
161
|
+
_define_property(this, "results", new Map());
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
class storage_provider_NoOpStorageProvider {
|
|
165
|
+
async saveMessages(_messages) {}
|
|
166
|
+
async loadMessages() {
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
169
|
+
async clearMessages() {}
|
|
170
|
+
async saveResult(_id, _result) {}
|
|
171
|
+
}
|
|
172
|
+
var storage_provider_StorageType = /*#__PURE__*/ function(StorageType) {
|
|
173
|
+
StorageType["INDEXEDDB"] = "indexeddb";
|
|
174
|
+
StorageType["LOCALSTORAGE"] = "localStorage";
|
|
175
|
+
StorageType["MEMORY"] = "memory";
|
|
176
|
+
StorageType["NONE"] = "none";
|
|
177
|
+
return StorageType;
|
|
178
|
+
}({});
|
|
179
|
+
function createStorageProvider() {
|
|
180
|
+
let type = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "indexeddb", namespace = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : 'playground';
|
|
181
|
+
switch(type){
|
|
182
|
+
case "indexeddb":
|
|
183
|
+
if ('undefined' != typeof indexedDB) return new IndexedDBStorageProvider(namespace);
|
|
184
|
+
console.warn('IndexedDB not available, falling back to localStorage');
|
|
185
|
+
return createStorageProvider("localStorage", namespace);
|
|
186
|
+
case "localStorage":
|
|
187
|
+
if ('undefined' != typeof localStorage) return new LocalStorageProvider(namespace);
|
|
188
|
+
console.warn('localStorage not available, falling back to memory storage');
|
|
189
|
+
return createStorageProvider("memory", namespace);
|
|
190
|
+
case "memory":
|
|
191
|
+
return new storage_provider_MemoryStorageProvider();
|
|
192
|
+
case "none":
|
|
193
|
+
return new storage_provider_NoOpStorageProvider();
|
|
194
|
+
default:
|
|
195
|
+
throw new Error(`Unknown storage type: ${type}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
function detectBestStorageType() {
|
|
199
|
+
if ('undefined' != typeof indexedDB) try {
|
|
200
|
+
indexedDB.open('test', 1).onerror = ()=>{};
|
|
201
|
+
return "indexeddb";
|
|
202
|
+
} catch (e) {}
|
|
203
|
+
if ('undefined' != typeof localStorage) try {
|
|
204
|
+
localStorage.setItem('test', 'test');
|
|
205
|
+
localStorage.removeItem('test');
|
|
206
|
+
return "localStorage";
|
|
207
|
+
} catch (e) {}
|
|
208
|
+
return "memory";
|
|
209
|
+
}
|
|
210
|
+
export { MemoryStorageProvider as IndexedDBMemoryStorageProvider, NoOpStorageProvider as IndexedDBNoOpStorageProvider, IndexedDBStorageProvider, LocalStorageProvider, storage_provider_MemoryStorageProvider as MemoryStorageProvider, storage_provider_NoOpStorageProvider as NoOpStorageProvider, storage_provider_StorageType as StorageType, createStorageProvider, detectBestStorageType };
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { useEnvConfig } from "../store/store.mjs";
|
|
3
|
+
import { noReplayAPIs } from "@sqaitech/playground";
|
|
4
|
+
import { BLANK_RESULT } from "../utils/constants.mjs";
|
|
5
|
+
import { allScriptsFromDump } from "../utils/replay-scripts.mjs";
|
|
6
|
+
function usePlaygroundExecution(playgroundSDK, storage, actionSpace, loading, setLoading, infoList, setInfoList, replayCounter, setReplayCounter, verticalMode, currentRunningIdRef, interruptedFlagRef) {
|
|
7
|
+
const { deepThink, screenshotIncluded, domIncluded } = useEnvConfig();
|
|
8
|
+
const handleRun = useCallback(async (value)=>{
|
|
9
|
+
if (!playgroundSDK) return void console.warn('PlaygroundSDK is not available');
|
|
10
|
+
const thisRunningId = Date.now();
|
|
11
|
+
const actionType = value.type;
|
|
12
|
+
const displayContent = `${value.type}: ${value.prompt || JSON.stringify(value.params)}`;
|
|
13
|
+
const userItem = {
|
|
14
|
+
id: `user-${Date.now()}`,
|
|
15
|
+
type: 'user',
|
|
16
|
+
content: displayContent,
|
|
17
|
+
timestamp: new Date()
|
|
18
|
+
};
|
|
19
|
+
setInfoList((prev)=>[
|
|
20
|
+
...prev,
|
|
21
|
+
userItem
|
|
22
|
+
]);
|
|
23
|
+
setLoading(true);
|
|
24
|
+
const result = {
|
|
25
|
+
...BLANK_RESULT
|
|
26
|
+
};
|
|
27
|
+
const systemItem = {
|
|
28
|
+
id: `system-${thisRunningId}`,
|
|
29
|
+
type: 'system',
|
|
30
|
+
content: '',
|
|
31
|
+
timestamp: new Date(),
|
|
32
|
+
loading: true,
|
|
33
|
+
loadingProgressText: ''
|
|
34
|
+
};
|
|
35
|
+
setInfoList((prev)=>[
|
|
36
|
+
...prev,
|
|
37
|
+
systemItem
|
|
38
|
+
]);
|
|
39
|
+
try {
|
|
40
|
+
currentRunningIdRef.current = thisRunningId;
|
|
41
|
+
interruptedFlagRef.current[thisRunningId] = false;
|
|
42
|
+
if (playgroundSDK.onProgressUpdate) playgroundSDK.onProgressUpdate(()=>{});
|
|
43
|
+
if (playgroundSDK.onProgressUpdate) playgroundSDK.onProgressUpdate((tip)=>{
|
|
44
|
+
if (interruptedFlagRef.current[thisRunningId]) return;
|
|
45
|
+
setInfoList((prev)=>{
|
|
46
|
+
const lastItem = prev[prev.length - 1];
|
|
47
|
+
if (lastItem && 'progress' === lastItem.type && lastItem.content === tip) return prev;
|
|
48
|
+
const progressItem = {
|
|
49
|
+
id: `progress-${thisRunningId}-${Date.now()}`,
|
|
50
|
+
type: 'progress',
|
|
51
|
+
content: tip,
|
|
52
|
+
timestamp: new Date()
|
|
53
|
+
};
|
|
54
|
+
return [
|
|
55
|
+
...prev,
|
|
56
|
+
progressItem
|
|
57
|
+
];
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
result.result = await playgroundSDK.executeAction(actionType, value, {
|
|
61
|
+
requestId: thisRunningId.toString(),
|
|
62
|
+
deepThink,
|
|
63
|
+
screenshotIncluded,
|
|
64
|
+
domIncluded
|
|
65
|
+
});
|
|
66
|
+
if ('object' == typeof result.result && null !== result.result) {
|
|
67
|
+
const resultObj = result.result;
|
|
68
|
+
if (resultObj.dump) result.dump = resultObj.dump;
|
|
69
|
+
if (resultObj.reportHTML) result.reportHTML = resultObj.reportHTML;
|
|
70
|
+
if (resultObj.error) result.error = resultObj.error;
|
|
71
|
+
if (void 0 !== resultObj.result) result.result = resultObj.result;
|
|
72
|
+
}
|
|
73
|
+
} catch (e) {
|
|
74
|
+
result.error = (null == e ? void 0 : e.message) || String(e);
|
|
75
|
+
console.error('Playground execution error:', e);
|
|
76
|
+
}
|
|
77
|
+
if (interruptedFlagRef.current[thisRunningId]) return;
|
|
78
|
+
setLoading(false);
|
|
79
|
+
currentRunningIdRef.current = null;
|
|
80
|
+
let replayInfo = null;
|
|
81
|
+
let counter = replayCounter;
|
|
82
|
+
if ((null == result ? void 0 : result.dump) && !noReplayAPIs.includes(actionType)) {
|
|
83
|
+
const info = allScriptsFromDump(result.dump);
|
|
84
|
+
setReplayCounter((c)=>c + 1);
|
|
85
|
+
replayInfo = info;
|
|
86
|
+
counter = replayCounter + 1;
|
|
87
|
+
}
|
|
88
|
+
setInfoList((prev)=>prev.map((item)=>item.id === `system-${thisRunningId}` ? {
|
|
89
|
+
...item,
|
|
90
|
+
content: '',
|
|
91
|
+
loading: false,
|
|
92
|
+
loadingProgressText: ''
|
|
93
|
+
} : item));
|
|
94
|
+
const resultItem = {
|
|
95
|
+
id: `result-${thisRunningId}`,
|
|
96
|
+
type: 'result',
|
|
97
|
+
content: 'Execution result',
|
|
98
|
+
timestamp: new Date(),
|
|
99
|
+
result: result,
|
|
100
|
+
loading: false,
|
|
101
|
+
replayScriptsInfo: replayInfo,
|
|
102
|
+
replayCounter: counter,
|
|
103
|
+
loadingProgressText: '',
|
|
104
|
+
verticalMode: verticalMode
|
|
105
|
+
};
|
|
106
|
+
setInfoList((prev)=>[
|
|
107
|
+
...prev,
|
|
108
|
+
resultItem
|
|
109
|
+
]);
|
|
110
|
+
if (null == storage ? void 0 : storage.saveResult) try {
|
|
111
|
+
await storage.saveResult(resultItem.id, resultItem);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
console.error('Failed to save result:', error);
|
|
114
|
+
}
|
|
115
|
+
const separatorItem = {
|
|
116
|
+
id: `separator-${thisRunningId}`,
|
|
117
|
+
type: 'separator',
|
|
118
|
+
content: 'New Session',
|
|
119
|
+
timestamp: new Date()
|
|
120
|
+
};
|
|
121
|
+
setInfoList((prev)=>[
|
|
122
|
+
...prev,
|
|
123
|
+
separatorItem
|
|
124
|
+
]);
|
|
125
|
+
}, [
|
|
126
|
+
playgroundSDK,
|
|
127
|
+
storage,
|
|
128
|
+
actionSpace,
|
|
129
|
+
setLoading,
|
|
130
|
+
setInfoList,
|
|
131
|
+
replayCounter,
|
|
132
|
+
setReplayCounter,
|
|
133
|
+
verticalMode,
|
|
134
|
+
currentRunningIdRef,
|
|
135
|
+
interruptedFlagRef,
|
|
136
|
+
deepThink,
|
|
137
|
+
screenshotIncluded,
|
|
138
|
+
domIncluded
|
|
139
|
+
]);
|
|
140
|
+
const handleStop = useCallback(async ()=>{
|
|
141
|
+
const thisRunningId = currentRunningIdRef.current;
|
|
142
|
+
if (thisRunningId && playgroundSDK && playgroundSDK.cancelExecution) try {
|
|
143
|
+
await playgroundSDK.cancelExecution(thisRunningId.toString());
|
|
144
|
+
interruptedFlagRef.current[thisRunningId] = true;
|
|
145
|
+
setLoading(false);
|
|
146
|
+
if (playgroundSDK.onProgressUpdate) playgroundSDK.onProgressUpdate(()=>{});
|
|
147
|
+
setInfoList((prev)=>prev.map((item)=>item.id === `system-${thisRunningId}` && item.loading ? {
|
|
148
|
+
...item,
|
|
149
|
+
content: 'Operation stopped',
|
|
150
|
+
loading: false,
|
|
151
|
+
loadingProgressText: ''
|
|
152
|
+
} : item));
|
|
153
|
+
const separatorItem = {
|
|
154
|
+
id: `separator-${thisRunningId}`,
|
|
155
|
+
type: 'separator',
|
|
156
|
+
content: 'New Session',
|
|
157
|
+
timestamp: new Date()
|
|
158
|
+
};
|
|
159
|
+
setInfoList((prev)=>[
|
|
160
|
+
...prev,
|
|
161
|
+
separatorItem
|
|
162
|
+
]);
|
|
163
|
+
} catch (error) {
|
|
164
|
+
console.error('Failed to stop execution:', error);
|
|
165
|
+
}
|
|
166
|
+
}, [
|
|
167
|
+
playgroundSDK,
|
|
168
|
+
currentRunningIdRef,
|
|
169
|
+
interruptedFlagRef,
|
|
170
|
+
setLoading,
|
|
171
|
+
setInfoList
|
|
172
|
+
]);
|
|
173
|
+
const canStop = loading && !!currentRunningIdRef.current && !!playgroundSDK && !!playgroundSDK.cancelExecution;
|
|
174
|
+
return {
|
|
175
|
+
handleRun,
|
|
176
|
+
handleStop,
|
|
177
|
+
canStop
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
export { usePlaygroundExecution };
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { createStorageProvider, detectBestStorageType } from "../component/universal-playground/providers/storage-provider.mjs";
|
|
3
|
+
import { WELCOME_MESSAGE_TEMPLATE } from "../utils/constants.mjs";
|
|
4
|
+
function usePlaygroundState(playgroundSDK, storage, contextProvider) {
|
|
5
|
+
const [loading, setLoading] = useState(false);
|
|
6
|
+
const [infoList, setInfoList] = useState([]);
|
|
7
|
+
const [actionSpace, setActionSpace] = useState([]);
|
|
8
|
+
const [actionSpaceLoading, setActionSpaceLoading] = useState(true);
|
|
9
|
+
const [uiContextPreview, setUiContextPreview] = useState();
|
|
10
|
+
const [showScrollToBottomButton, setShowScrollToBottomButton] = useState(false);
|
|
11
|
+
const [verticalMode, setVerticalMode] = useState(false);
|
|
12
|
+
const [replayCounter, setReplayCounter] = useState(0);
|
|
13
|
+
const infoListRef = useRef(null);
|
|
14
|
+
const currentRunningIdRef = useRef(null);
|
|
15
|
+
const interruptedFlagRef = useRef({});
|
|
16
|
+
const initializedRef = useRef(false);
|
|
17
|
+
useEffect(()=>{
|
|
18
|
+
const migrateFromOldNamespace = async ()=>{
|
|
19
|
+
const oldStorage = createStorageProvider(detectBestStorageType(), 'playground-default');
|
|
20
|
+
try {
|
|
21
|
+
if (null == oldStorage ? void 0 : oldStorage.loadMessages) {
|
|
22
|
+
const oldMessages = await oldStorage.loadMessages();
|
|
23
|
+
if (oldMessages.length > 1) {
|
|
24
|
+
console.log('Found data in old namespace, migrating...');
|
|
25
|
+
if (null == storage ? void 0 : storage.saveMessages) await storage.saveMessages(oldMessages);
|
|
26
|
+
if (oldStorage.clearMessages) await oldStorage.clearMessages();
|
|
27
|
+
return oldMessages;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.debug('No data found in old namespace:', error);
|
|
32
|
+
}
|
|
33
|
+
return [];
|
|
34
|
+
};
|
|
35
|
+
const initializeMessages = async ()=>{
|
|
36
|
+
const welcomeMessage = {
|
|
37
|
+
...WELCOME_MESSAGE_TEMPLATE,
|
|
38
|
+
id: 'welcome',
|
|
39
|
+
timestamp: new Date()
|
|
40
|
+
};
|
|
41
|
+
if (null == storage ? void 0 : storage.loadMessages) try {
|
|
42
|
+
let storedMessages = await storage.loadMessages();
|
|
43
|
+
if (0 === storedMessages.length) storedMessages = await migrateFromOldNamespace();
|
|
44
|
+
const hasWelcomeMessage = storedMessages.some((msg)=>'welcome' === msg.id);
|
|
45
|
+
hasWelcomeMessage ? setInfoList(storedMessages) : setInfoList([
|
|
46
|
+
welcomeMessage,
|
|
47
|
+
...storedMessages
|
|
48
|
+
]);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
console.error('Failed to load messages:', error);
|
|
51
|
+
setInfoList([
|
|
52
|
+
welcomeMessage
|
|
53
|
+
]);
|
|
54
|
+
}
|
|
55
|
+
else setInfoList([
|
|
56
|
+
welcomeMessage
|
|
57
|
+
]);
|
|
58
|
+
};
|
|
59
|
+
if (storage && !initializedRef.current) {
|
|
60
|
+
initializedRef.current = true;
|
|
61
|
+
initializeMessages();
|
|
62
|
+
} else if (!storage && 0 === infoList.length) initializeMessages();
|
|
63
|
+
}, [
|
|
64
|
+
storage
|
|
65
|
+
]);
|
|
66
|
+
useEffect(()=>{
|
|
67
|
+
if ((null == storage ? void 0 : storage.saveMessages) && infoList.length > 1) storage.saveMessages(infoList).catch((error)=>{
|
|
68
|
+
if (error instanceof DOMException && 'QuotaExceededError' === error.name) console.warn('Storage quota exceeded - some messages may not be saved persistently');
|
|
69
|
+
else console.error('Failed to save messages:', error);
|
|
70
|
+
});
|
|
71
|
+
}, [
|
|
72
|
+
infoList,
|
|
73
|
+
storage
|
|
74
|
+
]);
|
|
75
|
+
useEffect(()=>{
|
|
76
|
+
if (!(null == contextProvider ? void 0 : contextProvider.getUIContext) || uiContextPreview) return;
|
|
77
|
+
contextProvider.getUIContext().then((context)=>setUiContextPreview(context)).catch((error)=>{
|
|
78
|
+
console.error('Failed to get UI context:', error);
|
|
79
|
+
});
|
|
80
|
+
}, [
|
|
81
|
+
contextProvider,
|
|
82
|
+
uiContextPreview
|
|
83
|
+
]);
|
|
84
|
+
useEffect(()=>{
|
|
85
|
+
const loadActionSpace = async ()=>{
|
|
86
|
+
setActionSpaceLoading(true);
|
|
87
|
+
try {
|
|
88
|
+
var _contextProvider_getUIContext;
|
|
89
|
+
if (!playgroundSDK) return void setActionSpace([]);
|
|
90
|
+
const context = uiContextPreview || await (null == contextProvider ? void 0 : null == (_contextProvider_getUIContext = contextProvider.getUIContext) ? void 0 : _contextProvider_getUIContext.call(contextProvider));
|
|
91
|
+
const space = await playgroundSDK.getActionSpace(context);
|
|
92
|
+
setActionSpace(space || []);
|
|
93
|
+
} catch (error) {
|
|
94
|
+
console.error('Failed to load action space:', error);
|
|
95
|
+
setActionSpace([]);
|
|
96
|
+
} finally{
|
|
97
|
+
setActionSpaceLoading(false);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
loadActionSpace();
|
|
101
|
+
}, [
|
|
102
|
+
playgroundSDK,
|
|
103
|
+
uiContextPreview,
|
|
104
|
+
contextProvider
|
|
105
|
+
]);
|
|
106
|
+
useEffect(()=>{
|
|
107
|
+
const sizeThreshold = 750;
|
|
108
|
+
setVerticalMode(window.innerWidth < sizeThreshold);
|
|
109
|
+
const handleResize = ()=>{
|
|
110
|
+
setVerticalMode(window.innerWidth < sizeThreshold);
|
|
111
|
+
};
|
|
112
|
+
window.addEventListener('resize', handleResize);
|
|
113
|
+
return ()=>window.removeEventListener('resize', handleResize);
|
|
114
|
+
}, []);
|
|
115
|
+
const scrollToBottom = useCallback(()=>{
|
|
116
|
+
setTimeout(()=>{
|
|
117
|
+
if (infoListRef.current) infoListRef.current.scrollTop = infoListRef.current.scrollHeight;
|
|
118
|
+
}, 100);
|
|
119
|
+
}, []);
|
|
120
|
+
const checkIfScrolledToBottom = useCallback(()=>{
|
|
121
|
+
if (infoListRef.current) {
|
|
122
|
+
const { scrollTop, scrollHeight, clientHeight } = infoListRef.current;
|
|
123
|
+
const isAtBottom = scrollTop + clientHeight >= scrollHeight - 10;
|
|
124
|
+
setShowScrollToBottomButton(!isAtBottom);
|
|
125
|
+
}
|
|
126
|
+
}, []);
|
|
127
|
+
const handleScrollToBottom = useCallback(()=>{
|
|
128
|
+
if (infoListRef.current) {
|
|
129
|
+
infoListRef.current.scrollTo({
|
|
130
|
+
top: infoListRef.current.scrollHeight,
|
|
131
|
+
behavior: 'smooth'
|
|
132
|
+
});
|
|
133
|
+
setShowScrollToBottomButton(false);
|
|
134
|
+
}
|
|
135
|
+
}, []);
|
|
136
|
+
useEffect(()=>{
|
|
137
|
+
if (infoList.length > 0) scrollToBottom();
|
|
138
|
+
}, [
|
|
139
|
+
infoList,
|
|
140
|
+
scrollToBottom
|
|
141
|
+
]);
|
|
142
|
+
useEffect(()=>{
|
|
143
|
+
const container = infoListRef.current;
|
|
144
|
+
if (container) {
|
|
145
|
+
container.addEventListener('scroll', checkIfScrolledToBottom);
|
|
146
|
+
checkIfScrolledToBottom();
|
|
147
|
+
return ()=>{
|
|
148
|
+
container.removeEventListener('scroll', checkIfScrolledToBottom);
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}, [
|
|
152
|
+
checkIfScrolledToBottom
|
|
153
|
+
]);
|
|
154
|
+
const clearInfoList = useCallback(async ()=>{
|
|
155
|
+
const welcomeMessage = {
|
|
156
|
+
...WELCOME_MESSAGE_TEMPLATE,
|
|
157
|
+
id: 'welcome',
|
|
158
|
+
timestamp: new Date()
|
|
159
|
+
};
|
|
160
|
+
setInfoList([
|
|
161
|
+
welcomeMessage
|
|
162
|
+
]);
|
|
163
|
+
if (null == storage ? void 0 : storage.clearMessages) try {
|
|
164
|
+
await storage.clearMessages();
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.error('Failed to clear stored messages:', error);
|
|
167
|
+
}
|
|
168
|
+
}, [
|
|
169
|
+
storage
|
|
170
|
+
]);
|
|
171
|
+
const refreshContext = useCallback(async ()=>{
|
|
172
|
+
if (null == contextProvider ? void 0 : contextProvider.refreshContext) try {
|
|
173
|
+
const newContext = await contextProvider.refreshContext();
|
|
174
|
+
setUiContextPreview(newContext);
|
|
175
|
+
} catch (error) {
|
|
176
|
+
console.error('Failed to refresh context:', error);
|
|
177
|
+
}
|
|
178
|
+
}, [
|
|
179
|
+
contextProvider
|
|
180
|
+
]);
|
|
181
|
+
return {
|
|
182
|
+
loading,
|
|
183
|
+
setLoading,
|
|
184
|
+
infoList,
|
|
185
|
+
setInfoList,
|
|
186
|
+
actionSpace,
|
|
187
|
+
actionSpaceLoading,
|
|
188
|
+
uiContextPreview,
|
|
189
|
+
setUiContextPreview,
|
|
190
|
+
showScrollToBottomButton,
|
|
191
|
+
verticalMode,
|
|
192
|
+
replayCounter,
|
|
193
|
+
setReplayCounter,
|
|
194
|
+
infoListRef,
|
|
195
|
+
currentRunningIdRef,
|
|
196
|
+
interruptedFlagRef,
|
|
197
|
+
clearInfoList,
|
|
198
|
+
refreshContext,
|
|
199
|
+
handleScrollToBottom,
|
|
200
|
+
scrollToBottom
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
export { usePlaygroundState };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { overrideAIConfig } from "@sqaitech/shared/env";
|
|
2
|
+
import { message } from "antd";
|
|
3
|
+
function safeOverrideAIConfig(newConfig) {
|
|
4
|
+
let extendMode = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : false, showErrorMessage = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : true;
|
|
5
|
+
try {
|
|
6
|
+
overrideAIConfig(newConfig, extendMode);
|
|
7
|
+
return true;
|
|
8
|
+
} catch (error) {
|
|
9
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
10
|
+
console.error('Failed to override AI config:', err);
|
|
11
|
+
if (showErrorMessage) message.error(`Failed to apply AI configuration: ${err.message}`);
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function useSafeOverrideAIConfig() {
|
|
16
|
+
const applyConfig = function(newConfig) {
|
|
17
|
+
let extendMode = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : false, showErrorMessage = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : true;
|
|
18
|
+
return safeOverrideAIConfig(newConfig, extendMode, showErrorMessage);
|
|
19
|
+
};
|
|
20
|
+
return {
|
|
21
|
+
applyConfig
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export { safeOverrideAIConfig, useSafeOverrideAIConfig };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { PlaygroundSDK } from "@sqaitech/playground";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { useEnvConfig } from "../store/store.mjs";
|
|
4
|
+
const useServerValid = function() {
|
|
5
|
+
let shouldRun = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : true;
|
|
6
|
+
const [serverValid, setServerValid] = useState(true);
|
|
7
|
+
const { serviceMode } = useEnvConfig();
|
|
8
|
+
useEffect(()=>{
|
|
9
|
+
let interruptFlag = false;
|
|
10
|
+
if (!shouldRun) return;
|
|
11
|
+
Promise.resolve((async ()=>{
|
|
12
|
+
while(!interruptFlag){
|
|
13
|
+
const playgroundSDK = new PlaygroundSDK({
|
|
14
|
+
type: 'remote-execution'
|
|
15
|
+
});
|
|
16
|
+
const status = await playgroundSDK.checkStatus();
|
|
17
|
+
status ? setServerValid(true) : setServerValid(false);
|
|
18
|
+
await new Promise((resolve)=>setTimeout(resolve, 1000));
|
|
19
|
+
}
|
|
20
|
+
})());
|
|
21
|
+
return ()=>{
|
|
22
|
+
interruptFlag = true;
|
|
23
|
+
};
|
|
24
|
+
}, [
|
|
25
|
+
serviceMode,
|
|
26
|
+
shouldRun
|
|
27
|
+
]);
|
|
28
|
+
return serverValid;
|
|
29
|
+
};
|
|
30
|
+
export { useServerValid };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "react";
|
|
3
|
+
const SvgAvatar = (props)=>/*#__PURE__*/ jsxs("svg", {
|
|
4
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
5
|
+
width: 20,
|
|
6
|
+
height: 20,
|
|
7
|
+
fill: "none",
|
|
8
|
+
"aria-label": "Playground",
|
|
9
|
+
viewBox: "0 0 20 20",
|
|
10
|
+
...props,
|
|
11
|
+
children: [
|
|
12
|
+
/*#__PURE__*/ jsx("rect", {
|
|
13
|
+
width: 20,
|
|
14
|
+
height: 20,
|
|
15
|
+
fill: "#2B83FF",
|
|
16
|
+
rx: 10
|
|
17
|
+
}),
|
|
18
|
+
/*#__PURE__*/ jsx("path", {
|
|
19
|
+
fill: "#2B83FF",
|
|
20
|
+
stroke: "#fff",
|
|
21
|
+
strokeLinejoin: "round",
|
|
22
|
+
strokeWidth: 1.125,
|
|
23
|
+
d: "M6.866 5.882a.56.56 0 0 1 .667-.078l3.248 1.875 3.247 1.875a.563.563 0 0 1 0 .974l-3.247 1.875-3.248 1.875a.563.563 0 0 1-.784-.74l1.749-3.497-1.75-3.498a.56.56 0 0 1 .118-.661Z"
|
|
24
|
+
})
|
|
25
|
+
]
|
|
26
|
+
});
|
|
27
|
+
const avatar = SvgAvatar;
|
|
28
|
+
export { avatar as default };
|