zidane 5.6.14 → 5.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +3 -1
  2. package/dist/{agent-ClkpElCZ.d.ts → agent-BNS2nx_T.d.ts} +535 -15
  3. package/dist/agent-BNS2nx_T.d.ts.map +1 -0
  4. package/dist/chat/pure.d.ts +4 -0
  5. package/dist/chat/pure.js +3 -0
  6. package/dist/chat.d.ts +31 -661
  7. package/dist/chat.d.ts.map +1 -1
  8. package/dist/chat.js +5 -3
  9. package/dist/chat.js.map +1 -1
  10. package/dist/contexts/docker.d.ts +1 -1
  11. package/dist/contexts/docker.d.ts.map +1 -1
  12. package/dist/contexts/docker.js.map +1 -1
  13. package/dist/{contexts-BOtMvzli.js → contexts-BD2U_xpi.js} +2 -2
  14. package/dist/{contexts-BOtMvzli.js.map → contexts-BD2U_xpi.js.map} +1 -1
  15. package/dist/contexts.d.ts +3 -3
  16. package/dist/contexts.js +1 -1
  17. package/dist/edit-utils-DnfNoj16.js +574 -0
  18. package/dist/edit-utils-DnfNoj16.js.map +1 -0
  19. package/dist/{errors-DdZXnyXE.js → errors-CoQnKRf1.js} +32 -2
  20. package/dist/{errors-DdZXnyXE.js.map → errors-CoQnKRf1.js.map} +1 -1
  21. package/dist/fetch-url-CPxfiXDa.js +518 -0
  22. package/dist/fetch-url-CPxfiXDa.js.map +1 -0
  23. package/dist/image-sniff-B7uFSNO1.js +90 -0
  24. package/dist/image-sniff-B7uFSNO1.js.map +1 -0
  25. package/dist/{index-CbS75MD3.d.ts → index-CZOwAJIX.d.ts} +2 -2
  26. package/dist/index-CZOwAJIX.d.ts.map +1 -0
  27. package/dist/{index-CTDMMdIy.d.ts → index-Ck_AWt8P.d.ts} +3 -4
  28. package/dist/index-Ck_AWt8P.d.ts.map +1 -0
  29. package/dist/{index-v3Tzobqr.d.ts → index-KiS7w0dC.d.ts} +3 -3
  30. package/dist/index-KiS7w0dC.d.ts.map +1 -0
  31. package/dist/index.d.ts +6 -6
  32. package/dist/index.js +13 -12
  33. package/dist/index.js.map +1 -1
  34. package/dist/{interpolate-DM1UcKeQ.js → interpolate-TySiqKzc.js} +23 -23
  35. package/dist/{interpolate-DM1UcKeQ.js.map → interpolate-TySiqKzc.js.map} +1 -1
  36. package/dist/{login-7tHcckmX.js → login-BDeqENSe.js} +7 -58
  37. package/dist/login-BDeqENSe.js.map +1 -0
  38. package/dist/{mcp-DGeB7-3D.js → mcp-Kqzz-Rs_.js} +8 -6
  39. package/dist/mcp-Kqzz-Rs_.js.map +1 -0
  40. package/dist/mcp.d.ts +2 -2
  41. package/dist/mcp.js +1 -1
  42. package/dist/{messages-Dym8S_YH.js → messages-CvRQTdbR.js} +118 -39
  43. package/dist/messages-CvRQTdbR.js.map +1 -0
  44. package/dist/{presets-w9Px_aAm.js → presets-JuOnSI-i.js} +2 -2
  45. package/dist/{presets-w9Px_aAm.js.map → presets-JuOnSI-i.js.map} +1 -1
  46. package/dist/presets.d.ts +3 -3
  47. package/dist/presets.js +1 -1
  48. package/dist/{providers-beXyD9W9.js → providers-h4HJPbbv.js} +485 -31
  49. package/dist/providers-h4HJPbbv.js.map +1 -0
  50. package/dist/providers.d.ts +2 -2
  51. package/dist/providers.js +3 -3
  52. package/dist/restate.d.ts +1 -1
  53. package/dist/restate.d.ts.map +1 -1
  54. package/dist/restate.js.map +1 -1
  55. package/dist/session/sqlite.d.ts +1 -1
  56. package/dist/session/sqlite.d.ts.map +1 -1
  57. package/dist/session/sqlite.js +1 -1
  58. package/dist/session/sqlite.js.map +1 -1
  59. package/dist/{session-BRIsmBSY.js → session-BzLou2_-.js} +2 -2
  60. package/dist/{session-BRIsmBSY.js.map → session-BzLou2_-.js.map} +1 -1
  61. package/dist/session.d.ts +2 -2
  62. package/dist/session.js +2 -2
  63. package/dist/skills.d.ts +3 -3
  64. package/dist/skills.js +1 -1
  65. package/dist/skills.js.map +1 -1
  66. package/dist/{stats-Lc3zL3RM.js → stats-DAKBEKjc.js} +12 -2
  67. package/dist/stats-DAKBEKjc.js.map +1 -0
  68. package/dist/{stdio-loader-EVAF5KlU.js → stdio-loader-Ce68wUmM.js} +4 -4
  69. package/dist/stdio-loader-Ce68wUmM.js.map +1 -0
  70. package/dist/tool-formatters-CU-j3a3e.d.ts +1471 -0
  71. package/dist/tool-formatters-CU-j3a3e.d.ts.map +1 -0
  72. package/dist/tools/fetch-url.d.ts +70 -0
  73. package/dist/tools/fetch-url.d.ts.map +1 -0
  74. package/dist/tools/fetch-url.js +2 -0
  75. package/dist/tools/web-search.d.ts +7 -0
  76. package/dist/tools/web-search.d.ts.map +1 -0
  77. package/dist/tools/web-search.js +190 -0
  78. package/dist/tools/web-search.js.map +1 -0
  79. package/dist/{tools-DhrLrOEr.js → tools-BGtJK0vo.js} +1368 -421
  80. package/dist/tools-BGtJK0vo.js.map +1 -0
  81. package/dist/tools.d.ts +3 -3
  82. package/dist/tools.js +1 -1
  83. package/dist/{turn-operations-UAkOjO-u.js → transcript-anchors-BTSZAPVc.js} +147 -2713
  84. package/dist/transcript-anchors-BTSZAPVc.js.map +1 -0
  85. package/dist/{transcript-anchors-D0TR6djV.d.ts → transcript-anchors-DX90kXc4.d.ts} +13 -1299
  86. package/dist/transcript-anchors-DX90kXc4.d.ts.map +1 -0
  87. package/dist/tui.d.ts +58 -28
  88. package/dist/tui.d.ts.map +1 -1
  89. package/dist/tui.js +1349 -422
  90. package/dist/tui.js.map +1 -1
  91. package/dist/turn-operations-CCHfR9eC.js +1938 -0
  92. package/dist/turn-operations-CCHfR9eC.js.map +1 -0
  93. package/dist/turn-operations-DDIl4YVk.d.ts +658 -0
  94. package/dist/turn-operations-DDIl4YVk.d.ts.map +1 -0
  95. package/dist/{types-oKPBdCmL.js → types-BPw_i5vb.js} +1 -1
  96. package/dist/types-BPw_i5vb.js.map +1 -0
  97. package/dist/{types-KukEp-mi.d.ts → types-CEAMIUXw.d.ts} +1 -1
  98. package/dist/types-CEAMIUXw.d.ts.map +1 -0
  99. package/dist/types.d.ts +4 -4
  100. package/dist/types.js +3 -3
  101. package/docs/CHAT.md +53 -6
  102. package/docs/SKILL.md +3 -0
  103. package/docs/TUI.md +7 -0
  104. package/package.json +18 -2
  105. package/dist/agent-ClkpElCZ.d.ts.map +0 -1
  106. package/dist/index-CTDMMdIy.d.ts.map +0 -1
  107. package/dist/index-CbS75MD3.d.ts.map +0 -1
  108. package/dist/index-v3Tzobqr.d.ts.map +0 -1
  109. package/dist/login-7tHcckmX.js.map +0 -1
  110. package/dist/mcp-DGeB7-3D.js.map +0 -1
  111. package/dist/messages-Dym8S_YH.js.map +0 -1
  112. package/dist/providers-beXyD9W9.js.map +0 -1
  113. package/dist/stats-Lc3zL3RM.js.map +0 -1
  114. package/dist/stdio-loader-EVAF5KlU.js.map +0 -1
  115. package/dist/tools-DhrLrOEr.js.map +0 -1
  116. package/dist/transcript-anchors-D0TR6djV.d.ts.map +0 -1
  117. package/dist/turn-operations-UAkOjO-u.js.map +0 -1
  118. package/dist/types-KukEp-mi.d.ts.map +0 -1
  119. package/dist/types-oKPBdCmL.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-formatters-CU-j3a3e.d.ts","names":[],"sources":["../src/chat/providers.ts","../src/chat/auth.ts","../src/chat/completion-core.ts","../src/chat/types.ts","../src/chat/turn-selection.ts","../src/chat/safe-mode-context.tsx","../src/chat/prompt-segments.ts","../src/chat/tool-formatters.ts"],"mappings":";;;;;;;;;;;;;;;;;UA8CiB,SAAA;EACf,EAAA;EACA,IAAA;EACA,aAAA;EACA,SAAA;EACA,SAAA;EACA,KAAA;EACA,IAAA;IAAS,KAAA;IAAe,MAAA;IAAgB,SAAA;IAAoB,UAAA;EAAA;EAC5D,QAAA;EA4BkF;AAAA;AAgBpF;;;;;EApCE,OAAA,YAAmB,WAAW;AAAA;;;;;AAgDtB;UAxCO,WAAA;EA2CkB;EAzCjC,EAAA;EAwDe;EAtDf,KAAA;EAqGkB;EAnGlB,WAAA;EAwHuB;;;;;EAlHvB,cAAA;IAAmB,KAAA;IAAgB,MAAA;IAAiB,SAAA;IAAoB,UAAA;EAAA;AAAA;;;;;;;;;;;;;;UAgBzD,WAAA;EAwHI;EAtHnB,GAAA;EA0Hc;EAxHd,KAAA;;EAEA,MAAA;EAsHgD;EApHhD,WAAA;EAyHoB;EAvHpB,IAAA;EAuH2B;EArH3B,QAAA;AAAA;AAAA,UAGe,kBAAA;;;AAqIhB;AAED;EAlIE,GAAA;;EAEA,KAAA;EA0ID;AAED;;;;AAOC;AAED;EA7IE,OAAA,QAAe,QAAA;;;AAoJhB;AAoCD;;;;AAmDC;EAlOC,YAAA;EAoRD;;;;;EA9QC,MAAA;EAwQsC;;;;;AAAkC;EAjQxE,iBAAA;EAmRiC;EAjRjC,iBAAA;EAiRqF;;;;EA5QrF,aAAA,GAAgB,sBAAA;EA4QqE;AAsCvF;;;;;EA3SE,SAAA;EA2S2D;;;AAA2B;EAtStF,YAAA;EA8X8B;;;;;EAxX9B,MAAA,YAAkB,SAAA;EAwX4D;AAAA;AAmBhF;;;;AAAkC;AAalC;;;;AAA+D;EA3Y7D,YAAA,YAAwB,WAAA;EAwZY;;;;;;;EAhZpC,WAAA,YAAuB,SAAA;EAyZT;;;;;;;EAjZd,UAAA,IAAc,OAAA,sBAA6B,WAAA;EAiZyD;AAAA;AActG;;;;AAAyD;AAoBzD;;;;;;EAraE,mBAAA;AAAA;;iBAIc,SAAA,CAAU,IAAwB,EAAlB,kBAAkB;;iBAKlC,MAAA,CAAO,IAAwB,EAAlB,kBAAkB;AAAA,cAQlC,mBAAA,EAAqB,kBAWjC;AAAA,cAEY,gBAAA,EAAkB,kBAU9B;AAAA,cAEY,oBAAA,EAAsB,kBAOlC;AAAA,cAEY,kBAAA,EAAoB,kBAOhC;;AA+WQ;;;;ACznBT;;;;AAAuB;AAEvB;;;;AAGQ;AAGR;;;;cDsSa,eAAA,EAAiB,kBAmD7B;;;;;;ACpVoB;AAgBrB;;;;;;;;;;cDgXa,iBAAA,EAAmB,QAAA,CAAS,MAAA,SAAe,kBAAA;;;;;;;iBAkBxC,mBAAA,CAAoB,UAAA,EAAY,kBAAA,YAA8B,SAAS;;AC9XxE;;;;ACff;iBFmbgB,YAAA,CAAa,UAAA,EAAY,kBAAA,EAAoB,OAAA,WAAkB,SAAS;;;;;;;;;;iBAwFxE,gBAAA,CAAiB,UAAA,EAAY,kBAAkB,EAAE,OAAA;;;;;;;;;;;cAmBpD,qBAAA;;;;;;;;;;;AEvdmB;iBFoehB,sBAAA,CAAuB,SAAwB;;;;AEzdvD;AAQR;;;iBF8dgB,sBAAA,CAAuB,UAAA,EAAY,kBAAkB,EAAE,OAAA;;;;;;iBASvD,eAAA,CAAgB,UAAA,EAAY,kBAAA,EAAoB,OAAA,oBAA2B,WAAW;;;;AEle1E;AAoB5B;;;;;;iBF4dgB,mBAAA,CAAoB,GAAA,YAAe,MAAM;;;;;;;;;;iBAoBzC,mBAAA,CACd,UAAA,EAAY,kBAAA,EACZ,OAAA,UACA,UAAA,EAAY,MAAA,SAAe,MAAA,iCAC1B,MAAA;;;;;;;AArlBH;KCpCY,WAAA;AAAA,UAEK,UAAA;EACf,MAAA;EDkCA;EChCA,MAAM;AAAA;AAAA,UAGS,YAAA;EACf,GAAA,EAAK,WAAA;EACL,KAAA;EDiCA;EC/BA,SAAA;EACA,OAAA,EAAS,UAAU;AAAA;;;;;;ADuCW;AAQhC;;;;;;;iBC/BgB,UAAA,CACd,OAAA,UACA,QAAA,EAAU,QAAA,CAAS,MAAA,SAAe,kBAAA,IAClC,GAAA,GAAK,MAAA,+BACJ,YAAA;;;;;;;;ADGH;;;;;;;;;;;;;;;;;;UElBiB,cAAA;EFkCe;EEhC9B,EAAA;EFwC0B;EEtC1B,KAAA;EFsC0B;EEpC1B,WAAA;EFwCA;;;;;EElCA,UAAA;EF0CwE;EExCxE,IAAA,EAAM,KAAK;AAAA;AFwDb;;;;;;;;;AAAA,UE5CiB,mBAAA;EACf,UAAA;EACA,KAAA;EACA,GAAA;EACA,MAAA;EACA,IAAA,EAAM,KAAK;AAAA;;;;;UAOI,kBAAA;EF0IuC;EExItD,EAAA;EFkDA;;;;;;EE3CA,OAAA;EF6EA;EE3EA,KAAA;EFgFgB;;;;;;;;EEvEhB,OAAA,GACE,KAAA,UACA,GAAA,EAAK,iBAAA,EACL,MAAA,EAAQ,WAAA,KACL,cAAA,CAAe,KAAA,MAAW,OAAA,CAAQ,cAAA,CAAe,KAAA;EFkHtD;;;;;EE5GA,eAAA,GACE,IAAA,UACA,GAAA,EAAK,iBAAA,KACF,mBAAA,CAAoB,KAAA;AAAA;;;;AF2HuB;UEpHjC,iBAAA;EFyHK;EEvHpB,IAAA;EFuH2B;EErH3B,MAAM;AAAA;;;;AFwIP;AAED;UElIiB,aAAA;EACf,QAAA,EAAU,kBAAkB,CAAC,KAAA;EF2I9B;EEzIC,KAAA;EF2IW;EEzIX,IAAA;IAAQ,KAAA;IAAe,GAAA;EAAA;AAAA;;;;AFyJxB;AAoCD;;;;AAmDC;AA4CD;;;;iBExQgB,iBAAA,OAAA,CACd,IAAA,UACA,MAAA,UACA,SAAA,WAAoB,kBAAA,CAAmB,KAAA,KACvC,OAAA;EAAW,cAAA;AAAA,IACV,aAAA,CAAc,KAAA;;;;;iBAqCD,WAAA,CACd,IAAA,UACA,IAAA;EAAQ,KAAA;EAAe,GAAA;AAAA,GACvB,UAAA;EACG,IAAA;EAAc,MAAA;AAAA;;;;AF4OoE;AAsCvF;;iBEvQgB,eAAA,OAAA,CACd,IAAA,WAAe,mBAAA,CAAoB,KAAA,MAClC,mBAAA,CAAoB,KAAA;;;;;;iBAkBP,iBAAA,OAAA,CACd,IAAA,UACA,SAAA,WAAoB,kBAAA,CAAmB,KAAA,KACvC,MAAA,YACC,mBAAA,CAAoB,KAAA;;;KC7NX,MAAA;;KAGA,KAAA;AAAA,UAEK,WAAA;EACf,IAAA;;;;;;;;;;;EH4CwB;;;;EAAA;EASL;;AAAW;AAQhC;;;;;;;;EARqB;EAoBgB;;;;AAA+C;AAgBpF;;;;;;;;;;EAhBqC;EGrBnC,IAAA;EHoDe;;;;;;EG7Cf,IAAA;IACE,MAAA,UHuIyC;IGrIzC,MAAA;IACA,QAAA,UH8CF;IG5CE,UAAA,UHsDF;IGpDE,OAAA,UH6DF;IG3DE,UAAA;EAAA;EH0EF;;;;;EGnEA,OAAA;IH0FkB,iFGxFhB,aAAA,UHqGsB;IGnGtB,KAAA,UH2GqB;IGzGrB,WAAA,UHiHY;IG/GZ,WAAA;IACA,YAAA;IACA,eAAA;IACA,mBAAA;EAAA;EH8HqB;;;AAAyB;AAKlD;;;EG1HE,SAAA;EH0H6C;EGxH7C,OAAA;EH2ID;EGzIC,KAAA;EHyID;AAAA;AAED;;;;EGpIE,IAAA;EHgJW;;;;AAOZ;AAED;;;;AAOC;AAoCD;;;;EGrLE,MAAA;EHoRW;;;;;;EG7QX,KAAA,GAAQ,MAAA;EH6Q8B;;;;;AAAkC;AAkB1E;EGvRE,IAAA,GAAO,WAAW;;;;;;;AHuRmE;AAsCvF;;EGnTE,IAAA;IAAkB,KAAA;IAAe,GAAA;IAAa,UAAA;EAAA;EHmT+B;;AAAS;AAwFxF;;;EGpYE,WAAA;IAAyB,IAAA;IAAc,SAAA;IAAmB,IAAA;EAAA;EHoYoB;AAmBhF;;;;AAAkC;AAalC;;;;AAA+D;EGxZ7D,MAAA;AAAA;;;;;;;AHqaoF;AAStF;;;;;;;;;AAAsG;AActG;UGvaiB,WAAA;;EAEf,IAAA;EHqauD;EGnavD,IAAA;EHubiC;EGrbjC,KAAA,WAAgB,QAAA;EHsbJ;;;;;;;;;;;;EGzaZ,QAAA,YAAoB,WAAW;EH4axB;AAAA;;;;ACznBT;;;;AAAuB;AAEvB;;;;AAGQ;EEwNN,YAAA;AAAA;AAAA,UAGe,QAAA;EACf,SAAA;EACA,SAAA;EFzNK;EE2NL,UAAA;AAAA;;;;AFvNmB;AAgBrB;;;;;;;;KEsNY,eAAA;AAAA,UAEK,WAAA;EACf,IAAA,EAAM,eAAe;EFvNX;EEyNV,MAAA;AAAA;AAAA,UAGe,MAAA;EACf,QAAA,EAAU,YAAA;EACV,KAAA;EF5NC;;AAAY;;;;EEmOb,MAAA,GAAS,aAAA;EDlPoB;;;;;;;EC0P7B,YAAA,GAAe,MAAA;AAAA;AAAA,UAGA,WAAA;EACf,EAAA;EACA,KAAA;EDrOe;ECuOf,SAAA;EDvOkC;ECyOlC,gBAAA;EDzOmC;EC2OnC,QAAA;EDzOA;;;;;;ECgPA,WAAA;EACA,SAAA;AAAA;;;;;;;;;;;;;;;KAiBU,eAAA;;;;;;;;;;;;;;;KAgBA,eAAA;;;;;;ADvOoB;AAOhC;;;;AAIQ;AAQR;;;;;;;;;;;;;AAK4B;AAoB5B;KCuNY,MAAA;;UAGK,QAAA;EACf,YAAA;EDtNe;;;;;EC4Nf,eAAA,EAAiB,eAAA;EACjB,eAAA;ED/NoB;;;;;ECqOpB,QAAA;EDnOe;;AAAK;AAqCtB;;;;;;;ECyME,kBAAA;EDtMA;;;;AACuB;EC2MvB,KAAA;EDhM6B;;;;;;;ECwM7B,eAAA;EDxM8B;;;;;;;AAEJ;AAkB5B;;;ECgME,iBAAA;ED9LoB;;;;;;;;;;;;;;AAEM;EC4M1B,kBAAA;;;AAzaF;;;;AAAkB;AAGlB;;;;AAAiB;AAEjB;;;;;;EAubE,WAAA;EA1XE;;;;;;;;;;;;EAuYF,oBAAA;EA5WE;;;;;;;;;;;EAwXF,aAAA;EA5TiC;;;;EAiUjC,eAAA,EAAiB,eAAA;EA1TyC;;;AAYpD;AAqBR;;;;;;;;;;;;AAmCc;AAGd;;;;;;EA2QE,SAAA;EAvQU;AAAA;AAeZ;;;;AAA2B;AAE3B;;;;;;;;AAGQ;EAoQN,gBAAA;EAjQqB;;;;;;;;;;;;;;;AAiBA;AAGvB;;EAgQE,eAAA;EAhQ0B;;;;;;;;;AAgBjB;AAiBX;EA2OE,iBAAA;;;AA3OyB;AAgB3B;;;;AAA2B;AA4B3B;;;EA2ME,YAAA;EA3MgB;AAGlB;;;;;;;;;;;;;;;;;;;EA6NE,eAAA;EA1HA;;;;;;;EAkIA,MAAA,EAAQ,MAAA;EA7BR;;;;;;;;;;;;AA0Ha;;;;AC9pBf;;;;AAAyC;AAmBzC;;;EDukBE,qBAAA;ECvkB4C;AA+B9C;;;;ED8iBE,aAAA;EC9iBwB;;;;AAAsC;EDojB9D,WAAA;EC7foC;;;;;;;AAAqC;AAiD3E;;;;;;;;;;;EDgeE,gBAAA,GAAmB,MAAA;EC7dR;;;AAA2B;AA6BxC;;;;;;;;;AAEqB;;;;ACtKrB;;;;AAK6B;EFsnB3B,kBAAA;EE9mB4B;;;;;;;AAEF;AAE5B;;;;EFunBE,aAAA;AAAA;;;;cC9pBW,eAAA,EAAiB,WAAW;;;AJiCzC;;;;;;;;;;;;;;;iBIdgB,iBAAA,CAAkB,IAAY;;;;AJ8Bd;AAQhC;;;;;;;;;iBIPgB,SAAA,CAAU,KAAA,EAAO,WAAA,EAAa,QAAA,EAAU,QAAQ;;;;AJmBoB;AAgBpF;;;;;;;;;;;AAYU;AAGV;;;;;;;;;;;iBIKgB,sBAAA,CAAuB,MAAA,WAAiB,WAAA,KAAgB,GAAG;;;;;;;;;;;;iBAiD3D,iBAAA,CACd,KAAA,EAAO,IAAA,CAAK,WAAA,aACZ,cAAA,iBACA,SAAA,EAAW,WAAA;;;;;;;;;;;AJgDQ;AAIrB;;;;AAAkD;AAKlD;;;;iBI5BgB,iBAAA,CACd,MAAA,WAAiB,WAAA,IACjB,QAAA,GAAW,QAAQ;;;;;;AJ3IW;AAQhC;;;;;;;KKnCY,gBAAA;EAKJ,IAAA;EAAiB,IAAI;AAAA;;;AL0CuD;AAgBpF;;;KKlDY,kBAAA;EACJ,IAAA;AAAA;EACA,IAAA;EAAe,KAAA;AAAA;AAAA,UAEN,eAAA;EACf,EAAA;EACA,IAAA;EACA,KAAA,EAAO,MAAA;EACP,OAAA,GAAU,QAAA,EAAU,gBAAA;;EAEpB,UAAA,GAAa,kBAAA;AAAA;;KAIH,eAAA,IACV,IAAA,UACA,KAAA,EAAO,MAAA,mBACP,UAAA,GAAa,kBAAA,KACV,OAAA,CAAQ,gBAAA;AAAA,UAEI,eAAA;ELwI4B;EKtI3C,eAAA,EAAiB,eAAA;ELsIqC;EKpItD,WAAA,GAAc,QAAA,EAAU,gBAAgB;ELgDxC;EK9CA,OAAA;AAAA;;;;;iBAmBc,gBAAA,CAAA;EAAmB;AAAA;EAAc,QAAA,EAAU,SAAS;AAAA,gCAAE,GAAA,CAAA,OAAA;AAAA,iBAuDtD,gBAAA,CAAA,YAA6B,eAAe;AAAA,iBAI5C,kBAAA,CAAA,GAAsB,eAAe;;;;;;;;AL1GrD;;;;;;;;;;;UM7BiB,gBAAA;EACf,KAAA;EACA,GAAA;ENkC4D;EMhC5D,UAAA;AAAA;;;ANyC8B;AAQhC;;;KMxCY,aAAA;EACJ,IAAA;EAAe,IAAA;AAAA;EACf,IAAA;EAAc,IAAA;EAAc,UAAA;AAAA;;;ANkDgD;AAgBpF;;;;;;;;;;;AAYU;AAGV;;;;;;;iBMzDgB,mBAAA,CACd,IAAA,UACA,IAAA,WAAe,gBAAA,KACd,aAAa;;;;;;;;ANbhB;;;;;;;;;;;;UO1BiB,cAAA;EPiCyB;;;;;EO3BxC,MAAA;EPoC8B;AAQhC;;;;EOtCE,IAAI;AAAA;AAAA,UAGW,eAAA;EP+Cf;;;;;;AAAkF;AAgBpF;;EOrDE,WAAA,aAAwB,KAAA,EAAO,MAAA;EPqDL;;;;;EO/C1B,MAAA,GAAS,KAAA,EAAO,MAAA,sBAA4B,cAAA;AAAA;AAAA,cAOjC,YAAA,EAAc,QAAA,CAAS,MAAA,SAAe,eAAA;APoDzC;AAGV;;;;;;;;;;;;;;AAHU,iBO4OM,cAAA,CACd,IAAA,UACA,KAAA,GAAQ,MAAM;;;;;;;iBAkBA,cAAA,CAAe,IAAA,UAAc,KAAA,EAAO,MAAA,oBAA0B,cAAc"}
