@midscene/playground-app 1.7.3 → 1.7.4
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/dist/es/PlaygroundApp.css +0 -128
- package/dist/es/PlaygroundApp.mjs +74 -464
- package/dist/es/PlaygroundThemeProvider.mjs +10 -0
- package/dist/es/PreviewRenderer.mjs +4 -1
- package/dist/es/ScrcpyPanel.mjs +97 -89
- package/dist/es/SessionSetupPanel.css +292 -0
- package/dist/es/SessionSetupPanel.mjs +60 -39
- package/dist/es/controller/ai-config.mjs +37 -0
- package/dist/es/controller/auto-create.mjs +19 -0
- package/dist/es/controller/selectors.mjs +66 -0
- package/dist/es/controller/types.mjs +0 -0
- package/dist/es/controller/usePlaygroundController.mjs +356 -0
- package/dist/es/icons/dropdown-chevron.mjs +61 -0
- package/dist/es/icons/midscene-logo.mjs +247 -0
- package/dist/es/index.mjs +4 -1
- package/dist/es/panels/PlaygroundConversationPanel.css +20 -0
- package/dist/es/panels/PlaygroundConversationPanel.mjs +134 -0
- package/dist/es/scrcpy-preview.mjs +30 -0
- package/dist/lib/PlaygroundApp.css +0 -128
- package/dist/lib/PlaygroundApp.js +70 -460
- package/dist/lib/PlaygroundThemeProvider.js +44 -0
- package/dist/lib/PreviewRenderer.js +4 -1
- package/dist/lib/ScrcpyPanel.js +96 -88
- package/dist/lib/SessionSetupPanel.css +292 -0
- package/dist/lib/SessionSetupPanel.js +70 -38
- package/dist/lib/controller/ai-config.js +74 -0
- package/dist/lib/controller/auto-create.js +59 -0
- package/dist/lib/controller/selectors.js +103 -0
- package/dist/lib/controller/types.js +18 -0
- package/dist/lib/controller/usePlaygroundController.js +390 -0
- package/dist/lib/icons/dropdown-chevron.js +95 -0
- package/dist/lib/icons/midscene-logo.js +281 -0
- package/dist/lib/index.js +14 -2
- package/dist/lib/panels/PlaygroundConversationPanel.css +20 -0
- package/dist/lib/panels/PlaygroundConversationPanel.js +168 -0
- package/dist/lib/scrcpy-preview.js +79 -0
- package/dist/types/PlaygroundPreview.d.ts +6 -0
- package/dist/types/PlaygroundThemeProvider.d.ts +2 -0
- package/dist/types/PreviewRenderer.d.ts +7 -1
- package/dist/types/ScrcpyPanel.d.ts +14 -1
- package/dist/types/SessionSetupPanel.d.ts +4 -3
- package/dist/types/controller/ai-config.d.ts +4 -0
- package/dist/types/controller/auto-create.d.ts +15 -0
- package/dist/types/controller/selectors.d.ts +5 -0
- package/dist/types/controller/types.d.ts +36 -0
- package/dist/types/controller/usePlaygroundController.d.ts +9 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/panels/PlaygroundConversationPanel.d.ts +20 -0
- package/dist/types/scrcpy-preview.d.ts +11 -0
- package/package.json +4 -3
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Alert,
|
|
3
|
-
|
|
2
|
+
import { Alert, Form, Input, InputNumber, Radio, Select } from "antd";
|
|
3
|
+
import dropdown_chevron from "./icons/dropdown-chevron.mjs";
|
|
4
|
+
import midscene_logo from "./icons/midscene-logo.mjs";
|
|
5
|
+
import "./SessionSetupPanel.css";
|
|
4
6
|
function getPlatformSelectorFieldKey(setup) {
|
|
5
7
|
var _setup_platformSelector;
|
|
6
8
|
return null == setup ? void 0 : null == (_setup_platformSelector = setup.platformSelector) ? void 0 : _setup_platformSelector.fieldKey;
|
|
@@ -18,6 +20,12 @@ function getPlatformSelectorOptions(field, setup) {
|
|
|
18
20
|
}));
|
|
19
21
|
return registryOptions.length > 0 ? registryOptions : field.options;
|
|
20
22
|
}
|
|
23
|
+
function DropdownSuffix() {
|
|
24
|
+
return /*#__PURE__*/ jsx(dropdown_chevron, {
|
|
25
|
+
"aria-hidden": "true",
|
|
26
|
+
className: "session-setup-select-icon"
|
|
27
|
+
});
|
|
28
|
+
}
|
|
21
29
|
function renderSessionField(field, sessionSetup) {
|
|
22
30
|
if ('number' === field.type) return /*#__PURE__*/ jsx(InputNumber, {
|
|
23
31
|
style: {
|
|
@@ -47,9 +55,11 @@ function renderSessionField(field, sessionSetup) {
|
|
|
47
55
|
]
|
|
48
56
|
}, String(option.value)))
|
|
49
57
|
});
|
|
58
|
+
var _ref;
|
|
50
59
|
return /*#__PURE__*/ jsx(Select, {
|
|
51
60
|
placeholder: field.placeholder,
|
|
52
|
-
|
|
61
|
+
suffixIcon: /*#__PURE__*/ jsx(DropdownSuffix, {}),
|
|
62
|
+
options: (null != (_ref = null != platformOptions ? platformOptions : field.options) ? _ref : []).map((option)=>({
|
|
53
63
|
label: option.label,
|
|
54
64
|
value: option.value,
|
|
55
65
|
description: option.description
|
|
@@ -77,63 +87,74 @@ function renderSessionField(field, sessionSetup) {
|
|
|
77
87
|
placeholder: field.placeholder
|
|
78
88
|
});
|
|
79
89
|
}
|
|
80
|
-
|
|
90
|
+
const DEFAULT_TITLE = 'Create Agent';
|
|
91
|
+
const DEFAULT_DESCRIPTION = 'Create a platform session before running actions.';
|
|
92
|
+
function SessionSetupPanel({ form, sessionSetup, sessionSetupError, sessionViewState, sessionLoading, sessionMutating, onCreateSession }) {
|
|
93
|
+
const submitDisabled = sessionMutating || sessionLoading || 'blocked' === sessionViewState.setupState;
|
|
94
|
+
var _sessionSetup_primaryActionLabel;
|
|
95
|
+
const primaryLabel = null != (_sessionSetup_primaryActionLabel = null == sessionSetup ? void 0 : sessionSetup.primaryActionLabel) ? _sessionSetup_primaryActionLabel : DEFAULT_TITLE;
|
|
96
|
+
var _sessionSetup_title;
|
|
97
|
+
const title = null != (_sessionSetup_title = null == sessionSetup ? void 0 : sessionSetup.title) ? _sessionSetup_title : DEFAULT_TITLE;
|
|
98
|
+
var _sessionSetup_description;
|
|
99
|
+
const description = null != (_sessionSetup_description = null == sessionSetup ? void 0 : sessionSetup.description) ? _sessionSetup_description : DEFAULT_DESCRIPTION;
|
|
100
|
+
var _sessionSetup_fields;
|
|
81
101
|
return /*#__PURE__*/ jsx("div", {
|
|
82
102
|
className: "session-setup-panel",
|
|
83
103
|
children: /*#__PURE__*/ jsxs("div", {
|
|
84
104
|
className: "session-setup-card",
|
|
85
105
|
children: [
|
|
86
|
-
/*#__PURE__*/ jsx(
|
|
87
|
-
|
|
88
|
-
|
|
106
|
+
/*#__PURE__*/ jsx(midscene_logo, {
|
|
107
|
+
"aria-hidden": "true",
|
|
108
|
+
className: "session-setup-logo"
|
|
109
|
+
}),
|
|
110
|
+
/*#__PURE__*/ jsx("h1", {
|
|
111
|
+
className: "session-setup-title",
|
|
112
|
+
children: title
|
|
89
113
|
}),
|
|
90
|
-
/*#__PURE__*/ jsx(
|
|
91
|
-
|
|
92
|
-
children:
|
|
114
|
+
/*#__PURE__*/ jsx("p", {
|
|
115
|
+
className: "session-setup-description",
|
|
116
|
+
children: description
|
|
93
117
|
}),
|
|
94
118
|
'blocked' === sessionViewState.setupState && sessionViewState.setupBlockingReason && /*#__PURE__*/ jsx(Alert, {
|
|
95
119
|
type: "error",
|
|
96
120
|
showIcon: true,
|
|
97
121
|
message: "Setup blocked",
|
|
98
|
-
description: sessionViewState.setupBlockingReason
|
|
122
|
+
description: sessionViewState.setupBlockingReason,
|
|
123
|
+
className: "session-setup-alert"
|
|
99
124
|
}),
|
|
100
125
|
sessionSetupError ? /*#__PURE__*/ jsx(Alert, {
|
|
101
126
|
type: "error",
|
|
102
127
|
showIcon: true,
|
|
103
128
|
message: "Failed to load setup",
|
|
104
|
-
description: sessionSetupError
|
|
129
|
+
description: sessionSetupError,
|
|
130
|
+
className: "session-setup-alert"
|
|
105
131
|
}) : null,
|
|
106
|
-
/*#__PURE__*/
|
|
132
|
+
/*#__PURE__*/ jsxs(Form, {
|
|
107
133
|
form: form,
|
|
108
134
|
layout: "vertical",
|
|
109
135
|
className: "session-setup-form",
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
rules: field.required ? [
|
|
115
|
-
{
|
|
116
|
-
required: true,
|
|
117
|
-
message: `${field.label} is required`
|
|
118
|
-
}
|
|
119
|
-
] : void 0,
|
|
120
|
-
children: renderSessionField(field, sessionSetup)
|
|
121
|
-
}, field.key))
|
|
122
|
-
}),
|
|
123
|
-
/*#__PURE__*/ jsxs(Space, {
|
|
124
|
-
size: 12,
|
|
136
|
+
onFinish: ()=>{
|
|
137
|
+
if (submitDisabled) return;
|
|
138
|
+
onCreateSession();
|
|
139
|
+
},
|
|
125
140
|
children: [
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
141
|
+
(null != (_sessionSetup_fields = null == sessionSetup ? void 0 : sessionSetup.fields) ? _sessionSetup_fields : []).map((field)=>/*#__PURE__*/ jsx(Form.Item, {
|
|
142
|
+
label: field.label,
|
|
143
|
+
name: field.key,
|
|
144
|
+
tooltip: field.description,
|
|
145
|
+
rules: field.required ? [
|
|
146
|
+
{
|
|
147
|
+
required: true,
|
|
148
|
+
message: `${field.label} is required`
|
|
149
|
+
}
|
|
150
|
+
] : void 0,
|
|
151
|
+
children: renderSessionField(field, sessionSetup)
|
|
152
|
+
}, field.key)),
|
|
153
|
+
/*#__PURE__*/ jsx("button", {
|
|
154
|
+
type: "submit",
|
|
155
|
+
className: "session-setup-submit",
|
|
156
|
+
disabled: submitDisabled,
|
|
157
|
+
children: sessionMutating ? 'Creating...' : primaryLabel
|
|
137
158
|
})
|
|
138
159
|
]
|
|
139
160
|
})
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
2
|
+
try {
|
|
3
|
+
var info = gen[key](arg);
|
|
4
|
+
var value = info.value;
|
|
5
|
+
} catch (error) {
|
|
6
|
+
reject(error);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
if (info.done) resolve(value);
|
|
10
|
+
else Promise.resolve(value).then(_next, _throw);
|
|
11
|
+
}
|
|
12
|
+
function _async_to_generator(fn) {
|
|
13
|
+
return function() {
|
|
14
|
+
var self = this, args = arguments;
|
|
15
|
+
return new Promise(function(resolve, reject) {
|
|
16
|
+
var gen = fn.apply(self, args);
|
|
17
|
+
function _next(value) {
|
|
18
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
19
|
+
}
|
|
20
|
+
function _throw(err) {
|
|
21
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
22
|
+
}
|
|
23
|
+
_next(void 0);
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function hasPlaygroundAiConfig(config) {
|
|
28
|
+
return Object.keys(config).length > 0;
|
|
29
|
+
}
|
|
30
|
+
function applyPlaygroundAiConfig(playgroundSDK, config) {
|
|
31
|
+
return _async_to_generator(function*() {
|
|
32
|
+
if (!hasPlaygroundAiConfig(config)) return false;
|
|
33
|
+
yield playgroundSDK.overrideConfig(config);
|
|
34
|
+
return true;
|
|
35
|
+
})();
|
|
36
|
+
}
|
|
37
|
+
export { applyPlaygroundAiConfig, hasPlaygroundAiConfig };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
function serializeAutoCreateInput(autoCreateInput) {
|
|
2
|
+
if (!autoCreateInput) return null;
|
|
3
|
+
return JSON.stringify(autoCreateInput);
|
|
4
|
+
}
|
|
5
|
+
function resolveAutoCreateDecision({ autoCreateInput, lastAttemptedSignature, blockedSignature }) {
|
|
6
|
+
const signature = serializeAutoCreateInput(autoCreateInput);
|
|
7
|
+
if (!signature) return {
|
|
8
|
+
signature: null,
|
|
9
|
+
shouldCreate: false
|
|
10
|
+
};
|
|
11
|
+
return {
|
|
12
|
+
signature,
|
|
13
|
+
shouldCreate: signature !== lastAttemptedSignature && signature !== blockedSignature
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function shouldResetAutoCreateBlock(options) {
|
|
17
|
+
return !(null == options ? void 0 : options.silent);
|
|
18
|
+
}
|
|
19
|
+
export { resolveAutoCreateDecision, serializeAutoCreateInput, shouldResetAutoCreateBlock };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
3
|
+
value: value,
|
|
4
|
+
enumerable: true,
|
|
5
|
+
configurable: true,
|
|
6
|
+
writable: true
|
|
7
|
+
});
|
|
8
|
+
else obj[key] = value;
|
|
9
|
+
return obj;
|
|
10
|
+
}
|
|
11
|
+
function _object_spread(target) {
|
|
12
|
+
for(var i = 1; i < arguments.length; i++){
|
|
13
|
+
var source = null != arguments[i] ? arguments[i] : {};
|
|
14
|
+
var ownKeys = Object.keys(source);
|
|
15
|
+
if ("function" == typeof Object.getOwnPropertySymbols) ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
16
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
17
|
+
}));
|
|
18
|
+
ownKeys.forEach(function(key) {
|
|
19
|
+
_define_property(target, key, source[key]);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return target;
|
|
23
|
+
}
|
|
24
|
+
function selectors_ownKeys(object, enumerableOnly) {
|
|
25
|
+
var keys = Object.keys(object);
|
|
26
|
+
if (Object.getOwnPropertySymbols) {
|
|
27
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
28
|
+
if (enumerableOnly) symbols = symbols.filter(function(sym) {
|
|
29
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
30
|
+
});
|
|
31
|
+
keys.push.apply(keys, symbols);
|
|
32
|
+
}
|
|
33
|
+
return keys;
|
|
34
|
+
}
|
|
35
|
+
function _object_spread_props(target, source) {
|
|
36
|
+
source = null != source ? source : {};
|
|
37
|
+
if (Object.getOwnPropertyDescriptors) Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
38
|
+
else selectors_ownKeys(Object(source)).forEach(function(key) {
|
|
39
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
40
|
+
});
|
|
41
|
+
return target;
|
|
42
|
+
}
|
|
43
|
+
function buildConversationConfig(state, playgroundConfig) {
|
|
44
|
+
return _object_spread({
|
|
45
|
+
showContextPreview: false,
|
|
46
|
+
layout: 'vertical',
|
|
47
|
+
showVersionInfo: true,
|
|
48
|
+
enableScrollToBottom: true,
|
|
49
|
+
serverMode: true,
|
|
50
|
+
showEnvConfigReminder: true,
|
|
51
|
+
deviceType: state.deviceType,
|
|
52
|
+
executionUx: {
|
|
53
|
+
hints: state.executionUxHints,
|
|
54
|
+
countdownSeconds: state.countdownSeconds
|
|
55
|
+
}
|
|
56
|
+
}, playgroundConfig);
|
|
57
|
+
}
|
|
58
|
+
function buildConversationBranding(runtimeInfo, title, appVersion, deviceType, branding) {
|
|
59
|
+
var _runtimeInfo_title, _runtimeInfo_platformId, _ref, _ref1;
|
|
60
|
+
return _object_spread_props(_object_spread({}, branding), {
|
|
61
|
+
title: null != (_runtimeInfo_title = null == runtimeInfo ? void 0 : runtimeInfo.title) ? _runtimeInfo_title : title,
|
|
62
|
+
version: appVersion,
|
|
63
|
+
targetName: null != (_ref1 = null != (_ref = null != (_runtimeInfo_platformId = null == runtimeInfo ? void 0 : runtimeInfo.platformId) ? _runtimeInfo_platformId : null == branding ? void 0 : branding.targetName) ? _ref : deviceType) ? _ref1 : 'screen'
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
export { buildConversationBranding, buildConversationConfig };
|
|
File without changes
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import { PlaygroundSDK } from "@midscene/playground";
|
|
2
|
+
import { useEnvConfig } from "@midscene/visualizer";
|
|
3
|
+
import { Form, message } from "antd";
|
|
4
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { resolveAutoCreateSessionInput } from "../session-setup.mjs";
|
|
6
|
+
import { buildSessionInitialValues, resolveSessionViewState } from "../session-state.mjs";
|
|
7
|
+
import { useServerStatus } from "../useServerStatus.mjs";
|
|
8
|
+
import { applyPlaygroundAiConfig, hasPlaygroundAiConfig } from "./ai-config.mjs";
|
|
9
|
+
import { resolveAutoCreateDecision, serializeAutoCreateInput, shouldResetAutoCreateBlock } from "./auto-create.mjs";
|
|
10
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
11
|
+
try {
|
|
12
|
+
var info = gen[key](arg);
|
|
13
|
+
var value = info.value;
|
|
14
|
+
} catch (error) {
|
|
15
|
+
reject(error);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (info.done) resolve(value);
|
|
19
|
+
else Promise.resolve(value).then(_next, _throw);
|
|
20
|
+
}
|
|
21
|
+
function _async_to_generator(fn) {
|
|
22
|
+
return function() {
|
|
23
|
+
var self = this, args = arguments;
|
|
24
|
+
return new Promise(function(resolve, reject) {
|
|
25
|
+
var gen = fn.apply(self, args);
|
|
26
|
+
function _next(value) {
|
|
27
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
28
|
+
}
|
|
29
|
+
function _throw(err) {
|
|
30
|
+
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
31
|
+
}
|
|
32
|
+
_next(void 0);
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function _define_property(obj, key, value) {
|
|
37
|
+
if (key in obj) Object.defineProperty(obj, key, {
|
|
38
|
+
value: value,
|
|
39
|
+
enumerable: true,
|
|
40
|
+
configurable: true,
|
|
41
|
+
writable: true
|
|
42
|
+
});
|
|
43
|
+
else obj[key] = value;
|
|
44
|
+
return obj;
|
|
45
|
+
}
|
|
46
|
+
function _object_spread(target) {
|
|
47
|
+
for(var i = 1; i < arguments.length; i++){
|
|
48
|
+
var source = null != arguments[i] ? arguments[i] : {};
|
|
49
|
+
var ownKeys = Object.keys(source);
|
|
50
|
+
if ("function" == typeof Object.getOwnPropertySymbols) ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
51
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
52
|
+
}));
|
|
53
|
+
ownKeys.forEach(function(key) {
|
|
54
|
+
_define_property(target, key, source[key]);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return target;
|
|
58
|
+
}
|
|
59
|
+
function usePlaygroundController_ownKeys(object, enumerableOnly) {
|
|
60
|
+
var keys = Object.keys(object);
|
|
61
|
+
if (Object.getOwnPropertySymbols) {
|
|
62
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
63
|
+
if (enumerableOnly) symbols = symbols.filter(function(sym) {
|
|
64
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
65
|
+
});
|
|
66
|
+
keys.push.apply(keys, symbols);
|
|
67
|
+
}
|
|
68
|
+
return keys;
|
|
69
|
+
}
|
|
70
|
+
function _object_spread_props(target, source) {
|
|
71
|
+
source = null != source ? source : {};
|
|
72
|
+
if (Object.getOwnPropertyDescriptors) Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
73
|
+
else usePlaygroundController_ownKeys(Object(source)).forEach(function(key) {
|
|
74
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
75
|
+
});
|
|
76
|
+
return target;
|
|
77
|
+
}
|
|
78
|
+
function getPlatformSelectorFieldKey(setup) {
|
|
79
|
+
var _setup_platformSelector;
|
|
80
|
+
return null == setup ? void 0 : null == (_setup_platformSelector = setup.platformSelector) ? void 0 : _setup_platformSelector.fieldKey;
|
|
81
|
+
}
|
|
82
|
+
function usePlaygroundController({ serverUrl, defaultDeviceType = 'web', pollIntervalMs = 5000, countdownSeconds = 3 }) {
|
|
83
|
+
const [form] = Form.useForm();
|
|
84
|
+
var _Form_useWatch;
|
|
85
|
+
const formValues = null != (_Form_useWatch = Form.useWatch([], form)) ? _Form_useWatch : {};
|
|
86
|
+
const [countdown, setCountdown] = useState(null);
|
|
87
|
+
const [sessionSetup, setSessionSetup] = useState(null);
|
|
88
|
+
const [sessionSetupError, setSessionSetupError] = useState(null);
|
|
89
|
+
const [sessionLoading, setSessionLoading] = useState(false);
|
|
90
|
+
const [sessionMutating, setSessionMutating] = useState(false);
|
|
91
|
+
const aiConfig = useEnvConfig((state)=>state.config);
|
|
92
|
+
const platformSelectorFieldKey = getPlatformSelectorFieldKey(sessionSetup);
|
|
93
|
+
const selectedPlatformId = 'string' == typeof platformSelectorFieldKey ? formValues[platformSelectorFieldKey] : void 0;
|
|
94
|
+
const playgroundSDK = useMemo(()=>new PlaygroundSDK({
|
|
95
|
+
type: 'remote-execution',
|
|
96
|
+
serverUrl
|
|
97
|
+
}), [
|
|
98
|
+
serverUrl
|
|
99
|
+
]);
|
|
100
|
+
const { serverOnline, isUserOperating, deviceType, runtimeInfo, executionUxHints, refreshServerState } = useServerStatus(playgroundSDK, defaultDeviceType, pollIntervalMs);
|
|
101
|
+
const sessionViewState = useMemo(()=>resolveSessionViewState(runtimeInfo), [
|
|
102
|
+
runtimeInfo
|
|
103
|
+
]);
|
|
104
|
+
const applyAiConfig = useCallback(()=>_async_to_generator(function*() {
|
|
105
|
+
if (!hasPlaygroundAiConfig(aiConfig)) return true;
|
|
106
|
+
try {
|
|
107
|
+
yield applyPlaygroundAiConfig(playgroundSDK, aiConfig);
|
|
108
|
+
return true;
|
|
109
|
+
} catch (error) {
|
|
110
|
+
const errorMessage = error instanceof Error ? error.message : 'Failed to apply AI configuration';
|
|
111
|
+
message.error(errorMessage);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
})(), [
|
|
115
|
+
aiConfig,
|
|
116
|
+
playgroundSDK
|
|
117
|
+
]);
|
|
118
|
+
const countdownTimerRef = useRef(null);
|
|
119
|
+
const countdownResolveRef = useRef(null);
|
|
120
|
+
const mountedRef = useRef(true);
|
|
121
|
+
const lastSetupPlatformIdRef = useRef(void 0);
|
|
122
|
+
const autoCreateSignatureRef = useRef(null);
|
|
123
|
+
const autoCreateBlockedSignatureRef = useRef(null);
|
|
124
|
+
const finishCountdown = useCallback(()=>{
|
|
125
|
+
if (null !== countdownTimerRef.current) {
|
|
126
|
+
window.clearInterval(countdownTimerRef.current);
|
|
127
|
+
countdownTimerRef.current = null;
|
|
128
|
+
}
|
|
129
|
+
const resolve = countdownResolveRef.current;
|
|
130
|
+
countdownResolveRef.current = null;
|
|
131
|
+
if (mountedRef.current) setCountdown(null);
|
|
132
|
+
null == resolve || resolve();
|
|
133
|
+
}, []);
|
|
134
|
+
const showCountdownModal = useCallback(()=>_async_to_generator(function*() {
|
|
135
|
+
if (countdownSeconds <= 0) return;
|
|
136
|
+
finishCountdown();
|
|
137
|
+
return new Promise((resolve)=>{
|
|
138
|
+
countdownResolveRef.current = resolve;
|
|
139
|
+
let count = countdownSeconds;
|
|
140
|
+
if (mountedRef.current) setCountdown(count);
|
|
141
|
+
countdownTimerRef.current = window.setInterval(()=>{
|
|
142
|
+
count -= 1;
|
|
143
|
+
if (count > 0) {
|
|
144
|
+
if (mountedRef.current) setCountdown(count);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (0 === count) {
|
|
148
|
+
if (mountedRef.current) setCountdown('GO!');
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
finishCountdown();
|
|
152
|
+
}, 1000);
|
|
153
|
+
});
|
|
154
|
+
})(), [
|
|
155
|
+
countdownSeconds,
|
|
156
|
+
finishCountdown
|
|
157
|
+
]);
|
|
158
|
+
useEffect(()=>{
|
|
159
|
+
mountedRef.current = true;
|
|
160
|
+
return ()=>{
|
|
161
|
+
mountedRef.current = false;
|
|
162
|
+
finishCountdown();
|
|
163
|
+
};
|
|
164
|
+
}, [
|
|
165
|
+
finishCountdown
|
|
166
|
+
]);
|
|
167
|
+
useEffect(()=>{
|
|
168
|
+
if (!executionUxHints.includes('countdown-before-run')) return void playgroundSDK.setBeforeActionHook(void 0);
|
|
169
|
+
playgroundSDK.setBeforeActionHook(()=>_async_to_generator(function*() {
|
|
170
|
+
yield showCountdownModal();
|
|
171
|
+
})());
|
|
172
|
+
return ()=>{
|
|
173
|
+
playgroundSDK.setBeforeActionHook(void 0);
|
|
174
|
+
};
|
|
175
|
+
}, [
|
|
176
|
+
executionUxHints,
|
|
177
|
+
playgroundSDK,
|
|
178
|
+
showCountdownModal
|
|
179
|
+
]);
|
|
180
|
+
const refreshSessionSetup = useCallback((input)=>_async_to_generator(function*() {
|
|
181
|
+
const currentValues = _object_spread({}, form.getFieldsValue(true), input || {});
|
|
182
|
+
setSessionLoading(true);
|
|
183
|
+
try {
|
|
184
|
+
const setup = yield playgroundSDK.getSessionSetup(input);
|
|
185
|
+
setSessionSetup(setup);
|
|
186
|
+
setSessionSetupError(null);
|
|
187
|
+
const currentPlatformSelectorFieldKey = getPlatformSelectorFieldKey(setup);
|
|
188
|
+
lastSetupPlatformIdRef.current = currentPlatformSelectorFieldKey && 'string' == typeof currentValues[currentPlatformSelectorFieldKey] ? currentValues[currentPlatformSelectorFieldKey] : void 0;
|
|
189
|
+
form.setFieldsValue(buildSessionInitialValues(setup, currentValues));
|
|
190
|
+
} catch (error) {
|
|
191
|
+
console.error('Failed to load session setup:', error);
|
|
192
|
+
setSessionSetupError(error instanceof Error ? error.message : 'Failed to load session setup');
|
|
193
|
+
} finally{
|
|
194
|
+
setSessionLoading(false);
|
|
195
|
+
}
|
|
196
|
+
})(), [
|
|
197
|
+
form,
|
|
198
|
+
playgroundSDK
|
|
199
|
+
]);
|
|
200
|
+
const createSession = useCallback((input, options)=>_async_to_generator(function*() {
|
|
201
|
+
try {
|
|
202
|
+
if (!(yield applyAiConfig())) return false;
|
|
203
|
+
const values = null != input ? input : yield form.validateFields();
|
|
204
|
+
setSessionMutating(true);
|
|
205
|
+
yield playgroundSDK.createSession(values);
|
|
206
|
+
if (shouldResetAutoCreateBlock(options)) autoCreateBlockedSignatureRef.current = null;
|
|
207
|
+
if (!(null == options ? void 0 : options.silent)) message.success('Agent created');
|
|
208
|
+
yield refreshServerState();
|
|
209
|
+
return true;
|
|
210
|
+
} catch (error) {
|
|
211
|
+
if (error.errorFields) return false;
|
|
212
|
+
const errorMessage = error instanceof Error ? error.message : 'Failed to create Agent';
|
|
213
|
+
message.error(errorMessage);
|
|
214
|
+
return false;
|
|
215
|
+
} finally{
|
|
216
|
+
setSessionMutating(false);
|
|
217
|
+
}
|
|
218
|
+
})(), [
|
|
219
|
+
applyAiConfig,
|
|
220
|
+
form,
|
|
221
|
+
playgroundSDK,
|
|
222
|
+
refreshServerState
|
|
223
|
+
]);
|
|
224
|
+
const destroySession = useCallback(()=>_async_to_generator(function*() {
|
|
225
|
+
try {
|
|
226
|
+
autoCreateBlockedSignatureRef.current = serializeAutoCreateInput(resolveAutoCreateSessionInput(sessionSetup, form.getFieldsValue(true)));
|
|
227
|
+
setSessionMutating(true);
|
|
228
|
+
yield playgroundSDK.destroySession();
|
|
229
|
+
message.success('Session disconnected');
|
|
230
|
+
yield refreshServerState();
|
|
231
|
+
yield refreshSessionSetup();
|
|
232
|
+
} catch (error) {
|
|
233
|
+
const errorMessage = error instanceof Error ? error.message : 'Failed to disconnect session';
|
|
234
|
+
message.error(errorMessage);
|
|
235
|
+
} finally{
|
|
236
|
+
setSessionMutating(false);
|
|
237
|
+
}
|
|
238
|
+
})(), [
|
|
239
|
+
form,
|
|
240
|
+
playgroundSDK,
|
|
241
|
+
refreshServerState,
|
|
242
|
+
refreshSessionSetup,
|
|
243
|
+
sessionSetup
|
|
244
|
+
]);
|
|
245
|
+
useEffect(()=>{
|
|
246
|
+
if (!serverOnline) return;
|
|
247
|
+
applyAiConfig();
|
|
248
|
+
}, [
|
|
249
|
+
applyAiConfig,
|
|
250
|
+
serverOnline
|
|
251
|
+
]);
|
|
252
|
+
useEffect(()=>{
|
|
253
|
+
if (!serverOnline || sessionViewState.connected) return;
|
|
254
|
+
let disposed = false;
|
|
255
|
+
let refreshing = false;
|
|
256
|
+
const refreshTargets = ()=>_async_to_generator(function*() {
|
|
257
|
+
if (disposed || refreshing) return;
|
|
258
|
+
refreshing = true;
|
|
259
|
+
try {
|
|
260
|
+
yield refreshSessionSetup(form.getFieldsValue(true));
|
|
261
|
+
} finally{
|
|
262
|
+
refreshing = false;
|
|
263
|
+
}
|
|
264
|
+
})();
|
|
265
|
+
refreshTargets();
|
|
266
|
+
const intervalId = window.setInterval(()=>{
|
|
267
|
+
refreshTargets();
|
|
268
|
+
}, pollIntervalMs);
|
|
269
|
+
return ()=>{
|
|
270
|
+
disposed = true;
|
|
271
|
+
window.clearInterval(intervalId);
|
|
272
|
+
};
|
|
273
|
+
}, [
|
|
274
|
+
form,
|
|
275
|
+
pollIntervalMs,
|
|
276
|
+
refreshSessionSetup,
|
|
277
|
+
serverOnline,
|
|
278
|
+
sessionViewState.connected
|
|
279
|
+
]);
|
|
280
|
+
useEffect(()=>{
|
|
281
|
+
if (!serverOnline || sessionViewState.connected || !selectedPlatformId) return;
|
|
282
|
+
const currentPlatformSelectorFieldKey = getPlatformSelectorFieldKey(sessionSetup);
|
|
283
|
+
if (!currentPlatformSelectorFieldKey) return;
|
|
284
|
+
if (lastSetupPlatformIdRef.current === selectedPlatformId) return;
|
|
285
|
+
refreshSessionSetup(_object_spread_props(_object_spread({}, form.getFieldsValue(true)), {
|
|
286
|
+
[currentPlatformSelectorFieldKey]: selectedPlatformId
|
|
287
|
+
}));
|
|
288
|
+
}, [
|
|
289
|
+
form,
|
|
290
|
+
refreshSessionSetup,
|
|
291
|
+
selectedPlatformId,
|
|
292
|
+
serverOnline,
|
|
293
|
+
sessionSetup,
|
|
294
|
+
sessionViewState.connected
|
|
295
|
+
]);
|
|
296
|
+
useEffect(()=>{
|
|
297
|
+
if (sessionViewState.connected) {
|
|
298
|
+
autoCreateSignatureRef.current = null;
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (!serverOnline || sessionLoading || sessionMutating || sessionSetupError) return;
|
|
302
|
+
const autoCreateInput = resolveAutoCreateSessionInput(sessionSetup, form.getFieldsValue(true));
|
|
303
|
+
const { signature, shouldCreate } = resolveAutoCreateDecision({
|
|
304
|
+
autoCreateInput,
|
|
305
|
+
lastAttemptedSignature: autoCreateSignatureRef.current,
|
|
306
|
+
blockedSignature: autoCreateBlockedSignatureRef.current
|
|
307
|
+
});
|
|
308
|
+
if (!shouldCreate || !signature) {
|
|
309
|
+
if (!signature) autoCreateSignatureRef.current = null;
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
autoCreateSignatureRef.current = signature;
|
|
313
|
+
(()=>_async_to_generator(function*() {
|
|
314
|
+
const created = yield createSession(null != autoCreateInput ? autoCreateInput : void 0, {
|
|
315
|
+
silent: true
|
|
316
|
+
});
|
|
317
|
+
if (!created) autoCreateSignatureRef.current = null;
|
|
318
|
+
})())();
|
|
319
|
+
}, [
|
|
320
|
+
createSession,
|
|
321
|
+
form,
|
|
322
|
+
serverOnline,
|
|
323
|
+
sessionLoading,
|
|
324
|
+
sessionMutating,
|
|
325
|
+
sessionSetup,
|
|
326
|
+
sessionSetupError,
|
|
327
|
+
sessionViewState.connected
|
|
328
|
+
]);
|
|
329
|
+
return {
|
|
330
|
+
state: {
|
|
331
|
+
playgroundSDK,
|
|
332
|
+
form,
|
|
333
|
+
formValues,
|
|
334
|
+
serverOnline,
|
|
335
|
+
isUserOperating,
|
|
336
|
+
deviceType,
|
|
337
|
+
runtimeInfo,
|
|
338
|
+
executionUxHints,
|
|
339
|
+
sessionViewState,
|
|
340
|
+
sessionSetup,
|
|
341
|
+
sessionSetupError,
|
|
342
|
+
sessionLoading,
|
|
343
|
+
sessionMutating,
|
|
344
|
+
countdown,
|
|
345
|
+
countdownSeconds
|
|
346
|
+
},
|
|
347
|
+
actions: {
|
|
348
|
+
refreshServerState,
|
|
349
|
+
refreshSessionSetup,
|
|
350
|
+
createSession,
|
|
351
|
+
destroySession,
|
|
352
|
+
finishCountdown
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
export { usePlaygroundController };
|