@page-agent/ui 0.2.4 → 0.3.0-beta.2
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/lib/index.d.ts +94 -81
- package/dist/lib/page-agent-ui.js +294 -304
- package/dist/lib/page-agent-ui.js.map +1 -1
- package/package.json +1 -1
package/dist/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,34 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Agent activity - transient state for immediate UI feedback.
|
|
3
|
+
*
|
|
4
|
+
* Unlike historical events (which are persisted), activities are ephemeral
|
|
5
|
+
* and represent "what the agent is doing right now". UI components should
|
|
6
|
+
* listen to 'activity' events to show real-time feedback.
|
|
7
|
+
*
|
|
8
|
+
* Note: There is no 'idle' activity - absence of activity events means idle.
|
|
9
|
+
*
|
|
10
|
+
* Events dispatched: CustomEvent<AgentActivity>
|
|
11
|
+
*/
|
|
12
|
+
export declare type AgentActivity = {
|
|
13
|
+
type: 'thinking';
|
|
14
|
+
} | {
|
|
15
|
+
type: 'executing';
|
|
16
|
+
tool: string;
|
|
17
|
+
input: unknown;
|
|
18
|
+
} | {
|
|
19
|
+
type: 'executed';
|
|
20
|
+
tool: string;
|
|
21
|
+
input: unknown;
|
|
22
|
+
output: string;
|
|
23
|
+
duration: number;
|
|
24
|
+
} | {
|
|
25
|
+
type: 'retrying';
|
|
26
|
+
attempt: number;
|
|
27
|
+
maxAttempts: number;
|
|
28
|
+
} | {
|
|
29
|
+
type: 'error';
|
|
30
|
+
message: string;
|
|
31
|
+
};
|
|
2
32
|
|
|
3
33
|
declare type DeepStringify<T> = {
|
|
4
34
|
[K in keyof T]: T[K] extends string ? string : T[K] extends object ? DeepStringify<T[K]> : T[K];
|
|
@@ -27,6 +57,7 @@ declare const enUS: {
|
|
|
27
57
|
readonly selecting: "Selecting option \"{{text}}\"...";
|
|
28
58
|
readonly scrolling: "Scrolling page...";
|
|
29
59
|
readonly waiting: "Waiting {{seconds}} seconds...";
|
|
60
|
+
readonly askingUser: "Asking user...";
|
|
30
61
|
readonly done: "Task done";
|
|
31
62
|
readonly clicked: "🖱️ Clicked element [{{index}}]";
|
|
32
63
|
readonly inputted: "⌨️ Inputted text \"{{text}}\"";
|
|
@@ -83,6 +114,7 @@ declare const locales: {
|
|
|
83
114
|
readonly selecting: "Selecting option \"{{text}}\"...";
|
|
84
115
|
readonly scrolling: "Scrolling page...";
|
|
85
116
|
readonly waiting: "Waiting {{seconds}} seconds...";
|
|
117
|
+
readonly askingUser: "Asking user...";
|
|
86
118
|
readonly done: "Task done";
|
|
87
119
|
readonly clicked: "🖱️ Clicked element [{{index}}]";
|
|
88
120
|
readonly inputted: "⌨️ Inputted text \"{{text}}\"";
|
|
@@ -127,6 +159,7 @@ declare const locales: {
|
|
|
127
159
|
readonly selecting: "正在选择选项 \"{{text}}\"...";
|
|
128
160
|
readonly scrolling: "正在滚动页面...";
|
|
129
161
|
readonly waiting: "等待 {{seconds}} 秒...";
|
|
162
|
+
readonly askingUser: "正在询问用户...";
|
|
130
163
|
readonly done: "结束任务";
|
|
131
164
|
readonly clicked: "🖱️ 已点击元素 [{{index}}]";
|
|
132
165
|
readonly inputted: "⌨️ 已输入文本 \"{{text}}\"";
|
|
@@ -156,27 +189,76 @@ declare type NestedKeyOf<ObjectType extends object> = {
|
|
|
156
189
|
|
|
157
190
|
/**
|
|
158
191
|
* Agent control panel
|
|
192
|
+
*
|
|
193
|
+
* Architecture:
|
|
194
|
+
* - History list: renders directly from agent.history (historical events)
|
|
195
|
+
* - Header bar: shows activity events (transient state) and agent status
|
|
196
|
+
*
|
|
197
|
+
* This separation ensures data consistency - history is the single source of truth
|
|
198
|
+
* for what has been done, while activity shows what is happening now.
|
|
159
199
|
*/
|
|
160
200
|
export declare class Panel {
|
|
161
201
|
#private;
|
|
162
202
|
get wrapper(): HTMLElement;
|
|
163
|
-
constructor(config: PanelConfig);
|
|
164
203
|
/**
|
|
165
|
-
*
|
|
204
|
+
* Create a Panel bound to an agent
|
|
205
|
+
* @param agent - Agent instance that implements PanelAgentAdapter
|
|
206
|
+
* @param config - Optional panel configuration
|
|
166
207
|
*/
|
|
167
|
-
|
|
208
|
+
constructor(agent: PanelAgentAdapter, config?: PanelConfig);
|
|
168
209
|
show(): void;
|
|
169
210
|
hide(): void;
|
|
170
211
|
reset(): void;
|
|
171
212
|
expand(): void;
|
|
172
213
|
collapse(): void;
|
|
173
214
|
/**
|
|
174
|
-
*
|
|
215
|
+
* Dispose panel and clean up event listeners
|
|
175
216
|
*/
|
|
176
|
-
|
|
217
|
+
dispose(): void;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Minimal interface that Panel expects from an agent.
|
|
222
|
+
* Panel does not depend on PageAgent directly - it only requires this interface.
|
|
223
|
+
* This enables decoupling and allows any agent implementation to work with Panel.
|
|
224
|
+
*
|
|
225
|
+
* Events:
|
|
226
|
+
* - 'statuschange': Agent status changed (idle/running/completed/error)
|
|
227
|
+
* - 'historychange': Historical events updated (persisted)
|
|
228
|
+
* - 'activity': Transient activity for immediate UI feedback (thinking/executing/etc)
|
|
229
|
+
* - 'dispose': Agent is being disposed
|
|
230
|
+
*/
|
|
231
|
+
export declare interface PanelAgentAdapter extends EventTarget {
|
|
232
|
+
/** Current agent status */
|
|
233
|
+
readonly status: 'idle' | 'running' | 'completed' | 'error';
|
|
234
|
+
/** History of agent events */
|
|
235
|
+
readonly history: readonly {
|
|
236
|
+
type: 'step' | 'observation' | 'user_takeover' | 'error';
|
|
237
|
+
/** For 'step' type */
|
|
238
|
+
reflection?: {
|
|
239
|
+
evaluation_previous_goal?: string;
|
|
240
|
+
memory?: string;
|
|
241
|
+
next_goal?: string;
|
|
242
|
+
};
|
|
243
|
+
/** For 'step' type */
|
|
244
|
+
action?: {
|
|
245
|
+
name: string;
|
|
246
|
+
input: unknown;
|
|
247
|
+
output: string;
|
|
248
|
+
};
|
|
249
|
+
/** For 'observation' type */
|
|
250
|
+
content?: string;
|
|
251
|
+
}[];
|
|
252
|
+
/** Current task being executed */
|
|
253
|
+
readonly task: string;
|
|
177
254
|
/**
|
|
178
|
-
*
|
|
255
|
+
* Callback for when agent needs user input.
|
|
256
|
+
* Panel will set this to handle user questions via its UI.
|
|
179
257
|
*/
|
|
258
|
+
onAskUser?: (question: string) => Promise<string>;
|
|
259
|
+
/** Execute a task */
|
|
260
|
+
execute(task: string): Promise<unknown>;
|
|
261
|
+
/** Dispose the agent */
|
|
180
262
|
dispose(): void;
|
|
181
263
|
}
|
|
182
264
|
|
|
@@ -185,65 +267,11 @@ export declare class Panel {
|
|
|
185
267
|
*/
|
|
186
268
|
export declare interface PanelConfig {
|
|
187
269
|
language?: SupportedLanguage;
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
* Semantic update types - Panel handles i18n internally
|
|
194
|
-
*/
|
|
195
|
-
export declare type PanelUpdate = {
|
|
196
|
-
type: 'thinking';
|
|
197
|
-
text?: string;
|
|
198
|
-
} | {
|
|
199
|
-
type: 'input';
|
|
200
|
-
task: string;
|
|
201
|
-
} | {
|
|
202
|
-
type: 'question';
|
|
203
|
-
question: string;
|
|
204
|
-
} | {
|
|
205
|
-
type: 'userAnswer';
|
|
206
|
-
input: string;
|
|
207
|
-
} | {
|
|
208
|
-
type: 'retry';
|
|
209
|
-
current: number;
|
|
210
|
-
max: number;
|
|
211
|
-
} | {
|
|
212
|
-
type: 'error';
|
|
213
|
-
message: string;
|
|
214
|
-
} | {
|
|
215
|
-
type: 'output';
|
|
216
|
-
text: string;
|
|
217
|
-
} | {
|
|
218
|
-
type: 'completed';
|
|
219
|
-
} | {
|
|
220
|
-
type: 'toolExecuting';
|
|
221
|
-
toolName: string;
|
|
222
|
-
args: any;
|
|
223
|
-
} | {
|
|
224
|
-
type: 'toolCompleted';
|
|
225
|
-
toolName: string;
|
|
226
|
-
args: any;
|
|
227
|
-
result?: string;
|
|
228
|
-
duration?: number;
|
|
229
|
-
} | {
|
|
230
|
-
type: 'observation';
|
|
231
|
-
content: string;
|
|
232
|
-
};
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* Agent execution state management
|
|
236
|
-
*/
|
|
237
|
-
export declare interface Step {
|
|
238
|
-
id: string;
|
|
239
|
-
stepNumber: number;
|
|
240
|
-
timestamp: Date;
|
|
241
|
-
type: 'thinking' | 'tool_executing' | 'completed' | 'error' | 'output' | 'input' | 'retry' | 'observation';
|
|
242
|
-
toolName?: string;
|
|
243
|
-
toolArgs?: any;
|
|
244
|
-
toolResult?: any;
|
|
245
|
-
displayText: string;
|
|
246
|
-
duration?: number;
|
|
270
|
+
/**
|
|
271
|
+
* Whether to prompt for next task after task completion
|
|
272
|
+
* @default true
|
|
273
|
+
*/
|
|
274
|
+
promptForNextTask?: boolean;
|
|
247
275
|
}
|
|
248
276
|
|
|
249
277
|
export declare type SupportedLanguage = keyof typeof locales;
|
|
@@ -254,19 +282,4 @@ declare type TranslationParams = Record<string, string | number>;
|
|
|
254
282
|
|
|
255
283
|
declare type TranslationSchema = DeepStringify<typeof enUS>;
|
|
256
284
|
|
|
257
|
-
export declare class UIState {
|
|
258
|
-
private steps;
|
|
259
|
-
private currentStep;
|
|
260
|
-
private status;
|
|
261
|
-
private stepCounter;
|
|
262
|
-
addStep(stepData: Omit<Step, 'id' | 'stepNumber' | 'timestamp'>): Step;
|
|
263
|
-
updateCurrentStep(updates: Partial<Step>): Step | null;
|
|
264
|
-
getCurrentStep(): Step | null;
|
|
265
|
-
getAllSteps(): Step[];
|
|
266
|
-
getStatus(): AgentStatus;
|
|
267
|
-
reset(): void;
|
|
268
|
-
private updateStatus;
|
|
269
|
-
private generateId;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
285
|
export { }
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
try {
|
|
4
4
|
if (typeof document != "undefined") {
|
|
5
5
|
var elementStyle = document.createElement("style");
|
|
6
|
-
elementStyle.appendChild(document.createTextNode("._wrapper_1x12x_1 {\n position: fixed;\n bottom: 100px;\n left: 50%;\n transform: translateX(-50%) translateY(20px);\n opacity: 0;\n z-index: 2147483642; /* 比 SimulatorMask 高一层 */\n box-sizing: border-box;\n\n overflow: visible;\n\n * {\n box-sizing: border-box;\n }\n\n --width: 360px;\n --height: 40px;\n --border-radius: 12px;\n\n --side-space: 12px; /* 控制栏两侧的间距 */\n --history-width: calc(var(--width) - var(--side-space) * 2);\n\n --color-1: rgb(57, 182, 255);\n --color-2: rgb(189, 69, 251);\n --color-3: rgb(255, 87, 51);\n --color-4: rgb(255, 214, 0);\n\n width: var(--width);\n height: var(--height);\n\n transition: all 0.3s ease-in-out;\n\n /* 响应式设计 */\n @media (max-width: 480px) {\n width: calc(100vw - 40px);\n --width: calc(100vw - 40px);\n }\n\n ._background_1x12x_39 {\n position: absolute;\n inset: -2px -8px;\n border-radius: calc(var(--border-radius) + 4px);\n filter: blur(16px);\n overflow: hidden;\n /* mix-blend-mode: lighten; */\n /* display: none; */\n\n &::before {\n content: '';\n z-index: -1;\n pointer-events: none;\n position: absolute;\n width: 100%;\n height: 100%;\n /* left: -100%; */\n left: 0;\n top: 0;\n\n background-image: linear-gradient(\n to bottom left,\n var(--color-1),\n var(--color-2),\n var(--color-1)\n );\n animation: _mask-running_1x12x_1 2s linear infinite;\n }\n &::after {\n content: '';\n z-index: -1;\n pointer-events: none;\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n\n background-image: linear-gradient(\n to bottom left,\n var(--color-2),\n var(--color-1),\n var(--color-2)\n );\n animation: _mask-running_1x12x_1 2s linear infinite;\n animation-delay: 1s;\n }\n }\n}\n\n@keyframes _mask-running_1x12x_1 {\n from {\n transform: translateX(-100%);\n }\n to {\n transform: translateX(100%);\n }\n}\n\n/* 控制栏 */\n._header_1x12x_99 {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n user-select: none;\n\n position: absolute;\n inset: 0;\n\n cursor: pointer;\n flex-shrink: 0; /* 防止 header 被压缩 */\n\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(10px);\n border-radius: var(--border-radius);\n background-clip: padding-box;\n\n box-shadow:\n 0 0 0px 2px rgba(255, 255, 255, 0.4),\n 0 0 5px 1px rgba(255, 255, 255, 0.3);\n\n ._statusSection_1x12x_121 {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-height: 24px; /* 确保垂直居中 */\n\n ._indicator_1x12x_128 {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.5);\n flex-shrink: 0;\n animation: none; /* 默认无动画 */\n\n /* 运行状态 - 有动画 */\n &._thinking_1x12x_137 {\n background: rgb(57, 182, 255);\n animation: _pulse_1x12x_1 0.8s ease-in-out infinite;\n }\n\n &._tool_executing_1x12x_142 {\n background: rgb(189, 69, 251);\n animation: _pulse_1x12x_1 0.6s ease-in-out infinite;\n }\n\n &._retry_1x12x_147 {\n background: rgb(255, 214, 0);\n animation: _retryPulse_1x12x_1 1s ease-in-out infinite;\n }\n\n /* 静止状态 - 无动画 */\n &._completed_1x12x_153,\n &._input_1x12x_154,\n &._output_1x12x_155 {\n background: rgb(34, 197, 94);\n animation: none;\n }\n\n &._error_1x12x_160 {\n background: rgb(239, 68, 68);\n animation: none;\n }\n }\n\n ._statusText_1x12x_166 {\n color: white;\n font-size: 12px;\n line-height: 1;\n font-weight: 500;\n transition: all 0.3s ease-in-out;\n position: relative;\n overflow: hidden;\n display: flex;\n align-items: center;\n min-height: 24px; /* 确保垂直居中 */\n\n &._fadeOut_1x12x_178 {\n animation: _statusTextFadeOut_1x12x_1 0.3s ease forwards;\n }\n\n &._fadeIn_1x12x_182 {\n animation: _statusTextFadeIn_1x12x_1 0.3s ease forwards;\n }\n }\n }\n\n ._controls_1x12x_188 {\n display: flex;\n align-items: center;\n gap: 4px;\n\n ._controlButton_1x12x_193 {\n width: 24px;\n height: 24px;\n border: none;\n border-radius: 4px;\n background: rgba(255, 255, 255, 0.1);\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n line-height: 1;\n\n &:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n }\n\n ._stopButton_1x12x_212 {\n background: rgba(239, 68, 68, 0.2);\n color: rgb(255, 41, 41);\n font-weight: 600;\n\n &:hover {\n background: rgba(239, 68, 68, 0.3);\n }\n }\n }\n}\n\n@keyframes _statusTextFadeIn_1x12x_1 {\n 0% {\n opacity: 0;\n transform: translateY(5px);\n }\n 100% {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _statusTextFadeOut_1x12x_1 {\n 0% {\n opacity: 1;\n transform: translateY(0);\n }\n 100% {\n opacity: 0;\n transform: translateY(-5px);\n }\n}\n\n._historySectionWrapper_1x12x_246 {\n position: absolute;\n width: var(--history-width);\n bottom: var(--height);\n left: var(--side-space);\n z-index: -2;\n\n padding-top: 0px;\n visibility: collapse;\n overflow: hidden;\n\n transition: all 0.2s;\n\n background: rgba(2, 0, 20, 0.5);\n /* background: rgba(186, 186, 186, 0.2); */\n backdrop-filter: blur(10px);\n\n text-shadow: 0 0 1px rgba(0, 0, 0, 0.2);\n\n border-top-left-radius: calc(var(--border-radius) + 4px);\n border-top-right-radius: calc(var(--border-radius) + 4px);\n\n /* border: 2px solid rgba(255, 255, 255, 0.8); */\n border: 2px solid rgba(255, 255, 255, 0.4);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6);\n\n /* @media (prefers-color-scheme: dark) {\n box-shadow:\n 0 8px 32px 0 rgba(0, 0, 0, 0.85),\n 0 2px 12px 0 rgba(57, 182, 255, 0.1);\n } */\n\n ._expanded_1x12x_278 & {\n padding-top: 8px;\n visibility: visible;\n }\n\n ._historySection_1x12x_246 {\n position: relative;\n overflow-y: auto;\n overscroll-behavior: contain;\n scrollbar-width: none;\n max-height: 0;\n padding-inline: 8px;\n\n transition: max-height 0.2s;\n\n ._expanded_1x12x_278 & {\n max-height: 400px;\n }\n\n ._historyItem_1x12x_297 {\n /* backdrop-filter: blur(10px); */\n padding: 8px 10px;\n margin-bottom: 6px;\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.03));\n border-radius: 8px;\n border-left: 2px solid rgba(57, 182, 255, 0.5);\n font-size: 12px;\n color: white;\n /* color: black; */\n line-height: 1.3;\n position: relative;\n overflow: hidden;\n\n /* 微妙的内阴影 */\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.1),\n 0 1px 3px rgba(0, 0, 0, 0.1);\n\n &::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 1px;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);\n }\n\n &:hover {\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.06));\n /* transform: translateY(-1px); */\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.15),\n 0 2px 4px rgba(0, 0, 0, 0.15);\n }\n\n &:last-child {\n margin-bottom: 10px;\n }\n\n &._completed_1x12x_153,\n &._input_1x12x_154,\n &._output_1x12x_155 {\n border-left-color: rgb(34, 197, 94);\n background: linear-gradient(135deg, rgba(34, 197, 94, 0.1), rgba(34, 197, 94, 0.05));\n }\n\n &._error_1x12x_160 {\n border-left-color: rgb(239, 68, 68);\n background: linear-gradient(135deg, rgba(239, 68, 68, 0.1), rgba(239, 68, 68, 0.05));\n }\n\n &._retry_1x12x_147 {\n border-left-color: rgb(255, 214, 0);\n background: linear-gradient(135deg, rgba(255, 214, 0, 0.1), rgba(255, 214, 0, 0.05));\n }\n\n &._observation_1x12x_355 {\n border-left-color: rgb(147, 51, 234);\n background: linear-gradient(135deg, rgba(147, 51, 234, 0.1), rgba(147, 51, 234, 0.05));\n }\n\n /* 突出显示 done 成功结果 */\n &._doneSuccess_1x12x_361 {\n background: linear-gradient(\n 135deg,\n rgba(34, 197, 94, 0.25),\n rgba(34, 197, 94, 0.15),\n rgba(34, 197, 94, 0.08)\n );\n border: none;\n border-left: 4px solid rgb(34, 197, 94);\n box-shadow:\n 0 4px 12px rgba(34, 197, 94, 0.3),\n inset 0 1px 0 rgba(255, 255, 255, 0.2),\n 0 0 20px rgba(34, 197, 94, 0.1);\n font-weight: 600;\n color: rgb(220, 252, 231);\n padding: 10px 12px;\n margin-bottom: 8px;\n border-radius: 8px;\n position: relative;\n overflow: hidden;\n\n &::before {\n background: linear-gradient(90deg, transparent, rgba(34, 197, 94, 0.4), transparent);\n }\n\n &::after {\n content: '';\n position: absolute;\n top: 0;\n left: -100%;\n width: 100%;\n height: 100%;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);\n animation: _shimmer_1x12x_1 2s ease-in-out infinite;\n }\n\n ._historyContent_1x12x_397 {\n ._statusIcon_1x12x_398 {\n font-size: 16px;\n animation: _celebrate_1x12x_1 0.8s ease-in-out;\n filter: drop-shadow(0 2px 4px rgba(34, 197, 94, 0.5));\n }\n }\n }\n\n /* 突出显示 done 失败结果 */\n &._doneError_1x12x_407 {\n background: linear-gradient(\n 135deg,\n rgba(239, 68, 68, 0.25),\n rgba(239, 68, 68, 0.15),\n rgba(239, 68, 68, 0.08)\n );\n border: none;\n border-left: 4px solid rgb(239, 68, 68);\n box-shadow:\n 0 4px 12px rgba(239, 68, 68, 0.3),\n inset 0 1px 0 rgba(255, 255, 255, 0.2),\n 0 0 20px rgba(239, 68, 68, 0.1);\n font-weight: 600;\n color: rgb(254, 226, 226);\n padding: 10px 12px;\n margin-bottom: 8px;\n border-radius: 8px;\n position: relative;\n overflow: hidden;\n\n &::before {\n background: linear-gradient(90deg, transparent, rgba(239, 68, 68, 0.4), transparent);\n }\n\n ._historyContent_1x12x_397 {\n ._statusIcon_1x12x_398 {\n font-size: 16px;\n filter: drop-shadow(0 2px 4px rgba(239, 68, 68, 0.5));\n }\n }\n }\n\n ._historyContent_1x12x_397 {\n display: flex;\n align-items: center;\n gap: 8px;\n\n word-break: break-all;\n white-space: pre-wrap;\n\n /* overflow-x: auto; */\n\n ._statusIcon_1x12x_398 {\n font-size: 12px;\n flex-shrink: 0;\n line-height: 1;\n transition: all 0.3s ease;\n }\n }\n\n ._historyMeta_1x12x_458 {\n font-size: 10px;\n color: rgba(255, 255, 255, 0.6);\n /* color: rgb(61, 61, 61); */\n margin-top: 8px;\n line-height: 1;\n }\n }\n }\n}\n\n/* 动画关键帧 - 更快的闪烁 */\n@keyframes _pulse_1x12x_1 {\n 0%,\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.4;\n transform: scale(1.3);\n }\n}\n\n/* 重试动画 - 旋转脉冲 */\n@keyframes _retryPulse_1x12x_1 {\n 0%,\n 100% {\n opacity: 1;\n transform: scale(1) rotate(0deg);\n }\n 25% {\n opacity: 0.6;\n transform: scale(1.2) rotate(90deg);\n }\n 50% {\n opacity: 0.8;\n transform: scale(1.1) rotate(180deg);\n }\n 75% {\n opacity: 0.6;\n transform: scale(1.2) rotate(270deg);\n }\n}\n\n/* 庆祝动画 */\n@keyframes _celebrate_1x12x_1 {\n 0%,\n 100% {\n transform: scale(1);\n }\n 25% {\n transform: scale(1.2) rotate(-5deg);\n }\n 75% {\n transform: scale(1.2) rotate(5deg);\n }\n}\n\n/* done 卡片的光泽效果 */\n@keyframes _shimmer_1x12x_1 {\n 0% {\n left: -100%;\n }\n 100% {\n left: 100%;\n }\n}\n\n/* 输入区域样式 */\n._inputSectionWrapper_1x12x_528 {\n position: absolute;\n width: var(--history-width);\n top: var(--height);\n left: var(--side-space);\n z-index: -1;\n\n visibility: visible;\n overflow: hidden;\n\n height: 48px;\n\n transition: all 0.2s;\n\n background: rgba(186, 186, 186, 0.2);\n backdrop-filter: blur(10px);\n\n border-bottom-left-radius: calc(var(--border-radius) + 4px);\n border-bottom-right-radius: calc(var(--border-radius) + 4px);\n\n border: 2px solid rgba(255, 255, 255, 0.3);\n box-shadow: 0 1px 16px rgba(0, 0, 0, 0.4);\n\n &._hidden_1x12x_551 {\n visibility: collapse;\n height: 0;\n }\n\n ._inputSection_1x12x_528 {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 8px 8px;\n\n ._taskInput_1x12x_562 {\n flex: 1;\n background: rgba(255, 255, 255, 0.4);\n border: 1px solid rgba(255, 255, 255, 0.3);\n border-radius: 10px;\n padding-inline: 10px;\n color: rgb(20, 20, 20);\n font-size: 12px;\n height: 28px;\n line-height: 1;\n outline: none;\n transition: all 0.2s ease;\n\n /* text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); */\n\n /* border-color: rgba(57, 182, 255, 0.3); */\n\n &::placeholder {\n color: rgb(53, 53, 53);\n }\n\n &:focus {\n background: rgba(255, 255, 255, 0.8);\n border-color: rgba(57, 182, 255, 0.6);\n box-shadow: 0 0 0 2px rgba(57, 182, 255, 0.2);\n }\n }\n }\n}"));
|
|
6
|
+
elementStyle.appendChild(document.createTextNode("._wrapper_gtdpc_1 {\n position: fixed;\n bottom: 100px;\n left: 50%;\n transform: translateX(-50%) translateY(20px);\n opacity: 0;\n z-index: 2147483642; /* 比 SimulatorMask 高一层 */\n box-sizing: border-box;\n\n overflow: visible;\n\n * {\n box-sizing: border-box;\n }\n\n --width: 360px;\n --height: 40px;\n --border-radius: 12px;\n\n --side-space: 12px; /* 控制栏两侧的间距 */\n --history-width: calc(var(--width) - var(--side-space) * 2);\n\n --color-1: rgb(57, 182, 255);\n --color-2: rgb(189, 69, 251);\n --color-3: rgb(255, 87, 51);\n --color-4: rgb(255, 214, 0);\n\n width: var(--width);\n height: var(--height);\n\n transition: all 0.3s ease-in-out;\n\n /* 响应式设计 */\n @media (max-width: 480px) {\n width: calc(100vw - 40px);\n --width: calc(100vw - 40px);\n }\n\n ._background_gtdpc_39 {\n position: absolute;\n inset: -2px -8px;\n border-radius: calc(var(--border-radius) + 4px);\n filter: blur(16px);\n overflow: hidden;\n /* mix-blend-mode: lighten; */\n /* display: none; */\n\n &::before {\n content: '';\n z-index: -1;\n pointer-events: none;\n position: absolute;\n width: 100%;\n height: 100%;\n /* left: -100%; */\n left: 0;\n top: 0;\n\n background-image: linear-gradient(\n to bottom left,\n var(--color-1),\n var(--color-2),\n var(--color-1)\n );\n animation: _mask-running_gtdpc_1 2s linear infinite;\n }\n &::after {\n content: '';\n z-index: -1;\n pointer-events: none;\n position: absolute;\n width: 100%;\n height: 100%;\n left: 0;\n top: 0;\n\n background-image: linear-gradient(\n to bottom left,\n var(--color-2),\n var(--color-1),\n var(--color-2)\n );\n animation: _mask-running_gtdpc_1 2s linear infinite;\n animation-delay: 1s;\n }\n }\n}\n\n@keyframes _mask-running_gtdpc_1 {\n from {\n transform: translateX(-100%);\n }\n to {\n transform: translateX(100%);\n }\n}\n\n/* 控制栏 */\n._header_gtdpc_99 {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n user-select: none;\n\n position: absolute;\n inset: 0;\n\n cursor: pointer;\n flex-shrink: 0; /* 防止 header 被压缩 */\n\n background: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(10px);\n border-radius: var(--border-radius);\n background-clip: padding-box;\n\n box-shadow:\n 0 0 0px 2px rgba(255, 255, 255, 0.4),\n 0 0 5px 1px rgba(255, 255, 255, 0.3);\n\n ._statusSection_gtdpc_121 {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-height: 24px; /* 确保垂直居中 */\n\n ._indicator_gtdpc_128 {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.5);\n flex-shrink: 0;\n animation: none; /* 默认无动画 */\n\n /* 运行状态 - 有动画 */\n &._thinking_gtdpc_137 {\n background: rgb(57, 182, 255);\n animation: _pulse_gtdpc_1 0.8s ease-in-out infinite;\n }\n\n &._tool_executing_gtdpc_142 {\n background: rgb(189, 69, 251);\n animation: _pulse_gtdpc_1 0.6s ease-in-out infinite;\n }\n\n &._retry_gtdpc_147 {\n background: rgb(255, 214, 0);\n animation: _retryPulse_gtdpc_1 1s ease-in-out infinite;\n }\n\n /* 静止状态 - 无动画 */\n &._completed_gtdpc_153,\n &._input_gtdpc_154,\n &._output_gtdpc_155 {\n background: rgb(34, 197, 94);\n animation: none;\n }\n\n &._error_gtdpc_160 {\n background: rgb(239, 68, 68);\n animation: none;\n }\n }\n\n ._statusText_gtdpc_166 {\n color: white;\n font-size: 12px;\n line-height: 1;\n font-weight: 500;\n transition: all 0.3s ease-in-out;\n position: relative;\n overflow: hidden;\n display: flex;\n align-items: center;\n min-height: 24px; /* 确保垂直居中 */\n\n &._fadeOut_gtdpc_178 {\n animation: _statusTextFadeOut_gtdpc_1 0.3s ease forwards;\n }\n\n &._fadeIn_gtdpc_182 {\n animation: _statusTextFadeIn_gtdpc_1 0.3s ease forwards;\n }\n }\n }\n\n ._controls_gtdpc_188 {\n display: flex;\n align-items: center;\n gap: 4px;\n\n ._controlButton_gtdpc_193 {\n width: 24px;\n height: 24px;\n border: none;\n border-radius: 4px;\n background: rgba(255, 255, 255, 0.1);\n color: white;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n line-height: 1;\n\n &:hover {\n background: rgba(255, 255, 255, 0.2);\n }\n }\n\n ._stopButton_gtdpc_212 {\n background: rgba(239, 68, 68, 0.2);\n color: rgb(255, 41, 41);\n font-weight: 600;\n\n &:hover {\n background: rgba(239, 68, 68, 0.3);\n }\n }\n }\n}\n\n@keyframes _statusTextFadeIn_gtdpc_1 {\n 0% {\n opacity: 0;\n transform: translateY(5px);\n }\n 100% {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes _statusTextFadeOut_gtdpc_1 {\n 0% {\n opacity: 1;\n transform: translateY(0);\n }\n 100% {\n opacity: 0;\n transform: translateY(-5px);\n }\n}\n\n._historySectionWrapper_gtdpc_246 {\n position: absolute;\n width: var(--history-width);\n bottom: var(--height);\n left: var(--side-space);\n z-index: -2;\n\n padding-top: 0px;\n visibility: collapse;\n overflow: hidden;\n\n transition: all 0.2s;\n\n background: rgba(2, 0, 20, 0.5);\n /* background: rgba(186, 186, 186, 0.2); */\n backdrop-filter: blur(10px);\n\n text-shadow: 0 0 1px rgba(0, 0, 0, 0.2);\n\n border-top-left-radius: calc(var(--border-radius) + 4px);\n border-top-right-radius: calc(var(--border-radius) + 4px);\n\n /* border: 2px solid rgba(255, 255, 255, 0.8); */\n border: 2px solid rgba(255, 255, 255, 0.4);\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6);\n\n /* @media (prefers-color-scheme: dark) {\n box-shadow:\n 0 8px 32px 0 rgba(0, 0, 0, 0.85),\n 0 2px 12px 0 rgba(57, 182, 255, 0.1);\n } */\n\n ._expanded_gtdpc_278 & {\n padding-top: 8px;\n visibility: visible;\n }\n\n ._historySection_gtdpc_246 {\n position: relative;\n overflow-y: auto;\n overscroll-behavior: contain;\n scrollbar-width: none;\n max-height: 0;\n padding-inline: 8px;\n\n transition: max-height 0.2s;\n\n ._expanded_gtdpc_278 & {\n max-height: 400px;\n }\n\n ._historyItem_gtdpc_297 {\n /* backdrop-filter: blur(10px); */\n padding: 8px 10px;\n margin-bottom: 6px;\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.03));\n border-radius: 8px;\n border-left: 2px solid rgba(57, 182, 255, 0.5);\n font-size: 12px;\n color: white;\n /* color: black; */\n line-height: 1.3;\n position: relative;\n overflow: hidden;\n\n /* 微妙的内阴影 */\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.1),\n 0 1px 3px rgba(0, 0, 0, 0.1);\n\n &::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 1px;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);\n }\n\n &:hover {\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.06));\n /* transform: translateY(-1px); */\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.15),\n 0 2px 4px rgba(0, 0, 0, 0.15);\n }\n\n &:last-child {\n margin-bottom: 10px;\n }\n\n &._completed_gtdpc_153,\n &._input_gtdpc_154,\n &._output_gtdpc_155 {\n border-left-color: rgb(34, 197, 94);\n background: linear-gradient(135deg, rgba(34, 197, 94, 0.1), rgba(34, 197, 94, 0.05));\n }\n\n &._error_gtdpc_160 {\n border-left-color: rgb(239, 68, 68);\n background: linear-gradient(135deg, rgba(239, 68, 68, 0.1), rgba(239, 68, 68, 0.05));\n }\n\n &._retry_gtdpc_147 {\n border-left-color: rgb(255, 214, 0);\n background: linear-gradient(135deg, rgba(255, 214, 0, 0.1), rgba(255, 214, 0, 0.05));\n }\n\n &._observation_gtdpc_355 {\n border-left-color: rgb(147, 51, 234);\n background: linear-gradient(135deg, rgba(147, 51, 234, 0.1), rgba(147, 51, 234, 0.05));\n }\n\n &._question_gtdpc_360 {\n border-left-color: rgb(255, 159, 67);\n background: linear-gradient(135deg, rgba(255, 159, 67, 0.15), rgba(255, 159, 67, 0.08));\n }\n\n /* 突出显示 done 成功结果 */\n &._doneSuccess_gtdpc_366 {\n background: linear-gradient(\n 135deg,\n rgba(34, 197, 94, 0.25),\n rgba(34, 197, 94, 0.15),\n rgba(34, 197, 94, 0.08)\n );\n border: none;\n border-left: 4px solid rgb(34, 197, 94);\n box-shadow:\n 0 4px 12px rgba(34, 197, 94, 0.3),\n inset 0 1px 0 rgba(255, 255, 255, 0.2),\n 0 0 20px rgba(34, 197, 94, 0.1);\n font-weight: 600;\n color: rgb(220, 252, 231);\n padding: 10px 12px;\n margin-bottom: 8px;\n border-radius: 8px;\n position: relative;\n overflow: hidden;\n\n &::before {\n background: linear-gradient(90deg, transparent, rgba(34, 197, 94, 0.4), transparent);\n }\n\n &::after {\n content: '';\n position: absolute;\n top: 0;\n left: -100%;\n width: 100%;\n height: 100%;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.1), transparent);\n animation: _shimmer_gtdpc_1 2s ease-in-out infinite;\n }\n\n ._historyContent_gtdpc_402 {\n ._statusIcon_gtdpc_403 {\n font-size: 16px;\n animation: _celebrate_gtdpc_1 0.8s ease-in-out;\n filter: drop-shadow(0 2px 4px rgba(34, 197, 94, 0.5));\n }\n }\n }\n\n /* 突出显示 done 失败结果 */\n &._doneError_gtdpc_412 {\n background: linear-gradient(\n 135deg,\n rgba(239, 68, 68, 0.25),\n rgba(239, 68, 68, 0.15),\n rgba(239, 68, 68, 0.08)\n );\n border: none;\n border-left: 4px solid rgb(239, 68, 68);\n box-shadow:\n 0 4px 12px rgba(239, 68, 68, 0.3),\n inset 0 1px 0 rgba(255, 255, 255, 0.2),\n 0 0 20px rgba(239, 68, 68, 0.1);\n font-weight: 600;\n color: rgb(254, 226, 226);\n padding: 10px 12px;\n margin-bottom: 8px;\n border-radius: 8px;\n position: relative;\n overflow: hidden;\n\n &::before {\n background: linear-gradient(90deg, transparent, rgba(239, 68, 68, 0.4), transparent);\n }\n\n ._historyContent_gtdpc_402 {\n ._statusIcon_gtdpc_403 {\n font-size: 16px;\n filter: drop-shadow(0 2px 4px rgba(239, 68, 68, 0.5));\n }\n }\n }\n\n ._historyContent_gtdpc_402 {\n display: flex;\n align-items: flex-start;\n gap: 8px;\n\n word-break: break-all;\n white-space: pre-wrap;\n\n /* overflow-x: auto; */\n\n ._statusIcon_gtdpc_403 {\n font-size: 12px;\n flex-shrink: 0;\n line-height: 1;\n transition: all 0.3s ease;\n }\n\n ._reflectionLines_gtdpc_462 {\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n }\n\n ._historyMeta_gtdpc_469 {\n font-size: 10px;\n color: rgba(255, 255, 255, 0.6);\n /* color: rgb(61, 61, 61); */\n margin-top: 8px;\n line-height: 1;\n }\n }\n }\n}\n\n/* 动画关键帧 - 更快的闪烁 */\n@keyframes _pulse_gtdpc_1 {\n 0%,\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n 50% {\n opacity: 0.4;\n transform: scale(1.3);\n }\n}\n\n/* 重试动画 - 旋转脉冲 */\n@keyframes _retryPulse_gtdpc_1 {\n 0%,\n 100% {\n opacity: 1;\n transform: scale(1) rotate(0deg);\n }\n 25% {\n opacity: 0.6;\n transform: scale(1.2) rotate(90deg);\n }\n 50% {\n opacity: 0.8;\n transform: scale(1.1) rotate(180deg);\n }\n 75% {\n opacity: 0.6;\n transform: scale(1.2) rotate(270deg);\n }\n}\n\n/* 庆祝动画 */\n@keyframes _celebrate_gtdpc_1 {\n 0%,\n 100% {\n transform: scale(1);\n }\n 25% {\n transform: scale(1.2) rotate(-5deg);\n }\n 75% {\n transform: scale(1.2) rotate(5deg);\n }\n}\n\n/* done 卡片的光泽效果 */\n@keyframes _shimmer_gtdpc_1 {\n 0% {\n left: -100%;\n }\n 100% {\n left: 100%;\n }\n}\n\n/* 输入区域样式 */\n._inputSectionWrapper_gtdpc_539 {\n position: absolute;\n width: var(--history-width);\n top: var(--height);\n left: var(--side-space);\n z-index: -1;\n\n visibility: visible;\n overflow: hidden;\n\n height: 48px;\n\n transition: all 0.2s;\n\n background: rgba(186, 186, 186, 0.2);\n backdrop-filter: blur(10px);\n\n border-bottom-left-radius: calc(var(--border-radius) + 4px);\n border-bottom-right-radius: calc(var(--border-radius) + 4px);\n\n border: 2px solid rgba(255, 255, 255, 0.3);\n box-shadow: 0 1px 16px rgba(0, 0, 0, 0.4);\n\n &._hidden_gtdpc_562 {\n visibility: collapse;\n height: 0;\n }\n\n ._inputSection_gtdpc_539 {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 8px 8px;\n\n ._taskInput_gtdpc_573 {\n flex: 1;\n background: rgba(255, 255, 255, 0.4);\n border: 1px solid rgba(255, 255, 255, 0.3);\n border-radius: 10px;\n padding-inline: 10px;\n color: rgb(20, 20, 20);\n font-size: 12px;\n height: 28px;\n line-height: 1;\n outline: none;\n transition: all 0.2s ease;\n\n /* text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); */\n\n /* border-color: rgba(57, 182, 255, 0.3); */\n\n &::placeholder {\n color: rgb(53, 53, 53);\n }\n\n &:focus {\n background: rgba(255, 255, 255, 0.8);\n border-color: rgba(57, 182, 255, 0.6);\n box-shadow: 0 0 0 2px rgba(57, 182, 255, 0.2);\n }\n }\n }\n}"));
|
|
7
7
|
document.head.appendChild(elementStyle);
|
|
8
8
|
}
|
|
9
9
|
} catch (e) {
|
|
@@ -20,67 +20,7 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
|
|
|
20
20
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
21
21
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
22
22
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
23
|
-
var _wrapper, _indicator, _statusText, _historySection, _expandButton, _stopButton, _inputSection, _taskInput,
|
|
24
|
-
const _UIState = class _UIState {
|
|
25
|
-
steps = [];
|
|
26
|
-
currentStep = null;
|
|
27
|
-
status = "idle";
|
|
28
|
-
stepCounter = 0;
|
|
29
|
-
addStep(stepData) {
|
|
30
|
-
const step = {
|
|
31
|
-
id: this.generateId(),
|
|
32
|
-
stepNumber: ++this.stepCounter,
|
|
33
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
34
|
-
...stepData
|
|
35
|
-
};
|
|
36
|
-
this.steps.push(step);
|
|
37
|
-
this.currentStep = step;
|
|
38
|
-
this.updateStatus(step.type);
|
|
39
|
-
return step;
|
|
40
|
-
}
|
|
41
|
-
updateCurrentStep(updates) {
|
|
42
|
-
if (!this.currentStep) return null;
|
|
43
|
-
Object.assign(this.currentStep, updates);
|
|
44
|
-
return this.currentStep;
|
|
45
|
-
}
|
|
46
|
-
getCurrentStep() {
|
|
47
|
-
return this.currentStep;
|
|
48
|
-
}
|
|
49
|
-
getAllSteps() {
|
|
50
|
-
return [...this.steps];
|
|
51
|
-
}
|
|
52
|
-
getStatus() {
|
|
53
|
-
return this.status;
|
|
54
|
-
}
|
|
55
|
-
reset() {
|
|
56
|
-
this.steps = [];
|
|
57
|
-
this.currentStep = null;
|
|
58
|
-
this.status = "idle";
|
|
59
|
-
this.stepCounter = 0;
|
|
60
|
-
}
|
|
61
|
-
updateStatus(stepType) {
|
|
62
|
-
switch (stepType) {
|
|
63
|
-
case "thinking":
|
|
64
|
-
case "tool_executing":
|
|
65
|
-
case "output":
|
|
66
|
-
case "input":
|
|
67
|
-
case "retry":
|
|
68
|
-
this.status = "running";
|
|
69
|
-
break;
|
|
70
|
-
case "completed":
|
|
71
|
-
this.status = "completed";
|
|
72
|
-
break;
|
|
73
|
-
case "error":
|
|
74
|
-
this.status = "error";
|
|
75
|
-
break;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
generateId() {
|
|
79
|
-
return `step_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
__name(_UIState, "UIState");
|
|
83
|
-
let UIState = _UIState;
|
|
23
|
+
var _wrapper, _indicator, _statusText, _historySection, _expandButton, _stopButton, _inputSection, _taskInput, _agent, _config, _isExpanded, _i18n, _userAnswerResolver, _isWaitingForUserAnswer, _headerUpdateTimer, _pendingHeaderText, _isAnimating, _onStatusChange, _onHistoryChange, _onActivity, _onAgentDispose, _Panel_instances, handleStatusChange_fn, handleHistoryChange_fn, handleActivity_fn, askUser_fn, getToolExecutingText_fn, stopAgent_fn, submitTask_fn, handleUserAnswer_fn, showInputArea_fn, hideInputArea_fn, shouldShowInputArea_fn, createWrapper_fn, setupEventListeners_fn, toggle_fn, expand_fn, collapse_fn, startHeaderUpdateLoop_fn, stopHeaderUpdateLoop_fn, checkAndUpdateHeader_fn, animateTextChange_fn, updateStatusIndicator_fn, scrollToBottom_fn, renderHistory_fn, createTaskCard_fn, createHistoryCards_fn, createActionCards_fn;
|
|
84
24
|
const enUS = {
|
|
85
25
|
ui: {
|
|
86
26
|
panel: {
|
|
@@ -104,6 +44,7 @@ const enUS = {
|
|
|
104
44
|
selecting: 'Selecting option "{{text}}"...',
|
|
105
45
|
scrolling: "Scrolling page...",
|
|
106
46
|
waiting: "Waiting {{seconds}} seconds...",
|
|
47
|
+
askingUser: "Asking user...",
|
|
107
48
|
done: "Task done",
|
|
108
49
|
clicked: "🖱️ Clicked element [{{index}}]",
|
|
109
50
|
inputted: '⌨️ Inputted text "{{text}}"',
|
|
@@ -148,6 +89,7 @@ const zhCN = {
|
|
|
148
89
|
selecting: '正在选择选项 "{{text}}"...',
|
|
149
90
|
scrolling: "正在滚动页面...",
|
|
150
91
|
waiting: "等待 {{seconds}} 秒...",
|
|
92
|
+
askingUser: "正在询问用户...",
|
|
151
93
|
done: "结束任务",
|
|
152
94
|
clicked: "🖱️ 已点击元素 [{{index}}]",
|
|
153
95
|
inputted: '⌨️ 已输入文本 "{{text}}"',
|
|
@@ -217,47 +159,49 @@ function escapeHtml(text) {
|
|
|
217
159
|
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
218
160
|
}
|
|
219
161
|
__name(escapeHtml, "escapeHtml");
|
|
220
|
-
const wrapper = "
|
|
221
|
-
const background = "
|
|
222
|
-
const header = "
|
|
223
|
-
const pulse = "
|
|
224
|
-
const retryPulse = "
|
|
225
|
-
const statusTextFadeOut = "
|
|
226
|
-
const statusTextFadeIn = "
|
|
227
|
-
const statusSection = "
|
|
228
|
-
const indicator = "
|
|
229
|
-
const thinking = "
|
|
230
|
-
const tool_executing = "
|
|
231
|
-
const retry = "
|
|
232
|
-
const completed = "
|
|
233
|
-
const input = "
|
|
234
|
-
const output = "
|
|
235
|
-
const error = "
|
|
236
|
-
const statusText = "
|
|
237
|
-
const fadeOut = "
|
|
238
|
-
const fadeIn = "
|
|
239
|
-
const controls = "
|
|
240
|
-
const controlButton = "
|
|
241
|
-
const stopButton = "
|
|
242
|
-
const historySectionWrapper = "
|
|
243
|
-
const shimmer = "
|
|
244
|
-
const celebrate = "
|
|
245
|
-
const expanded = "
|
|
246
|
-
const historySection = "
|
|
247
|
-
const historyItem = "
|
|
248
|
-
const observation = "
|
|
249
|
-
const
|
|
250
|
-
const
|
|
251
|
-
const
|
|
252
|
-
const
|
|
253
|
-
const
|
|
254
|
-
const
|
|
255
|
-
const
|
|
256
|
-
const
|
|
257
|
-
const
|
|
162
|
+
const wrapper = "_wrapper_gtdpc_1";
|
|
163
|
+
const background = "_background_gtdpc_39";
|
|
164
|
+
const header = "_header_gtdpc_99";
|
|
165
|
+
const pulse = "_pulse_gtdpc_1";
|
|
166
|
+
const retryPulse = "_retryPulse_gtdpc_1";
|
|
167
|
+
const statusTextFadeOut = "_statusTextFadeOut_gtdpc_1";
|
|
168
|
+
const statusTextFadeIn = "_statusTextFadeIn_gtdpc_1";
|
|
169
|
+
const statusSection = "_statusSection_gtdpc_121";
|
|
170
|
+
const indicator = "_indicator_gtdpc_128";
|
|
171
|
+
const thinking = "_thinking_gtdpc_137";
|
|
172
|
+
const tool_executing = "_tool_executing_gtdpc_142";
|
|
173
|
+
const retry = "_retry_gtdpc_147";
|
|
174
|
+
const completed = "_completed_gtdpc_153";
|
|
175
|
+
const input = "_input_gtdpc_154";
|
|
176
|
+
const output = "_output_gtdpc_155";
|
|
177
|
+
const error = "_error_gtdpc_160";
|
|
178
|
+
const statusText = "_statusText_gtdpc_166";
|
|
179
|
+
const fadeOut = "_fadeOut_gtdpc_178";
|
|
180
|
+
const fadeIn = "_fadeIn_gtdpc_182";
|
|
181
|
+
const controls = "_controls_gtdpc_188";
|
|
182
|
+
const controlButton = "_controlButton_gtdpc_193";
|
|
183
|
+
const stopButton = "_stopButton_gtdpc_212";
|
|
184
|
+
const historySectionWrapper = "_historySectionWrapper_gtdpc_246";
|
|
185
|
+
const shimmer = "_shimmer_gtdpc_1";
|
|
186
|
+
const celebrate = "_celebrate_gtdpc_1";
|
|
187
|
+
const expanded = "_expanded_gtdpc_278";
|
|
188
|
+
const historySection = "_historySection_gtdpc_246";
|
|
189
|
+
const historyItem = "_historyItem_gtdpc_297";
|
|
190
|
+
const observation = "_observation_gtdpc_355";
|
|
191
|
+
const question = "_question_gtdpc_360";
|
|
192
|
+
const doneSuccess = "_doneSuccess_gtdpc_366";
|
|
193
|
+
const historyContent = "_historyContent_gtdpc_402";
|
|
194
|
+
const statusIcon = "_statusIcon_gtdpc_403";
|
|
195
|
+
const doneError = "_doneError_gtdpc_412";
|
|
196
|
+
const reflectionLines = "_reflectionLines_gtdpc_462";
|
|
197
|
+
const historyMeta = "_historyMeta_gtdpc_469";
|
|
198
|
+
const inputSectionWrapper = "_inputSectionWrapper_gtdpc_539";
|
|
199
|
+
const hidden = "_hidden_gtdpc_562";
|
|
200
|
+
const inputSection = "_inputSection_gtdpc_539";
|
|
201
|
+
const taskInput = "_taskInput_gtdpc_573";
|
|
258
202
|
const styles = {
|
|
259
203
|
wrapper,
|
|
260
|
-
"mask-running": "_mask-
|
|
204
|
+
"mask-running": "_mask-running_gtdpc_1",
|
|
261
205
|
background,
|
|
262
206
|
header,
|
|
263
207
|
pulse,
|
|
@@ -286,18 +230,62 @@ const styles = {
|
|
|
286
230
|
historySection,
|
|
287
231
|
historyItem,
|
|
288
232
|
observation,
|
|
233
|
+
question,
|
|
289
234
|
doneSuccess,
|
|
290
235
|
historyContent,
|
|
291
236
|
statusIcon,
|
|
292
237
|
doneError,
|
|
238
|
+
reflectionLines,
|
|
293
239
|
historyMeta,
|
|
294
240
|
inputSectionWrapper,
|
|
295
241
|
hidden,
|
|
296
242
|
inputSection,
|
|
297
243
|
taskInput
|
|
298
244
|
};
|
|
245
|
+
function createCard({ icon, content, meta, type }) {
|
|
246
|
+
const typeClass = type ? styles[type] : "";
|
|
247
|
+
const contentHtml = Array.isArray(content) ? `<div class="${styles.reflectionLines}">${content.join("")}</div>` : `<span>${escapeHtml(content)}</span>`;
|
|
248
|
+
return `
|
|
249
|
+
<div class="${styles.historyItem} ${typeClass}">
|
|
250
|
+
<div class="${styles.historyContent}">
|
|
251
|
+
<span class="${styles.statusIcon}">${icon}</span>
|
|
252
|
+
${contentHtml}
|
|
253
|
+
</div>
|
|
254
|
+
${meta ? `<div class="${styles.historyMeta}">${meta}</div>` : ""}
|
|
255
|
+
</div>
|
|
256
|
+
`;
|
|
257
|
+
}
|
|
258
|
+
__name(createCard, "createCard");
|
|
259
|
+
function formatTime(locale = "en-US") {
|
|
260
|
+
return (/* @__PURE__ */ new Date()).toLocaleTimeString(locale, {
|
|
261
|
+
hour12: false,
|
|
262
|
+
hour: "2-digit",
|
|
263
|
+
minute: "2-digit",
|
|
264
|
+
second: "2-digit"
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
__name(formatTime, "formatTime");
|
|
268
|
+
function createReflectionLines(reflection) {
|
|
269
|
+
const lines = [];
|
|
270
|
+
if (reflection.evaluation_previous_goal) {
|
|
271
|
+
lines.push(`<div>🔍 ${escapeHtml(reflection.evaluation_previous_goal)}</div>`);
|
|
272
|
+
}
|
|
273
|
+
if (reflection.memory) {
|
|
274
|
+
lines.push(`<div>💾 ${escapeHtml(reflection.memory)}</div>`);
|
|
275
|
+
}
|
|
276
|
+
if (reflection.next_goal) {
|
|
277
|
+
lines.push(`<div>🎯 ${escapeHtml(reflection.next_goal)}</div>`);
|
|
278
|
+
}
|
|
279
|
+
return lines;
|
|
280
|
+
}
|
|
281
|
+
__name(createReflectionLines, "createReflectionLines");
|
|
299
282
|
const _Panel = class _Panel {
|
|
300
|
-
|
|
283
|
+
/**
|
|
284
|
+
* Create a Panel bound to an agent
|
|
285
|
+
* @param agent - Agent instance that implements PanelAgentAdapter
|
|
286
|
+
* @param config - Optional panel configuration
|
|
287
|
+
*/
|
|
288
|
+
constructor(agent, config = {}) {
|
|
301
289
|
__privateAdd(this, _Panel_instances);
|
|
302
290
|
__privateAdd(this, _wrapper);
|
|
303
291
|
__privateAdd(this, _indicator);
|
|
@@ -307,17 +295,24 @@ const _Panel = class _Panel {
|
|
|
307
295
|
__privateAdd(this, _stopButton);
|
|
308
296
|
__privateAdd(this, _inputSection);
|
|
309
297
|
__privateAdd(this, _taskInput);
|
|
310
|
-
__privateAdd(this,
|
|
311
|
-
__privateAdd(this, _isExpanded, false);
|
|
298
|
+
__privateAdd(this, _agent);
|
|
312
299
|
__privateAdd(this, _config);
|
|
300
|
+
__privateAdd(this, _isExpanded, false);
|
|
313
301
|
__privateAdd(this, _i18n);
|
|
314
302
|
__privateAdd(this, _userAnswerResolver, null);
|
|
315
303
|
__privateAdd(this, _isWaitingForUserAnswer, false);
|
|
316
304
|
__privateAdd(this, _headerUpdateTimer, null);
|
|
317
305
|
__privateAdd(this, _pendingHeaderText, null);
|
|
318
306
|
__privateAdd(this, _isAnimating, false);
|
|
307
|
+
// Event handlers (bound for removal)
|
|
308
|
+
__privateAdd(this, _onStatusChange, /* @__PURE__ */ __name(() => __privateMethod(this, _Panel_instances, handleStatusChange_fn).call(this), "#onStatusChange"));
|
|
309
|
+
__privateAdd(this, _onHistoryChange, /* @__PURE__ */ __name(() => __privateMethod(this, _Panel_instances, handleHistoryChange_fn).call(this), "#onHistoryChange"));
|
|
310
|
+
__privateAdd(this, _onActivity, /* @__PURE__ */ __name((e) => __privateMethod(this, _Panel_instances, handleActivity_fn).call(this, e.detail), "#onActivity"));
|
|
311
|
+
__privateAdd(this, _onAgentDispose, /* @__PURE__ */ __name(() => this.dispose(), "#onAgentDispose"));
|
|
312
|
+
__privateSet(this, _agent, agent);
|
|
319
313
|
__privateSet(this, _config, config);
|
|
320
314
|
__privateSet(this, _i18n, new I18n(config.language ?? "en-US"));
|
|
315
|
+
__privateGet(this, _agent).onAskUser = (question2) => __privateMethod(this, _Panel_instances, askUser_fn).call(this, question2);
|
|
321
316
|
__privateSet(this, _wrapper, __privateMethod(this, _Panel_instances, createWrapper_fn).call(this));
|
|
322
317
|
__privateSet(this, _indicator, __privateGet(this, _wrapper).querySelector(`.${styles.indicator}`));
|
|
323
318
|
__privateSet(this, _statusText, __privateGet(this, _wrapper).querySelector(`.${styles.statusText}`));
|
|
@@ -326,6 +321,10 @@ const _Panel = class _Panel {
|
|
|
326
321
|
__privateSet(this, _stopButton, __privateGet(this, _wrapper).querySelector(`.${styles.stopButton}`));
|
|
327
322
|
__privateSet(this, _inputSection, __privateGet(this, _wrapper).querySelector(`.${styles.inputSectionWrapper}`));
|
|
328
323
|
__privateSet(this, _taskInput, __privateGet(this, _wrapper).querySelector(`.${styles.taskInput}`));
|
|
324
|
+
__privateGet(this, _agent).addEventListener("statuschange", __privateGet(this, _onStatusChange));
|
|
325
|
+
__privateGet(this, _agent).addEventListener("historychange", __privateGet(this, _onHistoryChange));
|
|
326
|
+
__privateGet(this, _agent).addEventListener("activity", __privateGet(this, _onActivity));
|
|
327
|
+
__privateGet(this, _agent).addEventListener("dispose", __privateGet(this, _onAgentDispose));
|
|
329
328
|
__privateMethod(this, _Panel_instances, setupEventListeners_fn).call(this);
|
|
330
329
|
__privateMethod(this, _Panel_instances, startHeaderUpdateLoop_fn).call(this);
|
|
331
330
|
__privateMethod(this, _Panel_instances, showInputArea_fn).call(this);
|
|
@@ -334,23 +333,6 @@ const _Panel = class _Panel {
|
|
|
334
333
|
get wrapper() {
|
|
335
334
|
return __privateGet(this, _wrapper);
|
|
336
335
|
}
|
|
337
|
-
/**
|
|
338
|
-
* Ask for user input
|
|
339
|
-
*/
|
|
340
|
-
async askUser(question) {
|
|
341
|
-
return new Promise((resolve) => {
|
|
342
|
-
__privateSet(this, _isWaitingForUserAnswer, true);
|
|
343
|
-
__privateSet(this, _userAnswerResolver, resolve);
|
|
344
|
-
__privateMethod(this, _Panel_instances, updateInternal_fn).call(this, {
|
|
345
|
-
type: "output",
|
|
346
|
-
displayText: __privateGet(this, _i18n).t("ui.panel.question", { question })
|
|
347
|
-
});
|
|
348
|
-
if (!__privateGet(this, _isExpanded)) {
|
|
349
|
-
__privateMethod(this, _Panel_instances, expand_fn).call(this);
|
|
350
|
-
}
|
|
351
|
-
__privateMethod(this, _Panel_instances, showInputArea_fn).call(this, __privateGet(this, _i18n).t("ui.panel.userAnswerPrompt"));
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
336
|
// ========== Public control methods ==========
|
|
355
337
|
show() {
|
|
356
338
|
this.wrapper.style.display = "block";
|
|
@@ -364,10 +346,9 @@ const _Panel = class _Panel {
|
|
|
364
346
|
this.wrapper.style.display = "none";
|
|
365
347
|
}
|
|
366
348
|
reset() {
|
|
367
|
-
__privateGet(this, _state).reset();
|
|
368
349
|
__privateGet(this, _statusText).textContent = __privateGet(this, _i18n).t("ui.panel.ready");
|
|
369
350
|
__privateMethod(this, _Panel_instances, updateStatusIndicator_fn).call(this, "thinking");
|
|
370
|
-
__privateMethod(this, _Panel_instances,
|
|
351
|
+
__privateMethod(this, _Panel_instances, renderHistory_fn).call(this);
|
|
371
352
|
__privateMethod(this, _Panel_instances, collapse_fn).call(this);
|
|
372
353
|
__privateSet(this, _isWaitingForUserAnswer, false);
|
|
373
354
|
__privateSet(this, _userAnswerResolver, null);
|
|
@@ -380,16 +361,13 @@ const _Panel = class _Panel {
|
|
|
380
361
|
__privateMethod(this, _Panel_instances, collapse_fn).call(this);
|
|
381
362
|
}
|
|
382
363
|
/**
|
|
383
|
-
*
|
|
384
|
-
*/
|
|
385
|
-
update(data) {
|
|
386
|
-
const stepData = __privateMethod(this, _Panel_instances, toStepData_fn).call(this, data);
|
|
387
|
-
__privateMethod(this, _Panel_instances, updateInternal_fn).call(this, stepData);
|
|
388
|
-
}
|
|
389
|
-
/**
|
|
390
|
-
* Dispose panel
|
|
364
|
+
* Dispose panel and clean up event listeners
|
|
391
365
|
*/
|
|
392
366
|
dispose() {
|
|
367
|
+
__privateGet(this, _agent).removeEventListener("statuschange", __privateGet(this, _onStatusChange));
|
|
368
|
+
__privateGet(this, _agent).removeEventListener("historychange", __privateGet(this, _onHistoryChange));
|
|
369
|
+
__privateGet(this, _agent).removeEventListener("activity", __privateGet(this, _onActivity));
|
|
370
|
+
__privateGet(this, _agent).removeEventListener("dispose", __privateGet(this, _onAgentDispose));
|
|
393
371
|
__privateSet(this, _isWaitingForUserAnswer, false);
|
|
394
372
|
__privateMethod(this, _Panel_instances, stopHeaderUpdateLoop_fn).call(this);
|
|
395
373
|
this.wrapper.remove();
|
|
@@ -403,133 +381,121 @@ _expandButton = new WeakMap();
|
|
|
403
381
|
_stopButton = new WeakMap();
|
|
404
382
|
_inputSection = new WeakMap();
|
|
405
383
|
_taskInput = new WeakMap();
|
|
406
|
-
|
|
407
|
-
_isExpanded = new WeakMap();
|
|
384
|
+
_agent = new WeakMap();
|
|
408
385
|
_config = new WeakMap();
|
|
386
|
+
_isExpanded = new WeakMap();
|
|
409
387
|
_i18n = new WeakMap();
|
|
410
388
|
_userAnswerResolver = new WeakMap();
|
|
411
389
|
_isWaitingForUserAnswer = new WeakMap();
|
|
412
390
|
_headerUpdateTimer = new WeakMap();
|
|
413
391
|
_pendingHeaderText = new WeakMap();
|
|
414
392
|
_isAnimating = new WeakMap();
|
|
393
|
+
_onStatusChange = new WeakMap();
|
|
394
|
+
_onHistoryChange = new WeakMap();
|
|
395
|
+
_onActivity = new WeakMap();
|
|
396
|
+
_onAgentDispose = new WeakMap();
|
|
415
397
|
_Panel_instances = new WeakSet();
|
|
416
|
-
// ==========
|
|
398
|
+
// ========== Agent event handlers ==========
|
|
399
|
+
/** Handle agent status change */
|
|
400
|
+
handleStatusChange_fn = /* @__PURE__ */ __name(function() {
|
|
401
|
+
const status = __privateGet(this, _agent).status;
|
|
402
|
+
const indicatorType = status === "running" ? "thinking" : status === "idle" ? "thinking" : status;
|
|
403
|
+
__privateMethod(this, _Panel_instances, updateStatusIndicator_fn).call(this, indicatorType);
|
|
404
|
+
if (status === "running") {
|
|
405
|
+
this.show();
|
|
406
|
+
__privateMethod(this, _Panel_instances, hideInputArea_fn).call(this);
|
|
407
|
+
}
|
|
408
|
+
if (status === "completed" || status === "error") {
|
|
409
|
+
if (!__privateGet(this, _isExpanded)) {
|
|
410
|
+
__privateMethod(this, _Panel_instances, expand_fn).call(this);
|
|
411
|
+
}
|
|
412
|
+
if (__privateMethod(this, _Panel_instances, shouldShowInputArea_fn).call(this)) {
|
|
413
|
+
__privateMethod(this, _Panel_instances, showInputArea_fn).call(this);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}, "#handleStatusChange");
|
|
417
|
+
/** Handle agent history change - re-render history list from agent.history */
|
|
418
|
+
handleHistoryChange_fn = /* @__PURE__ */ __name(function() {
|
|
419
|
+
__privateMethod(this, _Panel_instances, renderHistory_fn).call(this);
|
|
420
|
+
}, "#handleHistoryChange");
|
|
417
421
|
/**
|
|
418
|
-
*
|
|
422
|
+
* Handle agent activity - transient state for immediate UI feedback
|
|
423
|
+
* Activity events are NOT persisted in history, only used for header bar updates
|
|
419
424
|
*/
|
|
420
|
-
|
|
421
|
-
switch (
|
|
425
|
+
handleActivity_fn = /* @__PURE__ */ __name(function(activity) {
|
|
426
|
+
switch (activity.type) {
|
|
422
427
|
case "thinking":
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
case "
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
return { type: "retry", displayText: `retry-ing (${data.current} / ${data.max})` };
|
|
428
|
+
__privateSet(this, _pendingHeaderText, __privateGet(this, _i18n).t("ui.panel.thinking"));
|
|
429
|
+
__privateMethod(this, _Panel_instances, updateStatusIndicator_fn).call(this, "thinking");
|
|
430
|
+
break;
|
|
431
|
+
case "executing":
|
|
432
|
+
__privateSet(this, _pendingHeaderText, __privateMethod(this, _Panel_instances, getToolExecutingText_fn).call(this, activity.tool, activity.input));
|
|
433
|
+
__privateMethod(this, _Panel_instances, updateStatusIndicator_fn).call(this, "executing");
|
|
434
|
+
break;
|
|
435
|
+
case "executed":
|
|
436
|
+
__privateSet(this, _pendingHeaderText, truncate(activity.output, 50));
|
|
437
|
+
break;
|
|
438
|
+
case "retrying":
|
|
439
|
+
__privateSet(this, _pendingHeaderText, `Retrying (${activity.attempt}/${activity.maxAttempts})`);
|
|
440
|
+
__privateMethod(this, _Panel_instances, updateStatusIndicator_fn).call(this, "retrying");
|
|
441
|
+
break;
|
|
438
442
|
case "error":
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
case "completed":
|
|
443
|
-
return { type: "completed", displayText: __privateGet(this, _i18n).t("ui.panel.taskCompleted") };
|
|
444
|
-
case "toolExecuting":
|
|
445
|
-
return {
|
|
446
|
-
type: "tool_executing",
|
|
447
|
-
toolName: data.toolName,
|
|
448
|
-
toolArgs: data.args,
|
|
449
|
-
displayText: __privateMethod(this, _Panel_instances, getToolExecutingText_fn).call(this, data.toolName, data.args)
|
|
450
|
-
};
|
|
451
|
-
case "toolCompleted": {
|
|
452
|
-
const displayText = __privateMethod(this, _Panel_instances, getToolCompletedText_fn).call(this, data.toolName, data.args);
|
|
453
|
-
if (!displayText) return { type: "tool_executing", displayText: "" };
|
|
454
|
-
return {
|
|
455
|
-
type: "tool_executing",
|
|
456
|
-
toolName: data.toolName,
|
|
457
|
-
toolArgs: data.args,
|
|
458
|
-
toolResult: data.result,
|
|
459
|
-
displayText,
|
|
460
|
-
duration: data.duration
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
case "observation":
|
|
464
|
-
return { type: "observation", displayText: data.content };
|
|
443
|
+
__privateSet(this, _pendingHeaderText, truncate(activity.message, 50));
|
|
444
|
+
__privateMethod(this, _Panel_instances, updateStatusIndicator_fn).call(this, "error");
|
|
445
|
+
break;
|
|
465
446
|
}
|
|
466
|
-
}, "#
|
|
447
|
+
}, "#handleActivity");
|
|
448
|
+
/**
|
|
449
|
+
* Ask for user input (internal, called by agent via onAskUser)
|
|
450
|
+
*/
|
|
451
|
+
askUser_fn = /* @__PURE__ */ __name(function(question2) {
|
|
452
|
+
return new Promise((resolve) => {
|
|
453
|
+
__privateSet(this, _isWaitingForUserAnswer, true);
|
|
454
|
+
__privateSet(this, _userAnswerResolver, resolve);
|
|
455
|
+
if (!__privateGet(this, _isExpanded)) {
|
|
456
|
+
__privateMethod(this, _Panel_instances, expand_fn).call(this);
|
|
457
|
+
}
|
|
458
|
+
const tempCard = document.createElement("div");
|
|
459
|
+
tempCard.innerHTML = createCard({
|
|
460
|
+
icon: "❓",
|
|
461
|
+
content: `Question: ${question2}`,
|
|
462
|
+
meta: formatTime(__privateGet(this, _config).language ?? "en-US"),
|
|
463
|
+
type: "question"
|
|
464
|
+
});
|
|
465
|
+
const cardElement = tempCard.firstElementChild;
|
|
466
|
+
cardElement.setAttribute("data-temp-card", "true");
|
|
467
|
+
__privateGet(this, _historySection).appendChild(cardElement);
|
|
468
|
+
__privateMethod(this, _Panel_instances, scrollToBottom_fn).call(this);
|
|
469
|
+
__privateMethod(this, _Panel_instances, showInputArea_fn).call(this, __privateGet(this, _i18n).t("ui.panel.userAnswerPrompt"));
|
|
470
|
+
});
|
|
471
|
+
}, "#askUser");
|
|
472
|
+
// ========== Private methods ==========
|
|
467
473
|
getToolExecutingText_fn = /* @__PURE__ */ __name(function(toolName, args) {
|
|
474
|
+
const a = args;
|
|
468
475
|
switch (toolName) {
|
|
469
476
|
case "click_element_by_index":
|
|
470
|
-
return __privateGet(this, _i18n).t("ui.tools.clicking", { index:
|
|
477
|
+
return __privateGet(this, _i18n).t("ui.tools.clicking", { index: a.index });
|
|
471
478
|
case "input_text":
|
|
472
|
-
return __privateGet(this, _i18n).t("ui.tools.inputting", { index:
|
|
479
|
+
return __privateGet(this, _i18n).t("ui.tools.inputting", { index: a.index });
|
|
473
480
|
case "select_dropdown_option":
|
|
474
|
-
return __privateGet(this, _i18n).t("ui.tools.selecting", { text:
|
|
481
|
+
return __privateGet(this, _i18n).t("ui.tools.selecting", { text: a.text });
|
|
475
482
|
case "scroll":
|
|
476
483
|
return __privateGet(this, _i18n).t("ui.tools.scrolling");
|
|
477
484
|
case "wait":
|
|
478
|
-
return __privateGet(this, _i18n).t("ui.tools.waiting", { seconds:
|
|
485
|
+
return __privateGet(this, _i18n).t("ui.tools.waiting", { seconds: a.seconds });
|
|
486
|
+
case "ask_user":
|
|
487
|
+
return __privateGet(this, _i18n).t("ui.tools.askingUser");
|
|
479
488
|
case "done":
|
|
480
489
|
return __privateGet(this, _i18n).t("ui.tools.done");
|
|
481
490
|
default:
|
|
482
491
|
return __privateGet(this, _i18n).t("ui.tools.executing", { toolName });
|
|
483
492
|
}
|
|
484
493
|
}, "#getToolExecutingText");
|
|
485
|
-
getToolCompletedText_fn = /* @__PURE__ */ __name(function(toolName, args) {
|
|
486
|
-
switch (toolName) {
|
|
487
|
-
case "click_element_by_index":
|
|
488
|
-
return __privateGet(this, _i18n).t("ui.tools.clicked", { index: args.index });
|
|
489
|
-
case "input_text":
|
|
490
|
-
return __privateGet(this, _i18n).t("ui.tools.inputted", { text: args.text });
|
|
491
|
-
case "select_dropdown_option":
|
|
492
|
-
return __privateGet(this, _i18n).t("ui.tools.selected", { text: args.text });
|
|
493
|
-
case "scroll":
|
|
494
|
-
return __privateGet(this, _i18n).t("ui.tools.scrolled");
|
|
495
|
-
case "wait":
|
|
496
|
-
return __privateGet(this, _i18n).t("ui.tools.waited");
|
|
497
|
-
case "done":
|
|
498
|
-
return null;
|
|
499
|
-
default:
|
|
500
|
-
return null;
|
|
501
|
-
}
|
|
502
|
-
}, "#getToolCompletedText");
|
|
503
|
-
/**
|
|
504
|
-
* Update status (internal)
|
|
505
|
-
*/
|
|
506
|
-
updateInternal_fn = /* @__PURE__ */ __name(function(stepData) {
|
|
507
|
-
if (!stepData.displayText) return;
|
|
508
|
-
const step = __privateGet(this, _state).addStep(stepData);
|
|
509
|
-
const headerText = truncate(step.displayText, 20);
|
|
510
|
-
__privateSet(this, _pendingHeaderText, headerText);
|
|
511
|
-
__privateMethod(this, _Panel_instances, updateStatusIndicator_fn).call(this, step.type);
|
|
512
|
-
__privateMethod(this, _Panel_instances, updateHistory_fn).call(this);
|
|
513
|
-
if (step.type === "completed" || step.type === "error") {
|
|
514
|
-
if (!__privateGet(this, _isExpanded)) {
|
|
515
|
-
__privateMethod(this, _Panel_instances, expand_fn).call(this);
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
if (__privateMethod(this, _Panel_instances, shouldShowInputArea_fn).call(this)) {
|
|
519
|
-
__privateMethod(this, _Panel_instances, showInputArea_fn).call(this);
|
|
520
|
-
} else {
|
|
521
|
-
__privateMethod(this, _Panel_instances, hideInputArea_fn).call(this);
|
|
522
|
-
}
|
|
523
|
-
}, "#updateInternal");
|
|
524
494
|
/**
|
|
525
495
|
* Stop Agent
|
|
526
496
|
*/
|
|
527
497
|
stopAgent_fn = /* @__PURE__ */ __name(function() {
|
|
528
|
-
|
|
529
|
-
type: "error",
|
|
530
|
-
displayText: __privateGet(this, _i18n).t("ui.panel.taskTerminated")
|
|
531
|
-
});
|
|
532
|
-
__privateGet(this, _config).onStop();
|
|
498
|
+
__privateGet(this, _agent).dispose();
|
|
533
499
|
}, "#stopAgent");
|
|
534
500
|
/**
|
|
535
501
|
* Submit task
|
|
@@ -541,16 +507,17 @@ submitTask_fn = /* @__PURE__ */ __name(function() {
|
|
|
541
507
|
if (__privateGet(this, _isWaitingForUserAnswer)) {
|
|
542
508
|
__privateMethod(this, _Panel_instances, handleUserAnswer_fn).call(this, input2);
|
|
543
509
|
} else {
|
|
544
|
-
__privateGet(this,
|
|
510
|
+
__privateGet(this, _agent).execute(input2);
|
|
545
511
|
}
|
|
546
512
|
}, "#submitTask");
|
|
547
513
|
/**
|
|
548
514
|
* Handle user answer
|
|
549
515
|
*/
|
|
550
516
|
handleUserAnswer_fn = /* @__PURE__ */ __name(function(input2) {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
517
|
+
Array.from(__privateGet(this, _historySection).children).forEach((child) => {
|
|
518
|
+
if (child.getAttribute("data-temp-card") === "true") {
|
|
519
|
+
child.remove();
|
|
520
|
+
}
|
|
554
521
|
});
|
|
555
522
|
__privateSet(this, _isWaitingForUserAnswer, false);
|
|
556
523
|
if (__privateGet(this, _userAnswerResolver)) {
|
|
@@ -580,12 +547,16 @@ hideInputArea_fn = /* @__PURE__ */ __name(function() {
|
|
|
580
547
|
*/
|
|
581
548
|
shouldShowInputArea_fn = /* @__PURE__ */ __name(function() {
|
|
582
549
|
if (__privateGet(this, _isWaitingForUserAnswer)) return true;
|
|
583
|
-
const
|
|
584
|
-
if (
|
|
550
|
+
const history = __privateGet(this, _agent).history;
|
|
551
|
+
if (history.length === 0) {
|
|
585
552
|
return true;
|
|
586
553
|
}
|
|
587
|
-
const
|
|
588
|
-
|
|
554
|
+
const status = __privateGet(this, _agent).status;
|
|
555
|
+
const isTaskEnded = status === "completed" || status === "error";
|
|
556
|
+
if (isTaskEnded) {
|
|
557
|
+
return __privateGet(this, _config).promptForNextTask ?? true;
|
|
558
|
+
}
|
|
559
|
+
return false;
|
|
589
560
|
}, "#shouldShowInputArea");
|
|
590
561
|
createWrapper_fn = /* @__PURE__ */ __name(function() {
|
|
591
562
|
const wrapper2 = document.createElement("div");
|
|
@@ -596,13 +567,12 @@ createWrapper_fn = /* @__PURE__ */ __name(function() {
|
|
|
596
567
|
<div class="${styles.background}"></div>
|
|
597
568
|
<div class="${styles.historySectionWrapper}">
|
|
598
569
|
<div class="${styles.historySection}">
|
|
599
|
-
${
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
})}
|
|
570
|
+
<div class="${styles.historyItem}">
|
|
571
|
+
<div class="${styles.historyContent}">
|
|
572
|
+
<span class="${styles.statusIcon}">🧠</span>
|
|
573
|
+
<span>${__privateGet(this, _i18n).t("ui.panel.waitingPlaceholder")}</span>
|
|
574
|
+
</div>
|
|
575
|
+
</div>
|
|
606
576
|
</div>
|
|
607
577
|
</div>
|
|
608
578
|
<div class="${styles.header}">
|
|
@@ -728,80 +698,100 @@ updateStatusIndicator_fn = /* @__PURE__ */ __name(function(type) {
|
|
|
728
698
|
__privateGet(this, _indicator).className = styles.indicator;
|
|
729
699
|
__privateGet(this, _indicator).classList.add(styles[type]);
|
|
730
700
|
}, "#updateStatusIndicator");
|
|
731
|
-
updateHistory_fn = /* @__PURE__ */ __name(function() {
|
|
732
|
-
const steps = __privateGet(this, _state).getAllSteps();
|
|
733
|
-
__privateGet(this, _historySection).innerHTML = steps.map((step) => __privateMethod(this, _Panel_instances, createHistoryItem_fn).call(this, step)).join("");
|
|
734
|
-
__privateMethod(this, _Panel_instances, scrollToBottom_fn).call(this);
|
|
735
|
-
}, "#updateHistory");
|
|
736
701
|
scrollToBottom_fn = /* @__PURE__ */ __name(function() {
|
|
737
702
|
setTimeout(() => {
|
|
738
703
|
__privateGet(this, _historySection).scrollTop = __privateGet(this, _historySection).scrollHeight;
|
|
739
704
|
}, 0);
|
|
740
705
|
}, "#scrollToBottom");
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
706
|
+
/**
|
|
707
|
+
* Render history directly from agent.history
|
|
708
|
+
*
|
|
709
|
+
* Renders:
|
|
710
|
+
* 1. Task (first item, from agent.task)
|
|
711
|
+
* 2. Reflection cards (evaluation, memory, next_goal)
|
|
712
|
+
* 3. Tool execution with output
|
|
713
|
+
* 4. Observations
|
|
714
|
+
*/
|
|
715
|
+
renderHistory_fn = /* @__PURE__ */ __name(function() {
|
|
716
|
+
const items = [];
|
|
717
|
+
const task = __privateGet(this, _agent).task;
|
|
718
|
+
if (task) {
|
|
719
|
+
items.push(__privateMethod(this, _Panel_instances, createTaskCard_fn).call(this, task));
|
|
720
|
+
}
|
|
721
|
+
const history = __privateGet(this, _agent).history;
|
|
722
|
+
for (let i = 0; i < history.length; i++) {
|
|
723
|
+
const event = history[i];
|
|
724
|
+
items.push(...__privateMethod(this, _Panel_instances, createHistoryCards_fn).call(this, event, i + 1));
|
|
725
|
+
}
|
|
726
|
+
__privateGet(this, _historySection).innerHTML = items.join("");
|
|
727
|
+
__privateMethod(this, _Panel_instances, scrollToBottom_fn).call(this);
|
|
728
|
+
}, "#renderHistory");
|
|
729
|
+
createTaskCard_fn = /* @__PURE__ */ __name(function(task) {
|
|
730
|
+
return createCard({ icon: "🎯", content: task, type: "input" });
|
|
731
|
+
}, "#createTaskCard");
|
|
732
|
+
/** Create cards for a history event */
|
|
733
|
+
createHistoryCards_fn = /* @__PURE__ */ __name(function(event, stepNumber) {
|
|
734
|
+
const cards = [];
|
|
735
|
+
const time = formatTime(__privateGet(this, _config).language ?? "en-US");
|
|
736
|
+
const meta = __privateGet(this, _i18n).t("ui.panel.step", {
|
|
737
|
+
number: stepNumber.toString(),
|
|
738
|
+
time,
|
|
739
|
+
duration: ""
|
|
747
740
|
});
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
741
|
+
if (event.type === "step") {
|
|
742
|
+
if (event.reflection) {
|
|
743
|
+
const lines = createReflectionLines(event.reflection);
|
|
744
|
+
if (lines.length > 0) {
|
|
745
|
+
cards.push(createCard({ icon: "🧠", content: lines, meta }));
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
const action = event.action;
|
|
749
|
+
if (action) {
|
|
750
|
+
cards.push(...__privateMethod(this, _Panel_instances, createActionCards_fn).call(this, action, meta));
|
|
751
|
+
}
|
|
752
|
+
} else if (event.type === "observation") {
|
|
753
|
+
cards.push(
|
|
754
|
+
createCard({ icon: "👁️", content: event.content || "", meta, type: "observation" })
|
|
755
|
+
);
|
|
756
|
+
} else if (event.type === "user_takeover") {
|
|
757
|
+
cards.push(createCard({ icon: "👤", content: "User takeover", meta, type: "input" }));
|
|
758
|
+
}
|
|
759
|
+
return cards;
|
|
760
|
+
}, "#createHistoryCards");
|
|
761
|
+
/** Create cards for an action */
|
|
762
|
+
createActionCards_fn = /* @__PURE__ */ __name(function(action, meta) {
|
|
763
|
+
const cards = [];
|
|
764
|
+
if (action.name === "done") {
|
|
765
|
+
const input2 = action.input;
|
|
766
|
+
const text = input2.text || action.output || "";
|
|
767
|
+
if (text) {
|
|
768
|
+
cards.push(createCard({ icon: "🤖", content: text, meta, type: "output" }));
|
|
760
769
|
}
|
|
761
|
-
} else if (
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
typeClass = styles.retry;
|
|
774
|
-
statusIcon2 = "🔄";
|
|
775
|
-
} else if (step.type === "observation") {
|
|
776
|
-
typeClass = styles.observation;
|
|
777
|
-
statusIcon2 = "👁️";
|
|
770
|
+
} else if (action.name === "ask_user") {
|
|
771
|
+
const input2 = action.input;
|
|
772
|
+
const answer = action.output.replace(/^User answered:\s*/i, "");
|
|
773
|
+
cards.push(
|
|
774
|
+
createCard({
|
|
775
|
+
icon: "❓",
|
|
776
|
+
content: `Question: ${input2.question || ""}`,
|
|
777
|
+
meta,
|
|
778
|
+
type: "question"
|
|
779
|
+
})
|
|
780
|
+
);
|
|
781
|
+
cards.push(createCard({ icon: "💬", content: `Answer: ${answer}`, meta, type: "input" }));
|
|
778
782
|
} else {
|
|
779
|
-
|
|
783
|
+
const toolText = __privateMethod(this, _Panel_instances, getToolExecutingText_fn).call(this, action.name, action.input);
|
|
784
|
+
cards.push(createCard({ icon: "🔨", content: toolText, meta }));
|
|
785
|
+
if (action.output?.length > 0) {
|
|
786
|
+
cards.push(createCard({ icon: "🔨", content: action.output, meta, type: "output" }));
|
|
787
|
+
}
|
|
780
788
|
}
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
number: step.stepNumber.toString(),
|
|
784
|
-
time,
|
|
785
|
-
duration: durationText || ""
|
|
786
|
-
// Explicitly pass empty string to replace template
|
|
787
|
-
});
|
|
788
|
-
return `
|
|
789
|
-
<div class="${styles.historyItem} ${typeClass}">
|
|
790
|
-
<div class="${styles.historyContent}">
|
|
791
|
-
<span class="${styles.statusIcon}">${statusIcon2}</span>
|
|
792
|
-
<span>${escapeHtml(step.displayText)}</span>
|
|
793
|
-
</div>
|
|
794
|
-
<div class="${styles.historyMeta}">
|
|
795
|
-
${stepLabel}
|
|
796
|
-
</div>
|
|
797
|
-
</div>
|
|
798
|
-
`;
|
|
799
|
-
}, "#createHistoryItem");
|
|
789
|
+
return cards;
|
|
790
|
+
}, "#createActionCards");
|
|
800
791
|
__name(_Panel, "Panel");
|
|
801
792
|
let Panel = _Panel;
|
|
802
793
|
export {
|
|
803
794
|
I18n,
|
|
804
|
-
Panel
|
|
805
|
-
UIState
|
|
795
|
+
Panel
|
|
806
796
|
};
|
|
807
797
|
//# sourceMappingURL=page-agent-ui.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-agent-ui.js","sources":["../../src/UIState.ts","../../src/i18n/locales.ts","../../src/i18n/index.ts","../../src/utils.ts","../../src/Panel.ts"],"sourcesContent":["/**\n * Agent execution state management\n */\n\nexport interface Step {\n\tid: string\n\tstepNumber: number\n\ttimestamp: Date\n\ttype:\n\t\t| 'thinking'\n\t\t| 'tool_executing'\n\t\t| 'completed'\n\t\t| 'error'\n\t\t| 'output'\n\t\t| 'input'\n\t\t| 'retry'\n\t\t| 'observation'\n\n\t// Tool execution related\n\ttoolName?: string\n\ttoolArgs?: any\n\ttoolResult?: any\n\n\t// Display data\n\tdisplayText: string\n\tduration?: number\n}\n\nexport type AgentStatus = 'idle' | 'running' | 'completed' | 'error'\n\nexport class UIState {\n\tprivate steps: Step[] = []\n\tprivate currentStep: Step | null = null\n\tprivate status: AgentStatus = 'idle'\n\tprivate stepCounter = 0\n\n\taddStep(stepData: Omit<Step, 'id' | 'stepNumber' | 'timestamp'>): Step {\n\t\tconst step: Step = {\n\t\t\tid: this.generateId(),\n\t\t\tstepNumber: ++this.stepCounter,\n\t\t\ttimestamp: new Date(),\n\t\t\t...stepData,\n\t\t}\n\n\t\tthis.steps.push(step)\n\t\tthis.currentStep = step\n\n\t\t// Update overall status\n\t\tthis.updateStatus(step.type)\n\n\t\treturn step\n\t}\n\n\tupdateCurrentStep(updates: Partial<Step>): Step | null {\n\t\tif (!this.currentStep) return null\n\n\t\tObject.assign(this.currentStep, updates)\n\t\treturn this.currentStep\n\t}\n\n\tgetCurrentStep(): Step | null {\n\t\treturn this.currentStep\n\t}\n\n\tgetAllSteps(): Step[] {\n\t\treturn [...this.steps]\n\t}\n\n\tgetStatus(): AgentStatus {\n\t\treturn this.status\n\t}\n\n\treset(): void {\n\t\tthis.steps = []\n\t\tthis.currentStep = null\n\t\tthis.status = 'idle'\n\t\tthis.stepCounter = 0\n\t}\n\n\tprivate updateStatus(stepType: Step['type']): void {\n\t\tswitch (stepType) {\n\t\t\tcase 'thinking':\n\t\t\tcase 'tool_executing':\n\t\t\tcase 'output':\n\t\t\tcase 'input':\n\t\t\tcase 'retry':\n\t\t\t\tthis.status = 'running'\n\t\t\t\tbreak\n\t\t\tcase 'completed':\n\t\t\t\tthis.status = 'completed'\n\t\t\t\tbreak\n\t\t\tcase 'error':\n\t\t\t\tthis.status = 'error'\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\tprivate generateId(): string {\n\t\treturn `step_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`\n\t}\n}\n","// English translations (base/reference language)\nconst enUS = {\n\tui: {\n\t\tpanel: {\n\t\t\tready: 'Ready',\n\t\t\tthinking: 'Thinking...',\n\t\t\ttaskInput: 'Enter new task, describe steps in detail, press Enter to submit',\n\t\t\tuserAnswerPrompt: 'Please answer the question above, press Enter to submit',\n\t\t\ttaskTerminated: 'Task terminated',\n\t\t\ttaskCompleted: 'Task completed',\n\t\t\tuserAnswer: 'User answer: {{input}}',\n\t\t\tquestion: 'Question: {{question}}',\n\t\t\twaitingPlaceholder: 'Waiting for task to start...',\n\t\t\tstop: 'Stop',\n\t\t\texpand: 'Expand history',\n\t\t\tcollapse: 'Collapse history',\n\t\t\tstep: 'Step {{number}} · {{time}}{{duration}}',\n\t\t},\n\t\ttools: {\n\t\t\tclicking: 'Clicking element [{{index}}]...',\n\t\t\tinputting: 'Inputting text to element [{{index}}]...',\n\t\t\tselecting: 'Selecting option \"{{text}}\"...',\n\t\t\tscrolling: 'Scrolling page...',\n\t\t\twaiting: 'Waiting {{seconds}} seconds...',\n\t\t\tdone: 'Task done',\n\t\t\tclicked: '🖱️ Clicked element [{{index}}]',\n\t\t\tinputted: '⌨️ Inputted text \"{{text}}\"',\n\t\t\tselected: '☑️ Selected option \"{{text}}\"',\n\t\t\tscrolled: '🛞 Page scrolled',\n\t\t\twaited: '⌛️ Wait completed',\n\t\t\texecuting: 'Executing {{toolName}}...',\n\t\t\tresultSuccess: 'success',\n\t\t\tresultFailure: 'failed',\n\t\t\tresultError: 'error',\n\t\t},\n\t\terrors: {\n\t\t\telementNotFound: 'No interactive element found at index {{index}}',\n\t\t\ttaskRequired: 'Task description is required',\n\t\t\texecutionFailed: 'Task execution failed',\n\t\t\tnotInputElement: 'Element is not an input or textarea',\n\t\t\tnotSelectElement: 'Element is not a select element',\n\t\t\toptionNotFound: 'Option \"{{text}}\" not found',\n\t\t},\n\t},\n} as const\n\n// Chinese translations (must match the structure of enUS)\nconst zhCN = {\n\tui: {\n\t\tpanel: {\n\t\t\tready: '准备就绪',\n\t\t\tthinking: '正在思考...',\n\t\t\ttaskInput: '输入新任务,详细描述步骤,回车提交',\n\t\t\tuserAnswerPrompt: '请回答上面问题,回车提交',\n\t\t\ttaskTerminated: '任务已终止',\n\t\t\ttaskCompleted: '任务结束',\n\t\t\tuserAnswer: '用户回答: {{input}}',\n\t\t\tquestion: '询问: {{question}}',\n\t\t\twaitingPlaceholder: '等待任务开始...',\n\t\t\tstop: '终止',\n\t\t\texpand: '展开历史',\n\t\t\tcollapse: '收起历史',\n\t\t\tstep: '步骤 {{number}} · {{time}}{{duration}}',\n\t\t},\n\t\ttools: {\n\t\t\tclicking: '正在点击元素 [{{index}}]...',\n\t\t\tinputting: '正在输入文本到元素 [{{index}}]...',\n\t\t\tselecting: '正在选择选项 \"{{text}}\"...',\n\t\t\tscrolling: '正在滚动页面...',\n\t\t\twaiting: '等待 {{seconds}} 秒...',\n\t\t\tdone: '结束任务',\n\t\t\tclicked: '🖱️ 已点击元素 [{{index}}]',\n\t\t\tinputted: '⌨️ 已输入文本 \"{{text}}\"',\n\t\t\tselected: '☑️ 已选择选项 \"{{text}}\"',\n\t\t\tscrolled: '🛞 页面滚动完成',\n\t\t\twaited: '⌛️ 等待完成',\n\t\t\texecuting: '正在执行 {{toolName}}...',\n\t\t\tresultSuccess: '成功',\n\t\t\tresultFailure: '失败',\n\t\t\tresultError: '错误',\n\t\t},\n\t\terrors: {\n\t\t\telementNotFound: '未找到索引为 {{index}} 的交互元素',\n\t\t\ttaskRequired: '任务描述不能为空',\n\t\t\texecutionFailed: '任务执行失败',\n\t\t\tnotInputElement: '元素不是输入框或文本域',\n\t\t\tnotSelectElement: '元素不是选择框',\n\t\t\toptionNotFound: '未找到选项 \"{{text}}\"',\n\t\t},\n\t},\n} as const\n\n// Type definitions generated from English base structure (but with string values)\ntype DeepStringify<T> = {\n\t[K in keyof T]: T[K] extends string ? string : T[K] extends object ? DeepStringify<T[K]> : T[K]\n}\n\nexport type TranslationSchema = DeepStringify<typeof enUS>\n\n// Utility type: Extract all nested paths from translation object\ntype NestedKeyOf<ObjectType extends object> = {\n\t[Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object\n\t\t? `${Key}` | `${Key}.${NestedKeyOf<ObjectType[Key]>}`\n\t\t: `${Key}`\n}[keyof ObjectType & (string | number)]\n\n// Extract all possible key paths from translation structure\nexport type TranslationKey = NestedKeyOf<TranslationSchema>\n\n// Parameterized translation types\nexport type TranslationParams = Record<string, string | number>\n\nexport const locales = {\n\t'en-US': enUS,\n\t'zh-CN': zhCN,\n} as const\n\nexport type SupportedLanguage = keyof typeof locales\n","import {\n\ttype SupportedLanguage,\n\ttype TranslationKey,\n\ttype TranslationParams,\n\ttype TranslationSchema,\n\tlocales,\n} from './locales'\n\nexport class I18n {\n\tprivate language: SupportedLanguage\n\tprivate translations: TranslationSchema\n\n\tconstructor(language: SupportedLanguage = 'en-US') {\n\t\tthis.language = language in locales ? language : 'en-US'\n\t\tthis.translations = locales[this.language]\n\t}\n\n\t// 类型安全的翻译方法\n\tt(key: TranslationKey, params?: TranslationParams): string {\n\t\tconst value = this.getNestedValue(this.translations, key)\n\t\tif (!value) {\n\t\t\tconsole.warn(`Translation key \"${key}\" not found for language \"${this.language}\"`)\n\t\t\treturn key\n\t\t}\n\n\t\tif (params) {\n\t\t\treturn this.interpolate(value, params)\n\t\t}\n\t\treturn value\n\t}\n\n\tprivate getNestedValue(obj: any, path: string): string | undefined {\n\t\treturn path.split('.').reduce((current, key) => current?.[key], obj)\n\t}\n\n\tprivate interpolate(template: string, params: TranslationParams): string {\n\t\treturn template.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key) => {\n\t\t\t// Use != null to check for both null and undefined, allow empty strings\n\t\t\treturn params[key] != null ? params[key].toString() : match\n\t\t})\n\t}\n\n\tgetLanguage(): SupportedLanguage {\n\t\treturn this.language\n\t}\n}\n\n// 导出类型和实例创建函数\nexport type { TranslationKey, SupportedLanguage, TranslationParams }\nexport { locales }\n","export function truncate(text: string, maxLength: number): string {\n\tif (text.length > maxLength) {\n\t\treturn text.substring(0, maxLength) + '...'\n\t}\n\treturn text\n}\n\n/**\n * Escape HTML special characters to prevent XSS and rendering issues\n */\nexport function escapeHtml(text: string): string {\n\treturn text\n\t\t.replace(/&/g, '&')\n\t\t.replace(/</g, '<')\n\t\t.replace(/>/g, '>')\n\t\t.replace(/\"/g, '"')\n\t\t.replace(/'/g, ''')\n}\n","import { type Step, UIState } from './UIState'\nimport { I18n, type SupportedLanguage } from './i18n'\nimport { escapeHtml, truncate } from './utils'\n\nimport styles from './Panel.module.css'\n\n/**\n * Panel configuration\n */\nexport interface PanelConfig {\n\tlanguage?: SupportedLanguage\n\tonExecuteTask: (task: string) => void\n\tonStop: () => void\n}\n\n/**\n * Semantic update types - Panel handles i18n internally\n */\nexport type PanelUpdate =\n\t| { type: 'thinking'; text?: string } // text is optional, defaults to i18n thinking text\n\t| { type: 'input'; task: string }\n\t| { type: 'question'; question: string }\n\t| { type: 'userAnswer'; input: string }\n\t| { type: 'retry'; current: number; max: number }\n\t| { type: 'error'; message: string }\n\t| { type: 'output'; text: string }\n\t| { type: 'completed' }\n\t| { type: 'toolExecuting'; toolName: string; args: any }\n\t| { type: 'toolCompleted'; toolName: string; args: any; result?: string; duration?: number }\n\t| { type: 'observation'; content: string }\n\n/**\n * Agent control panel\n */\nexport class Panel {\n\t#wrapper: HTMLElement\n\t#indicator: HTMLElement\n\t#statusText: HTMLElement\n\t#historySection: HTMLElement\n\t#expandButton: HTMLElement\n\t#stopButton: HTMLElement\n\t#inputSection: HTMLElement\n\t#taskInput: HTMLInputElement\n\n\t#state = new UIState()\n\t#isExpanded = false\n\t#config: PanelConfig\n\t#i18n: I18n\n\t#userAnswerResolver: ((input: string) => void) | null = null\n\t#isWaitingForUserAnswer: boolean = false\n\t#headerUpdateTimer: ReturnType<typeof setInterval> | null = null\n\t#pendingHeaderText: string | null = null\n\t#isAnimating = false\n\n\tget wrapper(): HTMLElement {\n\t\treturn this.#wrapper\n\t}\n\n\tconstructor(config: PanelConfig) {\n\t\tthis.#config = config\n\t\tthis.#i18n = new I18n(config.language ?? 'en-US')\n\t\tthis.#wrapper = this.#createWrapper()\n\t\tthis.#indicator = this.#wrapper.querySelector(`.${styles.indicator}`)!\n\t\tthis.#statusText = this.#wrapper.querySelector(`.${styles.statusText}`)!\n\t\tthis.#historySection = this.#wrapper.querySelector(`.${styles.historySection}`)!\n\t\tthis.#expandButton = this.#wrapper.querySelector(`.${styles.expandButton}`)!\n\t\tthis.#stopButton = this.#wrapper.querySelector(`.${styles.stopButton}`)!\n\t\tthis.#inputSection = this.#wrapper.querySelector(`.${styles.inputSectionWrapper}`)!\n\t\tthis.#taskInput = this.#wrapper.querySelector(`.${styles.taskInput}`)!\n\n\t\tthis.#setupEventListeners()\n\t\tthis.#startHeaderUpdateLoop()\n\n\t\tthis.#showInputArea()\n\n\t\tthis.hide() // Start hidden\n\t}\n\n\t/**\n\t * Ask for user input\n\t */\n\tasync askUser(question: string): Promise<string> {\n\t\treturn new Promise((resolve) => {\n\t\t\t// Set `waiting for user answer` state\n\t\t\tthis.#isWaitingForUserAnswer = true\n\t\t\tthis.#userAnswerResolver = resolve\n\n\t\t\t// Update state to `running`\n\t\t\tthis.#updateInternal({\n\t\t\t\ttype: 'output',\n\t\t\t\tdisplayText: this.#i18n.t('ui.panel.question', { question }),\n\t\t\t}) // Expand history panel\n\t\t\tif (!this.#isExpanded) {\n\t\t\t\tthis.#expand()\n\t\t\t}\n\n\t\t\tthis.#showInputArea(this.#i18n.t('ui.panel.userAnswerPrompt'))\n\t\t})\n\t}\n\n\t// ========== Public control methods ==========\n\n\tshow(): void {\n\t\tthis.wrapper.style.display = 'block'\n\t\tvoid this.wrapper.offsetHeight\n\t\tthis.wrapper.style.opacity = '1'\n\t\tthis.wrapper.style.transform = 'translateX(-50%) translateY(0)'\n\t}\n\n\thide(): void {\n\t\tthis.wrapper.style.opacity = '0'\n\t\tthis.wrapper.style.transform = 'translateX(-50%) translateY(20px)'\n\t\tthis.wrapper.style.display = 'none'\n\t}\n\n\treset(): void {\n\t\tthis.#state.reset()\n\t\tthis.#statusText.textContent = this.#i18n.t('ui.panel.ready')\n\t\tthis.#updateStatusIndicator('thinking')\n\t\tthis.#updateHistory()\n\t\tthis.#collapse()\n\t\t// Reset user input state\n\t\tthis.#isWaitingForUserAnswer = false\n\t\tthis.#userAnswerResolver = null\n\t\t// Show input area\n\t\tthis.#showInputArea()\n\t}\n\n\texpand(): void {\n\t\tthis.#expand()\n\t}\n\n\tcollapse(): void {\n\t\tthis.#collapse()\n\t}\n\n\t/**\n\t * Update panel with semantic data - i18n handled internally\n\t */\n\tupdate(data: PanelUpdate): void {\n\t\tconst stepData = this.#toStepData(data)\n\t\tthis.#updateInternal(stepData)\n\t}\n\n\t/**\n\t * Dispose panel\n\t */\n\tdispose(): void {\n\t\tthis.#isWaitingForUserAnswer = false\n\t\tthis.#stopHeaderUpdateLoop()\n\t\tthis.wrapper.remove()\n\t}\n\n\t// ========== Private methods ==========\n\n\t/**\n\t * Convert semantic update to step data with i18n\n\t */\n\t#toStepData(data: PanelUpdate): Omit<Step, 'id' | 'stepNumber' | 'timestamp'> {\n\t\tswitch (data.type) {\n\t\t\tcase 'thinking':\n\t\t\t\treturn { type: 'thinking', displayText: data.text ?? this.#i18n.t('ui.panel.thinking') }\n\t\t\tcase 'input':\n\t\t\t\treturn { type: 'input', displayText: data.task }\n\t\t\tcase 'question':\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'output',\n\t\t\t\t\tdisplayText: this.#i18n.t('ui.panel.question', { question: data.question }),\n\t\t\t\t}\n\t\t\tcase 'userAnswer':\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'input',\n\t\t\t\t\tdisplayText: this.#i18n.t('ui.panel.userAnswer', { input: data.input }),\n\t\t\t\t}\n\t\t\tcase 'retry':\n\t\t\t\treturn { type: 'retry', displayText: `retry-ing (${data.current} / ${data.max})` }\n\t\t\tcase 'error':\n\t\t\t\treturn { type: 'error', displayText: data.message }\n\t\t\tcase 'output':\n\t\t\t\treturn { type: 'output', displayText: data.text }\n\t\t\tcase 'completed':\n\t\t\t\treturn { type: 'completed', displayText: this.#i18n.t('ui.panel.taskCompleted') }\n\t\t\tcase 'toolExecuting':\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'tool_executing',\n\t\t\t\t\ttoolName: data.toolName,\n\t\t\t\t\ttoolArgs: data.args,\n\t\t\t\t\tdisplayText: this.#getToolExecutingText(data.toolName, data.args),\n\t\t\t\t}\n\t\t\tcase 'toolCompleted': {\n\t\t\t\tconst displayText = this.#getToolCompletedText(data.toolName, data.args)\n\t\t\t\tif (!displayText) return { type: 'tool_executing', displayText: '' } // will be filtered\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'tool_executing',\n\t\t\t\t\ttoolName: data.toolName,\n\t\t\t\t\ttoolArgs: data.args,\n\t\t\t\t\ttoolResult: data.result,\n\t\t\t\t\tdisplayText,\n\t\t\t\t\tduration: data.duration,\n\t\t\t\t}\n\t\t\t}\n\t\t\tcase 'observation':\n\t\t\t\treturn { type: 'observation', displayText: data.content }\n\t\t}\n\t}\n\n\t#getToolExecutingText(toolName: string, args: any): string {\n\t\tswitch (toolName) {\n\t\t\tcase 'click_element_by_index':\n\t\t\t\treturn this.#i18n.t('ui.tools.clicking', { index: args.index })\n\t\t\tcase 'input_text':\n\t\t\t\treturn this.#i18n.t('ui.tools.inputting', { index: args.index })\n\t\t\tcase 'select_dropdown_option':\n\t\t\t\treturn this.#i18n.t('ui.tools.selecting', { text: args.text })\n\t\t\tcase 'scroll':\n\t\t\t\treturn this.#i18n.t('ui.tools.scrolling')\n\t\t\tcase 'wait':\n\t\t\t\treturn this.#i18n.t('ui.tools.waiting', { seconds: args.seconds })\n\t\t\tcase 'done':\n\t\t\t\treturn this.#i18n.t('ui.tools.done')\n\t\t\tdefault:\n\t\t\t\treturn this.#i18n.t('ui.tools.executing', { toolName })\n\t\t}\n\t}\n\n\t#getToolCompletedText(toolName: string, args: any): string | null {\n\t\tswitch (toolName) {\n\t\t\tcase 'click_element_by_index':\n\t\t\t\treturn this.#i18n.t('ui.tools.clicked', { index: args.index })\n\t\t\tcase 'input_text':\n\t\t\t\treturn this.#i18n.t('ui.tools.inputted', { text: args.text })\n\t\t\tcase 'select_dropdown_option':\n\t\t\t\treturn this.#i18n.t('ui.tools.selected', { text: args.text })\n\t\t\tcase 'scroll':\n\t\t\t\treturn this.#i18n.t('ui.tools.scrolled')\n\t\t\tcase 'wait':\n\t\t\t\treturn this.#i18n.t('ui.tools.waited')\n\t\t\tcase 'done':\n\t\t\t\treturn null\n\t\t\tdefault:\n\t\t\t\treturn null\n\t\t}\n\t}\n\n\t/**\n\t * Update status (internal)\n\t */\n\t#updateInternal(stepData: Omit<Step, 'id' | 'stepNumber' | 'timestamp'>): void {\n\t\t// Skip empty displayText (filtered toolCompleted for 'done')\n\t\tif (!stepData.displayText) return\n\n\t\tconst step = this.#state.addStep(stepData)\n\n\t\t// Queue header text update (will be processed by periodic check)\n\t\tconst headerText = truncate(step.displayText, 20)\n\t\tthis.#pendingHeaderText = headerText\n\n\t\tthis.#updateStatusIndicator(step.type)\n\t\tthis.#updateHistory()\n\n\t\t// Auto-expand history after task completion\n\t\tif (step.type === 'completed' || step.type === 'error') {\n\t\t\tif (!this.#isExpanded) {\n\t\t\t\tthis.#expand()\n\t\t\t}\n\t\t}\n\n\t\t// Control input area display based on status\n\t\tif (this.#shouldShowInputArea()) {\n\t\t\tthis.#showInputArea()\n\t\t} else {\n\t\t\tthis.#hideInputArea()\n\t\t}\n\t}\n\n\t/**\n\t * Stop Agent\n\t */\n\t#stopAgent(): void {\n\t\t// Update status display\n\t\tthis.#updateInternal({\n\t\t\ttype: 'error',\n\t\t\tdisplayText: this.#i18n.t('ui.panel.taskTerminated'),\n\t\t})\n\n\t\tthis.#config.onStop()\n\t}\n\n\t/**\n\t * Submit task\n\t */\n\t#submitTask() {\n\t\tconst input = this.#taskInput.value.trim()\n\t\tif (!input) return\n\n\t\t// Hide input area\n\t\tthis.#hideInputArea()\n\n\t\tif (this.#isWaitingForUserAnswer) {\n\t\t\t// Handle user input mode\n\t\t\tthis.#handleUserAnswer(input)\n\t\t} else {\n\t\t\tthis.#config.onExecuteTask(input)\n\t\t}\n\t}\n\n\t/**\n\t * Handle user answer\n\t */\n\t#handleUserAnswer(input: string): void {\n\t\t// Add user input to history\n\t\tthis.#updateInternal({\n\t\t\ttype: 'input',\n\t\t\tdisplayText: this.#i18n.t('ui.panel.userAnswer', { input }),\n\t\t})\n\n\t\t// Reset state\n\t\tthis.#isWaitingForUserAnswer = false\n\n\t\t// Call resolver to return user input\n\t\tif (this.#userAnswerResolver) {\n\t\t\tthis.#userAnswerResolver(input)\n\t\t\tthis.#userAnswerResolver = null\n\t\t}\n\t}\n\n\t/**\n\t * Show input area\n\t */\n\t#showInputArea(placeholder?: string): void {\n\t\t// Clear input field\n\t\tthis.#taskInput.value = ''\n\t\tthis.#taskInput.placeholder = placeholder || this.#i18n.t('ui.panel.taskInput')\n\t\tthis.#inputSection.classList.remove(styles.hidden)\n\t\t// Focus on input field\n\t\tsetTimeout(() => {\n\t\t\tthis.#taskInput.focus()\n\t\t}, 100)\n\t}\n\n\t/**\n\t * Hide input area\n\t */\n\t#hideInputArea(): void {\n\t\tthis.#inputSection.classList.add(styles.hidden)\n\t}\n\n\t/**\n\t * Check if input area should be shown\n\t */\n\t#shouldShowInputArea(): boolean {\n\t\t// Always show input area if waiting for user input\n\t\tif (this.#isWaitingForUserAnswer) return true\n\n\t\tconst steps = this.#state.getAllSteps()\n\t\tif (steps.length === 0) {\n\t\t\treturn true // Initial state\n\t\t}\n\n\t\tconst lastStep = steps[steps.length - 1]\n\t\treturn lastStep.type === 'completed' || lastStep.type === 'error'\n\t}\n\n\t#createWrapper(): HTMLElement {\n\t\tconst wrapper = document.createElement('div')\n\t\twrapper.id = 'page-agent-runtime_agent-panel'\n\t\twrapper.className = styles.wrapper\n\t\twrapper.setAttribute('data-browser-use-ignore', 'true')\n\n\t\twrapper.innerHTML = `\n\t\t\t<div class=\"${styles.background}\"></div>\n\t\t\t<div class=\"${styles.historySectionWrapper}\">\n\t\t\t\t<div class=\"${styles.historySection}\">\n\t\t\t\t\t${this.#createHistoryItem({\n\t\t\t\t\t\tid: 'placeholder',\n\t\t\t\t\t\tstepNumber: 0,\n\t\t\t\t\t\ttimestamp: new Date(),\n\t\t\t\t\t\ttype: 'thinking',\n\t\t\t\t\t\tdisplayText: this.#i18n.t('ui.panel.waitingPlaceholder'),\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"${styles.header}\">\n\t\t\t\t<div class=\"${styles.statusSection}\">\n\t\t\t\t\t<div class=\"${styles.indicator} ${styles.thinking}\"></div>\n\t\t\t\t\t<div class=\"${styles.statusText}\">${this.#i18n.t('ui.panel.ready')}</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"${styles.controls}\">\n\t\t\t\t\t<button class=\"${styles.controlButton} ${styles.expandButton}\" title=\"${this.#i18n.t('ui.panel.expand')}\">\n\t\t\t\t\t\t▼\n\t\t\t\t\t</button>\n\t\t\t\t\t<button class=\"${styles.controlButton} ${styles.stopButton}\" title=\"${this.#i18n.t('ui.panel.stop')}\">\n\t\t\t\t\t\tX\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"${styles.inputSectionWrapper} ${styles.hidden}\">\n\t\t\t\t<div class=\"${styles.inputSection}\">\n\t\t\t\t\t<input \n\t\t\t\t\t\ttype=\"text\" \n\t\t\t\t\t\tclass=\"${styles.taskInput}\" \n\t\t\t\t\t\tmaxlength=\"200\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`\n\n\t\tdocument.body.appendChild(wrapper)\n\t\treturn wrapper\n\t}\n\n\t#setupEventListeners(): void {\n\t\t// Click header area to expand/collapse\n\t\tconst header = this.wrapper.querySelector(`.${styles.header}`)!\n\t\theader.addEventListener('click', (e) => {\n\t\t\t// Don't trigger expand/collapse if clicking on buttons\n\t\t\tif ((e.target as HTMLElement).closest(`.${styles.controlButton}`)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.#toggle()\n\t\t})\n\n\t\t// Expand button\n\t\tthis.#expandButton.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t\tthis.#toggle()\n\t\t})\n\n\t\t// Stop button\n\t\tthis.#stopButton.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t\tthis.#stopAgent()\n\t\t})\n\n\t\t// Submit on Enter key in input field\n\t\tthis.#taskInput.addEventListener('keydown', (e) => {\n\t\t\tif (e.isComposing) return // Ignore IME composition keys\n\t\t\tif (e.key === 'Enter') {\n\t\t\t\te.preventDefault()\n\t\t\t\tthis.#submitTask()\n\t\t\t}\n\t\t})\n\n\t\t// Prevent input area click event bubbling\n\t\tthis.#inputSection.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t})\n\t}\n\n\t#toggle(): void {\n\t\tif (this.#isExpanded) {\n\t\t\tthis.#collapse()\n\t\t} else {\n\t\t\tthis.#expand()\n\t\t}\n\t}\n\n\t#expand(): void {\n\t\tthis.#isExpanded = true\n\t\tthis.wrapper.classList.add(styles.expanded)\n\t\tthis.#expandButton.textContent = '▲'\n\t}\n\n\t#collapse(): void {\n\t\tthis.#isExpanded = false\n\t\tthis.wrapper.classList.remove(styles.expanded)\n\t\tthis.#expandButton.textContent = '▼'\n\t}\n\n\t/**\n\t * Start periodic header update loop\n\t */\n\t#startHeaderUpdateLoop(): void {\n\t\t// Check every 450ms (same as total animation duration)\n\t\tthis.#headerUpdateTimer = setInterval(() => {\n\t\t\tthis.#checkAndUpdateHeader()\n\t\t}, 450)\n\t}\n\n\t/**\n\t * Stop periodic header update loop\n\t */\n\t#stopHeaderUpdateLoop(): void {\n\t\tif (this.#headerUpdateTimer) {\n\t\t\tclearInterval(this.#headerUpdateTimer)\n\t\t\tthis.#headerUpdateTimer = null\n\t\t}\n\t}\n\n\t/**\n\t * Check if header needs update and trigger animation if not currently animating\n\t */\n\t#checkAndUpdateHeader(): void {\n\t\t// If no pending text or currently animating, skip\n\t\tif (!this.#pendingHeaderText || this.#isAnimating) {\n\t\t\treturn\n\t\t}\n\n\t\t// If text is already displayed, clear pending and skip\n\t\tif (this.#statusText.textContent === this.#pendingHeaderText) {\n\t\t\tthis.#pendingHeaderText = null\n\t\t\treturn\n\t\t}\n\n\t\t// Start animation\n\t\tconst textToShow = this.#pendingHeaderText\n\t\tthis.#pendingHeaderText = null\n\t\tthis.#animateTextChange(textToShow)\n\t}\n\n\t/**\n\t * Animate text change with fade out/in effect\n\t */\n\t#animateTextChange(newText: string): void {\n\t\tthis.#isAnimating = true\n\n\t\t// Fade out current text\n\t\tthis.#statusText.classList.add(styles.fadeOut)\n\n\t\tsetTimeout(() => {\n\t\t\t// Update text content\n\t\t\tthis.#statusText.textContent = newText\n\n\t\t\t// Fade in new text\n\t\t\tthis.#statusText.classList.remove(styles.fadeOut)\n\t\t\tthis.#statusText.classList.add(styles.fadeIn)\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.#statusText.classList.remove(styles.fadeIn)\n\t\t\t\tthis.#isAnimating = false\n\t\t\t}, 300)\n\t\t}, 150) // Half the duration of fade out animation\n\t}\n\n\t#updateStatusIndicator(type: Step['type']): void {\n\t\t// Clear all status classes\n\t\tthis.#indicator.className = styles.indicator\n\n\t\t// Add corresponding status class\n\t\tthis.#indicator.classList.add(styles[type])\n\t}\n\n\t#updateHistory(): void {\n\t\tconst steps = this.#state.getAllSteps()\n\t\tthis.#historySection.innerHTML = steps.map((step) => this.#createHistoryItem(step)).join('')\n\t\tthis.#scrollToBottom()\n\t}\n\n\t#scrollToBottom(): void {\n\t\t// Execute in next event loop to ensure DOM update completion\n\t\tsetTimeout(() => {\n\t\t\tthis.#historySection.scrollTop = this.#historySection.scrollHeight\n\t\t}, 0)\n\t}\n\n\t#createHistoryItem(step: Step): string {\n\t\tconst time = step.timestamp.toLocaleTimeString('zh-CN', {\n\t\t\thour12: false,\n\t\t\thour: '2-digit',\n\t\t\tminute: '2-digit',\n\t\t\tsecond: '2-digit',\n\t\t})\n\n\t\tlet typeClass = ''\n\t\tlet statusIcon = ''\n\n\t\t// Set styles and icons based on step type\n\t\tif (step.type === 'completed') {\n\t\t\t// Check if this is a result from done tool\n\t\t\tif (step.toolName === 'done') {\n\t\t\t\t// Judge success or failure based on result\n\t\t\t\tconst failureKeyword = this.#i18n.t('ui.tools.resultFailure')\n\t\t\t\tconst errorKeyword = this.#i18n.t('ui.tools.resultError')\n\t\t\t\tconst isSuccess =\n\t\t\t\t\t!step.toolResult ||\n\t\t\t\t\t(!step.toolResult.includes(failureKeyword) && !step.toolResult.includes(errorKeyword))\n\t\t\t\ttypeClass = isSuccess ? styles.doneSuccess : styles.doneError\n\t\t\t\tstatusIcon = isSuccess ? '🎉' : '❌'\n\t\t\t} else {\n\t\t\t\ttypeClass = styles.completed\n\t\t\t\tstatusIcon = '✅'\n\t\t\t}\n\t\t} else if (step.type === 'error') {\n\t\t\ttypeClass = styles.error\n\t\t\tstatusIcon = '❌'\n\t\t} else if (step.type === 'tool_executing') {\n\t\t\tstatusIcon = '🔨'\n\t\t} else if (step.type === 'output') {\n\t\t\ttypeClass = styles.output\n\t\t\tstatusIcon = '🤖'\n\t\t} else if (step.type === 'input') {\n\t\t\ttypeClass = styles.input\n\t\t\tstatusIcon = '🎯'\n\t\t} else if (step.type === 'retry') {\n\t\t\ttypeClass = styles.retry\n\t\t\tstatusIcon = '🔄'\n\t\t} else if (step.type === 'observation') {\n\t\t\ttypeClass = styles.observation\n\t\t\tstatusIcon = '👁️'\n\t\t} else {\n\t\t\tstatusIcon = '🧠'\n\t\t}\n\n\t\tconst durationText = step.duration ? ` · ${step.duration}ms` : ''\n\t\tconst stepLabel = this.#i18n.t('ui.panel.step', {\n\t\t\tnumber: step.stepNumber.toString(),\n\t\t\ttime,\n\t\t\tduration: durationText || '', // Explicitly pass empty string to replace template\n\t\t})\n\n\t\treturn `\n\t\t\t<div class=\"${styles.historyItem} ${typeClass}\">\n\t\t\t\t<div class=\"${styles.historyContent}\">\n\t\t\t\t\t<span class=\"${styles.statusIcon}\">${statusIcon}</span>\n\t\t\t\t\t<span>${escapeHtml(step.displayText)}</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"${styles.historyMeta}\">\n\t\t\t\t\t${stepLabel}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`\n\t}\n}\n"],"names":["input","wrapper","header","statusIcon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"page-agent-ui.js","sources":["../../src/i18n/locales.ts","../../src/i18n/index.ts","../../src/utils.ts","../../src/panel/cards.ts","../../src/panel/Panel.ts"],"sourcesContent":["// English translations (base/reference language)\nconst enUS = {\n\tui: {\n\t\tpanel: {\n\t\t\tready: 'Ready',\n\t\t\tthinking: 'Thinking...',\n\t\t\ttaskInput: 'Enter new task, describe steps in detail, press Enter to submit',\n\t\t\tuserAnswerPrompt: 'Please answer the question above, press Enter to submit',\n\t\t\ttaskTerminated: 'Task terminated',\n\t\t\ttaskCompleted: 'Task completed',\n\t\t\tuserAnswer: 'User answer: {{input}}',\n\t\t\tquestion: 'Question: {{question}}',\n\t\t\twaitingPlaceholder: 'Waiting for task to start...',\n\t\t\tstop: 'Stop',\n\t\t\texpand: 'Expand history',\n\t\t\tcollapse: 'Collapse history',\n\t\t\tstep: 'Step {{number}} · {{time}}{{duration}}',\n\t\t},\n\t\ttools: {\n\t\t\tclicking: 'Clicking element [{{index}}]...',\n\t\t\tinputting: 'Inputting text to element [{{index}}]...',\n\t\t\tselecting: 'Selecting option \"{{text}}\"...',\n\t\t\tscrolling: 'Scrolling page...',\n\t\t\twaiting: 'Waiting {{seconds}} seconds...',\n\t\t\taskingUser: 'Asking user...',\n\t\t\tdone: 'Task done',\n\t\t\tclicked: '🖱️ Clicked element [{{index}}]',\n\t\t\tinputted: '⌨️ Inputted text \"{{text}}\"',\n\t\t\tselected: '☑️ Selected option \"{{text}}\"',\n\t\t\tscrolled: '🛞 Page scrolled',\n\t\t\twaited: '⌛️ Wait completed',\n\t\t\texecuting: 'Executing {{toolName}}...',\n\t\t\tresultSuccess: 'success',\n\t\t\tresultFailure: 'failed',\n\t\t\tresultError: 'error',\n\t\t},\n\t\terrors: {\n\t\t\telementNotFound: 'No interactive element found at index {{index}}',\n\t\t\ttaskRequired: 'Task description is required',\n\t\t\texecutionFailed: 'Task execution failed',\n\t\t\tnotInputElement: 'Element is not an input or textarea',\n\t\t\tnotSelectElement: 'Element is not a select element',\n\t\t\toptionNotFound: 'Option \"{{text}}\" not found',\n\t\t},\n\t},\n} as const\n\n// Chinese translations (must match the structure of enUS)\nconst zhCN = {\n\tui: {\n\t\tpanel: {\n\t\t\tready: '准备就绪',\n\t\t\tthinking: '正在思考...',\n\t\t\ttaskInput: '输入新任务,详细描述步骤,回车提交',\n\t\t\tuserAnswerPrompt: '请回答上面问题,回车提交',\n\t\t\ttaskTerminated: '任务已终止',\n\t\t\ttaskCompleted: '任务结束',\n\t\t\tuserAnswer: '用户回答: {{input}}',\n\t\t\tquestion: '询问: {{question}}',\n\t\t\twaitingPlaceholder: '等待任务开始...',\n\t\t\tstop: '终止',\n\t\t\texpand: '展开历史',\n\t\t\tcollapse: '收起历史',\n\t\t\tstep: '步骤 {{number}} · {{time}}{{duration}}',\n\t\t},\n\t\ttools: {\n\t\t\tclicking: '正在点击元素 [{{index}}]...',\n\t\t\tinputting: '正在输入文本到元素 [{{index}}]...',\n\t\t\tselecting: '正在选择选项 \"{{text}}\"...',\n\t\t\tscrolling: '正在滚动页面...',\n\t\t\twaiting: '等待 {{seconds}} 秒...',\n\t\t\taskingUser: '正在询问用户...',\n\t\t\tdone: '结束任务',\n\t\t\tclicked: '🖱️ 已点击元素 [{{index}}]',\n\t\t\tinputted: '⌨️ 已输入文本 \"{{text}}\"',\n\t\t\tselected: '☑️ 已选择选项 \"{{text}}\"',\n\t\t\tscrolled: '🛞 页面滚动完成',\n\t\t\twaited: '⌛️ 等待完成',\n\t\t\texecuting: '正在执行 {{toolName}}...',\n\t\t\tresultSuccess: '成功',\n\t\t\tresultFailure: '失败',\n\t\t\tresultError: '错误',\n\t\t},\n\t\terrors: {\n\t\t\telementNotFound: '未找到索引为 {{index}} 的交互元素',\n\t\t\ttaskRequired: '任务描述不能为空',\n\t\t\texecutionFailed: '任务执行失败',\n\t\t\tnotInputElement: '元素不是输入框或文本域',\n\t\t\tnotSelectElement: '元素不是选择框',\n\t\t\toptionNotFound: '未找到选项 \"{{text}}\"',\n\t\t},\n\t},\n} as const\n\n// Type definitions generated from English base structure (but with string values)\ntype DeepStringify<T> = {\n\t[K in keyof T]: T[K] extends string ? string : T[K] extends object ? DeepStringify<T[K]> : T[K]\n}\n\nexport type TranslationSchema = DeepStringify<typeof enUS>\n\n// Utility type: Extract all nested paths from translation object\ntype NestedKeyOf<ObjectType extends object> = {\n\t[Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object\n\t\t? `${Key}` | `${Key}.${NestedKeyOf<ObjectType[Key]>}`\n\t\t: `${Key}`\n}[keyof ObjectType & (string | number)]\n\n// Extract all possible key paths from translation structure\nexport type TranslationKey = NestedKeyOf<TranslationSchema>\n\n// Parameterized translation types\nexport type TranslationParams = Record<string, string | number>\n\nexport const locales = {\n\t'en-US': enUS,\n\t'zh-CN': zhCN,\n} as const\n\nexport type SupportedLanguage = keyof typeof locales\n","import {\n\ttype SupportedLanguage,\n\ttype TranslationKey,\n\ttype TranslationParams,\n\ttype TranslationSchema,\n\tlocales,\n} from './locales'\n\nexport class I18n {\n\tprivate language: SupportedLanguage\n\tprivate translations: TranslationSchema\n\n\tconstructor(language: SupportedLanguage = 'en-US') {\n\t\tthis.language = language in locales ? language : 'en-US'\n\t\tthis.translations = locales[this.language]\n\t}\n\n\t// 类型安全的翻译方法\n\tt(key: TranslationKey, params?: TranslationParams): string {\n\t\tconst value = this.getNestedValue(this.translations, key)\n\t\tif (!value) {\n\t\t\tconsole.warn(`Translation key \"${key}\" not found for language \"${this.language}\"`)\n\t\t\treturn key\n\t\t}\n\n\t\tif (params) {\n\t\t\treturn this.interpolate(value, params)\n\t\t}\n\t\treturn value\n\t}\n\n\tprivate getNestedValue(obj: any, path: string): string | undefined {\n\t\treturn path.split('.').reduce((current, key) => current?.[key], obj)\n\t}\n\n\tprivate interpolate(template: string, params: TranslationParams): string {\n\t\treturn template.replace(/\\{\\{(\\w+)\\}\\}/g, (match, key) => {\n\t\t\t// Use != null to check for both null and undefined, allow empty strings\n\t\t\treturn params[key] != null ? params[key].toString() : match\n\t\t})\n\t}\n\n\tgetLanguage(): SupportedLanguage {\n\t\treturn this.language\n\t}\n}\n\n// 导出类型和实例创建函数\nexport type { TranslationKey, SupportedLanguage, TranslationParams }\nexport { locales }\n","export function truncate(text: string, maxLength: number): string {\n\tif (text.length > maxLength) {\n\t\treturn text.substring(0, maxLength) + '...'\n\t}\n\treturn text\n}\n\n/**\n * Escape HTML special characters to prevent XSS and rendering issues\n */\nexport function escapeHtml(text: string): string {\n\treturn text\n\t\t.replace(/&/g, '&')\n\t\t.replace(/</g, '<')\n\t\t.replace(/>/g, '>')\n\t\t.replace(/\"/g, '"')\n\t\t.replace(/'/g, ''')\n}\n","/**\n * Card HTML generation utilities for Panel\n */\nimport { escapeHtml } from '../utils'\n\nimport styles from './Panel.module.css'\n\ntype CardType = 'default' | 'input' | 'output' | 'question' | 'observation'\n\ninterface CardOptions {\n\ticon: string\n\tcontent: string | string[]\n\tmeta?: string\n\ttype?: CardType\n}\n\n/** Create a single history card */\nexport function createCard({ icon, content, meta, type }: CardOptions): string {\n\tconst typeClass = type ? styles[type] : ''\n\tconst contentHtml = Array.isArray(content)\n\t\t? `<div class=\"${styles.reflectionLines}\">${content.join('')}</div>`\n\t\t: `<span>${escapeHtml(content)}</span>`\n\n\treturn `\n\t\t<div class=\"${styles.historyItem} ${typeClass}\">\n\t\t\t<div class=\"${styles.historyContent}\">\n\t\t\t\t<span class=\"${styles.statusIcon}\">${icon}</span>\n\t\t\t\t${contentHtml}\n\t\t\t</div>\n\t\t\t${meta ? `<div class=\"${styles.historyMeta}\">${meta}</div>` : ''}\n\t\t</div>\n\t`\n}\n\n/** Format timestamp for cards */\nexport function formatTime(locale: string = 'en-US'): string {\n\treturn new Date().toLocaleTimeString(locale, {\n\t\thour12: false,\n\t\thour: '2-digit',\n\t\tminute: '2-digit',\n\t\tsecond: '2-digit',\n\t})\n}\n\n/** Create reflection lines from reflection object */\nexport function createReflectionLines(reflection: {\n\tevaluation_previous_goal?: string\n\tmemory?: string\n\tnext_goal?: string\n}): string[] {\n\tconst lines: string[] = []\n\tif (reflection.evaluation_previous_goal) {\n\t\tlines.push(`<div>🔍 ${escapeHtml(reflection.evaluation_previous_goal)}</div>`)\n\t}\n\tif (reflection.memory) {\n\t\tlines.push(`<div>💾 ${escapeHtml(reflection.memory)}</div>`)\n\t}\n\tif (reflection.next_goal) {\n\t\tlines.push(`<div>🎯 ${escapeHtml(reflection.next_goal)}</div>`)\n\t}\n\treturn lines\n}\n","import { I18n, type SupportedLanguage } from '../i18n'\nimport { truncate } from '../utils'\nimport { createCard, createReflectionLines, formatTime } from './cards'\nimport type { AgentActivity, PanelAgentAdapter } from './types'\n\nimport styles from './Panel.module.css'\n\n/**\n * Panel configuration\n */\nexport interface PanelConfig {\n\tlanguage?: SupportedLanguage\n\t/**\n\t * Whether to prompt for next task after task completion\n\t * @default true\n\t */\n\tpromptForNextTask?: boolean\n}\n\n/**\n * Agent control panel\n *\n * Architecture:\n * - History list: renders directly from agent.history (historical events)\n * - Header bar: shows activity events (transient state) and agent status\n *\n * This separation ensures data consistency - history is the single source of truth\n * for what has been done, while activity shows what is happening now.\n */\nexport class Panel {\n\t#wrapper: HTMLElement\n\t#indicator: HTMLElement\n\t#statusText: HTMLElement\n\t#historySection: HTMLElement\n\t#expandButton: HTMLElement\n\t#stopButton: HTMLElement\n\t#inputSection: HTMLElement\n\t#taskInput: HTMLInputElement\n\n\t#agent: PanelAgentAdapter\n\t#config: PanelConfig\n\t#isExpanded = false\n\t#i18n: I18n\n\t#userAnswerResolver: ((input: string) => void) | null = null\n\t#isWaitingForUserAnswer: boolean = false\n\t#headerUpdateTimer: ReturnType<typeof setInterval> | null = null\n\t#pendingHeaderText: string | null = null\n\t#isAnimating = false\n\n\t// Event handlers (bound for removal)\n\t#onStatusChange = () => this.#handleStatusChange()\n\t#onHistoryChange = () => this.#handleHistoryChange()\n\t#onActivity = (e: Event) => this.#handleActivity((e as CustomEvent<AgentActivity>).detail)\n\t#onAgentDispose = () => this.dispose()\n\n\tget wrapper(): HTMLElement {\n\t\treturn this.#wrapper\n\t}\n\n\t/**\n\t * Create a Panel bound to an agent\n\t * @param agent - Agent instance that implements PanelAgentAdapter\n\t * @param config - Optional panel configuration\n\t */\n\tconstructor(agent: PanelAgentAdapter, config: PanelConfig = {}) {\n\t\tthis.#agent = agent\n\t\tthis.#config = config\n\t\tthis.#i18n = new I18n(config.language ?? 'en-US')\n\n\t\t// Set up askUser callback on agent\n\t\tthis.#agent.onAskUser = (question) => this.#askUser(question)\n\n\t\t// Create UI elements\n\t\tthis.#wrapper = this.#createWrapper()\n\t\tthis.#indicator = this.#wrapper.querySelector(`.${styles.indicator}`)!\n\t\tthis.#statusText = this.#wrapper.querySelector(`.${styles.statusText}`)!\n\t\tthis.#historySection = this.#wrapper.querySelector(`.${styles.historySection}`)!\n\t\tthis.#expandButton = this.#wrapper.querySelector(`.${styles.expandButton}`)!\n\t\tthis.#stopButton = this.#wrapper.querySelector(`.${styles.stopButton}`)!\n\t\tthis.#inputSection = this.#wrapper.querySelector(`.${styles.inputSectionWrapper}`)!\n\t\tthis.#taskInput = this.#wrapper.querySelector(`.${styles.taskInput}`)!\n\n\t\t// Listen to agent events\n\t\tthis.#agent.addEventListener('statuschange', this.#onStatusChange)\n\t\tthis.#agent.addEventListener('historychange', this.#onHistoryChange)\n\t\tthis.#agent.addEventListener('activity', this.#onActivity)\n\t\tthis.#agent.addEventListener('dispose', this.#onAgentDispose)\n\n\t\tthis.#setupEventListeners()\n\t\tthis.#startHeaderUpdateLoop()\n\n\t\tthis.#showInputArea()\n\n\t\tthis.hide() // Start hidden\n\t}\n\n\t// ========== Agent event handlers ==========\n\n\t/** Handle agent status change */\n\t#handleStatusChange(): void {\n\t\tconst status = this.#agent.status\n\n\t\t// Map agent status to UI indicator type\n\t\tconst indicatorType =\n\t\t\tstatus === 'running' ? 'thinking' : status === 'idle' ? 'thinking' : status\n\t\tthis.#updateStatusIndicator(indicatorType)\n\n\t\t// Show/hide based on status\n\t\tif (status === 'running') {\n\t\t\tthis.show()\n\t\t\tthis.#hideInputArea() // Hide input while running\n\t\t}\n\n\t\t// Handle completion\n\t\tif (status === 'completed' || status === 'error') {\n\t\t\tif (!this.#isExpanded) {\n\t\t\t\tthis.#expand()\n\t\t\t}\n\t\t\tif (this.#shouldShowInputArea()) {\n\t\t\t\tthis.#showInputArea()\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Handle agent history change - re-render history list from agent.history */\n\t#handleHistoryChange(): void {\n\t\tthis.#renderHistory()\n\t}\n\n\t/**\n\t * Handle agent activity - transient state for immediate UI feedback\n\t * Activity events are NOT persisted in history, only used for header bar updates\n\t */\n\t#handleActivity(activity: AgentActivity): void {\n\t\tswitch (activity.type) {\n\t\t\tcase 'thinking':\n\t\t\t\tthis.#pendingHeaderText = this.#i18n.t('ui.panel.thinking')\n\t\t\t\tthis.#updateStatusIndicator('thinking')\n\t\t\t\tbreak\n\n\t\t\tcase 'executing':\n\t\t\t\tthis.#pendingHeaderText = this.#getToolExecutingText(activity.tool, activity.input)\n\t\t\t\tthis.#updateStatusIndicator('executing')\n\t\t\t\tbreak\n\n\t\t\tcase 'executed':\n\t\t\t\tthis.#pendingHeaderText = truncate(activity.output, 50)\n\t\t\t\tbreak\n\n\t\t\tcase 'retrying':\n\t\t\t\tthis.#pendingHeaderText = `Retrying (${activity.attempt}/${activity.maxAttempts})`\n\t\t\t\tthis.#updateStatusIndicator('retrying')\n\t\t\t\tbreak\n\n\t\t\tcase 'error':\n\t\t\t\tthis.#pendingHeaderText = truncate(activity.message, 50)\n\t\t\t\tthis.#updateStatusIndicator('error')\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\t/**\n\t * Ask for user input (internal, called by agent via onAskUser)\n\t */\n\t#askUser(question: string): Promise<string> {\n\t\treturn new Promise((resolve) => {\n\t\t\t// Set `waiting for user answer` state\n\t\t\tthis.#isWaitingForUserAnswer = true\n\t\t\tthis.#userAnswerResolver = resolve\n\n\t\t\t// Expand history panel\n\t\t\tif (!this.#isExpanded) {\n\t\t\t\tthis.#expand()\n\t\t\t}\n\n\t\t\t// Add temporary question card so user can see the full question\n\t\t\tconst tempCard = document.createElement('div')\n\t\t\ttempCard.innerHTML = createCard({\n\t\t\t\ticon: '❓',\n\t\t\t\tcontent: `Question: ${question}`,\n\t\t\t\tmeta: formatTime(this.#config.language ?? 'en-US'),\n\t\t\t\ttype: 'question',\n\t\t\t})\n\t\t\tconst cardElement = tempCard.firstElementChild as HTMLElement\n\t\t\tcardElement.setAttribute('data-temp-card', 'true')\n\t\t\tthis.#historySection.appendChild(cardElement)\n\t\t\tthis.#scrollToBottom()\n\n\t\t\tthis.#showInputArea(this.#i18n.t('ui.panel.userAnswerPrompt'))\n\t\t})\n\t}\n\n\t// ========== Public control methods ==========\n\n\tshow(): void {\n\t\tthis.wrapper.style.display = 'block'\n\t\tvoid this.wrapper.offsetHeight\n\t\tthis.wrapper.style.opacity = '1'\n\t\tthis.wrapper.style.transform = 'translateX(-50%) translateY(0)'\n\t}\n\n\thide(): void {\n\t\tthis.wrapper.style.opacity = '0'\n\t\tthis.wrapper.style.transform = 'translateX(-50%) translateY(20px)'\n\t\tthis.wrapper.style.display = 'none'\n\t}\n\n\treset(): void {\n\t\tthis.#statusText.textContent = this.#i18n.t('ui.panel.ready')\n\t\tthis.#updateStatusIndicator('thinking')\n\t\tthis.#renderHistory()\n\t\tthis.#collapse()\n\t\t// Reset user input state\n\t\tthis.#isWaitingForUserAnswer = false\n\t\tthis.#userAnswerResolver = null\n\t\t// Show input area\n\t\tthis.#showInputArea()\n\t}\n\n\texpand(): void {\n\t\tthis.#expand()\n\t}\n\n\tcollapse(): void {\n\t\tthis.#collapse()\n\t}\n\n\t/**\n\t * Dispose panel and clean up event listeners\n\t */\n\tdispose(): void {\n\t\t// Remove agent event listeners\n\t\tthis.#agent.removeEventListener('statuschange', this.#onStatusChange)\n\t\tthis.#agent.removeEventListener('historychange', this.#onHistoryChange)\n\t\tthis.#agent.removeEventListener('activity', this.#onActivity)\n\t\tthis.#agent.removeEventListener('dispose', this.#onAgentDispose)\n\n\t\t// Clean up UI\n\t\tthis.#isWaitingForUserAnswer = false\n\t\tthis.#stopHeaderUpdateLoop()\n\t\tthis.wrapper.remove()\n\t}\n\n\t// ========== Private methods ==========\n\n\t#getToolExecutingText(toolName: string, args: unknown): string {\n\t\tconst a = args as Record<string, string | number>\n\t\tswitch (toolName) {\n\t\t\tcase 'click_element_by_index':\n\t\t\t\treturn this.#i18n.t('ui.tools.clicking', { index: a.index })\n\t\t\tcase 'input_text':\n\t\t\t\treturn this.#i18n.t('ui.tools.inputting', { index: a.index })\n\t\t\tcase 'select_dropdown_option':\n\t\t\t\treturn this.#i18n.t('ui.tools.selecting', { text: a.text })\n\t\t\tcase 'scroll':\n\t\t\t\treturn this.#i18n.t('ui.tools.scrolling')\n\t\t\tcase 'wait':\n\t\t\t\treturn this.#i18n.t('ui.tools.waiting', { seconds: a.seconds })\n\t\t\tcase 'ask_user':\n\t\t\t\treturn this.#i18n.t('ui.tools.askingUser')\n\t\t\tcase 'done':\n\t\t\t\treturn this.#i18n.t('ui.tools.done')\n\t\t\tdefault:\n\t\t\t\treturn this.#i18n.t('ui.tools.executing', { toolName })\n\t\t}\n\t}\n\n\t/**\n\t * Stop Agent\n\t */\n\t#stopAgent(): void {\n\t\tthis.#agent.dispose()\n\t}\n\n\t/**\n\t * Submit task\n\t */\n\t#submitTask() {\n\t\tconst input = this.#taskInput.value.trim()\n\t\tif (!input) return\n\n\t\t// Hide input area\n\t\tthis.#hideInputArea()\n\n\t\tif (this.#isWaitingForUserAnswer) {\n\t\t\t// Handle user input mode\n\t\t\tthis.#handleUserAnswer(input)\n\t\t} else {\n\t\t\t// Execute task via agent\n\t\t\tthis.#agent.execute(input)\n\t\t}\n\t}\n\n\t/**\n\t * Handle user answer\n\t */\n\t#handleUserAnswer(input: string): void {\n\t\t// Remove temporary question cards (only direct children for safety)\n\t\tArray.from(this.#historySection.children).forEach((child) => {\n\t\t\tif (child.getAttribute('data-temp-card') === 'true') {\n\t\t\t\tchild.remove()\n\t\t\t}\n\t\t})\n\n\t\t// Reset state\n\t\tthis.#isWaitingForUserAnswer = false\n\n\t\t// Call resolver to return user input\n\t\tif (this.#userAnswerResolver) {\n\t\t\tthis.#userAnswerResolver(input)\n\t\t\tthis.#userAnswerResolver = null\n\t\t}\n\t}\n\n\t/**\n\t * Show input area\n\t */\n\t#showInputArea(placeholder?: string): void {\n\t\t// Clear input field\n\t\tthis.#taskInput.value = ''\n\t\tthis.#taskInput.placeholder = placeholder || this.#i18n.t('ui.panel.taskInput')\n\t\tthis.#inputSection.classList.remove(styles.hidden)\n\t\t// Focus on input field\n\t\tsetTimeout(() => {\n\t\t\tthis.#taskInput.focus()\n\t\t}, 100)\n\t}\n\n\t/**\n\t * Hide input area\n\t */\n\t#hideInputArea(): void {\n\t\tthis.#inputSection.classList.add(styles.hidden)\n\t}\n\n\t/**\n\t * Check if input area should be shown\n\t */\n\t#shouldShowInputArea(): boolean {\n\t\t// Always show input area if waiting for user input\n\t\tif (this.#isWaitingForUserAnswer) return true\n\n\t\tconst history = this.#agent.history\n\t\tif (history.length === 0) {\n\t\t\treturn true // Initial state\n\t\t}\n\n\t\tconst status = this.#agent.status\n\t\tconst isTaskEnded = status === 'completed' || status === 'error'\n\n\t\t// Only show input area after task completion if configured to do so\n\t\tif (isTaskEnded) {\n\t\t\treturn this.#config.promptForNextTask ?? true\n\t\t}\n\n\t\treturn false\n\t}\n\n\t#createWrapper(): HTMLElement {\n\t\tconst wrapper = document.createElement('div')\n\t\twrapper.id = 'page-agent-runtime_agent-panel'\n\t\twrapper.className = styles.wrapper\n\t\twrapper.setAttribute('data-browser-use-ignore', 'true')\n\n\t\twrapper.innerHTML = `\n\t\t\t<div class=\"${styles.background}\"></div>\n\t\t\t<div class=\"${styles.historySectionWrapper}\">\n\t\t\t\t<div class=\"${styles.historySection}\">\n\t\t\t\t\t<div class=\"${styles.historyItem}\">\n\t\t\t\t\t\t<div class=\"${styles.historyContent}\">\n\t\t\t\t\t\t\t<span class=\"${styles.statusIcon}\">🧠</span>\n\t\t\t\t\t\t\t<span>${this.#i18n.t('ui.panel.waitingPlaceholder')}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"${styles.header}\">\n\t\t\t\t<div class=\"${styles.statusSection}\">\n\t\t\t\t\t<div class=\"${styles.indicator} ${styles.thinking}\"></div>\n\t\t\t\t\t<div class=\"${styles.statusText}\">${this.#i18n.t('ui.panel.ready')}</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"${styles.controls}\">\n\t\t\t\t\t<button class=\"${styles.controlButton} ${styles.expandButton}\" title=\"${this.#i18n.t('ui.panel.expand')}\">\n\t\t\t\t\t\t▼\n\t\t\t\t\t</button>\n\t\t\t\t\t<button class=\"${styles.controlButton} ${styles.stopButton}\" title=\"${this.#i18n.t('ui.panel.stop')}\">\n\t\t\t\t\t\tX\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<div class=\"${styles.inputSectionWrapper} ${styles.hidden}\">\n\t\t\t\t<div class=\"${styles.inputSection}\">\n\t\t\t\t\t<input \n\t\t\t\t\t\ttype=\"text\" \n\t\t\t\t\t\tclass=\"${styles.taskInput}\" \n\t\t\t\t\t\tmaxlength=\"200\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t`\n\n\t\tdocument.body.appendChild(wrapper)\n\t\treturn wrapper\n\t}\n\n\t#setupEventListeners(): void {\n\t\t// Click header area to expand/collapse\n\t\tconst header = this.wrapper.querySelector(`.${styles.header}`)!\n\t\theader.addEventListener('click', (e) => {\n\t\t\t// Don't trigger expand/collapse if clicking on buttons\n\t\t\tif ((e.target as HTMLElement).closest(`.${styles.controlButton}`)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.#toggle()\n\t\t})\n\n\t\t// Expand button\n\t\tthis.#expandButton.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t\tthis.#toggle()\n\t\t})\n\n\t\t// Stop button\n\t\tthis.#stopButton.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t\tthis.#stopAgent()\n\t\t})\n\n\t\t// Submit on Enter key in input field\n\t\tthis.#taskInput.addEventListener('keydown', (e) => {\n\t\t\tif (e.isComposing) return // Ignore IME composition keys\n\t\t\tif (e.key === 'Enter') {\n\t\t\t\te.preventDefault()\n\t\t\t\tthis.#submitTask()\n\t\t\t}\n\t\t})\n\n\t\t// Prevent input area click event bubbling\n\t\tthis.#inputSection.addEventListener('click', (e) => {\n\t\t\te.stopPropagation()\n\t\t})\n\t}\n\n\t#toggle(): void {\n\t\tif (this.#isExpanded) {\n\t\t\tthis.#collapse()\n\t\t} else {\n\t\t\tthis.#expand()\n\t\t}\n\t}\n\n\t#expand(): void {\n\t\tthis.#isExpanded = true\n\t\tthis.wrapper.classList.add(styles.expanded)\n\t\tthis.#expandButton.textContent = '▲'\n\t}\n\n\t#collapse(): void {\n\t\tthis.#isExpanded = false\n\t\tthis.wrapper.classList.remove(styles.expanded)\n\t\tthis.#expandButton.textContent = '▼'\n\t}\n\n\t/**\n\t * Start periodic header update loop\n\t */\n\t#startHeaderUpdateLoop(): void {\n\t\t// Check every 450ms (same as total animation duration)\n\t\tthis.#headerUpdateTimer = setInterval(() => {\n\t\t\tthis.#checkAndUpdateHeader()\n\t\t}, 450)\n\t}\n\n\t/**\n\t * Stop periodic header update loop\n\t */\n\t#stopHeaderUpdateLoop(): void {\n\t\tif (this.#headerUpdateTimer) {\n\t\t\tclearInterval(this.#headerUpdateTimer)\n\t\t\tthis.#headerUpdateTimer = null\n\t\t}\n\t}\n\n\t/**\n\t * Check if header needs update and trigger animation if not currently animating\n\t */\n\t#checkAndUpdateHeader(): void {\n\t\t// If no pending text or currently animating, skip\n\t\tif (!this.#pendingHeaderText || this.#isAnimating) {\n\t\t\treturn\n\t\t}\n\n\t\t// If text is already displayed, clear pending and skip\n\t\tif (this.#statusText.textContent === this.#pendingHeaderText) {\n\t\t\tthis.#pendingHeaderText = null\n\t\t\treturn\n\t\t}\n\n\t\t// Start animation\n\t\tconst textToShow = this.#pendingHeaderText\n\t\tthis.#pendingHeaderText = null\n\t\tthis.#animateTextChange(textToShow)\n\t}\n\n\t/**\n\t * Animate text change with fade out/in effect\n\t */\n\t#animateTextChange(newText: string): void {\n\t\tthis.#isAnimating = true\n\n\t\t// Fade out current text\n\t\tthis.#statusText.classList.add(styles.fadeOut)\n\n\t\tsetTimeout(() => {\n\t\t\t// Update text content\n\t\t\tthis.#statusText.textContent = newText\n\n\t\t\t// Fade in new text\n\t\t\tthis.#statusText.classList.remove(styles.fadeOut)\n\t\t\tthis.#statusText.classList.add(styles.fadeIn)\n\n\t\t\tsetTimeout(() => {\n\t\t\t\tthis.#statusText.classList.remove(styles.fadeIn)\n\t\t\t\tthis.#isAnimating = false\n\t\t\t}, 300)\n\t\t}, 150) // Half the duration of fade out animation\n\t}\n\n\t#updateStatusIndicator(\n\t\ttype: 'thinking' | 'executing' | 'executed' | 'retrying' | 'completed' | 'error'\n\t): void {\n\t\t// Clear all status classes\n\t\tthis.#indicator.className = styles.indicator\n\n\t\t// Add corresponding status class\n\t\tthis.#indicator.classList.add(styles[type])\n\t}\n\n\t#scrollToBottom(): void {\n\t\t// Execute in next event loop to ensure DOM update completion\n\t\tsetTimeout(() => {\n\t\t\tthis.#historySection.scrollTop = this.#historySection.scrollHeight\n\t\t}, 0)\n\t}\n\n\t/**\n\t * Render history directly from agent.history\n\t *\n\t * Renders:\n\t * 1. Task (first item, from agent.task)\n\t * 2. Reflection cards (evaluation, memory, next_goal)\n\t * 3. Tool execution with output\n\t * 4. Observations\n\t */\n\t#renderHistory(): void {\n\t\tconst items: string[] = []\n\n\t\t// 1. Task card (always first)\n\t\tconst task = this.#agent.task\n\t\tif (task) {\n\t\t\titems.push(this.#createTaskCard(task))\n\t\t}\n\n\t\t// 2. Render each history event\n\t\tconst history = this.#agent.history\n\t\tfor (let i = 0; i < history.length; i++) {\n\t\t\tconst event = history[i]\n\t\t\titems.push(...this.#createHistoryCards(event, i + 1))\n\t\t}\n\n\t\tthis.#historySection.innerHTML = items.join('')\n\t\tthis.#scrollToBottom()\n\t}\n\n\t#createTaskCard(task: string): string {\n\t\treturn createCard({ icon: '🎯', content: task, type: 'input' })\n\t}\n\n\t/** Create cards for a history event */\n\t#createHistoryCards(event: PanelAgentAdapter['history'][number], stepNumber: number): string[] {\n\t\tconst cards: string[] = []\n\t\tconst time = formatTime(this.#config.language ?? 'en-US')\n\t\tconst meta = this.#i18n.t('ui.panel.step', {\n\t\t\tnumber: stepNumber.toString(),\n\t\t\ttime,\n\t\t\tduration: '',\n\t\t})\n\n\t\tif (event.type === 'step') {\n\t\t\t// Reflection card\n\t\t\tif (event.reflection) {\n\t\t\t\tconst lines = createReflectionLines(event.reflection)\n\t\t\t\tif (lines.length > 0) {\n\t\t\t\t\tcards.push(createCard({ icon: '🧠', content: lines, meta }))\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Action card\n\t\t\tconst action = event.action\n\t\t\tif (action) {\n\t\t\t\tcards.push(...this.#createActionCards(action, meta))\n\t\t\t}\n\t\t} else if (event.type === 'observation') {\n\t\t\tcards.push(\n\t\t\t\tcreateCard({ icon: '👁️', content: event.content || '', meta, type: 'observation' })\n\t\t\t)\n\t\t} else if (event.type === 'user_takeover') {\n\t\t\tcards.push(createCard({ icon: '👤', content: 'User takeover', meta, type: 'input' }))\n\t\t}\n\n\t\treturn cards\n\t}\n\n\t/** Create cards for an action */\n\t#createActionCards(\n\t\taction: { name: string; input: unknown; output: string },\n\t\tmeta: string\n\t): string[] {\n\t\tconst cards: string[] = []\n\n\t\tif (action.name === 'done') {\n\t\t\tconst input = action.input as { text?: string }\n\t\t\tconst text = input.text || action.output || ''\n\t\t\tif (text) {\n\t\t\t\tcards.push(createCard({ icon: '🤖', content: text, meta, type: 'output' }))\n\t\t\t}\n\t\t} else if (action.name === 'ask_user') {\n\t\t\tconst input = action.input as { question?: string }\n\t\t\tconst answer = action.output.replace(/^User answered:\\s*/i, '')\n\t\t\tcards.push(\n\t\t\t\tcreateCard({\n\t\t\t\t\ticon: '❓',\n\t\t\t\t\tcontent: `Question: ${input.question || ''}`,\n\t\t\t\t\tmeta,\n\t\t\t\t\ttype: 'question',\n\t\t\t\t})\n\t\t\t)\n\t\t\tcards.push(createCard({ icon: '💬', content: `Answer: ${answer}`, meta, type: 'input' }))\n\t\t} else {\n\t\t\tconst toolText = this.#getToolExecutingText(action.name, action.input)\n\t\t\tcards.push(createCard({ icon: '🔨', content: toolText, meta }))\n\t\t\tif (action.output?.length > 0) {\n\t\t\t\tcards.push(createCard({ icon: '🔨', content: action.output, meta, type: 'output' }))\n\t\t\t}\n\t\t}\n\n\t\treturn cards\n\t}\n}\n"],"names":["question","input","wrapper","header"],"mappings":";;;;;;;;;;AACA;AAAA,MAAM,OAAO;AAAA,EACZ,IAAI;AAAA,IACH,OAAO;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,MACX,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,oBAAoB;AAAA,MACpB,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,MAAM;AAAA,IAAA;AAAA,IAEP,OAAO;AAAA,MACN,UAAU;AAAA,MACV,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,MACX,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,eAAe;AAAA,MACf,eAAe;AAAA,MACf,aAAa;AAAA,IAAA;AAAA,IAEd,QAAQ;AAAA,MACP,iBAAiB;AAAA,MACjB,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,IAAA;AAAA,EACjB;AAEF;AAGA,MAAM,OAAO;AAAA,EACZ,IAAI;AAAA,IACH,OAAO;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA,MACV,WAAW;AAAA,MACX,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,oBAAoB;AAAA,MACpB,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,MAAM;AAAA,IAAA;AAAA,IAEP,OAAO;AAAA,MACN,UAAU;AAAA,MACV,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,MACX,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,UAAU;AAAA,MACV,UAAU;AAAA,MACV,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,eAAe;AAAA,MACf,eAAe;AAAA,MACf,aAAa;AAAA,IAAA;AAAA,IAEd,QAAQ;AAAA,MACP,iBAAiB;AAAA,MACjB,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,iBAAiB;AAAA,MACjB,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,IAAA;AAAA,EACjB;AAEF;AAsBO,MAAM,UAAU;AAAA,EACtB,SAAS;AAAA,EACT,SAAS;AACV;AC7GO,MAAM,QAAN,MAAM,MAAK;AAAA,EACT;AAAA,EACA;AAAA,EAER,YAAY,WAA8B,SAAS;AAClD,SAAK,WAAW,YAAY,UAAU,WAAW;AACjD,SAAK,eAAe,QAAQ,KAAK,QAAQ;AAAA,EAC1C;AAAA;AAAA,EAGA,EAAE,KAAqB,QAAoC;AAC1D,UAAM,QAAQ,KAAK,eAAe,KAAK,cAAc,GAAG;AACxD,QAAI,CAAC,OAAO;AACX,cAAQ,KAAK,oBAAoB,GAAG,6BAA6B,KAAK,QAAQ,GAAG;AACjF,aAAO;AAAA,IACR;AAEA,QAAI,QAAQ;AACX,aAAO,KAAK,YAAY,OAAO,MAAM;AAAA,IACtC;AACA,WAAO;AAAA,EACR;AAAA,EAEQ,eAAe,KAAU,MAAkC;AAClE,WAAO,KAAK,MAAM,GAAG,EAAE,OAAO,CAAC,SAAS,QAAQ,UAAU,GAAG,GAAG,GAAG;AAAA,EACpE;AAAA,EAEQ,YAAY,UAAkB,QAAmC;AACxE,WAAO,SAAS,QAAQ,kBAAkB,CAAC,OAAO,QAAQ;AAEzD,aAAO,OAAO,GAAG,KAAK,OAAO,OAAO,GAAG,EAAE,aAAa;AAAA,IACvD,CAAC;AAAA,EACF;AAAA,EAEA,cAAiC;AAChC,WAAO,KAAK;AAAA,EACb;AACD;AArCkB;AAAX,IAAM,OAAN;ACRA,SAAS,SAAS,MAAc,WAA2B;AACjE,MAAI,KAAK,SAAS,WAAW;AAC5B,WAAO,KAAK,UAAU,GAAG,SAAS,IAAI;AAAA,EACvC;AACA,SAAO;AACR;AALgB;AAUT,SAAS,WAAW,MAAsB;AAChD,SAAO,KACL,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,QAAQ;AACzB;AAPgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACOT,SAAS,WAAW,EAAE,MAAM,SAAS,MAAM,QAA6B;AAC9E,QAAM,YAAY,OAAO,OAAO,IAAI,IAAI;AACxC,QAAM,cAAc,MAAM,QAAQ,OAAO,IACtC,eAAe,OAAO,eAAe,KAAK,QAAQ,KAAK,EAAE,CAAC,WAC1D,SAAS,WAAW,OAAO,CAAC;AAE/B,SAAO;AAAA,gBACQ,OAAO,WAAW,IAAI,SAAS;AAAA,iBAC9B,OAAO,cAAc;AAAA,mBACnB,OAAO,UAAU,KAAK,IAAI;AAAA,MACvC,WAAW;AAAA;AAAA,KAEZ,OAAO,eAAe,OAAO,WAAW,KAAK,IAAI,WAAW,EAAE;AAAA;AAAA;AAGnE;AAfgB;AAkBT,SAAS,WAAW,SAAiB,SAAiB;AAC5D,UAAO,oBAAI,QAAO,mBAAmB,QAAQ;AAAA,IAC5C,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,EAAA,CACR;AACF;AAPgB;AAUT,SAAS,sBAAsB,YAIzB;AACZ,QAAM,QAAkB,CAAA;AACxB,MAAI,WAAW,0BAA0B;AACxC,UAAM,KAAK,WAAW,WAAW,WAAW,wBAAwB,CAAC,QAAQ;AAAA,EAC9E;AACA,MAAI,WAAW,QAAQ;AACtB,UAAM,KAAK,WAAW,WAAW,WAAW,MAAM,CAAC,QAAQ;AAAA,EAC5D;AACA,MAAI,WAAW,WAAW;AACzB,UAAM,KAAK,WAAW,WAAW,WAAW,SAAS,CAAC,QAAQ;AAAA,EAC/D;AACA,SAAO;AACR;AAhBgB;AChBT,MAAM,SAAN,MAAM,OAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmClB,YAAY,OAA0B,SAAsB,IAAI;AAnC1D;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA,oCAAc;AACd;AACA,4CAAwD;AACxD,gDAAmC;AACnC,2CAA4D;AAC5D,2CAAoC;AACpC,qCAAe;AAGf;AAAA,wCAAkB,6BAAM,sBAAK,yCAAL,YAAN;AAClB,yCAAmB,6BAAM,sBAAK,0CAAL,YAAN;AACnB,oCAAc,wBAAC,MAAa,sBAAK,qCAAL,WAAsB,EAAiC,SAArE;AACd,wCAAkB,6BAAM,KAAK,QAAA,GAAX;AAYjB,uBAAK,QAAS;AACd,uBAAK,SAAU;AACf,uBAAK,OAAQ,IAAI,KAAK,OAAO,YAAY,OAAO;AAGhD,uBAAK,QAAO,YAAY,CAACA,cAAa,sBAAK,8BAAL,WAAcA;AAGpD,uBAAK,UAAW,sBAAK,oCAAL;AAChB,uBAAK,YAAa,mBAAK,UAAS,cAAc,IAAI,OAAO,SAAS,EAAE;AACpE,uBAAK,aAAc,mBAAK,UAAS,cAAc,IAAI,OAAO,UAAU,EAAE;AACtE,uBAAK,iBAAkB,mBAAK,UAAS,cAAc,IAAI,OAAO,cAAc,EAAE;AAC9E,uBAAK,eAAgB,mBAAK,UAAS,cAAc,IAAI,OAAO,YAAY,EAAE;AAC1E,uBAAK,aAAc,mBAAK,UAAS,cAAc,IAAI,OAAO,UAAU,EAAE;AACtE,uBAAK,eAAgB,mBAAK,UAAS,cAAc,IAAI,OAAO,mBAAmB,EAAE;AACjF,uBAAK,YAAa,mBAAK,UAAS,cAAc,IAAI,OAAO,SAAS,EAAE;AAGpE,uBAAK,QAAO,iBAAiB,gBAAgB,mBAAK,gBAAe;AACjE,uBAAK,QAAO,iBAAiB,iBAAiB,mBAAK,iBAAgB;AACnE,uBAAK,QAAO,iBAAiB,YAAY,mBAAK,YAAW;AACzD,uBAAK,QAAO,iBAAiB,WAAW,mBAAK,gBAAe;AAE5D,0BAAK,0CAAL;AACA,0BAAK,4CAAL;AAEA,0BAAK,oCAAL;AAEA,SAAK,KAAA;AAAA,EACN;AAAA,EAvCA,IAAI,UAAuB;AAC1B,WAAO,mBAAK;AAAA,EACb;AAAA;AAAA,EAyIA,OAAa;AACZ,SAAK,QAAQ,MAAM,UAAU;AAC7B,SAAK,KAAK,QAAQ;AAClB,SAAK,QAAQ,MAAM,UAAU;AAC7B,SAAK,QAAQ,MAAM,YAAY;AAAA,EAChC;AAAA,EAEA,OAAa;AACZ,SAAK,QAAQ,MAAM,UAAU;AAC7B,SAAK,QAAQ,MAAM,YAAY;AAC/B,SAAK,QAAQ,MAAM,UAAU;AAAA,EAC9B;AAAA,EAEA,QAAc;AACb,uBAAK,aAAY,cAAc,mBAAK,OAAM,EAAE,gBAAgB;AAC5D,0BAAK,4CAAL,WAA4B;AAC5B,0BAAK,oCAAL;AACA,0BAAK,+BAAL;AAEA,uBAAK,yBAA0B;AAC/B,uBAAK,qBAAsB;AAE3B,0BAAK,oCAAL;AAAA,EACD;AAAA,EAEA,SAAe;AACd,0BAAK,6BAAL;AAAA,EACD;AAAA,EAEA,WAAiB;AAChB,0BAAK,+BAAL;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AAEf,uBAAK,QAAO,oBAAoB,gBAAgB,mBAAK,gBAAe;AACpE,uBAAK,QAAO,oBAAoB,iBAAiB,mBAAK,iBAAgB;AACtE,uBAAK,QAAO,oBAAoB,YAAY,mBAAK,YAAW;AAC5D,uBAAK,QAAO,oBAAoB,WAAW,mBAAK,gBAAe;AAG/D,uBAAK,yBAA0B;AAC/B,0BAAK,2CAAL;AACA,SAAK,QAAQ,OAAA;AAAA,EACd;AAuZD;AA1mBC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAxBM;AAAA;AAAA;AAsEN,wBAAA,kCAA4B;AAC3B,QAAM,SAAS,mBAAK,QAAO;AAG3B,QAAM,gBACL,WAAW,YAAY,aAAa,WAAW,SAAS,aAAa;AACtE,wBAAK,4CAAL,WAA4B;AAG5B,MAAI,WAAW,WAAW;AACzB,SAAK,KAAA;AACL,0BAAK,oCAAL;AAAA,EACD;AAGA,MAAI,WAAW,eAAe,WAAW,SAAS;AACjD,QAAI,CAAC,mBAAK,cAAa;AACtB,4BAAK,6BAAL;AAAA,IACD;AACA,QAAI,sBAAK,0CAAL,YAA6B;AAChC,4BAAK,oCAAL;AAAA,IACD;AAAA,EACD;AACD,GAvBA;AAAA;AA0BA,yBAAA,kCAA6B;AAC5B,wBAAK,oCAAL;AACD,GAFA;AAAA;AAAA;AAAA;AAAA;AAQA,oDAAgB,UAA+B;AAC9C,UAAQ,SAAS,MAAA;AAAA,IAChB,KAAK;AACJ,yBAAK,oBAAqB,mBAAK,OAAM,EAAE,mBAAmB;AAC1D,4BAAK,4CAAL,WAA4B;AAC5B;AAAA,IAED,KAAK;AACJ,yBAAK,oBAAqB,sBAAK,2CAAL,WAA2B,SAAS,MAAM,SAAS;AAC7E,4BAAK,4CAAL,WAA4B;AAC5B;AAAA,IAED,KAAK;AACJ,yBAAK,oBAAqB,SAAS,SAAS,QAAQ,EAAE;AACtD;AAAA,IAED,KAAK;AACJ,yBAAK,oBAAqB,aAAa,SAAS,OAAO,IAAI,SAAS,WAAW;AAC/E,4BAAK,4CAAL,WAA4B;AAC5B;AAAA,IAED,KAAK;AACJ,yBAAK,oBAAqB,SAAS,SAAS,SAAS,EAAE;AACvD,4BAAK,4CAAL,WAA4B;AAC5B;AAAA,EAAA;AAEH;;;;AAKA,6CAASA,WAAmC;AAC3C,SAAO,IAAI,QAAQ,CAAC,YAAY;AAE/B,uBAAK,yBAA0B;AAC/B,uBAAK,qBAAsB;AAG3B,QAAI,CAAC,mBAAK,cAAa;AACtB,4BAAK,6BAAL;AAAA,IACD;AAGA,UAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,aAAS,YAAY,WAAW;AAAA,MAC/B,MAAM;AAAA,MACN,SAAS,aAAaA,SAAQ;AAAA,MAC9B,MAAM,WAAW,mBAAK,SAAQ,YAAY,OAAO;AAAA,MACjD,MAAM;AAAA,IAAA,CACN;AACD,UAAM,cAAc,SAAS;AAC7B,gBAAY,aAAa,kBAAkB,MAAM;AACjD,uBAAK,iBAAgB,YAAY,WAAW;AAC5C,0BAAK,qCAAL;AAEA,0BAAK,oCAAL,WAAoB,mBAAK,OAAM,EAAE,2BAA2B;AAAA,EAC7D,CAAC;AACF;;AAuDA,0BAAA,gCAAsB,UAAkB,MAAuB;AAC9D,QAAM,IAAI;AACV,UAAQ,UAAA;AAAA,IACP,KAAK;AACJ,aAAO,mBAAK,OAAM,EAAE,qBAAqB,EAAE,OAAO,EAAE,OAAO;AAAA,IAC5D,KAAK;AACJ,aAAO,mBAAK,OAAM,EAAE,sBAAsB,EAAE,OAAO,EAAE,OAAO;AAAA,IAC7D,KAAK;AACJ,aAAO,mBAAK,OAAM,EAAE,sBAAsB,EAAE,MAAM,EAAE,MAAM;AAAA,IAC3D,KAAK;AACJ,aAAO,mBAAK,OAAM,EAAE,oBAAoB;AAAA,IACzC,KAAK;AACJ,aAAO,mBAAK,OAAM,EAAE,oBAAoB,EAAE,SAAS,EAAE,SAAS;AAAA,IAC/D,KAAK;AACJ,aAAO,mBAAK,OAAM,EAAE,qBAAqB;AAAA,IAC1C,KAAK;AACJ,aAAO,mBAAK,OAAM,EAAE,eAAe;AAAA,IACpC;AACC,aAAO,mBAAK,OAAM,EAAE,sBAAsB,EAAE,UAAU;AAAA,EAAA;AAEzD,GApBA;AAAA;AAAA;AAAA;AAyBA,eAAA,kCAAmB;AAClB,qBAAK,QAAO,QAAA;AACb,GAFA;AAAA;AAAA;AAAA;AAOA,gBAAA,kCAAc;AACb,QAAMC,SAAQ,mBAAK,YAAW,MAAM,KAAA;AACpC,MAAI,CAACA,OAAO;AAGZ,wBAAK,oCAAL;AAEA,MAAI,mBAAK,0BAAyB;AAEjC,0BAAK,uCAAL,WAAuBA;AAAA,EACxB,OAAO;AAEN,uBAAK,QAAO,QAAQA,MAAK;AAAA,EAC1B;AACD,GAdA;AAAA;AAAA;AAAA;AAmBA,sDAAkBA,QAAqB;AAEtC,QAAM,KAAK,mBAAK,iBAAgB,QAAQ,EAAE,QAAQ,CAAC,UAAU;AAC5D,QAAI,MAAM,aAAa,gBAAgB,MAAM,QAAQ;AACpD,YAAM,OAAA;AAAA,IACP;AAAA,EACD,CAAC;AAGD,qBAAK,yBAA0B;AAG/B,MAAI,mBAAK,sBAAqB;AAC7B,uBAAK,qBAAL,WAAyBA;AACzB,uBAAK,qBAAsB;AAAA,EAC5B;AACD;;;;AAKA,mDAAe,aAA4B;AAE1C,qBAAK,YAAW,QAAQ;AACxB,qBAAK,YAAW,cAAc,eAAe,mBAAK,OAAM,EAAE,oBAAoB;AAC9E,qBAAK,eAAc,UAAU,OAAO,OAAO,MAAM;AAEjD,aAAW,MAAM;AAChB,uBAAK,YAAW,MAAA;AAAA,EACjB,GAAG,GAAG;AACP;;;;AAKA,mBAAA,kCAAuB;AACtB,qBAAK,eAAc,UAAU,IAAI,OAAO,MAAM;AAC/C,GAFA;AAAA;AAAA;AAAA;AAOA,yBAAA,kCAAgC;AAE/B,MAAI,mBAAK,yBAAyB,QAAO;AAEzC,QAAM,UAAU,mBAAK,QAAO;AAC5B,MAAI,QAAQ,WAAW,GAAG;AACzB,WAAO;AAAA,EACR;AAEA,QAAM,SAAS,mBAAK,QAAO;AAC3B,QAAM,cAAc,WAAW,eAAe,WAAW;AAGzD,MAAI,aAAa;AAChB,WAAO,mBAAK,SAAQ,qBAAqB;AAAA,EAC1C;AAEA,SAAO;AACR,GAlBA;AAoBA,mBAAA,kCAA8B;AAC7B,QAAMC,WAAU,SAAS,cAAc,KAAK;AAC5C,EAAAA,SAAQ,KAAK;AACb,EAAAA,SAAQ,YAAY,OAAO;AAC3B,EAAAA,SAAQ,aAAa,2BAA2B,MAAM;AAEtD,EAAAA,SAAQ,YAAY;AAAA,iBACL,OAAO,UAAU;AAAA,iBACjB,OAAO,qBAAqB;AAAA,kBAC3B,OAAO,cAAc;AAAA,mBACpB,OAAO,WAAW;AAAA,oBACjB,OAAO,cAAc;AAAA,sBACnB,OAAO,UAAU;AAAA,eACxB,mBAAK,OAAM,EAAE,6BAA6B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,iBAKzC,OAAO,MAAM;AAAA,kBACZ,OAAO,aAAa;AAAA,mBACnB,OAAO,SAAS,IAAI,OAAO,QAAQ;AAAA,mBACnC,OAAO,UAAU,KAAK,mBAAK,OAAM,EAAE,gBAAgB,CAAC;AAAA;AAAA,kBAErD,OAAO,QAAQ;AAAA,sBACX,OAAO,aAAa,IAAI,OAAO,YAAY,YAAY,mBAAK,OAAM,EAAE,iBAAiB,CAAC;AAAA;AAAA;AAAA,sBAGtF,OAAO,aAAa,IAAI,OAAO,UAAU,YAAY,mBAAK,OAAM,EAAE,eAAe,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,iBAKvF,OAAO,mBAAmB,IAAI,OAAO,MAAM;AAAA,kBAC1C,OAAO,YAAY;AAAA;AAAA;AAAA,eAGtB,OAAO,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAO7B,WAAS,KAAK,YAAYA,QAAO;AACjC,SAAOA;AACR,GA7CA;AA+CA,yBAAA,kCAA6B;AAE5B,QAAMC,UAAS,KAAK,QAAQ,cAAc,IAAI,OAAO,MAAM,EAAE;AAC7D,EAAAA,QAAO,iBAAiB,SAAS,CAAC,MAAM;AAEvC,QAAK,EAAE,OAAuB,QAAQ,IAAI,OAAO,aAAa,EAAE,GAAG;AAClE;AAAA,IACD;AACA,0BAAK,6BAAL;AAAA,EACD,CAAC;AAGD,qBAAK,eAAc,iBAAiB,SAAS,CAAC,MAAM;AACnD,MAAE,gBAAA;AACF,0BAAK,6BAAL;AAAA,EACD,CAAC;AAGD,qBAAK,aAAY,iBAAiB,SAAS,CAAC,MAAM;AACjD,MAAE,gBAAA;AACF,0BAAK,gCAAL;AAAA,EACD,CAAC;AAGD,qBAAK,YAAW,iBAAiB,WAAW,CAAC,MAAM;AAClD,QAAI,EAAE,YAAa;AACnB,QAAI,EAAE,QAAQ,SAAS;AACtB,QAAE,eAAA;AACF,4BAAK,iCAAL;AAAA,IACD;AAAA,EACD,CAAC;AAGD,qBAAK,eAAc,iBAAiB,SAAS,CAAC,MAAM;AACnD,MAAE,gBAAA;AAAA,EACH,CAAC;AACF,GApCA;AAsCA,YAAA,kCAAgB;AACf,MAAI,mBAAK,cAAa;AACrB,0BAAK,+BAAL;AAAA,EACD,OAAO;AACN,0BAAK,6BAAL;AAAA,EACD;AACD,GANA;AAQA,YAAA,kCAAgB;AACf,qBAAK,aAAc;AACnB,OAAK,QAAQ,UAAU,IAAI,OAAO,QAAQ;AAC1C,qBAAK,eAAc,cAAc;AAClC,GAJA;AAMA,cAAA,kCAAkB;AACjB,qBAAK,aAAc;AACnB,OAAK,QAAQ,UAAU,OAAO,OAAO,QAAQ;AAC7C,qBAAK,eAAc,cAAc;AAClC,GAJA;AAAA;AAAA;AAAA;AASA,2BAAA,kCAA+B;AAE9B,qBAAK,oBAAqB,YAAY,MAAM;AAC3C,0BAAK,2CAAL;AAAA,EACD,GAAG,GAAG;AACP,GALA;AAAA;AAAA;AAAA;AAUA,0BAAA,kCAA8B;AAC7B,MAAI,mBAAK,qBAAoB;AAC5B,kBAAc,mBAAK,mBAAkB;AACrC,uBAAK,oBAAqB;AAAA,EAC3B;AACD,GALA;AAAA;AAAA;AAAA;AAUA,0BAAA,kCAA8B;AAE7B,MAAI,CAAC,mBAAK,uBAAsB,mBAAK,eAAc;AAClD;AAAA,EACD;AAGA,MAAI,mBAAK,aAAY,gBAAgB,mBAAK,qBAAoB;AAC7D,uBAAK,oBAAqB;AAC1B;AAAA,EACD;AAGA,QAAM,aAAa,mBAAK;AACxB,qBAAK,oBAAqB;AAC1B,wBAAK,wCAAL,WAAwB;AACzB,GAhBA;AAAA;AAAA;AAAA;AAqBA,uDAAmB,SAAuB;AACzC,qBAAK,cAAe;AAGpB,qBAAK,aAAY,UAAU,IAAI,OAAO,OAAO;AAE7C,aAAW,MAAM;AAEhB,uBAAK,aAAY,cAAc;AAG/B,uBAAK,aAAY,UAAU,OAAO,OAAO,OAAO;AAChD,uBAAK,aAAY,UAAU,IAAI,OAAO,MAAM;AAE5C,eAAW,MAAM;AAChB,yBAAK,aAAY,UAAU,OAAO,OAAO,MAAM;AAC/C,yBAAK,cAAe;AAAA,IACrB,GAAG,GAAG;AAAA,EACP,GAAG,GAAG;AACP;AAEA,2DACC,MACO;AAEP,qBAAK,YAAW,YAAY,OAAO;AAGnC,qBAAK,YAAW,UAAU,IAAI,OAAO,IAAI,CAAC;AAC3C;AAEA,oBAAA,kCAAwB;AAEvB,aAAW,MAAM;AAChB,uBAAK,iBAAgB,YAAY,mBAAK,iBAAgB;AAAA,EACvD,GAAG,CAAC;AACL,GALA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAgBA,mBAAA,kCAAuB;AACtB,QAAM,QAAkB,CAAA;AAGxB,QAAM,OAAO,mBAAK,QAAO;AACzB,MAAI,MAAM;AACT,UAAM,KAAK,sBAAK,qCAAL,WAAqB,KAAK;AAAA,EACtC;AAGA,QAAM,UAAU,mBAAK,QAAO;AAC5B,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACxC,UAAM,QAAQ,QAAQ,CAAC;AACvB,UAAM,KAAK,GAAG,sBAAK,yCAAL,WAAyB,OAAO,IAAI,EAAE;AAAA,EACrD;AAEA,qBAAK,iBAAgB,YAAY,MAAM,KAAK,EAAE;AAC9C,wBAAK,qCAAL;AACD,GAlBA;AAoBA,oDAAgB,MAAsB;AACrC,SAAO,WAAW,EAAE,MAAM,MAAM,SAAS,MAAM,MAAM,SAAS;AAC/D;;AAGA,wBAAA,gCAAoB,OAA6C,YAA8B;AAC9F,QAAM,QAAkB,CAAA;AACxB,QAAM,OAAO,WAAW,mBAAK,SAAQ,YAAY,OAAO;AACxD,QAAM,OAAO,mBAAK,OAAM,EAAE,iBAAiB;AAAA,IAC1C,QAAQ,WAAW,SAAA;AAAA,IACnB;AAAA,IACA,UAAU;AAAA,EAAA,CACV;AAED,MAAI,MAAM,SAAS,QAAQ;AAE1B,QAAI,MAAM,YAAY;AACrB,YAAM,QAAQ,sBAAsB,MAAM,UAAU;AACpD,UAAI,MAAM,SAAS,GAAG;AACrB,cAAM,KAAK,WAAW,EAAE,MAAM,MAAM,SAAS,OAAO,KAAA,CAAM,CAAC;AAAA,MAC5D;AAAA,IACD;AAGA,UAAM,SAAS,MAAM;AACrB,QAAI,QAAQ;AACX,YAAM,KAAK,GAAG,sBAAK,wCAAL,WAAwB,QAAQ,KAAK;AAAA,IACpD;AAAA,EACD,WAAW,MAAM,SAAS,eAAe;AACxC,UAAM;AAAA,MACL,WAAW,EAAE,MAAM,OAAO,SAAS,MAAM,WAAW,IAAI,MAAM,MAAM,cAAA,CAAe;AAAA,IAAA;AAAA,EAErF,WAAW,MAAM,SAAS,iBAAiB;AAC1C,UAAM,KAAK,WAAW,EAAE,MAAM,MAAM,SAAS,iBAAiB,MAAM,MAAM,QAAA,CAAS,CAAC;AAAA,EACrF;AAEA,SAAO;AACR,GAhCA;AAAA;AAmCA,uBAAA,gCACC,QACA,MACW;AACX,QAAM,QAAkB,CAAA;AAExB,MAAI,OAAO,SAAS,QAAQ;AAC3B,UAAMF,SAAQ,OAAO;AACrB,UAAM,OAAOA,OAAM,QAAQ,OAAO,UAAU;AAC5C,QAAI,MAAM;AACT,YAAM,KAAK,WAAW,EAAE,MAAM,MAAM,SAAS,MAAM,MAAM,MAAM,SAAA,CAAU,CAAC;AAAA,IAC3E;AAAA,EACD,WAAW,OAAO,SAAS,YAAY;AACtC,UAAMA,SAAQ,OAAO;AACrB,UAAM,SAAS,OAAO,OAAO,QAAQ,uBAAuB,EAAE;AAC9D,UAAM;AAAA,MACL,WAAW;AAAA,QACV,MAAM;AAAA,QACN,SAAS,aAAaA,OAAM,YAAY,EAAE;AAAA,QAC1C;AAAA,QACA,MAAM;AAAA,MAAA,CACN;AAAA,IAAA;AAEF,UAAM,KAAK,WAAW,EAAE,MAAM,MAAM,SAAS,WAAW,MAAM,IAAI,MAAM,MAAM,QAAA,CAAS,CAAC;AAAA,EACzF,OAAO;AACN,UAAM,WAAW,sBAAK,2CAAL,WAA2B,OAAO,MAAM,OAAO;AAChE,UAAM,KAAK,WAAW,EAAE,MAAM,MAAM,SAAS,UAAU,KAAA,CAAM,CAAC;AAC9D,QAAI,OAAO,QAAQ,SAAS,GAAG;AAC9B,YAAM,KAAK,WAAW,EAAE,MAAM,MAAM,SAAS,OAAO,QAAQ,MAAM,MAAM,SAAA,CAAU,CAAC;AAAA,IACpF;AAAA,EACD;AAEA,SAAO;AACR,GAjCA;AAzkBkB;AAAZ,IAAM,QAAN;"}
|