reasonix 0.48.1 → 0.49.0

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.
Files changed (123) hide show
  1. package/dashboard/dist/app.js +123 -16
  2. package/dashboard/dist/app.js.map +1 -1
  3. package/dist/cli/{acp-QJGGHQLA.js → acp-WFQIC6SO.js} +18 -18
  4. package/dist/cli/chat-D32JGNVH.js +51 -0
  5. package/dist/cli/{chunk-TIJ4ZHD6.js → chunk-23ZPCIPR.js} +12 -9
  6. package/dist/cli/chunk-23ZPCIPR.js.map +1 -0
  7. package/dist/cli/{chunk-TKVXTQ3T.js → chunk-3ZZXQ3CZ.js} +27 -27
  8. package/dist/cli/chunk-3ZZXQ3CZ.js.map +1 -0
  9. package/dist/cli/{chunk-H2F4LDNH.js → chunk-7AST3QQ3.js} +2 -2
  10. package/dist/cli/{chunk-XMR2VCGT.js → chunk-7JTKBJ2G.js} +3 -3
  11. package/dist/cli/{chunk-X53B3JIX.js → chunk-7X4JJOO7.js} +2 -61
  12. package/dist/cli/{chunk-X53B3JIX.js.map → chunk-7X4JJOO7.js.map} +1 -1
  13. package/dist/cli/{chunk-WKOXKCF3.js → chunk-ASOLXV67.js} +3 -3
  14. package/dist/cli/{chunk-43ROGEX2.js → chunk-AWEULQG6.js} +10 -9
  15. package/dist/cli/{chunk-43ROGEX2.js.map → chunk-AWEULQG6.js.map} +1 -1
  16. package/dist/cli/{chunk-5AW6NIHU.js → chunk-DFX5ZH5L.js} +2 -2
  17. package/dist/cli/{chunk-4E2BHJU4.js → chunk-GNS7BAT2.js} +2 -2
  18. package/dist/cli/{chunk-5U5LMMFF.js → chunk-J2IHQGPQ.js} +12 -6
  19. package/dist/cli/chunk-J2IHQGPQ.js.map +1 -0
  20. package/dist/cli/{chunk-O3AGYTG2.js → chunk-JGTX4RRQ.js} +3 -3
  21. package/dist/cli/{chunk-SLAFMXAZ.js → chunk-JNTMOX7G.js} +2 -2
  22. package/dist/cli/{chunk-RCLS63KE.js → chunk-MGTBP7GG.js} +2 -2
  23. package/dist/cli/{chunk-JFBGSWQB.js → chunk-MQWO32ZD.js} +323 -159
  24. package/dist/cli/chunk-MQWO32ZD.js.map +1 -0
  25. package/dist/cli/{chunk-FD7SNDWW.js → chunk-O5LIHAMP.js} +8 -4
  26. package/dist/cli/chunk-O5LIHAMP.js.map +1 -0
  27. package/dist/cli/{chunk-PJIQIYTV.js → chunk-PB3MAFEI.js} +3 -3
  28. package/dist/cli/{chunk-NQZ5U37J.js → chunk-PEMG6CUB.js} +2 -2
  29. package/dist/cli/{chunk-KH5JIJJD.js → chunk-PXBQ6IZ7.js} +3 -3
  30. package/dist/cli/{chunk-J2TQAWOM.js → chunk-Q46B3Z7H.js} +25 -10
  31. package/dist/cli/{chunk-J2TQAWOM.js.map → chunk-Q46B3Z7H.js.map} +1 -1
  32. package/dist/cli/{chunk-DABAOQSV.js → chunk-QF32ROX2.js} +1260 -1754
  33. package/dist/cli/chunk-QF32ROX2.js.map +1 -0
  34. package/dist/cli/{chunk-IKSYVBBZ.js → chunk-QX5TWXRZ.js} +2 -2
  35. package/dist/cli/{chunk-R7U44O3Y.js → chunk-TAIKVL35.js} +2 -2
  36. package/dist/cli/{chunk-B5CZL2SE.js → chunk-TEDWJKEI.js} +4 -9
  37. package/dist/cli/chunk-TEDWJKEI.js.map +1 -0
  38. package/dist/cli/{chunk-EO6RPTJG.js → chunk-U5XQDCK7.js} +5 -5
  39. package/dist/cli/{chunk-SWUMD2LX.js → chunk-W46ZMNKO.js} +3 -3
  40. package/dist/cli/{chunk-FPME5QOO.js → chunk-WMTMMSXU.js} +166 -5
  41. package/dist/cli/chunk-WMTMMSXU.js.map +1 -0
  42. package/dist/cli/{chunk-PIC5HJRD.js → chunk-YEF7C4XI.js} +154 -86
  43. package/dist/cli/chunk-YEF7C4XI.js.map +1 -0
  44. package/dist/cli/{chunk-3FULTFRB.js → chunk-ZAEJWKXB.js} +2 -2
  45. package/dist/cli/chunk-ZWHSHFDP.js +6173 -0
  46. package/dist/cli/chunk-ZWHSHFDP.js.map +1 -0
  47. package/dist/cli/{code-OKA5YPOH.js → code-R4IHI7SR.js} +30 -30
  48. package/dist/cli/{commands-3U6PUVSS.js → commands-DRHFCYMO.js} +4 -4
  49. package/dist/cli/{commit-HFB7SRBU.js → commit-AG5KB4YP.js} +3 -3
  50. package/dist/cli/{desktop-G7UMW3CJ.js → desktop-JGL6GORA.js} +19 -19
  51. package/dist/cli/{diff-PGXW4YZD.js → diff-4Z7ETWZO.js} +9 -9
  52. package/dist/cli/{doctor-WWJFLVCB.js → doctor-VA3RHQLB.js} +9 -9
  53. package/dist/cli/index.js +37 -36
  54. package/dist/cli/index.js.map +1 -1
  55. package/dist/cli/{mcp-Y3VKIK3T.js → mcp-LZO4HXFA.js} +34 -23
  56. package/dist/cli/mcp-LZO4HXFA.js.map +1 -0
  57. package/dist/cli/{mcp-browse-4IN2QIFR.js → mcp-browse-C3GXVMYZ.js} +3 -3
  58. package/dist/cli/{mcp-inspect-BUXFXDHB.js → mcp-inspect-ZMYUNFDS.js} +2 -2
  59. package/dist/cli/{prompt-US57R6BA.js → prompt-MC3U5KRP.js} +5 -5
  60. package/dist/cli/{prune-sessions-SEWX7GP6.js → prune-sessions-OEPFH4N6.js} +11 -7
  61. package/dist/cli/prune-sessions-OEPFH4N6.js.map +1 -0
  62. package/dist/cli/{replay-EQJMZRB3.js → replay-4TP7ZUMZ.js} +10 -10
  63. package/dist/cli/{run-KVEI66TR.js → run-6MXQYBOE.js} +16 -15
  64. package/dist/cli/run-6MXQYBOE.js.map +1 -0
  65. package/dist/cli/{server-D6C4GHWN.js → server-Z3IMJNNI.js} +63 -12
  66. package/dist/cli/server-Z3IMJNNI.js.map +1 -0
  67. package/dist/cli/{sessions-TGVS2RQZ.js → sessions-NXQ5SAV7.js} +18 -18
  68. package/dist/cli/sessions-NXQ5SAV7.js.map +1 -0
  69. package/dist/cli/{setup-WLKX6GGG.js → setup-LHZELI6I.js} +6 -6
  70. package/dist/cli/{stats-TCD7Q6MB.js → stats-SUIJ3QWY.js} +6 -6
  71. package/dist/cli/{version-BCWWS2OU.js → version-BIFONEUB.js} +13 -13
  72. package/dist/index.d.ts +63 -15
  73. package/dist/index.js +855 -360
  74. package/dist/index.js.map +1 -1
  75. package/package.json +2 -1
  76. package/dist/cli/chat-ZXF227MP.js +0 -51
  77. package/dist/cli/chunk-5U5LMMFF.js.map +0 -1
  78. package/dist/cli/chunk-6FRNXWDZ.js +0 -2265
  79. package/dist/cli/chunk-6FRNXWDZ.js.map +0 -1
  80. package/dist/cli/chunk-B5CZL2SE.js.map +0 -1
  81. package/dist/cli/chunk-DABAOQSV.js.map +0 -1
  82. package/dist/cli/chunk-FD7SNDWW.js.map +0 -1
  83. package/dist/cli/chunk-FPME5QOO.js.map +0 -1
  84. package/dist/cli/chunk-JFBGSWQB.js.map +0 -1
  85. package/dist/cli/chunk-PIC5HJRD.js.map +0 -1
  86. package/dist/cli/chunk-TIJ4ZHD6.js.map +0 -1
  87. package/dist/cli/chunk-TKVXTQ3T.js.map +0 -1
  88. package/dist/cli/mcp-Y3VKIK3T.js.map +0 -1
  89. package/dist/cli/prune-sessions-SEWX7GP6.js.map +0 -1
  90. package/dist/cli/run-KVEI66TR.js.map +0 -1
  91. package/dist/cli/server-D6C4GHWN.js.map +0 -1
  92. package/dist/cli/sessions-TGVS2RQZ.js.map +0 -1
  93. /package/dist/cli/{acp-QJGGHQLA.js.map → acp-WFQIC6SO.js.map} +0 -0
  94. /package/dist/cli/{chat-ZXF227MP.js.map → chat-D32JGNVH.js.map} +0 -0
  95. /package/dist/cli/{chunk-H2F4LDNH.js.map → chunk-7AST3QQ3.js.map} +0 -0
  96. /package/dist/cli/{chunk-XMR2VCGT.js.map → chunk-7JTKBJ2G.js.map} +0 -0
  97. /package/dist/cli/{chunk-WKOXKCF3.js.map → chunk-ASOLXV67.js.map} +0 -0
  98. /package/dist/cli/{chunk-5AW6NIHU.js.map → chunk-DFX5ZH5L.js.map} +0 -0
  99. /package/dist/cli/{chunk-4E2BHJU4.js.map → chunk-GNS7BAT2.js.map} +0 -0
  100. /package/dist/cli/{chunk-O3AGYTG2.js.map → chunk-JGTX4RRQ.js.map} +0 -0
  101. /package/dist/cli/{chunk-SLAFMXAZ.js.map → chunk-JNTMOX7G.js.map} +0 -0
  102. /package/dist/cli/{chunk-RCLS63KE.js.map → chunk-MGTBP7GG.js.map} +0 -0
  103. /package/dist/cli/{chunk-PJIQIYTV.js.map → chunk-PB3MAFEI.js.map} +0 -0
  104. /package/dist/cli/{chunk-NQZ5U37J.js.map → chunk-PEMG6CUB.js.map} +0 -0
  105. /package/dist/cli/{chunk-KH5JIJJD.js.map → chunk-PXBQ6IZ7.js.map} +0 -0
  106. /package/dist/cli/{chunk-IKSYVBBZ.js.map → chunk-QX5TWXRZ.js.map} +0 -0
  107. /package/dist/cli/{chunk-R7U44O3Y.js.map → chunk-TAIKVL35.js.map} +0 -0
  108. /package/dist/cli/{chunk-EO6RPTJG.js.map → chunk-U5XQDCK7.js.map} +0 -0
  109. /package/dist/cli/{chunk-SWUMD2LX.js.map → chunk-W46ZMNKO.js.map} +0 -0
  110. /package/dist/cli/{chunk-3FULTFRB.js.map → chunk-ZAEJWKXB.js.map} +0 -0
  111. /package/dist/cli/{code-OKA5YPOH.js.map → code-R4IHI7SR.js.map} +0 -0
  112. /package/dist/cli/{commands-3U6PUVSS.js.map → commands-DRHFCYMO.js.map} +0 -0
  113. /package/dist/cli/{commit-HFB7SRBU.js.map → commit-AG5KB4YP.js.map} +0 -0
  114. /package/dist/cli/{desktop-G7UMW3CJ.js.map → desktop-JGL6GORA.js.map} +0 -0
  115. /package/dist/cli/{diff-PGXW4YZD.js.map → diff-4Z7ETWZO.js.map} +0 -0
  116. /package/dist/cli/{doctor-WWJFLVCB.js.map → doctor-VA3RHQLB.js.map} +0 -0
  117. /package/dist/cli/{mcp-browse-4IN2QIFR.js.map → mcp-browse-C3GXVMYZ.js.map} +0 -0
  118. /package/dist/cli/{mcp-inspect-BUXFXDHB.js.map → mcp-inspect-ZMYUNFDS.js.map} +0 -0
  119. /package/dist/cli/{prompt-US57R6BA.js.map → prompt-MC3U5KRP.js.map} +0 -0
  120. /package/dist/cli/{replay-EQJMZRB3.js.map → replay-4TP7ZUMZ.js.map} +0 -0
  121. /package/dist/cli/{setup-WLKX6GGG.js.map → setup-LHZELI6I.js.map} +0 -0
  122. /package/dist/cli/{stats-TCD7Q6MB.js.map → stats-SUIJ3QWY.js.map} +0 -0
  123. /package/dist/cli/{version-BCWWS2OU.js.map → version-BIFONEUB.js.map} +0 -0