@@ -0,0 +1,70 @@
1
+ import { y as ToolDef } from "../agent-BNS2nx_T.js";
2
+
3
+ //#region src/tools/fetch-url.d.ts
4
+ declare function isBlockedAddress(ip: string): boolean;
5
+ /**
6
+ * Host-suffix allowlist check. An empty / undefined list means "no allowlist"
7
+ * → every host passes (the SSRF blocklist is the only gate). Otherwise the
8
+ * host must equal, or be a subdomain of, one of the entries. Subdomain match
9
+ * is on a dot boundary so `example.com` matches `docs.example.com` but not
10
+ * `notexample.com`.
11
+ */
12
+ declare function isHostAllowed(hostname: string, allowHosts: readonly string[] | undefined): boolean;
13
+ /**
14
+ * Pinned HTTP/HTTPS request. Connects to `pinnedIp` directly (bypassing
15
+ * Node/Bun's own DNS resolution) while preserving the `Host:` header and
16
+ * (for HTTPS) TLS SNI on the URL's original hostname. This is the
17
+ * concrete defense against DNS rebinding — see the file-level docstring.
18
+ *
19
+ * Reads up to `maxBufferBytes` of body and then forcibly closes the
20
+ * connection. The body is decoded as UTF-8; binary responses degrade to
21
+ * mojibake but the tool's contract is text payloads anyway.
22
+ */
23
+ interface PinnedResponse {
24
+ status: number;
25
+ url: string;
26
+ contentType: string;
27
+ body: string;
28
+ location: string | null;
29
+ }
30
+ declare function pinnedRequest(url: URL, pinnedIp: string, family: 4 | 6, headers: Record<string, string>, signal: AbortSignal, maxBufferBytes: number): Promise<PinnedResponse>;
31
+ /**
32
+ * Walk up to {@link MAX_REDIRECTS} hops, validating the target host of each
33
+ * 3xx response against the SSRF blocklist before following.
34
+ *
35
+ * `deps` is an internal seam for tests — production callers use the
36
+ * defaults. Both knobs are intentionally opaque: hosts that want to
37
+ * customize the blocklist should use a higher-level mechanism (a future
38
+ * `behavior.fetchUrlAllowHosts` setting) rather than reaching into this.
39
+ */
40
+ interface FetchSsrfDeps {
41
+ /** Resolve + validate a hostname. Defaults to {@link resolveAndCheck}. */
42
+ resolver?: (hostname: string) => Promise<{
43
+ address: string;
44
+ family: 4 | 6;
45
+ }>;
46
+ /** Execute a single pinned HTTP request. Defaults to {@link pinnedRequest}. */
47
+ requestImpl?: typeof pinnedRequest;
48
+ }
49
+ declare function fetchWithSsrfGuard(startUrl: URL, headers: Record<string, string>, signal: AbortSignal, maxBufferBytes: number, deps?: FetchSsrfDeps, allowHosts?: readonly string[]): Promise<PinnedResponse>;
50
+ declare function cacheKey(url: string, cap: number): string;
51
+ declare function cacheGet(key: string): string | null;
52
+ declare function cacheSet(key: string, output: string, ttlMs: number): void;
53
+ /** Test seam — drop all cached entries. */
54
+ declare function clearFetchUrlCache(): void;
55
+ /**
56
+ * Test seam — exercise the cache get/set/eviction in isolation without
57
+ * standing up the full SSRF + HTTP path. Not part of the public tool surface;
58
+ * `execute` uses the module-private functions directly.
59
+ */
60
+ declare const __fetchCacheTestApi: {
61
+ key: typeof cacheKey;
62
+ get: typeof cacheGet;
63
+ set: typeof cacheSet;
64
+ size: () => number;
65
+ bytes: () => number;
66
+ };
67
+ declare const fetchUrl: ToolDef;
68
+ //#endregion
69
+ export { FetchSsrfDeps, __fetchCacheTestApi, clearFetchUrlCache, fetchUrl, fetchWithSsrfGuard, isBlockedAddress, isHostAllowed, pinnedRequest };
70
+ //# sourceMappingURL=fetch-url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-url.d.ts","names":[],"sources":["../../src/tools/fetch-url.ts"],"mappings":";;;iBAgHgB,gBAAA,CAAiB,EAAU;;AAA3C;;;;AAA2C;AA8C3C;iBAAgB,aAAA,CAAc,QAAA,UAAkB,UAAyC;;;AAAA;AAYxF;;;;;;;UAiDS,cAAA;EACR,MAAA;EACA,GAAA;EACA,WAAA;EACA,IAAA;EACA,QAAA;AAAA;AAAA,iBAUc,aAAA,CACd,GAAA,EAAK,GAAA,EACL,QAAA,UACA,MAAA,SACA,OAAA,EAAS,MAAA,kBACT,MAAA,EAAQ,WAAA,EACR,cAAA,WACC,OAAA,CAAQ,cAAA;;;;;;;;;;UAgIM,aAAA;EAnIN;EAqIT,QAAA,IAAY,QAAA,aAAqB,OAAA;IAAU,OAAA;IAAiB,MAAA;EAAA;EAlI3D;EAoID,WAAA,UAAqB,aAAa;AAAA;AAAA,iBAGd,kBAAA,CACpB,QAAA,EAAU,GAAA,EACV,OAAA,EAAS,MAAA,kBACT,MAAA,EAAQ,WAAA,EACR,cAAA,UACA,IAAA,GAAM,aAAA,EACN,UAAA,uBACC,OAAA,CAAQ,cAAA;AAAA,iBAkDF,QAAA,CAAS,GAAA,UAAa,GAAW;AAAA,iBAIjC,QAAA,CAAS,GAAW;AAAA,iBAepB,QAAA,CAAS,GAAA,UAAa,MAAA,UAAgB,KAAA;;iBA0B/B,kBAAA,CAAA;;;;;;cAUH,mBAAA;;;;;;;cAQA,QAAA,EAAU,OA4FtB"}
@@ -0,0 +1,2 @@
1
+ import { a as isBlockedAddress, i as fetchWithSsrfGuard, n as clearFetchUrlCache, o as isHostAllowed, r as fetchUrl, s as pinnedRequest, t as __fetchCacheTestApi } from "../fetch-url-CPxfiXDa.js";
2
+ export { __fetchCacheTestApi, clearFetchUrlCache, fetchUrl, fetchWithSsrfGuard, isBlockedAddress, isHostAllowed, pinnedRequest };
@@ -0,0 +1,7 @@
1
+ import { y as ToolDef } from "../agent-BNS2nx_T.js";
2
+
3
+ //#region src/tools/web-search.d.ts
4
+ declare const webSearch: ToolDef;
5
+ //#endregion
6
+ export { webSearch };
7
+ //# sourceMappingURL=web-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-search.d.ts","names":[],"sources":["../../src/tools/web-search.ts"],"mappings":";;;cA6Ma,SAAA,EAAW,OAwDvB"}
@@ -0,0 +1,190 @@
1
+ import { l as errorMessage } from "../errors-CoQnKRf1.js";
2
+ import { c as stripHtmlInline, o as isHostAllowed } from "../fetch-url-CPxfiXDa.js";
3
+ //#region src/tools/web-search.ts
4
+ /**
5
+ * Web search tool with a runtime-resolved backend.
6
+ *
7
+ * Backend selection is keyless-fallback: the first backend whose env var
8
+ * is set wins, otherwise we fall through to DuckDuckGo's HTML endpoint
9
+ * (no key required, no auth, rate-limited and brittle to layout changes).
10
+ *
11
+ * 1. TAVILY_API_KEY → https://api.tavily.com/search
12
+ * 2. BRAVE_SEARCH_API_KEY → https://api.search.brave.com/res/v1/web/search
13
+ * 3. (fallback) → https://html.duckduckgo.com/html/
14
+ *
15
+ * Selection happens per call (not at module init) so a key added
16
+ * mid-session via the chat layer's auth flow is picked up on the very next
17
+ * search without restarting the agent. The 5 ms env-var read is negligible
18
+ * compared to the network round-trip.
19
+ *
20
+ * Anthropic providers can take over this tool server-side via the
21
+ * `nativeWebSearch` capability — when set, the provider's `formatTools`
22
+ * drops this `ToolDef` from the function-tools list and emits the
23
+ * server-tool block instead, so this `execute` body is never invoked.
24
+ */
25
+ const DEFAULT_MAX_RESULTS = 5;
26
+ const HARD_MAX_RESULTS = 20;
27
+ const HTTP_TIMEOUT_MS = 15e3;
28
+ const ERROR_BODY_MAX = 256;
29
+ /**
30
+ * Current "Month YYYY" for the search description's recency hint. A model with
31
+ * an older training cutoff otherwise queries with a stale year (`React docs
32
+ * 2023`) and misses everything newer. Resolved per read (the `description`
33
+ * getter below) so a long-lived process picks up a month rollover; the value
34
+ * is stable within a session, so it doesn't thrash the provider prompt cache.
35
+ */
36
+ function currentMonthYear() {
37
+ return (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", {
38
+ month: "long",
39
+ year: "numeric"
40
+ });
41
+ }
42
+ /** Egress host each backend talks to — gated against `fetchUrlAllowHosts`. */
43
+ const BACKEND_HOST = {
44
+ tavily: "api.tavily.com",
45
+ brave: "api.search.brave.com",
46
+ duckduckgo: "html.duckduckgo.com"
47
+ };
48
+ function pickBackend() {
49
+ if (process.env.TAVILY_API_KEY) return "tavily";
50
+ if (process.env.BRAVE_SEARCH_API_KEY) return "brave";
51
+ return "duckduckgo";
52
+ }
53
+ async function fetchWithTimeout(url, init, signal) {
54
+ const ctrl = new AbortController();
55
+ const onAbort = () => ctrl.abort();
56
+ signal.addEventListener("abort", onAbort, { once: true });
57
+ const timer = setTimeout(() => ctrl.abort(), HTTP_TIMEOUT_MS);
58
+ try {
59
+ return await fetch(url, {
60
+ ...init,
61
+ signal: ctrl.signal
62
+ });
63
+ } finally {
64
+ clearTimeout(timer);
65
+ signal.removeEventListener("abort", onAbort);
66
+ }
67
+ }
68
+ /**
69
+ * Truncate untrusted HTTP error bodies before embedding them in our own
70
+ * error string. Without this, a backend that returns an HTML 500 page
71
+ * leaks a kilobyte of unstructured chrome straight into the model's
72
+ * context window — which is both noisy and a small prompt-injection
73
+ * surface.
74
+ */
75
+ async function readErrorBody(res) {
76
+ const body = await res.text().catch(() => "");
77
+ if (body.length <= ERROR_BODY_MAX) return body;
78
+ return `${body.slice(0, ERROR_BODY_MAX)}… (truncated, ${body.length} bytes total)`;
79
+ }
80
+ async function searchTavily(query, max, signal) {
81
+ const res = await fetchWithTimeout("https://api.tavily.com/search", {
82
+ method: "POST",
83
+ headers: { "content-type": "application/json" },
84
+ body: JSON.stringify({
85
+ api_key: process.env.TAVILY_API_KEY,
86
+ query,
87
+ max_results: max,
88
+ search_depth: "basic"
89
+ })
90
+ }, signal);
91
+ if (!res.ok) throw new Error(`Tavily HTTP ${res.status}: ${await readErrorBody(res)}`);
92
+ return ((await res.json()).results ?? []).map((r) => ({
93
+ title: r.title ?? "",
94
+ url: r.url ?? "",
95
+ snippet: r.content ?? ""
96
+ }));
97
+ }
98
+ async function searchBrave(query, max, signal) {
99
+ const res = await fetchWithTimeout(`https://api.search.brave.com/res/v1/web/search?q=${encodeURIComponent(query)}&count=${max}`, { headers: {
100
+ "accept": "application/json",
101
+ "x-subscription-token": process.env.BRAVE_SEARCH_API_KEY
102
+ } }, signal);
103
+ if (!res.ok) throw new Error(`Brave HTTP ${res.status}: ${await readErrorBody(res)}`);
104
+ return ((await res.json()).web?.results ?? []).map((r) => ({
105
+ title: r.title ?? "",
106
+ url: r.url ?? "",
107
+ snippet: r.description ?? ""
108
+ }));
109
+ }
110
+ function unwrapDdgRedirect(href) {
111
+ try {
112
+ const u = new URL(href, "https://duckduckgo.com");
113
+ if (u.pathname === "/l/" || u.pathname === "/l") {
114
+ const target = u.searchParams.get("uddg");
115
+ if (target) return decodeURIComponent(target);
116
+ }
117
+ return u.toString();
118
+ } catch {
119
+ return href;
120
+ }
121
+ }
122
+ async function searchDuckDuckGo(query, max, signal) {
123
+ const res = await fetchWithTimeout(`https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`, { headers: {
124
+ "user-agent": "Mozilla/5.0 (compatible; zidane/1.0)",
125
+ "accept": "text/html"
126
+ } }, signal);
127
+ if (!res.ok) throw new Error(`DuckDuckGo HTTP ${res.status}: ${await readErrorBody(res)}`);
128
+ const html = await res.text();
129
+ const results = [];
130
+ const blockRe = /<a[^>]+class="[^"]*result__a[^"]*"[^>]+href="([^"]+)"[^>]*>([\s\S]*?)<\/a>[\s\S]*?<a[^>]+class="[^"]*result__snippet[^"]*"[^>]*>([\s\S]*?)<\/a>/g;
131
+ let m = blockRe.exec(html);
132
+ while (m !== null) {
133
+ results.push({
134
+ url: unwrapDdgRedirect(m[1]),
135
+ title: stripHtmlInline(m[2]),
136
+ snippet: stripHtmlInline(m[3])
137
+ });
138
+ if (results.length >= max) break;
139
+ m = blockRe.exec(html);
140
+ }
141
+ return results;
142
+ }
143
+ function formatResults(results, backend) {
144
+ if (results.length === 0) {
145
+ if (backend === "duckduckgo") return "(no results from the keyless DuckDuckGo fallback — it is rate-limited and brittle to layout changes. Set TAVILY_API_KEY or BRAVE_SEARCH_API_KEY for reliable search.)";
146
+ return `(no results from ${backend})`;
147
+ }
148
+ return `${`# Web search results (${backend}, ${results.length} ${results.length === 1 ? "hit" : "hits"})\n`}\n${results.map((r, i) => `${i + 1}. ${r.title}\n ${r.url}\n ${r.snippet}`).join("\n\n")}`;
149
+ }
150
+ const webSearch = {
151
+ isConcurrencySafe: true,
152
+ spec: {
153
+ name: "web_search",
154
+ get description() {
155
+ return `Search the public web and return ranked title / URL / snippet results. Use this to look up documentation, error messages, library versions, or recent events. If a \`fetch_url\` tool is also available, follow up with it to read a specific page in full.
156
+ IMPORTANT: the current month is ${currentMonthYear()}. When searching for recent information, docs, or current events, use the current year in the query — not a year from your training cutoff (e.g. search "React docs" with this year, not an older one).`;
157
+ },
158
+ inputSchema: {
159
+ type: "object",
160
+ properties: {
161
+ query: {
162
+ type: "string",
163
+ description: "Search query. Plain natural-language or keyword form; quoting and site: operators are passed through verbatim."
164
+ },
165
+ max_results: {
166
+ type: "number",
167
+ description: `Maximum number of results to return. Default: ${DEFAULT_MAX_RESULTS}. Capped at ${HARD_MAX_RESULTS}.`
168
+ }
169
+ },
170
+ required: ["query"]
171
+ }
172
+ },
173
+ async execute({ query, max_results }, ctx) {
174
+ const q = typeof query === "string" ? query.trim() : "";
175
+ if (!q) return "web_search error: `query` is required";
176
+ const max = Math.min(typeof max_results === "number" && max_results > 0 ? Math.floor(max_results) : DEFAULT_MAX_RESULTS, HARD_MAX_RESULTS);
177
+ const backend = pickBackend();
178
+ const allowHosts = ctx.behavior?.fetchUrlAllowHosts;
179
+ if (!isHostAllowed(BACKEND_HOST[backend], allowHosts)) return `web_search error: the ${backend} backend (${BACKEND_HOST[backend]}) is not in the configured egress allowlist`;
180
+ try {
181
+ return formatResults(backend === "tavily" ? await searchTavily(q, max, ctx.signal) : backend === "brave" ? await searchBrave(q, max, ctx.signal) : await searchDuckDuckGo(q, max, ctx.signal), backend);
182
+ } catch (err) {
183
+ return `web_search error (${backend}): ${errorMessage(err)}`;
184
+ }
185
+ }
186
+ };
187
+ //#endregion
188
+ export { webSearch };
189
+
190
+ //# sourceMappingURL=web-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-search.js","names":[],"sources":["../../src/tools/web-search.ts"],"sourcesContent":["import type { ToolContext, ToolDef } from './types'\nimport { errorMessage } from '../errors'\nimport { stripHtmlInline } from './_html'\nimport { isHostAllowed } from './fetch-url'\n\n/**\n * Web search tool with a runtime-resolved backend.\n *\n * Backend selection is keyless-fallback: the first backend whose env var\n * is set wins, otherwise we fall through to DuckDuckGo's HTML endpoint\n * (no key required, no auth, rate-limited and brittle to layout changes).\n *\n * 1. TAVILY_API_KEY → https://api.tavily.com/search\n * 2. BRAVE_SEARCH_API_KEY → https://api.search.brave.com/res/v1/web/search\n * 3. (fallback) → https://html.duckduckgo.com/html/\n *\n * Selection happens per call (not at module init) so a key added\n * mid-session via the chat layer's auth flow is picked up on the very next\n * search without restarting the agent. The 5 ms env-var read is negligible\n * compared to the network round-trip.\n *\n * Anthropic providers can take over this tool server-side via the\n * `nativeWebSearch` capability — when set, the provider's `formatTools`\n * drops this `ToolDef` from the function-tools list and emits the\n * server-tool block instead, so this `execute` body is never invoked.\n */\n\nconst DEFAULT_MAX_RESULTS = 5\nconst HARD_MAX_RESULTS = 20\nconst HTTP_TIMEOUT_MS = 15_000\nconst ERROR_BODY_MAX = 256\n\n/**\n * Current \"Month YYYY\" for the search description's recency hint. A model with\n * an older training cutoff otherwise queries with a stale year (`React docs\n * 2023`) and misses everything newer. Resolved per read (the `description`\n * getter below) so a long-lived process picks up a month rollover; the value\n * is stable within a session, so it doesn't thrash the provider prompt cache.\n */\nfunction currentMonthYear(): string {\n return new Date().toLocaleDateString('en-US', { month: 'long', year: 'numeric' })\n}\n\ninterface SearchResult {\n title: string\n url: string\n snippet: string\n}\n\ntype Backend = 'tavily' | 'brave' | 'duckduckgo'\n\n/** Egress host each backend talks to — gated against `fetchUrlAllowHosts`. */\nconst BACKEND_HOST: Record<Backend, string> = {\n tavily: 'api.tavily.com',\n brave: 'api.search.brave.com',\n duckduckgo: 'html.duckduckgo.com',\n}\n\nfunction pickBackend(): Backend {\n if (process.env.TAVILY_API_KEY)\n return 'tavily'\n if (process.env.BRAVE_SEARCH_API_KEY)\n return 'brave'\n return 'duckduckgo'\n}\n\nasync function fetchWithTimeout(url: string, init: RequestInit, signal: AbortSignal): Promise<Response> {\n const ctrl = new AbortController()\n const onAbort = (): void => ctrl.abort()\n signal.addEventListener('abort', onAbort, { once: true })\n const timer = setTimeout(() => ctrl.abort(), HTTP_TIMEOUT_MS)\n try {\n return await fetch(url, { ...init, signal: ctrl.signal })\n }\n finally {\n clearTimeout(timer)\n signal.removeEventListener('abort', onAbort)\n }\n}\n\n/**\n * Truncate untrusted HTTP error bodies before embedding them in our own\n * error string. Without this, a backend that returns an HTML 500 page\n * leaks a kilobyte of unstructured chrome straight into the model's\n * context window — which is both noisy and a small prompt-injection\n * surface.\n */\nasync function readErrorBody(res: Response): Promise<string> {\n const body = await res.text().catch(() => '')\n if (body.length <= ERROR_BODY_MAX)\n return body\n return `${body.slice(0, ERROR_BODY_MAX)}… (truncated, ${body.length} bytes total)`\n}\n\nasync function searchTavily(query: string, max: number, signal: AbortSignal): Promise<SearchResult[]> {\n const res = await fetchWithTimeout('https://api.tavily.com/search', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n api_key: process.env.TAVILY_API_KEY,\n query,\n max_results: max,\n search_depth: 'basic',\n }),\n }, signal)\n if (!res.ok)\n throw new Error(`Tavily HTTP ${res.status}: ${await readErrorBody(res)}`)\n const json = await res.json() as { results?: Array<{ title?: string, url?: string, content?: string }> }\n return (json.results ?? []).map(r => ({\n title: r.title ?? '',\n url: r.url ?? '',\n snippet: r.content ?? '',\n }))\n}\n\nasync function searchBrave(query: string, max: number, signal: AbortSignal): Promise<SearchResult[]> {\n const url = `https://api.search.brave.com/res/v1/web/search?q=${encodeURIComponent(query)}&count=${max}`\n const res = await fetchWithTimeout(url, {\n headers: {\n 'accept': 'application/json',\n 'x-subscription-token': process.env.BRAVE_SEARCH_API_KEY!,\n },\n }, signal)\n if (!res.ok)\n throw new Error(`Brave HTTP ${res.status}: ${await readErrorBody(res)}`)\n const json = await res.json() as { web?: { results?: Array<{ title?: string, url?: string, description?: string }> } }\n return (json.web?.results ?? []).map(r => ({\n title: r.title ?? '',\n url: r.url ?? '',\n snippet: r.description ?? '',\n }))\n}\n\n// DDG's HTML endpoint redirects through /l/?uddg=<encoded> — unwrap it so the\n// model sees the destination URL directly.\nfunction unwrapDdgRedirect(href: string): string {\n try {\n const u = new URL(href, 'https://duckduckgo.com')\n if (u.pathname === '/l/' || u.pathname === '/l') {\n const target = u.searchParams.get('uddg')\n if (target)\n return decodeURIComponent(target)\n }\n return u.toString()\n }\n catch {\n return href\n }\n}\n\nasync function searchDuckDuckGo(query: string, max: number, signal: AbortSignal): Promise<SearchResult[]> {\n const url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`\n const res = await fetchWithTimeout(url, {\n headers: {\n // DDG returns an empty results page to unbranded UAs.\n 'user-agent': 'Mozilla/5.0 (compatible; zidane/1.0)',\n 'accept': 'text/html',\n },\n }, signal)\n if (!res.ok)\n throw new Error(`DuckDuckGo HTTP ${res.status}: ${await readErrorBody(res)}`)\n const html = await res.text()\n // Each result block has anchor `result__a` (title+url) and `result__snippet`.\n // Brittle by design — DDG ships layout changes occasionally and the scrape\n // silently returns zero hits when its anchors move. The keyed-key\n // backends (Tavily / Brave) are the supported happy path; this fallback\n // exists only so the tool is usable with no setup. If `results` is empty,\n // the formatter surfaces a \"(no results from duckduckgo)\" line.\n const results: SearchResult[] = []\n const blockRe = /<a[^>]+class=\"[^\"]*result__a[^\"]*\"[^>]+href=\"([^\"]+)\"[^>]*>([\\s\\S]*?)<\\/a>[\\s\\S]*?<a[^>]+class=\"[^\"]*result__snippet[^\"]*\"[^>]*>([\\s\\S]*?)<\\/a>/g\n\n let m = blockRe.exec(html)\n\n while (m !== null) {\n results.push({\n url: unwrapDdgRedirect(m[1]!),\n title: stripHtmlInline(m[2]!),\n snippet: stripHtmlInline(m[3]!),\n })\n if (results.length >= max)\n break\n\n m = blockRe.exec(html)\n }\n return results\n}\n\nfunction formatResults(results: SearchResult[], backend: Backend): string {\n if (results.length === 0) {\n // The keyless DuckDuckGo scrape returns zero hits both for genuinely\n // empty queries AND when DDG ships a layout change that moves the anchors\n // this regex keys off. Distinguish it from the keyed backends with an\n // actionable hint so a confused model (or user reading the transcript)\n // knows the fix is a real search key, not a better query.\n if (backend === 'duckduckgo') {\n return '(no results from the keyless DuckDuckGo fallback — it is rate-limited and '\n + 'brittle to layout changes. Set TAVILY_API_KEY or BRAVE_SEARCH_API_KEY for reliable search.)'\n }\n return `(no results from ${backend})`\n }\n const header = `# Web search results (${backend}, ${results.length} ${results.length === 1 ? 'hit' : 'hits'})\\n`\n const body = results.map((r, i) => `${i + 1}. ${r.title}\\n ${r.url}\\n ${r.snippet}`).join('\\n\\n')\n return `${header}\\n${body}`\n}\n\nexport const webSearch: ToolDef = {\n isConcurrencySafe: true,\n spec: {\n name: 'web_search',\n // Getter, not a constant, so the recency hint reflects the current month\n // each time the spec is formatted for the provider (see `currentMonthYear`).\n get description(): string {\n return 'Search the public web and return ranked title / URL / snippet results. '\n + 'Use this to look up documentation, error messages, library versions, or recent events. '\n + 'If a `fetch_url` tool is also available, follow up with it to read a specific page in full.\\n'\n + `IMPORTANT: the current month is ${currentMonthYear()}. When searching for recent `\n + 'information, docs, or current events, use the current year in the query — not a year '\n + 'from your training cutoff (e.g. search \"React docs\" with this year, not an older one).'\n },\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search query. Plain natural-language or keyword form; quoting and site: operators are passed through verbatim.',\n },\n max_results: {\n type: 'number',\n description: `Maximum number of results to return. Default: ${DEFAULT_MAX_RESULTS}. Capped at ${HARD_MAX_RESULTS}.`,\n },\n },\n required: ['query'],\n },\n },\n async execute({ query, max_results }, ctx: ToolContext) {\n const q = typeof query === 'string' ? query.trim() : ''\n if (!q)\n return 'web_search error: `query` is required'\n const max = Math.min(\n typeof max_results === 'number' && max_results > 0 ? Math.floor(max_results) : DEFAULT_MAX_RESULTS,\n HARD_MAX_RESULTS,\n )\n const backend = pickBackend()\n // Honor the egress allowlist (when configured): refuse a backend whose\n // host isn't approved rather than silently making the request.\n const allowHosts = ctx.behavior?.fetchUrlAllowHosts\n if (!isHostAllowed(BACKEND_HOST[backend], allowHosts)) {\n return `web_search error: the ${backend} backend (${BACKEND_HOST[backend]}) is not in the configured egress allowlist`\n }\n try {\n const results = backend === 'tavily'\n ? await searchTavily(q, max, ctx.signal)\n : backend === 'brave'\n ? await searchBrave(q, max, ctx.signal)\n : await searchDuckDuckGo(q, max, ctx.signal)\n return formatResults(results, backend)\n }\n catch (err) {\n return `web_search error (${backend}): ${errorMessage(err)}`\n }\n },\n}\n"],"mappings":"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"}