page-agent 0.0.0 → 0.0.1

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.
@@ -22,19 +22,18 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
22
22
  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);
23
23
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
24
24
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
25
- var _openai, _model, _bus, _wrapper, _indicator, _statusText, _historySection, _expandButton, _pauseButton, _stopButton, _inputSection, _taskInput, _bus2, _state, _isExpanded, _pageAgent, _userAnswerResolver, _isWaitingForUserAnswer, _Panel_instances, update_fn, show_fn, hide_fn, reset_fn, togglePause_fn, updatePauseButton_fn, stopAgent_fn, submitTask_fn, handleUserAnswer_fn, showInputArea_fn, hideInputArea_fn, shouldShowInputArea_fn, createWrapper_fn, setupEventListeners_fn, toggle_fn, expand_fn, collapse_fn, animateTextChange_fn, updateStatusIndicator_fn, updateHistory_fn, scrollToBottom_fn, createHistoryItem_fn, _cursor, _currentCursorX, _currentCursorY, _targetCursorX, _targetCursorY, _SimulatorMask_instances, createCursor_fn, moveCursorToTarget_fn, _llm, _totalWaitTime, _abortController, _PageAgent_instances, packMacroTool_fn, getSystemPrompt_fn, assembleUserPrompt_fn, onDone_fn, getBrowserState_fn, updateTree_fn;
26
- import { generateText, stepCountIs, tool } from "ai";
25
+ var _bus, _wrapper, _indicator, _statusText, _historySection, _expandButton, _pauseButton, _stopButton, _inputSection, _taskInput, _bus2, _state, _isExpanded, _pageAgent, _userAnswerResolver, _isWaitingForUserAnswer, _Panel_instances, update_fn, show_fn, hide_fn, reset_fn, togglePause_fn, updatePauseButton_fn, stopAgent_fn, submitTask_fn, handleUserAnswer_fn, showInputArea_fn, hideInputArea_fn, shouldShowInputArea_fn, createWrapper_fn, setupEventListeners_fn, toggle_fn, expand_fn, collapse_fn, animateTextChange_fn, updateStatusIndicator_fn, updateHistory_fn, scrollToBottom_fn, createHistoryItem_fn, _cursor, _currentCursorX, _currentCursorY, _targetCursorX, _targetCursorY, _SimulatorMask_instances, createCursor_fn, moveCursorToTarget_fn, _llm, _totalWaitTime, _abortController, _PageAgent_instances, packMacroTool_fn, getSystemPrompt_fn, assembleUserPrompt_fn, onDone_fn, getBrowserState_fn, updateTree_fn;
27
26
  import chalk from "chalk";
28
- import zod from "zod";
29
- import { createOpenAI } from "@ai-sdk/openai";
27
+ import zod, { z } from "zod";
30
28
  import { Motion } from "ai-motion";
31
29
  const VIEWPORT_EXPANSION = -1;
32
30
  const DEFAULT_MODEL_NAME = "gpt-41-mini-0414-global";
33
31
  const DEFAULT_API_KEY = "not-needed";
34
32
  const DEFAULT_BASE_URL = "http://localhost:3000/api/agent";
35
- const MACRO_TOOL_NAME = "AgentOutput";
36
33
  const LLM_MAX_RETRIES = 2;
37
34
  const MAX_STEPS = 20;