@@ -19137,6 +19137,14 @@ var en = {
19137
19137
  effortHigh: "high (cheaper / faster)",
19138
19138
  webSearch: "web search",
19139
19139
  webSearchNote: "web_fetch + web_search tools",
19140
+ webSearchEngine: "search engine",
19141
+ webSearchEngineBing: "bing \u2014 default, works from CN without proxy",
19142
+ webSearchEngineSearxng: "searxng \u2014 self-hosted (set endpoint via /se searxng <url>)",
19143
+ webSearchEngineMetaso: "metaso \u2014 100/day free (CN-friendly, free key at metaso.cn)",
19144
+ webSearchEngineTavily: "tavily \u2014 1000/mo free (set TAVILY_API_KEY)",
19145
+ webSearchEnginePerplexity: "perplexity \u2014 AI-native (set PERPLEXITY_API_KEY)",
19146
+ webSearchEngineExa: "exa \u2014 AI-native 1000/mo free (set EXA_API_KEY)",
19147
+ webSearchEngineNote: "applies to the next web_search call",
19140
19148
  sectionCompute: "Compute",
19141
19149
  proNext: "/pro one-shot",
19142
19150
  proArm: "Arm for next turn",
@@ -19183,6 +19191,8 @@ var en = {
19183
19191
  modeView: "session view",
19184
19192
  placeholder: "Type a prompt \u2014 Enter sends, Shift+Enter for a newline \xB7 / @ for pickers",
19185
19193
  placeholderBusy: "wait for the current turn to finish\u2026",
19194
+ placeholderSteerBusy: "type to steer \u2014 commands and pickers are disabled while busy",
19195
+ steerHint: "message steers the current turn (added as instruction)",
19186
19196
  send: "Send",
19187
19197
  new: "New",
19188
19198
  clear: "Clear",
@@ -19662,6 +19672,12 @@ var en = {
19662
19672
  shellBgTitle: "background process",
19663
19673
  shellSubtitle: "model wants to run a shell command",
19664
19674
  shellBgSubtitle: "long-running \u2014 keeps running after approval",
19675
+ pathTitle: "file outside sandbox",
19676
+ pathSubtitle: "{intent} via {tool}",
19677
+ pathRead: "read",
19678
+ pathWrite: "write",
19679
+ pathSandboxLabel: "sandbox",
19680
+ pathAllowPrefixLabel: "allow prefix",
19665
19681
  runOnce: "Run once",
19666
19682
  alwaysAllow: 'Always allow "{prefix}"',
19667
19683
  deny: "Deny",
@@ -19848,6 +19864,14 @@ var zhCN = {
19848
19864
  effortHigh: "high\uFF08\u66F4\u4FBF\u5B9C / \u66F4\u5FEB\uFF09",
19849
19865
  webSearch: "\u7F51\u9875\u641C\u7D22",
19850
19866
  webSearchNote: "web_fetch + web_search \u5DE5\u5177",
19867
+ webSearchEngine: "\u641C\u7D22\u5F15\u64CE",
19868
+ webSearchEngineBing: "bing \u2014 \u9ED8\u8BA4\uFF0C\u56FD\u5185\u88F8 IP \u76F4\u8FDE\uFF0C\u65E0\u9700\u4EE3\u7406",
19869
+ webSearchEngineSearxng: "searxng \u2014 \u81EA\u6258\u7BA1\uFF08\u7AEF\u70B9\u7528 /se searxng <url> \u914D\u7F6E\uFF09",
19870
+ webSearchEngineMetaso: "metaso \u2014 \u6BCF\u65E5 100 \u6B21\u514D\u8D39\uFF08\u56FD\u5185\u53CB\u597D\uFF0Cmetaso.cn \u53EF\u9886\u514D\u8D39 key\uFF09",
19871
+ webSearchEngineTavily: "tavily \u2014 \u6BCF\u6708 1000 \u6B21\u514D\u8D39\uFF08\u8BBE\u7F6E TAVILY_API_KEY\uFF09",
19872
+ webSearchEnginePerplexity: "perplexity \u2014 AI \u76F4\u63A5\u56DE\u7B54\uFF08\u8BBE\u7F6E PERPLEXITY_API_KEY\uFF09",
19873
+ webSearchEngineExa: "exa \u2014 AI \u76F4\u63A5\u56DE\u7B54\uFF0C\u6BCF\u6708 1000 \u6B21\u514D\u8D39\uFF08\u8BBE\u7F6E EXA_API_KEY\uFF09",
19874
+ webSearchEngineNote: "\u4E0B\u4E00\u6B21 web_search \u8C03\u7528\u751F\u6548",
19851
19875
  sectionCompute: "\u8BA1\u7B97",
19852
19876
  proNext: "/pro \u5355\u8F6E",
19853
19877
  proArm: "\u4E3A\u4E0B\u4E00\u8F6E\u88C5\u5907",
@@ -19894,6 +19918,8 @@ var zhCN = {
19894
19918
  modeView: "\u4F1A\u8BDD\u89C6\u56FE",
19895
19919
  placeholder: "\u8F93\u5165\u63D0\u793A\u8BCD \u2014 Enter \u53D1\u9001\uFF0CShift+Enter \u6362\u884C \xB7 / @ \u6253\u5F00\u9009\u62E9\u5668",
19896
19920
  placeholderBusy: "\u8BF7\u7B49\u5F85\u5F53\u524D\u8F6E\u6B21\u5B8C\u6210\u2026",
19921
+ placeholderSteerBusy: "\u8F93\u5165\u6D88\u606F\u4EE5\u5F15\u5BFC\u5F53\u524D\u4EFB\u52A1 \u2014 \u5FD9\u788C\u65F6\u4E0D\u652F\u6301\u547D\u4EE4\u548C\u9009\u62E9\u5668",
19922
+ steerHint: "\u6D88\u606F\u5C06\u4F5C\u4E3A\u9644\u52A0\u6307\u793A\u5F15\u5BFC\u5F53\u524D\u8F6E\u6B21",
19897
19923
  send: "\u53D1\u9001",
19898
19924
  new: "\u65B0\u5EFA",
19899
19925
  clear: "\u6E05\u9664",
@@ -20373,6 +20399,12 @@ var zhCN = {
20373
20399
  shellBgTitle: "\u540E\u53F0\u8FDB\u7A0B",
20374
20400
  shellSubtitle: "\u6A21\u578B\u60F3\u8981\u8FD0\u884C\u4E00\u6761 Shell \u547D\u4EE4",
20375
20401
  shellBgSubtitle: "\u957F\u65F6\u95F4\u8FD0\u884C \u2014 \u6279\u51C6\u540E\u7EE7\u7EED\u8FD0\u884C",
20402
+ pathTitle: "\u6C99\u7BB1\u5916\u6587\u4EF6\u8BBF\u95EE",
20403
+ pathSubtitle: "{intent} \xB7 \u901A\u8FC7 {tool}",
20404
+ pathRead: "\u8BFB\u53D6",
20405
+ pathWrite: "\u5199\u5165",
20406
+ pathSandboxLabel: "\u6C99\u7BB1",
20407
+ pathAllowPrefixLabel: "\u5141\u8BB8\u524D\u7F00",
20376
20408
  runOnce: "\u8FD0\u884C\u4E00\u6B21",
20377
20409
  alwaysAllow: '\u59CB\u7EC8\u5141\u8BB8 "{prefix}"',
20378
20410
  deny: "\u62D2\u7EDD",
@@ -23255,6 +23287,29 @@ function ShellModal({ modal, onResolve }) {
23255
23287
  <//>
23256
23288
  `;
23257
23289
  }
23290
+ function PathModal({ modal, onResolve }) {
23291
+ useLang();
23292
+ const intentLabel = modal.intent === "write" ? t4("modal.pathWrite") : t4("modal.pathRead");
23293
+ return html4`
23294
+ <${ModalCard}
23295
+ accent="#fbbf24"
23296
+ icon="📂"
23297
+ title=${t4("modal.pathTitle")}
23298
+ subtitle=${t4("modal.pathSubtitle", { intent: intentLabel, tool: modal.toolName })}
23299
+ >
23300
+ <div class="modal-cmd"><code>${modal.path}</code></div>
23301
+ <div class="modal-meta">
23302
+ <div><span class="modal-meta-label">${t4("modal.pathSandboxLabel")}</span> <code>${modal.sandboxRoot}</code></div>
23303
+ ${modal.allowPrefix && modal.allowPrefix !== modal.path ? html4`<div><span class="modal-meta-label">${t4("modal.pathAllowPrefixLabel")}</span> <code>${modal.allowPrefix}</code></div>` : null}
23304
+ </div>
23305
+ <div class="modal-actions">
23306
+ <button class="primary" onClick=${() => onResolve("path", "run_once")}>${t4("modal.runOnce")}</button>
23307
+ <button onClick=${() => onResolve("path", "always_allow")}>${t4("modal.alwaysAllow", { prefix: modal.allowPrefix ?? modal.path })}</button>
23308
+ <button class="danger" onClick=${() => onResolve("path", "deny")}>${t4("modal.deny")}</button>
23309
+ </div>
23310
+ <//>
23311
+ `;
23312
+ }
23258
23313
  function ChoiceModal({ modal, onResolve }) {
23259
23314
  useLang();
23260
23315
  const [custom, setCustom] = d2("");
@@ -25318,6 +25373,10 @@ function ChatPane(props) {
25318
25373
  }, []);
25319
25374
  const updatePopover = q2(
25320
25375
  async (text) => {
25376
+ if (busy) {
25377
+ setPopoverKind(null);
25378
+ return;
25379
+ }
25321
25380
  const slashMatch = /^\/([A-Za-z0-9_-]*)$/.exec(text);
25322
25381
  if (slashMatch) {
25323
25382
  const prefix = slashMatch[1].toLowerCase();
@@ -25331,14 +25390,41 @@ function ChatPane(props) {
25331
25390
  setPopoverSel(0);
25332
25391
  return;
25333
25392
  }
25393
+ const mentionMatch = /(?:^|\s)@([^\s@]*)$/.exec(text);
25394
+ if (mentionMatch && MODE === "attached") {
25395
+ const prefix = mentionMatch[1] ?? "";
25396
+ try {
25397
+ const r3 = await api("/files", {
25398
+ method: "POST",
25399
+ body: { prefix }
25400
+ });
25401
+ const items = r3.files.slice(0, 12).map((f3) => ({
25402
+ label: f3,
25403
+ insert: `@${f3} `
25404
+ }));
25405
+ setPopoverKind("mention");
25406
+ setPopoverItems(items);
25407
+ setPopoverSel(0);
25408
+ } catch {
25409
+ setPopoverKind(null);
25410
+ }
25411
+ return;
25412
+ }
25334
25413
  setPopoverKind(null);
25335
25414
  },
25336
- [slashCommands]
25415
+ [busy, slashCommands]
25337
25416
  );
25338
25417
  const applyPopover = q2(() => {
25339
25418
  const item = popoverItems[popoverSel];
25340
25419
  if (!item) return false;
25341
- setInput(item.insert);
25420
+ if (popoverKind === "slash") {
25421
+ setInput(item.insert);
25422
+ } else if (popoverKind === "mention") {
25423
+ const m3 = /(?:^|\s)@([^\s@]*)$/.exec(input);
25424
+ if (!m3) return false;
25425
+ const start = input.length - m3[0].length + (m3[0].startsWith(" ") ? 1 : 0);
25426
+ setInput(`${input.slice(0, start)}${item.insert}`);
25427
+ }
25342
25428
  setPopoverKind(null);
25343
25429
  return true;
25344
25430
  }, [popoverItems, popoverSel, popoverKind, input]);
@@ -25353,7 +25439,6 @@ function ChatPane(props) {
25353
25439
  );
25354
25440
  const send = q2(async () => {
25355
25441
  const text = input.trim();
25356
- if (busy) return;
25357
25442
  if (!text && props.comments.length === 0) return;
25358
25443
  setError(null);
25359
25444
  let prompt = text;
@@ -25377,7 +25462,7 @@ ${commentRefs}` : commentRefs;
25377
25462
  } catch (err) {
25378
25463
  setError(err.message);
25379
25464
  }
25380
- }, [input, busy, props.comments]);
25465
+ }, [input, props.comments]);
25381
25466
  const abort = q2(async () => {
25382
25467
  try {
25383
25468
  await api("/abort", { method: "POST" });
@@ -25521,7 +25606,7 @@ ${commentRefs}` : commentRefs;
25521
25606
  <div style=${{ flex: 1, position: "relative" }}>
25522
25607
  ${popoverKind && popoverItems.length > 0 ? html6`
25523
25608
  <div class="popover" style="position:absolute;bottom:calc(100% + 6px);left:0;width:380px;max-height:280px;overflow-y:auto;z-index:10">
25524
- <div class="popover-h">${t4("chat.slashCommands")}</div>
25609
+ <div class="popover-h">${popoverKind === "slash" ? t4("chat.slashCommands") : t4("chat.projectFiles")}</div>
25525
25610
  ${popoverItems.map(
25526
25611
  (it, i3) => html6`
25527
25612
  <div
@@ -25532,7 +25617,7 @@ ${commentRefs}` : commentRefs;
25532
25617
  applyPopover();
25533
25618
  }}
25534
25619
  >
25535
- <span class="g">/</span>
25620
+ <span class="g">${popoverKind === "slash" ? "/" : "@"}</span>
25536
25621
  <span class="name">${it.label}</span>
25537
25622
  ${it.meta ? html6`<span class="meta">${it.meta}</span>` : null}
25538
25623
  </div>
@@ -25543,19 +25628,18 @@ ${commentRefs}` : commentRefs;
25543
25628
  <textarea
25544
25629
  class="input"
25545
25630
  style=${{ width: "100%", resize: "none", minHeight: "36px", fontFamily: "inherit", fontSize: "13px", padding: "8px 10px", lineHeight: "1.4", background: "var(--bg-input)", border: "1px solid var(--bd)", borderRadius: "4px", color: "var(--fg-0)" }}
25546
- placeholder=${busy ? t4("chat.placeholderBusy") : props.comments.length > 0 ? "\u603B\u7ED3\u8BC4\u8BBA..." : t4("changes.chatPlaceholder")}
25631
+ placeholder=${busy ? t4("chat.placeholderSteerBusy") : props.comments.length > 0 ? "\u603B\u7ED3\u8BC4\u8BBA..." : t4("changes.chatPlaceholder")}
25547
25632
  value=${input}
25548
25633
  onInput=${onInput}
25549
25634
  onKeyDown=${onKeyDown}
25550
25635
  onCompositionStart=${onCompositionStart}
25551
25636
  onCompositionEnd=${onCompositionEnd}
25552
25637
  onBlur=${() => setTimeout(() => setPopoverKind(null), 150)}
25553
- disabled=${busy}
25554
25638
  rows="2"
25555
25639
  />
25556
25640
  </div>
25557
25641
  <div style=${{ display: "flex", flexDirection: "column", gap: "6px", flexShrink: 0 }}>
25558
- <button class="primary" onClick=${send} disabled=${busy || !input.trim() && props.comments.length === 0} style=${{ padding: "8px 12px", borderRadius: "4px" }}>${t4("changes.chatSend")}</button>
25642
+ <button class="primary" onClick=${send} disabled=${!input.trim() && props.comments.length === 0} style=${{ padding: "8px 12px", borderRadius: "4px" }}>${t4("changes.chatSend")}</button>
25559
25643
  <div style=${{ display: "flex", gap: "6px" }}>
25560
25644
  <button onClick=${newConversation} title=${t4("changes.newTitle")}>${t4("changes.newConversation")}</button>
25561
25645
  <button onClick=${clearScrollback} title=${t4("changes.clearTitle")}>${t4("changes.clearConversation")}</button>
@@ -26090,7 +26174,7 @@ function ChatPanel() {
26090
26174
  </div>` : null}
26091
26175
  ${error ? html4`<div class="notice err">${error}</div>` : null}
26092
26176
 
26093
- ${modal ? modal.kind === "shell" ? html4`<${ShellModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "choice" ? html4`<${ChoiceModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "plan" ? html4`<${PlanModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "edit-review" ? html4`<${EditReviewModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "workspace" ? html4`<${WorkspaceModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "checkpoint" ? html4`<${CheckpointModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "revision" ? html4`<${RevisionModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "picker" ? html4`<${PickerModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "viewer" ? html4`<${ViewerModal} modal=${modal} onResolve=${resolveModal} />` : null : null}
26177
+ ${modal ? modal.kind === "shell" ? html4`<${ShellModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "path" ? html4`<${PathModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "choice" ? html4`<${ChoiceModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "plan" ? html4`<${PlanModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "edit-review" ? html4`<${EditReviewModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "workspace" ? html4`<${WorkspaceModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "checkpoint" ? html4`<${CheckpointModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "revision" ? html4`<${RevisionModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "picker" ? html4`<${PickerModal} modal=${modal} onResolve=${resolveModal} />` : modal.kind === "viewer" ? html4`<${ViewerModal} modal=${modal} onResolve=${resolveModal} />` : null : null}
26094
26178
 
26095
26179
  <div class="chat-body">
26096
26180
  <div class="chat-main">
@@ -26135,6 +26219,10 @@ var ChatInput = N2(function ChatInput2({
26135
26219
  const composing = A2(false);
26136
26220
  const updatePopover = q2(
26137
26221
  async (text) => {
26222
+ if (busy) {
26223
+ setPopoverKind(null);
26224
+ return;
26225
+ }
26138
26226
  const slashMatch = /^\/([A-Za-z0-9_-]*)$/.exec(text);
26139
26227
  if (slashMatch) {
26140
26228
  const prefix = slashMatch[1].toLowerCase();
@@ -26170,7 +26258,7 @@ var ChatInput = N2(function ChatInput2({
26170
26258
  }
26171
26259
  setPopoverKind(null);
26172
26260
  },
26173
- [slashCommands]
26261
+ [busy, slashCommands]
26174
26262
  );
26175
26263
  const applyPopover = q2(() => {
26176
26264
  const item = popoverItems[popoverSel];
@@ -26188,10 +26276,10 @@ var ChatInput = N2(function ChatInput2({
26188
26276
  }, [popoverItems, popoverSel, popoverKind, input]);
26189
26277
  const send = q2(async () => {
26190
26278
  const text = input.trim();
26191
- if (!text || busy) return;
26279
+ if (!text) return;
26192
26280
  const res = await onSubmit(text);
26193
26281
  if (res.accepted) setInput("");
26194
- }, [input, busy, onSubmit]);
26282
+ }, [input, onSubmit]);
26195
26283
  const onInput = q2(
26196
26284
  (e3) => {
26197
26285
  const v3 = e3.target.value;
@@ -26269,21 +26357,20 @@ var ChatInput = N2(function ChatInput2({
26269
26357
  </div>
26270
26358
  ` : null}
26271
26359
  <textarea
26272
- placeholder=${busy ? t4("chat.placeholderBusy") : t4("chat.placeholder")}
26360
+ placeholder=${busy ? t4("chat.placeholderSteerBusy") : t4("chat.placeholder")}
26273
26361
  value=${input}
26274
26362
  onInput=${onInput}
26275
26363
  onKeyDown=${onKeyDown}
26276
26364
  onCompositionStart=${onCompositionStart}
26277
26365
  onCompositionEnd=${onCompositionEnd}
26278
26366
  onBlur=${() => setTimeout(() => setPopoverKind(null), 150)}
26279
- disabled=${busy}
26280
26367
  rows="2"
26281
26368
  ></textarea>
26282
26369
  <div style="display: flex; flex-direction: column; gap: 6px; align-self: stretch; justify-content: flex-end;">
26283
26370
  <button
26284
26371
  class="primary"
26285
26372
  onClick=${send}
26286
- disabled=${busy || !input.trim()}
26373
+ disabled=${!input.trim()}
26287
26374
  >${t4("chat.send")}</button>
26288
26375
  <div style="display: flex; gap: 6px;">
26289
26376
  <button onClick=${onNew} title=${t4("chat.newTitle")}>${t4("chat.new")}</button>
@@ -29546,6 +29633,26 @@ function SettingsPanel() {
29546
29633
  >${v3.search ? t4("common.on") : t4("common.off")}</button>
29547
29634
  `,
29548
29635
  t4("settings.webSearchNote")
29636
+ )}
29637
+ ${fieldRow(
29638
+ t4("settings.webSearchEngine"),
29639
+ html4`
29640
+ <select
29641
+ value=${["bing", "searxng", "metaso", "tavily", "perplexity", "exa"].includes(
29642
+ v3.webSearchEngine ?? ""
29643
+ ) ? v3.webSearchEngine : "bing"}
29644
+ onChange=${(e3) => save({ webSearchEngine: e3.target.value })}
29645
+ disabled=${saving || !v3.search}
29646
+ >
29647
+ <option value="bing">${t4("settings.webSearchEngineBing")}</option>
29648
+ <option value="searxng">${t4("settings.webSearchEngineSearxng")}</option>
29649
+ <option value="metaso">${t4("settings.webSearchEngineMetaso")}</option>
29650
+ <option value="tavily">${t4("settings.webSearchEngineTavily")}</option>
29651
+ <option value="perplexity">${t4("settings.webSearchEnginePerplexity")}</option>
29652
+ <option value="exa">${t4("settings.webSearchEngineExa")}</option>
29653
+ </select>
29654
+ `,
29655
+ t4("settings.webSearchEngineNote")
29549
29656
  )}
29550
29657
  </div>
29551
29658