Skip to content

Commit ce0eabd

Browse files
authored
fix playground server mode in report (#1188)
* feat(visualizer): add EnvConfigReminder component for environment variable setup reminder * feat(playground): update configuration options for server mode and persistence handling
1 parent 7ee1a79 commit ce0eabd

File tree

15 files changed

+81
-54
lines changed

15 files changed

+81
-54
lines changed

apps/chrome-extension/src/components/playground/index.tsx

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ export function BrowserExtensionPlayground({
9090
return sdk.executeAction(actionType, value, options || {});
9191
},
9292
getActionSpace: (context?: any) => {
93-
// Don't create SDK immediately for getActionSpace - return empty array until config is confirmed ready
94-
if (!runEnabled) {
95-
return Promise.resolve([]);
96-
}
93+
// Only try to get action space when config is ready
9794
try {
95+
if (!runEnabled) {
96+
return Promise.resolve([]);
97+
}
9898
const sdk = getOrCreateSDK();
9999
return sdk.getActionSpace(context);
100100
} catch (error) {
@@ -136,18 +136,30 @@ export function BrowserExtensionPlayground({
136136
// Return a lazy context provider that only creates agent when needed
137137
return {
138138
async getUIContext() {
139-
const agent = getAgent(forceSameTabNavigation);
140-
if (!agent) {
141-
throw new Error('Please configure AI settings first');
139+
try {
140+
const agent = getAgent(forceSameTabNavigation);
141+
if (!agent) {
142+
throw new Error('Please configure AI settings first');
143+
}
144+
return agent.page.screenshot();
145+
} catch (error) {
146+
console.warn('Failed to get UI context:', error);
147+
// Return null context instead of throwing to allow UI to initialize
148+
return null;
142149
}
143-
return agent.page.screenshot();
144150
},
145151
async refreshContext() {
146-
const agent = getAgent(forceSameTabNavigation);
147-
if (!agent) {
148-
throw new Error('Please configure AI settings first');
152+
try {
153+
const agent = getAgent(forceSameTabNavigation);
154+
if (!agent) {
155+
throw new Error('Please configure AI settings first');
156+
}
157+
return agent.page.screenshot();
158+
} catch (error) {
159+
console.warn('Failed to refresh context:', error);
160+
// Return null context instead of throwing to allow UI to initialize
161+
return null;
149162
}
150-
return agent.page.screenshot();
151163
},
152164
};
153165
}, [showContextPreview, getAgent, forceSameTabNavigation]);

apps/chrome-extension/src/extension/popup/index.tsx

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -117,26 +117,16 @@ export function PlaygroundPopup() {
117117
<div className="popup-content">
118118
{/* Playground Component */}
119119
<div className="playground-component">
120-
{configReady && aiConfigReady ? (
121-
<BrowserExtensionPlayground
122-
getAgent={(forceSameTabNavigation?: boolean) => {
123-
console.log(
124-
'getAgent called with forceSameTabNavigation:',
125-
forceSameTabNavigation,
126-
);
127-
return extensionAgentForTab(forceSameTabNavigation);
128-
}}
129-
showContextPreview={false}
130-
/>
131-
) : (
132-
<div style={{ padding: '20px', textAlign: 'center' }}>
133-
<p>
134-
{!configReady
135-
? 'Please configure your AI settings to use the playground.'
136-
: 'Initializing AI configuration...'}
137-
</p>
138-
</div>
139-
)}
120+
<BrowserExtensionPlayground
121+
getAgent={(forceSameTabNavigation?: boolean) => {
122+
console.log(
123+
'getAgent called with forceSameTabNavigation:',
124+
forceSameTabNavigation,
125+
);
126+
return extensionAgentForTab(forceSameTabNavigation);
127+
}}
128+
showContextPreview={false}
129+
/>
140130
</div>
141131
</div>
142132
);

apps/chrome-extension/src/extension/recorder/components/RecordList.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ import { Alert, Button, Empty, List, Popconfirm } from 'antd';
88
import type React from 'react';
99
import type { RecordingSession } from '../../../store';
1010
import './RecordList.less';
11-
import { useEnvConfig } from '@midscene/visualizer';
12-
import { EnvConfigReminder } from '../../../components/env-config-reminder';
11+
import { EnvConfigReminder, useEnvConfig } from '@midscene/visualizer';
1312

1413
interface RecordListProps {
1514
sessions: RecordingSession[];

apps/playground/src/App.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,11 @@ export default function App() {
109109
storage={storage}
110110
config={{
111111
showContextPreview: false,
112-
enablePersistence: true,
112+
enablePersistence: false,
113113
layout: 'vertical',
114114
showVersionInfo: true,
115115
enableScrollToBottom: true,
116+
serverMode: true,
116117
}}
117118
branding={{
118119
title: 'Playground',

packages/playground/src/adapters/remote-execution.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { DeviceAction } from '@midscene/core';
2-
import { PLAYGROUND_SERVER_PORT } from '@midscene/shared/constants';
32
import type { ExecutionOptions, FormValue, ValidationResult } from '../types';
43
import { BasePlaygroundAdapter } from './base';
54

@@ -8,7 +7,7 @@ export class RemoteExecutionAdapter extends BasePlaygroundAdapter {
87
private progressPolling = new Map<string, NodeJS.Timeout>();
98
private progressCallback?: (tip: string) => void;
109

11-
constructor(serverUrl = `http://localhost:${PLAYGROUND_SERVER_PORT}`) {
10+
constructor(serverUrl: string) {
1211
super();
1312
this.serverUrl = serverUrl;
1413
}

packages/playground/src/sdk/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,11 @@ export class PlaygroundSDK {
3434
}
3535
return new LocalExecutionAdapter(agent);
3636
case 'remote-execution': {
37-
// Use provided serverUrl first, then fallback to current page origin or default
37+
// Use provided serverUrl first, then fallback to localhost if current page origin is file:// or default
3838
const finalServerUrl =
3939
serverUrl ||
40-
(typeof window !== 'undefined'
40+
(typeof window !== 'undefined' &&
41+
window.location.protocol.includes('http')
4142
? window.location.origin
4243
: `http://localhost:${PLAYGROUND_SERVER_PORT}`);
4344

apps/chrome-extension/src/components/env-config-reminder/index.less renamed to packages/visualizer/src/component/env-config-reminder/index.less

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@
1818
color: #000;
1919
font-size: 14px;
2020
}
21-
}
21+
}

apps/chrome-extension/src/components/env-config-reminder/index.tsx renamed to packages/visualizer/src/component/env-config-reminder/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { ExclamationCircleFilled } from '@ant-design/icons';
2-
import { EnvConfig, useEnvConfig } from '@midscene/visualizer';
2+
import { useEnvConfig } from '../../store/store';
3+
import { EnvConfig } from '../env-config';
4+
35
import './index.less';
46

57
interface EnvConfigReminderProps {

packages/visualizer/src/component/service-mode-control/index.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { useServerValid } from '../../hooks/useServerValid';
77
import { useEnvConfig } from '../../store/store';
88
import { EnvConfig } from '../env-config';
99
import { iconForStatus } from '../misc';
10-
1110
interface ServiceModeControlProps {
1211
serviceMode: 'Server' | 'In-Browser';
1312
}

packages/visualizer/src/component/universal-playground/index.tsx

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { usePlaygroundState } from '../../hooks/usePlaygroundState';
1010
import { useEnvConfig } from '../../store/store';
1111
import type { FormValue, UniversalPlaygroundProps } from '../../types';
1212
import { ContextPreview } from '../context-preview';
13+
import { EnvConfigReminder } from '../env-config-reminder';
1314
import { PlaygroundResultView } from '../playground-result';
1415
import './index.less';
1516
import PlaygroundIcon from '../../icons/avatar.svg';
@@ -47,6 +48,9 @@ export function UniversalPlayground({
4748
const { deepThink, screenshotIncluded, domIncluded, config } = useEnvConfig();
4849

4950
// Use custom hooks for state management
51+
// Apply configuration
52+
const enablePersistence = componentConfig.enablePersistence !== false;
53+
5054
const {
5155
loading,
5256
setLoading,
@@ -64,9 +68,13 @@ export function UniversalPlayground({
6468
currentRunningIdRef,
6569
interruptedFlagRef,
6670
clearInfoList,
67-
refreshContext,
6871
handleScrollToBottom,
69-
} = usePlaygroundState(playgroundSDK, storage, contextProvider);
72+
} = usePlaygroundState(
73+
playgroundSDK,
74+
storage,
75+
contextProvider,
76+
enablePersistence,
77+
);
7078

7179
// Use execution hook
7280
const {
@@ -115,15 +123,17 @@ export function UniversalPlayground({
115123
}, [form, executeAction]);
116124

117125
// Check if run button should be enabled
118-
const runButtonEnabled = !dryMode && !actionSpaceLoading;
126+
const configAlreadySet = Object.keys(config || {}).length >= 1;
127+
const runButtonEnabled =
128+
componentConfig.serverMode ||
129+
(!dryMode && !actionSpaceLoading && configAlreadySet);
119130

120131
// Get the currently selected type
121132
const selectedType = Form.useWatch('type', form);
122133

123134
// Apply configuration
124135
const finalShowContextPreview =
125136
showContextPreview && componentConfig.showContextPreview !== false;
126-
const enablePersistence = componentConfig.enablePersistence !== false;
127137
const layout = componentConfig.layout || 'vertical';
128138
const showVersionInfo = componentConfig.showVersionInfo !== false;
129139

@@ -144,7 +154,7 @@ export function UniversalPlayground({
144154
{/* Main Dialog Area */}
145155
<div className="middle-dialog-area">
146156
{/* Clear Button */}
147-
{infoList.length > 1 && enablePersistence && (
157+
{infoList.length > 1 && (
148158
<div className="clear-button-container">
149159
<Button
150160
size="small"
@@ -304,6 +314,7 @@ export function UniversalPlayground({
304314

305315
{/* Bottom Input Section */}
306316
<div className="bottom-input-section">
317+
{!componentConfig.serverMode && <EnvConfigReminder />}
307318
<PromptInput
308319
runButtonEnabled={runButtonEnabled}
309320
form={form}

0 commit comments

Comments
 (0)