35
+ const DEFAULT_TEMPERATURE = 0.7;
36
+ const DEFAULT_MAX_TOKENS = 4096;
38
37
  const domTree = /* @__PURE__ */ __name((args = {
39
38
  doHighlightElements: true,
40
39
  focusHighlightIndex: -1,
@@ -1396,49 +1395,6 @@ function getPageInfo() {
1396
1395
  };
1397
1396
  }
1398
1397
  __name(getPageInfo, "getPageInfo");
1399
- const zhCN = {
1400
- ui: {
1401
- panel: {
1402
- ready: "准备就绪",
1403
- thinking: "正在思考...",
1404
- paused: "暂停中,稍后",
1405
- taskInput: "输入新任务,详细描述步骤,回车提交",
1406
- userAnswerPrompt: "请回答上面问题,回车提交",
1407
- taskTerminated: "任务已终止",
1408
- taskCompleted: "任务结束",
1409
- continueExecution: "继续执行",
1410
- userAnswer: "用户回答: {{input}}",
1411
- pause: "暂停",
1412
- continue: "继续",
1413
- stop: "终止",
1414
- expand: "展开历史",
1415
- collapse: "收起历史",
1416
- step: "步骤 {{number}} · {{time}}{{duration}}"
1417
- },
1418
- tools: {
1419
- clicking: "正在点击元素 [{{index}}]...",
1420
- inputting: "正在输入文本到元素 [{{index}}]...",
1421
- selecting: '正在选择选项 "{{text}}"...',
1422
- scrolling: "正在滚动页面...",
1423
- waiting: "等待 {{seconds}} 秒...",
1424
- done: "结束任务",
1425
- clicked: "🖱️ 已点击元素 [{{index}}]",
1426
- inputted: '⌨️ 已输入文本 "{{text}}"',
1427
- selected: '☑️ 已选择选项 "{{text}}"',
1428
- scrolled: "🛞 页面滚动完成",
1429
- waited: "⌛️ 等待完成",
1430
- executing: "正在执行 {{toolName}}..."
1431
- },
1432
- errors: {
1433
- elementNotFound: "未找到索引为 {{index}} 的交互元素",
1434
- taskRequired: "任务描述不能为空",
1435
- executionFailed: "任务执行失败",
1436
- notInputElement: "元素不是输入框或文本域",
1437
- notSelectElement: "元素不是选择框",
1438
- optionNotFound: '未找到选项 "{{text}}"'
1439
- }
1440
- }
1441
- };
1442
1398
  const enUS = {
1443
1399
  ui: {
1444
1400
  panel: {
@@ -1451,6 +1407,8 @@ const enUS = {
1451
1407
  taskCompleted: "Task completed",
1452
1408
  continueExecution: "Continue execution",
1453
1409
  userAnswer: "User answer: {{input}}",
1410
+ question: "Question: {{question}}",
1411
+ waitingPlaceholder: "Waiting for task to start...",
1454
1412
  pause: "Pause",
1455
1413
  continue: "Continue",
1456
1414
  stop: "Stop",
@@ -1470,7 +1428,10 @@ const enUS = {
1470
1428
  selected: '☑️ Selected option "{{text}}"',
1471
1429
  scrolled: "🛞 Page scrolled",
1472
1430
  waited: "⌛️ Wait completed",
1473
- executing: "正在执行 {{toolName}}..."
1431
+ executing: "Executing {{toolName}}...",
1432
+ resultSuccess: "success",
1433
+ resultFailure: "failed",
1434
+ resultError: "error"
1474
1435
  },
1475
1436
  errors: {
1476
1437
  elementNotFound: "No interactive element found at index {{index}}",
@@ -1482,9 +1443,57 @@ const enUS = {
1482
1443
  }
1483
1444
  }
1484
1445
  };
1446
+ const zhCN = {
1447
+ ui: {
1448
+ panel: {
1449
+ ready: "准备就绪",
1450
+ thinking: "正在思考...",
1451
+ paused: "暂停中,稍后",
1452
+ taskInput: "输入新任务,详细描述步骤,回车提交",
1453
+ userAnswerPrompt: "请回答上面问题,回车提交",
1454
+ taskTerminated: "任务已终止",
1455
+ taskCompleted: "任务结束",
1456
+ continueExecution: "继续执行",
1457
+ userAnswer: "用户回答: {{input}}",
1458
+ question: "询问: {{question}}",
1459
+ waitingPlaceholder: "等待任务开始...",
1460
+ pause: "暂停",
1461
+ continue: "继续",
1462
+ stop: "终止",
1463
+ expand: "展开历史",
1464
+ collapse: "收起历史",
1465
+ step: "步骤 {{number}} · {{time}}{{duration}}"
1466
+ },
1467
+ tools: {
1468
+ clicking: "正在点击元素 [{{index}}]...",
1469
+ inputting: "正在输入文本到元素 [{{index}}]...",
1470
+ selecting: '正在选择选项 "{{text}}"...',
1471
+ scrolling: "正在滚动页面...",
1472
+ waiting: "等待 {{seconds}} 秒...",
1473
+ done: "结束任务",
1474
+ clicked: "🖱️ 已点击元素 [{{index}}]",
1475
+ inputted: '⌨️ 已输入文本 "{{text}}"',
1476
+ selected: '☑️ 已选择选项 "{{text}}"',
1477
+ scrolled: "🛞 页面滚动完成",
1478
+ waited: "⌛️ 等待完成",
1479
+ executing: "正在执行 {{toolName}}...",
1480
+ resultSuccess: "成功",
1481
+ resultFailure: "失败",
1482
+ resultError: "错误"
1483
+ },
1484
+ errors: {
1485
+ elementNotFound: "未找到索引为 {{index}} 的交互元素",
1486
+ taskRequired: "任务描述不能为空",
1487
+ executionFailed: "任务执行失败",
1488
+ notInputElement: "元素不是输入框或文本域",
1489
+ notSelectElement: "元素不是选择框",
1490
+ optionNotFound: '未找到选项 "{{text}}"'
1491
+ }
1492
+ }
1493
+ };
1485
1494
  const locales = {
1486
- "zh-CN": zhCN,
1487
- "en-US": enUS
1495
+ "en-US": enUS,
1496
+ "zh-CN": zhCN
1488
1497
  };
1489
1498
  const _I18n = class _I18n {
1490
1499
  language;
@@ -1510,7 +1519,7 @@ const _I18n = class _I18n {
1510
1519
  }
1511
1520
  interpolate(template, params) {
1512
1521
  return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
1513
- return params[key]?.toString() || match;
1522
+ return params[key] != null ? params[key].toString() : match;
1514
1523
  });
1515
1524
  }
1516
1525
  getLanguage() {
@@ -1519,14 +1528,17 @@ const _I18n = class _I18n {
1519
1528
  };
1520
1529
  __name(_I18n, "I18n");
1521
1530
  let I18n = _I18n;
1522
- function assert(condition, message, silent) {
1523
- if (!condition) {
1524
- const errorMessage = message ?? "Assertion failed";
1525
- if (!silent) console.error(chalk.red(`❌ assert: ${errorMessage}`));
1526
- throw new Error(errorMessage);
1527
- }
1531
+ function parseLLMConfig(config) {
1532
+ return {
1533
+ baseURL: config.baseURL ?? DEFAULT_BASE_URL,
1534
+ apiKey: config.apiKey ?? DEFAULT_API_KEY,
1535
+ model: config.model ?? DEFAULT_MODEL_NAME,
1536
+ temperature: config.temperature ?? DEFAULT_TEMPERATURE,
1537
+ maxTokens: config.maxTokens ?? DEFAULT_MAX_TOKENS,
1538
+ maxRetries: config.maxRetries ?? LLM_MAX_RETRIES
1539
+ };
1528
1540
  }
1529
- __name(assert, "assert");
1541
+ __name(parseLLMConfig, "parseLLMConfig");
1530
1542
  const _EventBus = class _EventBus extends EventTarget {
1531
1543
  /**
1532
1544
  * Listen to built-in events
@@ -1571,24 +1583,316 @@ function getEventBus(channel) {
1571
1583
  return bus;
1572
1584
  }
1573
1585
  __name(getEventBus, "getEventBus");
1586
+ const InvokeErrorType = {
1587
+ // Retryable
1588
+ NETWORK_ERROR: "network_error",
1589
+ // Network error, retry
1590
+ RATE_LIMIT: "rate_limit",
1591
+ // Rate limit, retry
1592
+ SERVER_ERROR: "server_error",
1593
+ // 5xx, retry
1594
+ NO_TOOL_CALL: "no_tool_call",
1595
+ // Model did not call tool
1596
+ INVALID_TOOL_ARGS: "invalid_tool_args",
1597
+ // Tool args don't match schema
1598
+ TOOL_EXECUTION_ERROR: "tool_execution_error",
1599
+ // Tool execution error
1600
+ UNKNOWN: "unknown",
1601
+ // Non-retryable
1602
+ AUTH_ERROR: "auth_error",
1603
+ // Authentication failed
1604
+ CONTEXT_LENGTH: "context_length",
1605
+ // Prompt too long
1606
+ CONTENT_FILTER: "content_filter"
1607
+ // Content filtered
1608
+ };
1609
+ const _InvokeError = class _InvokeError extends Error {
1610
+ type;
1611
+ retryable;
1612
+ statusCode;
1613
+ rawError;
1614
+ constructor(type, message, rawError) {
1615
+ super(message);
1616
+ this.name = "InvokeError";
1617
+ this.type = type;
1618
+ this.retryable = this.isRetryable(type);
1619
+ this.rawError = rawError;
1620
+ }
1621
+ isRetryable(type) {
1622
+ const retryableTypes = [
1623
+ InvokeErrorType.NETWORK_ERROR,
1624
+ InvokeErrorType.RATE_LIMIT,
1625
+ InvokeErrorType.SERVER_ERROR,
1626
+ InvokeErrorType.NO_TOOL_CALL,
1627
+ InvokeErrorType.INVALID_TOOL_ARGS,
1628
+ InvokeErrorType.TOOL_EXECUTION_ERROR,
1629
+ InvokeErrorType.UNKNOWN
1630
+ ];
1631
+ return retryableTypes.includes(type);
1632
+ }
1633
+ };
1634
+ __name(_InvokeError, "InvokeError");
1635
+ let InvokeError = _InvokeError;
1636
+ function zodToOpenAITool(name, tool2) {
1637
+ return {
1638
+ type: "function",
1639
+ function: {
1640
+ name,
1641
+ description: tool2.description,
1642
+ parameters: z.toJSONSchema(tool2.inputSchema, { target: "openapi-3.0" })
1643
+ }
1644
+ };
1645
+ }
1646
+ __name(zodToOpenAITool, "zodToOpenAITool");
1647
+ function lenientParseMacroToolCall(responseData, inputSchema) {
1648
+ const choice = responseData.choices?.[0];
1649
+ if (!choice) {
1650
+ throw new InvokeError(InvokeErrorType.UNKNOWN, "No choices in response", responseData);
1651
+ }
1652
+ switch (choice.finish_reason) {
1653
+ case "tool_calls":
1654
+ case "stop":
1655
+ break;
1656
+ case "length":
1657
+ throw new InvokeError(
1658
+ InvokeErrorType.CONTEXT_LENGTH,
1659
+ "Response truncated: max tokens reached"
1660
+ );
1661
+ case "content_filter":
1662
+ throw new InvokeError(InvokeErrorType.CONTENT_FILTER, "Content filtered by safety system");
1663
+ default:
1664
+ throw new InvokeError(
1665
+ InvokeErrorType.UNKNOWN,
1666
+ `Unexpected finish_reason: ${choice.finish_reason}`
1667
+ );
1668
+ }
1669
+ const actionSchema = inputSchema.shape.action;
1670
+ if (!actionSchema) {
1671
+ throw new Error('inputSchema must have an "action" field');
1672
+ }
1673
+ let arg = null;
1674
+ const toolCall = choice.message?.tool_calls?.[0]?.function;
1675
+ arg = toolCall?.arguments ?? null;
1676
+ if (arg && toolCall.name !== "AgentOutput") {
1677
+ console.log(chalk.yellow("lenientParseMacroToolCall: #1 fixing incorrect tool call"));
1678
+ let tmpArg;
1679
+ try {
1680
+ tmpArg = JSON.parse(arg);
1681
+ } catch (error2) {
1682
+ throw new InvokeError(
1683
+ InvokeErrorType.INVALID_TOOL_ARGS,
1684
+ "Failed to parse tool arguments as JSON",
1685
+ error2
1686
+ );
1687
+ }
1688
+ arg = JSON.stringify({ action: { [toolCall.name]: tmpArg } });
1689
+ }
1690
+ if (!arg) {
1691
+ arg = choice.message?.content.trim() || null;
1692
+ }
1693
+ if (!arg) {
1694
+ throw new InvokeError(
1695
+ InvokeErrorType.NO_TOOL_CALL,
1696
+ "No tool call or content found in response",
1697
+ responseData
1698
+ );
1699
+ }
1700
+ let parsedArgs;
1701
+ try {
1702
+ parsedArgs = JSON.parse(arg);
1703
+ } catch (error2) {
1704
+ throw new InvokeError(
1705
+ InvokeErrorType.INVALID_TOOL_ARGS,
1706
+ "Failed to parse tool arguments as JSON",
1707
+ error2
1708
+ );
1709
+ }
1710
+ if (parsedArgs.action || parsedArgs.evaluation_previous_goal || parsedArgs.next_goal) {
1711
+ if (!parsedArgs.action) {
1712
+ console.log(chalk.yellow("lenientParseMacroToolCall: #2 fixing incorrect tool call"));
1713
+ parsedArgs.action = {
1714
+ wait: { seconds: 1 }
1715
+ };
1716
+ }
1717
+ } else if (parsedArgs.type && parsedArgs.function) {
1718
+ if (parsedArgs.function.name !== "AgentOutput")
1719
+ throw new InvokeError(
1720
+ InvokeErrorType.INVALID_TOOL_ARGS,
1721
+ `Expected function name "AgentOutput", got "${parsedArgs.function.name}"`,
1722
+ null
1723
+ );
1724
+ console.log(chalk.yellow("lenientParseMacroToolCall: #3 fixing incorrect tool call"));
1725
+ parsedArgs = parsedArgs.function.arguments;
1726
+ } else if (parsedArgs.name && parsedArgs.arguments) {
1727
+ if (parsedArgs.name !== "AgentOutput")
1728
+ throw new InvokeError(
1729
+ InvokeErrorType.INVALID_TOOL_ARGS,
1730
+ `Expected function name "AgentOutput", got "${parsedArgs.name}"`,
1731
+ null
1732
+ );
1733
+ console.log(chalk.yellow("lenientParseMacroToolCall: #4 fixing incorrect tool call"));
1734
+ parsedArgs = parsedArgs.arguments;
1735
+ } else {
1736
+ console.log(chalk.yellow("lenientParseMacroToolCall: #5 fixing incorrect tool call"));
1737
+ parsedArgs = { action: parsedArgs };
1738
+ }
1739
+ if (typeof parsedArgs === "string") {
1740
+ console.log(chalk.yellow("lenientParseMacroToolCall: #6 fixing incorrect tool call"));
1741
+ try {
1742
+ parsedArgs = JSON.parse(parsedArgs);
1743
+ } catch (error2) {
1744
+ throw new InvokeError(
1745
+ InvokeErrorType.INVALID_TOOL_ARGS,
1746
+ "Failed to parse nested tool arguments as JSON",
1747
+ error2
1748
+ );
1749
+ }
1750
+ }
1751
+ const validation = inputSchema.safeParse(parsedArgs);
1752
+ if (validation.success) {
1753
+ return validation.data;
1754
+ } else {
1755
+ const action = parsedArgs.action ?? {};
1756
+ const actionName = Object.keys(action)[0] || "unknown";
1757
+ const actionArgs = JSON.stringify(action[actionName] || "unknown");
1758
+ throw new InvokeError(
1759
+ InvokeErrorType.INVALID_TOOL_ARGS,
1760
+ `Tool arguments validation failed: action "${actionName}" with args ${actionArgs}`,
1761
+ validation.error
1762
+ );
1763
+ }
1764
+ }
1765
+ __name(lenientParseMacroToolCall, "lenientParseMacroToolCall");
1766
+ function modelPatch(body) {
1767
+ const model = body.model || "";
1768
+ if (model.toLowerCase().startsWith("claude")) {
1769
+ body.tool_choice = { type: "tool", name: "AgentOutput" };
1770
+ body.thinking = { type: "disabled" };
1771
+ }
1772
+ if (model.toLowerCase().includes("grok")) {
1773
+ console.log("Applying Grok patch: removing tool_choice");
1774
+ delete body.tool_choice;
1775
+ console.log("Applying Grok patch: disable reasoning and thinking");
1776
+ body.thinking = { type: "disabled", effort: "minimal" };
1777
+ body.reasoning = { enabled: false, effort: "low" };
1778
+ }
1779
+ return body;
1780
+ }
1781
+ __name(modelPatch, "modelPatch");
1782
+ const _OpenAIClient = class _OpenAIClient {
1783
+ config;
1784
+ constructor(config) {
1785
+ this.config = config;
1786
+ }
1787
+ async invoke(messages, tools2, abortSignal) {
1788
+ const openaiTools = Object.entries(tools2).map(([name, tool22]) => zodToOpenAITool(name, tool22));
1789
+ let response;
1790
+ try {
1791
+ response = await fetch(`${this.config.baseURL}/chat/completions`, {
1792
+ method: "POST",
1793
+ headers: {
1794
+ "Content-Type": "application/json",
1795
+ Authorization: `Bearer ${this.config.apiKey}`
1796
+ },
1797
+ body: JSON.stringify(
1798
+ modelPatch({
1799
+ model: this.config.model,
1800
+ temperature: this.config.temperature,
1801
+ max_tokens: this.config.maxTokens,
1802
+ messages,
1803
+ tools: openaiTools,
1804
+ // tool_choice: 'required',
1805
+ tool_choice: { type: "function", function: { name: "AgentOutput" } },
1806
+ // model specific params
1807
+ // reasoning_effort: 'minimal',
1808
+ // verbosity: 'low',
1809
+ parallel_tool_calls: false
1810
+ })
1811
+ ),
1812
+ signal: abortSignal
1813
+ });
1814
+ } catch (error2) {
1815
+ throw new InvokeError(InvokeErrorType.NETWORK_ERROR, "Network request failed", error2);
1816
+ }
1817
+ if (!response.ok) {
1818
+ const errorData = await response.json().catch();
1819
+ const errorMessage = errorData.error?.message || response.statusText;
1820
+ if (response.status === 401 || response.status === 403) {
1821
+ throw new InvokeError(
1822
+ InvokeErrorType.AUTH_ERROR,
1823
+ `Authentication failed: ${errorMessage}`,
1824
+ errorData
1825
+ );
1826
+ }
1827
+ if (response.status === 429) {
1828
+ throw new InvokeError(
1829
+ InvokeErrorType.RATE_LIMIT,
1830
+ `Rate limit exceeded: ${errorMessage}`,
1831
+ errorData
1832
+ );
1833
+ }
1834
+ if (response.status >= 500) {
1835
+ throw new InvokeError(
1836
+ InvokeErrorType.SERVER_ERROR,
1837
+ `Server error: ${errorMessage}`,
1838
+ errorData
1839
+ );
1840
+ }
1841
+ throw new InvokeError(
1842
+ InvokeErrorType.UNKNOWN,
1843
+ `HTTP ${response.status}: ${errorMessage}`,
1844
+ errorData
1845
+ );
1846
+ }
1847
+ const data = await response.json();
1848
+ const tool2 = tools2.AgentOutput;
1849
+ const macroToolInput = lenientParseMacroToolCall(data, tool2.inputSchema);
1850
+ let toolResult;
1851
+ try {
1852
+ toolResult = await tool2.execute(macroToolInput);
1853
+ } catch (e) {
1854
+ throw new InvokeError(
1855
+ InvokeErrorType.TOOL_EXECUTION_ERROR,
1856
+ `Tool execution failed: ${e.message}`,
1857
+ e
1858
+ );
1859
+ }
1860
+ return {
1861
+ toolCall: {
1862
+ // id: toolCall.id,
1863
+ name: "AgentOutput",
1864
+ args: macroToolInput
1865
+ },
1866
+ toolResult,
1867
+ usage: {
1868
+ promptTokens: data.usage?.prompt_tokens ?? 0,
1869
+ completionTokens: data.usage?.completion_tokens ?? 0,
1870
+ totalTokens: data.usage?.total_tokens ?? 0,
1871
+ cachedTokens: data.usage?.prompt_tokens_details?.cached_tokens,
1872
+ reasoningTokens: data.usage?.completion_tokens_details?.reasoning_tokens
1873
+ },
1874
+ rawResponse: data
1875
+ };
1876
+ }
1877
+ };
1878
+ __name(_OpenAIClient, "OpenAIClient");
1879
+ let OpenAIClient = _OpenAIClient;
1574
1880
  const _LLM = class _LLM {
1575
1881
  constructor(config, id) {
1576
1882
  __publicField(this, "config");
1577
1883
  __publicField(this, "id");
1578
- __privateAdd(this, _openai);
1579
- __privateAdd(this, _model);
1884
+ __publicField(this, "client");
1580
1885
  __privateAdd(this, _bus);
1581
- this.config = {
1582
- baseURL: DEFAULT_BASE_URL,
1583
- apiKey: DEFAULT_API_KEY,
1584
- modelName: DEFAULT_MODEL_NAME,
1585
- maxRetries: LLM_MAX_RETRIES,
1586
- ...config
1587
- };
1886
+ this.config = parseLLMConfig(config);
1588
1887
  this.id = id;
1589
1888
  __privateSet(this, _bus, getEventBus(id));
1590
- __privateSet(this, _openai, createOpenAI({ baseURL: this.config.baseURL, apiKey: this.config.apiKey }));
1591
- __privateSet(this, _model, __privateGet(this, _openai).chat(this.config.modelName));
1889
+ this.client = new OpenAIClient({
1890
+ model: this.config.model,
1891
+ apiKey: this.config.apiKey,
1892
+ baseURL: this.config.baseURL,
1893
+ temperature: this.config.temperature,
1894
+ maxTokens: this.config.maxTokens
1895
+ });
1592
1896
  }
1593
1897
  /**
1594
1898
  * - call llm api *once*
@@ -1596,81 +1900,10 @@ const _LLM = class _LLM {
1596
1900
  * - return the result of the tool
1597
1901
  */
1598
1902
  async invoke(messages, tools2, abortSignal) {
1599
- const isClaude = this.config.modelName.slice(0, 8).includes("claude");
1600
- this.config.modelName.slice(0, 6).includes("qwen");
1601
- this.config.modelName.slice(0, 5).includes("gpt");
1602
1903
  return await withRetry(
1603
1904
  async () => {
1604
- const result = await generateText({
1605
- model: __privateGet(this, _model),
1606
- messages,
1607
- tools: tools2,
1608
- abortSignal,
1609
- /**
1610
- * 文档中没有说明,从源码看,@facts
1611
- * - 只会重试被识别为 retryable 的 API_CALL_ERROR
1612
- * - 返回无法解析的 json 应该不会重试
1613
- * - experimental_repairToolCall 只会执行一次,不算作重试
1614
- * @facts
1615
- * - 许多 proxy 过的 openAI 兼容接口返回的错误格式并不规范,通常不会被识别为 retryable
1616
- * @conclusion
1617
- * - 看起来并不实用,不如完全手工控制粗粒度重试
1618
- */
1619
- // maxRetries: this.config.maxRetries,
1620
- maxRetries: 0,
1621
- // toolChoice: 'required',
1622
- // @note incompatible to Claude
1623
- toolChoice: isClaude ? void 0 : { type: "tool", toolName: MACRO_TOOL_NAME },
1624
- /**
1625
- * controlled by main loop. our method only call api once
1626
- */
1627
- // stopWhen: [hasToolCall('done'), stepCountIs(100)],
1628
- stopWhen: [stepCountIs(1)],
1629
- // stopWhen: [hasToolCall('AgentOutput')],
1630
- providerOptions: {
1631
- openai: {
1632
- // @note this one needs all fields in tool schema must be `required`
1633
- // strictJsonSchema: true,
1634
- // This way only at most one tool can be called at a time
1635
- parallelToolCalls: false,
1636
- reasoningEffort: "minimal",
1637
- // @note not working
1638
- // serviceTier: 'priority',
1639
- textVerbosity: "low",
1640
- // @note Optimize OpenAI model caching, should be unique per user, currently has no effect
1641
- promptCacheKey: "page-agent:" + this.id
1642
- }
1643
- }
1644
- /**
1645
- * schema 出错时执行一次,不确定是否计入重试
1646
- * 目前看起来像是会直接抛错,被 withRetry 处理
1647
- * @note
1648
- * 如果不提供,则 ai-sdk 会把 tool-error 加入 message 中重新调用一次,
1649
- * 配合 stepCountIs 或者 hasToolCall 都会导致错误被 silent,toolResults 永远为 0
1650
- * 遗憾的是,这里没有办法抛错(抛错后回到默认逻辑),只要这里 repair 不好,就会导致 silent error
1651
- * 更糟糕的是,只要传入了 tools,无论 stopWhen 如何设置,都会被当作 multi-step,
1652
- * 本质上就和我们 single step 的逻辑冲突
1653
- * 长远来看必须删掉 ai-sdk,直接用 openAI API 实现
1654
- */
1655
- // experimental_repairToolCall: (options): Promise<LanguageModelV2ToolCall | null> => {
1656
- // console.error('hahhah', options)
1657
- // throw options.error
1658
- // },
1659
- });
1660
- console.log(chalk.blue.bold("LLM:invoke finished"), result);
1661
- const toolError = result.content.find((part) => part.type === "tool-error");
1662
- if (toolError) throw toolError.error;
1663
- assert(!result.text, "Model returned text without calling done tool", true);
1664
- assert(result.toolCalls.length === 1, "Model must call exactly one tool", true);
1665
- assert(result.toolResults.length === 1, "Step must have exactly one tool result", true);
1666
- const toolCall = result.toolCalls[0];
1667
- const toolResult = result.toolResults[0];
1668
- const usage = result.totalUsage;
1669
- return {
1670
- toolCall,
1671
- toolResult,
1672
- usage
1673
- };
1905
+ const result = await this.client.invoke(messages, tools2, abortSignal);
1906
+ return result;
1674
1907
  },
1675
1908
  // retry settings
1676
1909
  {
@@ -1691,8 +1924,6 @@ const _LLM = class _LLM {
1691
1924
  );
1692
1925
  }
1693
1926
  };
1694
- _openai = new WeakMap();
1695
- _model = new WeakMap();
1696
1927
  _bus = new WeakMap();
1697
1928
  __name(_LLM, "LLM");
1698
1929
  let LLM = _LLM;
@@ -1710,6 +1941,7 @@ async function withRetry(fn, settings) {
1710
1941
  console.error(error2);
1711
1942
  settings.onError(error2, retries < settings.maxRetries);
1712
1943
  if (error2?.name === "AbortError") throw error2;
1944
+ if (error2 instanceof InvokeError && !error2.retryable) throw error2;
1713
1945
  lastError = error2;
1714
1946
  retries++;
1715
1947
  await new Promise((resolve) => setTimeout(resolve, 100));
@@ -2049,6 +2281,10 @@ const utils = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
2049
2281
  waitFor
2050
2282
  }, Symbol.toStringTag, { value: "Module" }));
2051
2283
  window.utils = utils;
2284
+ function tool(options) {
2285
+ return options;
2286
+ }
2287
+ __name(tool, "tool");
2052
2288
  const tools = /* @__PURE__ */ new Map();
2053
2289
  tools.set(
2054
2290
  "done",
@@ -2058,7 +2294,8 @@ tools.set(
2058
2294
  text: zod.string(),
2059
2295
  success: zod.boolean().default(true)
2060
2296
  }),
2061
- execute: /* @__PURE__ */ __name(function(input2) {
2297
+ execute: /* @__PURE__ */ __name(async function(input2) {
2298
+ return Promise.resolve("Task completed");
2062
2299
  }, "execute")
2063
2300
  })
2064
2301
  );
@@ -2421,7 +2658,7 @@ const _Panel = class _Panel {
2421
2658
  __privateSet(this, _userAnswerResolver, resolve);
2422
2659
  __privateMethod(this, _Panel_instances, update_fn).call(this, {
2423
2660
  type: "output",
2424
- displayText: `询问: ${question}`
2661
+ displayText: __privateGet(this, _pageAgent).i18n.t("ui.panel.question", { question })
2425
2662
  });
2426
2663
  if (!__privateGet(this, _isExpanded)) {
2427
2664
  __privateMethod(this, _Panel_instances, expand_fn).call(this);
@@ -2482,7 +2719,7 @@ show_fn = /* @__PURE__ */ __name(function() {
2482
2719
  this.wrapper.style.transform = "translateX(-50%) translateY(0)";
2483
2720
  }, "#show");
2484
2721
  /**
2485
- * 隐藏面板
2722
+ * Hide panel
2486
2723
  */
2487
2724
  hide_fn = /* @__PURE__ */ __name(function() {
2488
2725
  this.wrapper.style.opacity = "0";
@@ -2490,7 +2727,7 @@ hide_fn = /* @__PURE__ */ __name(function() {
2490
2727
  this.wrapper.style.display = "none";
2491
2728
  }, "#hide");
2492
2729
  /**
2493
- * 重置状态
2730
+ * Reset state
2494
2731
  */
2495
2732
  reset_fn = /* @__PURE__ */ __name(function() {
2496
2733
  __privateGet(this, _state).reset();
@@ -2511,39 +2748,39 @@ togglePause_fn = /* @__PURE__ */ __name(function() {
2511
2748
  __privateGet(this, _pageAgent).paused = !__privateGet(this, _pageAgent).paused;
2512
2749
  __privateMethod(this, _Panel_instances, updatePauseButton_fn).call(this);
2513
2750
  if (__privateGet(this, _pageAgent).paused) {
2514
- __privateGet(this, _statusText).textContent = "暂停中,稍后";
2751
+ __privateGet(this, _statusText).textContent = __privateGet(this, _pageAgent).i18n.t("ui.panel.paused");
2515
2752
  __privateMethod(this, _Panel_instances, updateStatusIndicator_fn).call(this, "thinking");
2516
2753
  } else {
2517
- __privateGet(this, _statusText).textContent = "继续执行";
2754
+ __privateGet(this, _statusText).textContent = __privateGet(this, _pageAgent).i18n.t("ui.panel.continueExecution");
2518
2755
  __privateMethod(this, _Panel_instances, updateStatusIndicator_fn).call(this, "tool_executing");
2519
2756
  }
2520
2757
  }, "#togglePause");
2521
2758
  /**
2522
- * 更新暂停按钮状态
2759
+ * Update pause button state
2523
2760
  */
2524
2761
  updatePauseButton_fn = /* @__PURE__ */ __name(function() {
2525
2762
  if (__privateGet(this, _pageAgent).paused) {
2526
2763
  __privateGet(this, _pauseButton).textContent = "▶";
2527
- __privateGet(this, _pauseButton).title = "继续";
2764
+ __privateGet(this, _pauseButton).title = __privateGet(this, _pageAgent).i18n.t("ui.panel.continue");
2528
2765
  __privateGet(this, _pauseButton).classList.add(styles$1.paused);
2529
2766
  } else {
2530
2767
  __privateGet(this, _pauseButton).textContent = "⏸︎";
2531
- __privateGet(this, _pauseButton).title = "暂停";
2768
+ __privateGet(this, _pauseButton).title = __privateGet(this, _pageAgent).i18n.t("ui.panel.pause");
2532
2769
  __privateGet(this, _pauseButton).classList.remove(styles$1.paused);
2533
2770
  }
2534
2771
  }, "#updatePauseButton");
2535
2772
  /**
2536
- * 终止 Agent
2773
+ * Stop Agent
2537
2774
  */
2538
2775
  stopAgent_fn = /* @__PURE__ */ __name(function() {
2539
2776
  __privateMethod(this, _Panel_instances, update_fn).call(this, {
2540
2777
  type: "error",
2541
- displayText: "任务已终止"
2778
+ displayText: __privateGet(this, _pageAgent).i18n.t("ui.panel.taskTerminated")
2542
2779
  });
2543
2780
  __privateGet(this, _pageAgent).dispose();
2544
2781
  }, "#stopAgent");
2545
2782
  /**
2546
- * 提交任务
2783
+ * Submit task
2547
2784
  */
2548
2785
  submitTask_fn = /* @__PURE__ */ __name(function() {
2549
2786
  const input2 = __privateGet(this, _taskInput).value.trim();
@@ -2556,12 +2793,12 @@ submitTask_fn = /* @__PURE__ */ __name(function() {
2556
2793
  }
2557
2794
  }, "#submitTask");
2558
2795
  /**
2559
- * 处理用户回答
2796
+ * Handle user answer
2560
2797
  */
2561
2798
  handleUserAnswer_fn = /* @__PURE__ */ __name(function(input2) {
2562
2799
  __privateMethod(this, _Panel_instances, update_fn).call(this, {
2563
2800
  type: "input",
2564
- displayText: `用户回答: ${input2}`
2801
+ displayText: __privateGet(this, _pageAgent).i18n.t("ui.panel.userAnswer", { input: input2 })
2565
2802
  });
2566
2803
  __privateSet(this, _isWaitingForUserAnswer, false);
2567
2804
  if (__privateGet(this, _userAnswerResolver)) {
@@ -2570,24 +2807,24 @@ handleUserAnswer_fn = /* @__PURE__ */ __name(function(input2) {
2570
2807
  }
2571
2808
  }, "#handleUserAnswer");
2572
2809
  /**
2573
- * 显示输入区域
2810
+ * Show input area
2574
2811
  */
2575
2812
  showInputArea_fn = /* @__PURE__ */ __name(function(placeholder) {
2576
2813
  __privateGet(this, _taskInput).value = "";
2577
- __privateGet(this, _taskInput).placeholder = placeholder || "输入新任务,详细描述步骤,回车提交";
2814
+ __privateGet(this, _taskInput).placeholder = placeholder || __privateGet(this, _pageAgent).i18n.t("ui.panel.taskInput");
2578
2815
  __privateGet(this, _inputSection).classList.remove(styles$1.hidden);
2579
2816
  setTimeout(() => {
2580
2817
  __privateGet(this, _taskInput).focus();
2581
2818
  }, 100);
2582
2819
  }, "#showInputArea");
2583
2820
  /**
2584
- * 隐藏输入区域
2821
+ * Hide input area
2585
2822
  */
2586
2823
  hideInputArea_fn = /* @__PURE__ */ __name(function() {
2587
2824
  __privateGet(this, _inputSection).classList.add(styles$1.hidden);
2588
2825
  }, "#hideInputArea");
2589
2826
  /**
2590
- * 检查是否应该显示输入区域
2827
+ * Check if input area should be shown
2591
2828
  */
2592
2829
  shouldShowInputArea_fn = /* @__PURE__ */ __name(function() {
2593
2830
  if (__privateGet(this, _isWaitingForUserAnswer)) return true;
@@ -2612,23 +2849,23 @@ createWrapper_fn = /* @__PURE__ */ __name(function() {
2612
2849
  stepNumber: 0,
2613
2850
  timestamp: /* @__PURE__ */ new Date(),
2614
2851
  type: "thinking",
2615
- displayText: "等待任务开始..."
2852
+ displayText: __privateGet(this, _pageAgent).i18n.t("ui.panel.waitingPlaceholder")
2616
2853
  })}
2617
2854
  </div>
2618
2855
  </div>
2619
2856
  <div class="${styles$1.header}">
2620
2857
  <div class="${styles$1.statusSection}">
2621
2858
  <div class="${styles$1.indicator} ${styles$1.thinking}"></div>
2622
- <div class="${styles$1.statusText}">准备就绪</div>
2859
+ <div class="${styles$1.statusText}">${__privateGet(this, _pageAgent).i18n.t("ui.panel.ready")}</div>
2623
2860
  </div>
2624
2861
  <div class="${styles$1.controls}">
2625
- <button class="${styles$1.controlButton} ${styles$1.expandButton}" title="展开历史">
2862
+ <button class="${styles$1.controlButton} ${styles$1.expandButton}" title="${__privateGet(this, _pageAgent).i18n.t("ui.panel.expand")}">
2626
2863
 
2627
2864
  </button>
2628
- <button class="${styles$1.controlButton} ${styles$1.pauseButton}" title="暂停">
2865
+ <button class="${styles$1.controlButton} ${styles$1.pauseButton}" title="${__privateGet(this, _pageAgent).i18n.t("ui.panel.pause")}">
2629
2866
  ⏸︎
2630
2867
  </button>
2631
- <button class="${styles$1.controlButton} ${styles$1.stopButton}" title="终止">
2868
+ <button class="${styles$1.controlButton} ${styles$1.stopButton}" title="${__privateGet(this, _pageAgent).i18n.t("ui.panel.stop")}">
2632
2869
  X
2633
2870
  </button>
2634
2871
  </div>
@@ -2716,7 +2953,7 @@ updateStatusIndicator_fn = /* @__PURE__ */ __name(function(type) {
2716
2953
  }, "#updateStatusIndicator");
2717
2954
  updateHistory_fn = /* @__PURE__ */ __name(function() {
2718
2955
  const steps = __privateGet(this, _state).getAllSteps();
2719
- __privateGet(this, _historySection).innerHTML = steps.slice(-10).map((step) => __privateMethod(this, _Panel_instances, createHistoryItem_fn).call(this, step)).join("");
2956
+ __privateGet(this, _historySection).innerHTML = steps.map((step) => __privateMethod(this, _Panel_instances, createHistoryItem_fn).call(this, step)).join("");
2720
2957
  __privateMethod(this, _Panel_instances, scrollToBottom_fn).call(this);
2721
2958
  }, "#updateHistory");
2722
2959
  scrollToBottom_fn = /* @__PURE__ */ __name(function() {
@@ -2735,7 +2972,9 @@ createHistoryItem_fn = /* @__PURE__ */ __name(function(step) {
2735
2972
  let statusIcon2 = "";
2736
2973
  if (step.type === "completed") {
2737
2974
  if (step.toolName === "done") {
2738
- const isSuccess = !step.toolResult || !step.toolResult.includes("失败") && !step.toolResult.includes("错误");
2975
+ const failureKeyword = __privateGet(this, _pageAgent).i18n.t("ui.tools.resultFailure");
2976
+ const errorKeyword = __privateGet(this, _pageAgent).i18n.t("ui.tools.resultError");
2977
+ const isSuccess = !step.toolResult || !step.toolResult.includes(failureKeyword) && !step.toolResult.includes(errorKeyword);
2739
2978
  typeClass = isSuccess ? styles$1.doneSuccess : styles$1.doneError;
2740
2979
  statusIcon2 = isSuccess ? "🎉" : "❌";
2741
2980
  } else {
@@ -2759,6 +2998,13 @@ createHistoryItem_fn = /* @__PURE__ */ __name(function(step) {
2759
2998
  } else {
2760
2999
  statusIcon2 = "🧠";
2761
3000
  }
3001
+ const durationText = step.duration ? ` · ${step.duration}ms` : "";
3002
+ const stepLabel = __privateGet(this, _pageAgent).i18n.t("ui.panel.step", {
3003
+ number: step.stepNumber.toString(),
3004
+ time,
3005
+ duration: durationText || ""
3006
+ // Explicitly pass empty string to replace template
3007
+ });
2762
3008
  return `
2763
3009
  <div class="${styles$1.historyItem} ${typeClass}">
2764
3010
  <div class="${styles$1.historyContent}">
@@ -2766,8 +3012,7 @@ createHistoryItem_fn = /* @__PURE__ */ __name(function(step) {
2766
3012
  <span>${step.displayText}</span>
2767
3013
  </div>
2768
3014
  <div class="${styles$1.historyMeta}">
2769
- 步骤 ${step.stepNumber} · ${time}
2770
- ${step.duration ? ` · ${step.duration}ms` : ""}
3015
+ ${stepLabel}
2771
3016
  </div>
2772
3017
  </div>
2773
3018
  `;
@@ -3028,6 +3273,14 @@ moveCursorToTarget_fn = /* @__PURE__ */ __name(function() {
3028
3273
  }, "#moveCursorToTarget");
3029
3274
  __name(_SimulatorMask, "SimulatorMask");
3030
3275
  let SimulatorMask = _SimulatorMask;
3276
+ function assert(condition, message, silent) {
3277
+ if (!condition) {
3278
+ const errorMessage = message ?? "Assertion failed";
3279
+ console.error(chalk.red(`❌ assert: ${errorMessage}`));
3280
+ throw new Error(errorMessage);
3281
+ }
3282
+ }
3283
+ __name(assert, "assert");
3031
3284
  const _PageAgent = class _PageAgent extends EventTarget {
3032
3285
  constructor(config = {}) {
3033
3286
  super();
@@ -3036,6 +3289,7 @@ const _PageAgent = class _PageAgent extends EventTarget {
3036
3289
  __publicField(this, "id", uid());
3037
3290
  __publicField(this, "bus", getEventBus(this.id));
3038
3291
  __publicField(this, "i18n");
3292
+ __publicField(this, "panel");
3039
3293
  __publicField(this, "paused", false);
3040
3294
  __publicField(this, "disposed", false);
3041
3295
  __publicField(this, "task", "");
@@ -3059,13 +3313,12 @@ const _PageAgent = class _PageAgent extends EventTarget {
3059
3313
  __publicField(this, "tools", new Map(tools));
3060
3314
  /** Fullscreen mask */
3061
3315
  __publicField(this, "mask", new SimulatorMask());
3062
- /** Interactive panel */
3063
- __publicField(this, "panel", new Panel(this));
3064
3316
  /** History records */
3065
3317
  __publicField(this, "history", []);
3066
3318
  this.config = config;
3067
3319
  __privateSet(this, _llm, new LLM(this.config, this.id));
3068
3320
  this.i18n = new I18n(this.config.language);
3321
+ this.panel = new Panel(this);
3069
3322
  patchReact();
3070
3323
  }
3071
3324
  /**
@@ -3108,18 +3361,16 @@ const _PageAgent = class _PageAgent extends EventTarget {
3108
3361
  content: __privateMethod(this, _PageAgent_instances, assembleUserPrompt_fn).call(this)
3109
3362
  }
3110
3363
  ],
3111
- // tools,
3112
- __privateMethod(this, _PageAgent_instances, packMacroTool_fn).call(this),
3364
+ { AgentOutput: __privateMethod(this, _PageAgent_instances, packMacroTool_fn).call(this) },
3113
3365
  __privateGet(this, _abortController).signal
3114
3366
  );
3115
- const toolResult = result.toolResult;
3116
- const input2 = toolResult.input;
3117
- const output2 = toolResult.output;
3367
+ const macroResult = result.toolResult;
3368
+ const input2 = macroResult.input;
3369
+ const output2 = macroResult.output;
3118
3370
  const brain = {
3119
- thinking: input2.thinking,
3120
- evaluation_previous_goal: input2.evaluation_previous_goal,
3121
- memory: input2.memory,
3122
- next_goal: input2.next_goal
3371
+ evaluation_previous_goal: input2.evaluation_previous_goal || "",
3372
+ memory: input2.memory || "",
3373
+ next_goal: input2.next_goal || ""
3123
3374
  };
3124
3375
  const actionName = Object.keys(input2.action)[0];
3125
3376
  const action = {
@@ -3144,8 +3395,8 @@ const _PageAgent = class _PageAgent extends EventTarget {
3144
3395
  };
3145
3396
  }
3146
3397
  if (actionName === "done") {
3147
- const success = action.input.success || false;
3148
- const text = action.input.text || "no text provided";
3398
+ const success = action.input?.success ?? false;
3399
+ const text = action.input?.text || "no text provided";
3149
3400
  console.log(chalk.green.bold("Task completed"), success, text);
3150
3401
  __privateMethod(this, _PageAgent_instances, onDone_fn).call(this, text, success);
3151
3402
  return {
@@ -3190,42 +3441,6 @@ _PageAgent_instances = new WeakSet();
3190
3441
  * - next_goal: string
3191
3442
  * - action: { toolName: toolInput }
3192
3443
  * where action must be selected from tools defined in this.tools
3193
- *
3194
- * @topic 要不要合并成一个 tool?
3195
- * @facts
3196
- * - 我们需要模型每步返回 evaluation/memory/goal 等思考过程
3197
- * - browser use 合并成一个巨大的 tool
3198
- * ```json
3199
- * {
3200
- * "memory": "...",
3201
- * "goal": "...",
3202
- * "actions": [
3203
- * {
3204
- * "name": "...",
3205
- * "args": "..."
3206
- * }
3207
- * // ...
3208
- * ]
3209
- * }
3210
- * ```
3211
- * - qwen 目前必须指定 function name 来确保 tool call
3212
- * @reasoning
3213
- * - 不能为了 qwen 的缺陷而设计系统
3214
- * - 更复杂的 tool 更容易出错
3215
- * - 分散的 tool 更容易利用 ai-sdk 的重试机制,也更容易处理错误
3216
- * - 不能用额外的步骤生成这些数据,不仅性能过差,而且 goal 之类的必须和 call 一起生成
3217
- * @options
3218
- * - Plan @A
3219
- * - 和 browser use 使用完全一致的做法,合并成一个大 tool,要求每次调用
3220
- * - 会把 tool 定义变得非常复杂,增加出错率
3221
- * - Plan @B
3222
- * - 每次调用两个 tool,其中一个用来输出思考
3223
- * - 很难用提示词 enforce 这么复杂的规则
3224
- * - Plan @C
3225
- * - 自动为每个 tool 增加固定的 reasoning/memory/goal 等输入,并自动拦截提取这些数据
3226
- * - 会让 tool 定义变得很长
3227
- * @conclusion
3228
- * - 使用 @A
3229
3444
  */
3230
3445
  packMacroTool_fn = /* @__PURE__ */ __name(function() {
3231
3446
  const tools2 = this.tools;
@@ -3234,70 +3449,75 @@ packMacroTool_fn = /* @__PURE__ */ __name(function() {
3234
3449
  [toolName]: tool2.inputSchema
3235
3450
  });
3236
3451
  });
3237
- const actionSchema = zod.union(actionSchemas);
3452
+ const actionSchema = zod.union(
3453
+ actionSchemas
3454
+ );
3455
+ const macroToolSchema = zod.object({
3456
+ // thinking: zod.string().optional(),
3457
+ evaluation_previous_goal: zod.string().optional(),
3458
+ memory: zod.string().optional(),
3459
+ next_goal: zod.string().optional(),
3460
+ action: actionSchema
3461
+ });
3238
3462
  return {
3239
- [MACRO_TOOL_NAME]: tool({
3240
- // description: 'Output the result of the agent',
3241
- inputSchema: zod.object({
3242
- // thinking: zod.string().optional(),
3243
- evaluation_previous_goal: zod.string().optional(),
3244
- memory: zod.string().optional(),
3245
- next_goal: zod.string().optional(),
3246
- action: actionSchema
3247
- }),
3248
- execute: /* @__PURE__ */ __name(async (input2, options) => {
3249
- if (__privateGet(this, _abortController).signal.aborted) throw new Error("AbortError");
3250
- await waitUntil(() => !this.paused);
3251
- console.log(chalk.blue.bold("MacroTool execute"), input2);
3252
- const action = input2.action;
3253
- const toolName = Object.keys(action)[0];
3254
- const toolInput = action[toolName];
3255
- const brain = trimLines(`✅: ${input2.evaluation_previous_goal}
3463
+ // name: MACRO_TOOL_NAME,
3464
+ // description: 'Execute agent action', // @todo remote
3465
+ inputSchema: macroToolSchema,
3466
+ execute: /* @__PURE__ */ __name(async (input2) => {
3467
+ if (__privateGet(this, _abortController).signal.aborted) throw new Error("AbortError");
3468
+ await waitUntil(() => !this.paused);
3469
+ console.log(chalk.blue.bold("MacroTool execute"), input2);
3470
+ const action = input2.action;
3471
+ const toolName = Object.keys(action)[0];
3472
+ const toolInput = action[toolName];
3473
+ const brain = trimLines(`✅: ${input2.evaluation_previous_goal}
3256
3474
  💾: ${input2.memory}
3257
3475
  🎯: ${input2.next_goal}
3258
3476
  `);
3259
- console.log(brain);
3260
- this.bus.emit("panel:update", {
3261
- type: "thinking",
3262
- displayText: brain
3263
- });
3264
- const tool2 = tools2.get(toolName);
3265
- assert(tool2, `Tool ${toolName} not found. (@note should have been caught before this!!!)`);
3266
- console.log(chalk.blue.bold(`Executing tool: ${toolName}`), toolInput, options);
3477
+ console.log(brain);
3478
+ this.bus.emit("panel:update", {
3479
+ type: "thinking",
3480
+ displayText: brain
3481
+ });
3482
+ const tool2 = tools2.get(toolName);
3483
+ assert(tool2, `Tool ${toolName} not found. (@note should have been caught before this!!!)`);
3484
+ console.log(chalk.blue.bold(`Executing tool: ${toolName}`), toolInput);
3485
+ this.bus.emit("panel:update", {
3486
+ type: "tool_executing",
3487
+ toolName,
3488
+ toolArgs: toolInput,
3489
+ displayText: getToolExecutingText(toolName, toolInput, this.i18n)
3490
+ });
3491
+ const startTime = Date.now();
3492
+ let result = await tool2.execute.bind(this)(toolInput);
3493
+ const duration = Date.now() - startTime;
3494
+ console.log(chalk.green.bold(`Tool (${toolName}) executed for ${duration}ms`), result);
3495
+ if (toolName === "wait") {
3496
+ __privateSet(this, _totalWaitTime, __privateGet(this, _totalWaitTime) + Math.round(toolInput.seconds + duration / 1e3));
3497
+ result += `
3498
+ <sys> You have waited ${__privateGet(this, _totalWaitTime)} seconds accumulatively.`;
3499
+ if (__privateGet(this, _totalWaitTime) >= 3)
3500
+ result += "\nDo NOT wait any longer unless you have a good reason.\n";
3501
+ result += "</sys>";
3502
+ } else {
3503
+ __privateSet(this, _totalWaitTime, 0);
3504
+ }
3505
+ const displayResult = getToolCompletedText(toolName, toolInput, this.i18n);
3506
+ if (displayResult)
3267
3507
  this.bus.emit("panel:update", {
3268
3508
  type: "tool_executing",
3269
3509
  toolName,
3270
3510
  toolArgs: toolInput,
3271
- displayText: getToolExecutingText(toolName, toolInput, this.i18n)
3511
+ toolResult: result,
3512
+ displayText: displayResult,
3513
+ duration
3272
3514
  });
3273
- const startTime = Date.now();
3274
- let result = await tool2.execute.bind(this)(toolInput, options);
3275
- const duration = Date.now() - startTime;
3276
- console.log(chalk.green.bold(`Tool (${toolName}) executed for ${duration}ms`), result);
3277
- if (toolName === "wait") {
3278
- __privateSet(this, _totalWaitTime, __privateGet(this, _totalWaitTime) + Math.round(toolInput.seconds + duration / 1e3));
3279
- result += `
3280
- <sys> You have waited ${__privateGet(this, _totalWaitTime)} seconds accumulatively.`;
3281
- if (__privateGet(this, _totalWaitTime) >= 3)
3282
- result += "\nDo NOT wait any longer unless you have a good reason.\n";
3283
- result += "</sys>";
3284
- } else {
3285
- __privateSet(this, _totalWaitTime, 0);
3286
- }
3287
- const displayResult = getToolCompletedText(toolName, toolInput, this.i18n);
3288
- if (displayResult)
3289
- this.bus.emit("panel:update", {
3290
- type: "tool_executing",
3291
- toolName,
3292
- toolArgs: toolInput,
3293
- toolResult: result,
3294
- displayText: displayResult,
3295
- duration
3296
- });
3297
- await new Promise((resolve) => setTimeout(resolve, 100));
3298
- return result;
3299
- }, "execute")
3300
- })
3515
+ await new Promise((resolve) => setTimeout(resolve, 100));
3516
+ return {
3517
+ input: input2,
3518
+ output: result
3519
+ };
3520
+ }, "execute")
3301
3521
  };
3302
3522
  }, "#packMacroTool");
3303
3523
  /**