inspect-ai 0.3.98__py3-none-any.whl → 0.3.100__py3-none-any.whl

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 (131) hide show
  1. inspect_ai/__init__.py +2 -0
  2. inspect_ai/_cli/log.py +1 -1
  3. inspect_ai/_display/core/config.py +11 -5
  4. inspect_ai/_display/core/panel.py +66 -2
  5. inspect_ai/_display/core/textual.py +5 -2
  6. inspect_ai/_display/plain/display.py +1 -0
  7. inspect_ai/_display/rich/display.py +2 -2
  8. inspect_ai/_display/textual/widgets/transcript.py +41 -1
  9. inspect_ai/_eval/run.py +12 -4
  10. inspect_ai/_eval/score.py +2 -4
  11. inspect_ai/_eval/task/log.py +1 -1
  12. inspect_ai/_eval/task/run.py +59 -81
  13. inspect_ai/_eval/task/task.py +1 -1
  14. inspect_ai/_util/_async.py +1 -1
  15. inspect_ai/_util/content.py +11 -6
  16. inspect_ai/_util/interrupt.py +2 -2
  17. inspect_ai/_util/text.py +7 -0
  18. inspect_ai/_util/working.py +8 -37
  19. inspect_ai/_view/__init__.py +0 -0
  20. inspect_ai/_view/schema.py +3 -1
  21. inspect_ai/_view/view.py +14 -0
  22. inspect_ai/_view/www/CLAUDE.md +15 -0
  23. inspect_ai/_view/www/dist/assets/index.css +273 -169
  24. inspect_ai/_view/www/dist/assets/index.js +20079 -17019
  25. inspect_ai/_view/www/log-schema.json +122 -8
  26. inspect_ai/_view/www/package.json +5 -1
  27. inspect_ai/_view/www/src/@types/log.d.ts +20 -2
  28. inspect_ai/_view/www/src/app/App.tsx +1 -15
  29. inspect_ai/_view/www/src/app/appearance/icons.ts +4 -1
  30. inspect_ai/_view/www/src/app/content/MetaDataGrid.tsx +24 -6
  31. inspect_ai/_view/www/src/app/content/MetadataGrid.module.css +0 -5
  32. inspect_ai/_view/www/src/app/content/RenderedContent.tsx +221 -205
  33. inspect_ai/_view/www/src/app/log-view/LogViewContainer.tsx +2 -1
  34. inspect_ai/_view/www/src/app/log-view/tabs/SamplesTab.tsx +5 -0
  35. inspect_ai/_view/www/src/app/routing/url.ts +84 -4
  36. inspect_ai/_view/www/src/app/samples/InlineSampleDisplay.module.css +0 -5
  37. inspect_ai/_view/www/src/app/samples/SampleDialog.module.css +1 -1
  38. inspect_ai/_view/www/src/app/samples/SampleDisplay.module.css +7 -0
  39. inspect_ai/_view/www/src/app/samples/SampleDisplay.tsx +26 -19
  40. inspect_ai/_view/www/src/app/samples/SampleSummaryView.module.css +1 -2
  41. inspect_ai/_view/www/src/app/samples/chat/ChatMessage.tsx +8 -6
  42. inspect_ai/_view/www/src/app/samples/chat/ChatMessageRow.tsx +0 -4
  43. inspect_ai/_view/www/src/app/samples/chat/ChatViewVirtualList.tsx +3 -2
  44. inspect_ai/_view/www/src/app/samples/chat/MessageContent.tsx +2 -0
  45. inspect_ai/_view/www/src/app/samples/chat/MessageContents.tsx +2 -0
  46. inspect_ai/_view/www/src/app/samples/chat/messages.ts +1 -0
  47. inspect_ai/_view/www/src/app/samples/chat/tools/ToolCallView.tsx +1 -0
  48. inspect_ai/_view/www/src/app/samples/list/SampleRow.tsx +1 -1
  49. inspect_ai/_view/www/src/app/samples/scores/SampleScoresGrid.module.css +2 -2
  50. inspect_ai/_view/www/src/app/samples/transcript/ErrorEventView.tsx +2 -3
  51. inspect_ai/_view/www/src/app/samples/transcript/InfoEventView.tsx +1 -1
  52. inspect_ai/_view/www/src/app/samples/transcript/InputEventView.tsx +1 -2
  53. inspect_ai/_view/www/src/app/samples/transcript/ModelEventView.module.css +1 -1
  54. inspect_ai/_view/www/src/app/samples/transcript/ModelEventView.tsx +1 -1
  55. inspect_ai/_view/www/src/app/samples/transcript/SampleInitEventView.tsx +1 -1
  56. inspect_ai/_view/www/src/app/samples/transcript/SampleLimitEventView.tsx +3 -2
  57. inspect_ai/_view/www/src/app/samples/transcript/SandboxEventView.tsx +4 -5
  58. inspect_ai/_view/www/src/app/samples/transcript/ScoreEventView.tsx +1 -1
  59. inspect_ai/_view/www/src/app/samples/transcript/SpanEventView.tsx +1 -2
  60. inspect_ai/_view/www/src/app/samples/transcript/StepEventView.tsx +1 -3
  61. inspect_ai/_view/www/src/app/samples/transcript/SubtaskEventView.tsx +1 -2
  62. inspect_ai/_view/www/src/app/samples/transcript/ToolEventView.tsx +3 -4
  63. inspect_ai/_view/www/src/app/samples/transcript/TranscriptPanel.module.css +42 -0
  64. inspect_ai/_view/www/src/app/samples/transcript/TranscriptPanel.tsx +77 -0
  65. inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualList.tsx +27 -71
  66. inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualListComponent.module.css +13 -3
  67. inspect_ai/_view/www/src/app/samples/transcript/TranscriptVirtualListComponent.tsx +27 -2
  68. inspect_ai/_view/www/src/app/samples/transcript/event/EventPanel.module.css +1 -0
  69. inspect_ai/_view/www/src/app/samples/transcript/event/EventPanel.tsx +21 -22
  70. inspect_ai/_view/www/src/app/samples/transcript/outline/OutlineRow.module.css +45 -0
  71. inspect_ai/_view/www/src/app/samples/transcript/outline/OutlineRow.tsx +223 -0
  72. inspect_ai/_view/www/src/app/samples/transcript/outline/TranscriptOutline.module.css +10 -0
  73. inspect_ai/_view/www/src/app/samples/transcript/outline/TranscriptOutline.tsx +258 -0
  74. inspect_ai/_view/www/src/app/samples/transcript/outline/tree-visitors.ts +187 -0
  75. inspect_ai/_view/www/src/app/samples/transcript/state/StateEventRenderers.tsx +8 -1
  76. inspect_ai/_view/www/src/app/samples/transcript/state/StateEventView.tsx +3 -4
  77. inspect_ai/_view/www/src/app/samples/transcript/transform/hooks.ts +78 -0
  78. inspect_ai/_view/www/src/app/samples/transcript/transform/treeify.ts +340 -135
  79. inspect_ai/_view/www/src/app/samples/transcript/transform/utils.ts +3 -0
  80. inspect_ai/_view/www/src/app/samples/transcript/types.ts +2 -0
  81. inspect_ai/_view/www/src/app/types.ts +5 -1
  82. inspect_ai/_view/www/src/client/api/api-browser.ts +2 -2
  83. inspect_ai/_view/www/src/components/LiveVirtualList.tsx +6 -1
  84. inspect_ai/_view/www/src/components/MarkdownDiv.tsx +1 -1
  85. inspect_ai/_view/www/src/components/PopOver.tsx +422 -0
  86. inspect_ai/_view/www/src/components/PulsingDots.module.css +9 -9
  87. inspect_ai/_view/www/src/components/PulsingDots.tsx +4 -1
  88. inspect_ai/_view/www/src/components/StickyScroll.tsx +183 -0
  89. inspect_ai/_view/www/src/components/TabSet.tsx +4 -0
  90. inspect_ai/_view/www/src/state/hooks.ts +52 -2
  91. inspect_ai/_view/www/src/state/logSlice.ts +4 -3
  92. inspect_ai/_view/www/src/state/samplePolling.ts +8 -0
  93. inspect_ai/_view/www/src/state/sampleSlice.ts +53 -9
  94. inspect_ai/_view/www/src/state/scrolling.ts +152 -0
  95. inspect_ai/_view/www/src/utils/attachments.ts +7 -0
  96. inspect_ai/_view/www/src/utils/python.ts +18 -0
  97. inspect_ai/_view/www/yarn.lock +269 -6
  98. inspect_ai/agent/_react.py +12 -7
  99. inspect_ai/agent/_run.py +46 -11
  100. inspect_ai/analysis/beta/_dataframe/samples/table.py +19 -18
  101. inspect_ai/log/_bundle.py +5 -3
  102. inspect_ai/log/_log.py +3 -3
  103. inspect_ai/log/_recorders/file.py +2 -9
  104. inspect_ai/log/_transcript.py +1 -1
  105. inspect_ai/model/_call_tools.py +6 -2
  106. inspect_ai/model/_openai.py +1 -1
  107. inspect_ai/model/_openai_responses.py +78 -39
  108. inspect_ai/model/_openai_web_search.py +31 -0
  109. inspect_ai/model/_providers/anthropic.py +3 -6
  110. inspect_ai/model/_providers/azureai.py +72 -3
  111. inspect_ai/model/_providers/openai.py +2 -1
  112. inspect_ai/model/_providers/providers.py +1 -1
  113. inspect_ai/scorer/_metric.py +1 -2
  114. inspect_ai/solver/_task_state.py +2 -2
  115. inspect_ai/tool/_tool.py +6 -2
  116. inspect_ai/tool/_tool_def.py +27 -4
  117. inspect_ai/tool/_tool_info.py +2 -0
  118. inspect_ai/tool/_tools/_web_search/_google.py +15 -4
  119. inspect_ai/tool/_tools/_web_search/_tavily.py +35 -12
  120. inspect_ai/tool/_tools/_web_search/_web_search.py +214 -45
  121. inspect_ai/util/__init__.py +6 -0
  122. inspect_ai/util/_json.py +3 -0
  123. inspect_ai/util/_limit.py +374 -141
  124. inspect_ai/util/_sandbox/docker/compose.py +20 -11
  125. inspect_ai/util/_span.py +1 -1
  126. {inspect_ai-0.3.98.dist-info → inspect_ai-0.3.100.dist-info}/METADATA +3 -3
  127. {inspect_ai-0.3.98.dist-info → inspect_ai-0.3.100.dist-info}/RECORD +131 -117
  128. {inspect_ai-0.3.98.dist-info → inspect_ai-0.3.100.dist-info}/WHEEL +1 -1
  129. {inspect_ai-0.3.98.dist-info → inspect_ai-0.3.100.dist-info}/entry_points.txt +0 -0
  130. {inspect_ai-0.3.98.dist-info → inspect_ai-0.3.100.dist-info}/licenses/LICENSE +0 -0
  131. {inspect_ai-0.3.98.dist-info → inspect_ai-0.3.100.dist-info}/top_level.txt +0 -0
@@ -915,6 +915,11 @@
915
915
  dependencies:
916
916
  regenerator-runtime "^0.14.0"
917
917
 
918
+ "@babel/runtime@^7.27.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
919
+ version "7.27.1"
920
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.1.tgz#9fce313d12c9a77507f264de74626e87fd0dc541"
921
+ integrity sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==
922
+
918
923
  "@babel/template@^7.25.9", "@babel/template@^7.26.9", "@babel/template@^7.27.0", "@babel/template@^7.3.3":
919
924
  version "7.27.0"
920
925
  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.0.tgz#b253e5406cc1df1c57dcd18f11760c2dbf40c0b4"
@@ -1021,6 +1026,58 @@
1021
1026
  resolved "https://registry.yarnpkg.com/@dmsnell/diff-match-patch/-/diff-match-patch-1.1.0.tgz#5bac00243fa2583fa970d9865609f632dcd90e32"
1022
1027
  integrity sha512-yejLPmM5pjsGvxS9gXablUSbInW7H976c/FJ4iQxWIm7/38xBySRemTPDe34lhg1gVLbJntX0+sH0jYfU+PN9A==
1023
1028
 
1029
+ "@emotion/cache@^11.13.5":
1030
+ version "11.14.0"
1031
+ resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.14.0.tgz#ee44b26986eeb93c8be82bb92f1f7a9b21b2ed76"
1032
+ integrity sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==
1033
+ dependencies:
1034
+ "@emotion/memoize" "^0.9.0"
1035
+ "@emotion/sheet" "^1.4.0"
1036
+ "@emotion/utils" "^1.4.2"
1037
+ "@emotion/weak-memoize" "^0.4.0"
1038
+ stylis "4.2.0"
1039
+
1040
+ "@emotion/hash@^0.9.2":
1041
+ version "0.9.2"
1042
+ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b"
1043
+ integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==
1044
+
1045
+ "@emotion/memoize@^0.9.0":
1046
+ version "0.9.0"
1047
+ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102"
1048
+ integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
1049
+
1050
+ "@emotion/serialize@^1.3.3":
1051
+ version "1.3.3"
1052
+ resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.3.tgz#d291531005f17d704d0463a032fe679f376509e8"
1053
+ integrity sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==
1054
+ dependencies:
1055
+ "@emotion/hash" "^0.9.2"
1056
+ "@emotion/memoize" "^0.9.0"
1057
+ "@emotion/unitless" "^0.10.0"
1058
+ "@emotion/utils" "^1.4.2"
1059
+ csstype "^3.0.2"
1060
+
1061
+ "@emotion/sheet@^1.4.0":
1062
+ version "1.4.0"
1063
+ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.4.0.tgz#c9299c34d248bc26e82563735f78953d2efca83c"
1064
+ integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
1065
+
1066
+ "@emotion/unitless@^0.10.0":
1067
+ version "0.10.0"
1068
+ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.10.0.tgz#2af2f7c7e5150f497bdabd848ce7b218a27cf745"
1069
+ integrity sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==
1070
+
1071
+ "@emotion/utils@^1.4.2":
1072
+ version "1.4.2"
1073
+ resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.2.tgz#6df6c45881fcb1c412d6688a311a98b7f59c1b52"
1074
+ integrity sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==
1075
+
1076
+ "@emotion/weak-memoize@^0.4.0":
1077
+ version "0.4.0"
1078
+ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz#5e13fac887f08c44f76b0ccaf3370eb00fec9bb6"
1079
+ integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==
1080
+
1024
1081
  "@esbuild/aix-ppc64@0.21.5":
1025
1082
  version "0.21.5"
1026
1083
  resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f"
@@ -1482,6 +1539,11 @@
1482
1539
  resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796"
1483
1540
  integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==
1484
1541
 
1542
+ "@juggle/resize-observer@^3.3.1":
1543
+ version "3.4.0"
1544
+ resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60"
1545
+ integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==
1546
+
1485
1547
  "@lezer/common@^1.0.0", "@lezer/common@^1.1.0":
1486
1548
  version "1.2.3"
1487
1549
  resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.2.3.tgz#138fcddab157d83da557554851017c6c1e5667fd"
@@ -1506,6 +1568,106 @@
1506
1568
  resolved "https://registry.yarnpkg.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz#775374306116d51c0c500b8c4face0f9a04752d8"
1507
1569
  integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==
1508
1570
 
1571
+ "@mui/core-downloads-tracker@^7.1.0":
1572
+ version "7.1.0"
1573
+ resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-7.1.0.tgz#0767bad9a74aaeb0032da7390d1d1c32653e31d8"
1574
+ integrity sha512-E0OqhZv548Qdc0PwWhLVA2zmjJZSTvaL4ZhoswmI8NJEC1tpW2js6LLP827jrW9MEiXYdz3QS6+hask83w74yQ==
1575
+
1576
+ "@mui/material@^7.1.0":
1577
+ version "7.1.0"
1578
+ resolved "https://registry.yarnpkg.com/@mui/material/-/material-7.1.0.tgz#f25866fb507ada2a2b3ac433b13a2bc79d83f608"
1579
+ integrity sha512-ahUJdrhEv+mCp4XHW+tHIEYzZMSRLg8z4AjUOsj44QpD1ZaMxQoVOG2xiHvLFdcsIPbgSRx1bg1eQSheHBgvtg==
1580
+ dependencies:
1581
+ "@babel/runtime" "^7.27.1"
1582
+ "@mui/core-downloads-tracker" "^7.1.0"
1583
+ "@mui/system" "^7.1.0"
1584
+ "@mui/types" "^7.4.2"
1585
+ "@mui/utils" "^7.1.0"
1586
+ "@popperjs/core" "^2.11.8"
1587
+ "@types/react-transition-group" "^4.4.12"
1588
+ clsx "^2.1.1"
1589
+ csstype "^3.1.3"
1590
+ prop-types "^15.8.1"
1591
+ react-is "^19.1.0"
1592
+ react-transition-group "^4.4.5"
1593
+
1594
+ "@mui/private-theming@^7.1.0":
1595
+ version "7.1.0"
1596
+ resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-7.1.0.tgz#257b82cdbd4ec63132f3fc14e121e5acb3ff6e40"
1597
+ integrity sha512-4Kck4jxhqF6YxNwJdSae1WgDfXVg0lIH6JVJ7gtuFfuKcQCgomJxPvUEOySTFRPz1IZzwz5OAcToskRdffElDA==
1598
+ dependencies:
1599
+ "@babel/runtime" "^7.27.1"
1600
+ "@mui/utils" "^7.1.0"
1601
+ prop-types "^15.8.1"
1602
+
1603
+ "@mui/styled-engine@^7.1.0":
1604
+ version "7.1.0"
1605
+ resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-7.1.0.tgz#3bf1d7856b98934585f7d03582bd74073db2a4b4"
1606
+ integrity sha512-m0mJ0c6iRC+f9hMeRe0W7zZX1wme3oUX0+XTVHjPG7DJz6OdQ6K/ggEOq7ZdwilcpdsDUwwMfOmvO71qDkYd2w==
1607
+ dependencies:
1608
+ "@babel/runtime" "^7.27.1"
1609
+ "@emotion/cache" "^11.13.5"
1610
+ "@emotion/serialize" "^1.3.3"
1611
+ "@emotion/sheet" "^1.4.0"
1612
+ csstype "^3.1.3"
1613
+ prop-types "^15.8.1"
1614
+
1615
+ "@mui/system@^7.1.0":
1616
+ version "7.1.0"
1617
+ resolved "https://registry.yarnpkg.com/@mui/system/-/system-7.1.0.tgz#5ecc0248fc7a8f5af772b52297105fcd512f1f03"
1618
+ integrity sha512-iedAWgRJMCxeMHvkEhsDlbvkK+qKf9me6ofsf7twk/jfT4P1ImVf7Rwb5VubEA0sikrVL+1SkoZM41M4+LNAVA==
1619
+ dependencies:
1620
+ "@babel/runtime" "^7.27.1"
1621
+ "@mui/private-theming" "^7.1.0"
1622
+ "@mui/styled-engine" "^7.1.0"
1623
+ "@mui/types" "^7.4.2"
1624
+ "@mui/utils" "^7.1.0"
1625
+ clsx "^2.1.1"
1626
+ csstype "^3.1.3"
1627
+ prop-types "^15.8.1"
1628
+
1629
+ "@mui/types@^7.4.2":
1630
+ version "7.4.2"
1631
+ resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.4.2.tgz#fdeb9855a4968c360bcc998b9dba93e5f635b40f"
1632
+ integrity sha512-edRc5JcLPsrlNFYyTPxds+d5oUovuUxnnDtpJUbP6WMeV4+6eaX/mqai1ZIWT62lCOe0nlrON0s9HDiv5en5bA==
1633
+ dependencies:
1634
+ "@babel/runtime" "^7.27.1"
1635
+
1636
+ "@mui/utils@^7.0.2", "@mui/utils@^7.1.0":
1637
+ version "7.1.0"
1638
+ resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-7.1.0.tgz#464c0c1bc8f57c07d934ac674f3dcc81ac24f68b"
1639
+ integrity sha512-/OM3S8kSHHmWNOP+NH9xEtpYSG10upXeQ0wLZnfDgmgadTAk5F4MQfFLyZ5FCRJENB3eRzltMmaNl6UtDnPovw==
1640
+ dependencies:
1641
+ "@babel/runtime" "^7.27.1"
1642
+ "@mui/types" "^7.4.2"
1643
+ "@types/prop-types" "^15.7.14"
1644
+ clsx "^2.1.1"
1645
+ prop-types "^15.8.1"
1646
+ react-is "^19.1.0"
1647
+
1648
+ "@mui/x-internals@8.3.0":
1649
+ version "8.3.0"
1650
+ resolved "https://registry.yarnpkg.com/@mui/x-internals/-/x-internals-8.3.0.tgz#0255ad37dcf2451e3f01d6820391cf368b68b7b5"
1651
+ integrity sha512-wSVxg5aSO9xvJT7oarhsXqr03NeP355Whm7Qn6z3VvxdGwNc7K7vKpez3E+2KMxtdvywOmragwlSdTaO1K6qkg==
1652
+ dependencies:
1653
+ "@babel/runtime" "^7.27.1"
1654
+ "@mui/utils" "^7.0.2"
1655
+
1656
+ "@mui/x-tree-view@^8.3.0":
1657
+ version "8.3.0"
1658
+ resolved "https://registry.yarnpkg.com/@mui/x-tree-view/-/x-tree-view-8.3.0.tgz#eaf401af4f8d88809c5683f4216168ac050a62b3"
1659
+ integrity sha512-iK9xisIi0pYx8wMkY7C5o/eBQzOfSiy7Szpy8aNPaMO1mqTyYjVpv98fgQCkNsdluniqmFkLSnrN+W5xZEZqtQ==
1660
+ dependencies:
1661
+ "@babel/runtime" "^7.27.1"
1662
+ "@mui/utils" "^7.0.2"
1663
+ "@mui/x-internals" "8.3.0"
1664
+ "@types/react-transition-group" "^4.4.12"
1665
+ clsx "^2.1.1"
1666
+ prop-types "^15.8.1"
1667
+ react-transition-group "^4.4.5"
1668
+ reselect "^5.1.1"
1669
+ use-sync-external-store "^1.5.0"
1670
+
1509
1671
  "@nodelib/fs.scandir@2.1.5":
1510
1672
  version "2.1.5"
1511
1673
  resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
@@ -1823,11 +1985,21 @@
1823
1985
  resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.26.5.tgz#72499abbb4c4ec9982446509d2f14fb8483869d6"
1824
1986
  integrity sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==
1825
1987
 
1988
+ "@types/prop-types@^15.7.14":
1989
+ version "15.7.14"
1990
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.14.tgz#1433419d73b2a7ebfc6918dcefd2ec0d5cd698f2"
1991
+ integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==
1992
+
1826
1993
  "@types/react-dom@^19.0.3":
1827
1994
  version "19.1.2"
1828
1995
  resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.1.2.tgz#bd1fe3b8c28a3a2e942f85314dcfb71f531a242f"
1829
1996
  integrity sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==
1830
1997
 
1998
+ "@types/react-transition-group@^4.4.12":
1999
+ version "4.4.12"
2000
+ resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.12.tgz#b5d76568485b02a307238270bfe96cb51ee2a044"
2001
+ integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==
2002
+
1831
2003
  "@types/react@^19.0.7":
1832
2004
  version "19.1.2"
1833
2005
  resolved "https://registry.yarnpkg.com/@types/react/-/react-19.1.2.tgz#11df86f66f188f212c90ecb537327ec68bfd593f"
@@ -2435,7 +2607,7 @@ cssstyle@^2.3.0:
2435
2607
  dependencies:
2436
2608
  cssom "~0.3.6"
2437
2609
 
2438
- csstype@^3.0.2, csstype@^3.1.0:
2610
+ csstype@^3.0.2, csstype@^3.1.0, csstype@^3.1.3:
2439
2611
  version "3.1.3"
2440
2612
  resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
2441
2613
  integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
@@ -2506,6 +2678,14 @@ dom-accessibility-api@^0.6.3:
2506
2678
  resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8"
2507
2679
  integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==
2508
2680
 
2681
+ dom-helpers@^5.0.1:
2682
+ version "5.2.1"
2683
+ resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902"
2684
+ integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
2685
+ dependencies:
2686
+ "@babel/runtime" "^7.8.7"
2687
+ csstype "^3.0.2"
2688
+
2509
2689
  domexception@^4.0.0:
2510
2690
  version "4.0.0"
2511
2691
  resolved "https://registry.yarnpkg.com/domexception/-/domexception-4.0.0.tgz#4ad1be56ccadc86fc76d033353999a8037d03673"
@@ -3633,7 +3813,7 @@ jest@^29.7.0:
3633
3813
  import-local "^3.0.2"
3634
3814
  jest-cli "^29.7.0"
3635
3815
 
3636
- js-tokens@^4.0.0:
3816
+ "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
3637
3817
  version "4.0.0"
3638
3818
  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
3639
3819
  integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
@@ -3832,6 +4012,13 @@ lodash@^4.17.21:
3832
4012
  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
3833
4013
  integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
3834
4014
 
4015
+ loose-envify@^1.0.0, loose-envify@^1.4.0:
4016
+ version "1.4.0"
4017
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
4018
+ integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
4019
+ dependencies:
4020
+ js-tokens "^3.0.0 || ^4.0.0"
4021
+
3835
4022
  lru-cache@^5.1.1:
3836
4023
  version "5.1.1"
3837
4024
  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
@@ -4024,6 +4211,11 @@ nwsapi@^2.2.2:
4024
4211
  resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.20.tgz#22e53253c61e7b0e7e93cef42c891154bcca11ef"
4025
4212
  integrity sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==
4026
4213
 
4214
+ object-assign@^4.1.1:
4215
+ version "4.1.1"
4216
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
4217
+ integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
4218
+
4027
4219
  once@^1.3.0:
4028
4220
  version "1.4.0"
4029
4221
  resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -4205,6 +4397,15 @@ prompts@^2.0.1:
4205
4397
  kleur "^3.0.3"
4206
4398
  sisteransi "^1.0.5"
4207
4399
 
4400
+ prop-types@^15.6.2, prop-types@^15.8.1:
4401
+ version "15.8.1"
4402
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
4403
+ integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
4404
+ dependencies:
4405
+ loose-envify "^1.4.0"
4406
+ object-assign "^4.1.1"
4407
+ react-is "^16.13.1"
4408
+
4208
4409
  psl@^1.1.33:
4209
4410
  version "1.15.0"
4210
4411
  resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6"
@@ -4244,11 +4445,34 @@ react-dom@^19.0.0:
4244
4445
  dependencies:
4245
4446
  scheduler "^0.26.0"
4246
4447
 
4448
+ react-fast-compare@^3.0.1:
4449
+ version "3.2.2"
4450
+ resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49"
4451
+ integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==
4452
+
4453
+ react-is@^16.13.1:
4454
+ version "16.13.1"
4455
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
4456
+ integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
4457
+
4247
4458
  react-is@^18.0.0:
4248
4459
  version "18.3.1"
4249
4460
  resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
4250
4461
  integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
4251
4462
 
4463
+ react-is@^19.1.0:
4464
+ version "19.1.0"
4465
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-19.1.0.tgz#805bce321546b7e14c084989c77022351bbdd11b"
4466
+ integrity sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==
4467
+
4468
+ react-popper@^2.3.0:
4469
+ version "2.3.0"
4470
+ resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.3.0.tgz#17891c620e1320dce318bad9fede46a5f71c70ba"
4471
+ integrity sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==
4472
+ dependencies:
4473
+ react-fast-compare "^3.0.1"
4474
+ warning "^4.0.2"
4475
+
4252
4476
  react-refresh@^0.17.0:
4253
4477
  version "0.17.0"
4254
4478
  resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.17.0.tgz#b7e579c3657f23d04eccbe4ad2e58a8ed51e7e53"
@@ -4270,6 +4494,16 @@ react-router@7.5.3:
4270
4494
  set-cookie-parser "^2.6.0"
4271
4495
  turbo-stream "2.4.0"
4272
4496
 
4497
+ react-transition-group@^4.4.5:
4498
+ version "4.4.5"
4499
+ resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1"
4500
+ integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==
4501
+ dependencies:
4502
+ "@babel/runtime" "^7.5.5"
4503
+ dom-helpers "^5.0.1"
4504
+ loose-envify "^1.4.0"
4505
+ prop-types "^15.6.2"
4506
+
4273
4507
  react-virtuoso@^4.12.6:
4274
4508
  version "4.12.6"
4275
4509
  resolved "https://registry.yarnpkg.com/react-virtuoso/-/react-virtuoso-4.12.6.tgz#20fe374d43cce3c9821e29f4cc4d050596d06d01"
@@ -4346,6 +4580,11 @@ requires-port@^1.0.0:
4346
4580
  resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
4347
4581
  integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
4348
4582
 
4583
+ reselect@^5.1.1:
4584
+ version "5.1.1"
4585
+ resolved "https://registry.yarnpkg.com/reselect/-/reselect-5.1.1.tgz#c766b1eb5d558291e5e550298adb0becc24bb72e"
4586
+ integrity sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==
4587
+
4349
4588
  resolve-cwd@^3.0.0:
4350
4589
  version "3.0.0"
4351
4590
  resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
@@ -4582,6 +4821,11 @@ style-mod@^4.0.0, style-mod@^4.1.0:
4582
4821
  resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.1.2.tgz#ca238a1ad4786520f7515a8539d5a63691d7bf67"
4583
4822
  integrity sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==
4584
4823
 
4824
+ stylis@4.2.0:
4825
+ version "4.2.0"
4826
+ resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51"
4827
+ integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==
4828
+
4585
4829
  supports-color@^7.1.0:
4586
4830
  version "7.2.0"
4587
4831
  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
@@ -4780,6 +5024,18 @@ url-parse@^1.5.3:
4780
5024
  querystringify "^2.1.1"
4781
5025
  requires-port "^1.0.0"
4782
5026
 
5027
+ use-resize-observer@^9.1.0:
5028
+ version "9.1.0"
5029
+ resolved "https://registry.yarnpkg.com/use-resize-observer/-/use-resize-observer-9.1.0.tgz#14735235cf3268569c1ea468f8a90c5789fc5c6c"
5030
+ integrity sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==
5031
+ dependencies:
5032
+ "@juggle/resize-observer" "^3.3.1"
5033
+
5034
+ use-sync-external-store@^1.5.0:
5035
+ version "1.5.0"
5036
+ resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz#55122e2a3edd2a6c106174c27485e0fd59bcfca0"
5037
+ integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==
5038
+
4783
5039
  v8-to-istanbul@^9.0.1:
4784
5040
  version "9.3.0"
4785
5041
  resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175"
@@ -4819,6 +5075,13 @@ walker@^1.0.8:
4819
5075
  dependencies:
4820
5076
  makeerror "1.0.12"
4821
5077
 
5078
+ warning@^4.0.2:
5079
+ version "4.0.3"
5080
+ resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
5081
+ integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
5082
+ dependencies:
5083
+ loose-envify "^1.0.0"
5084
+
4822
5085
  webidl-conversions@^7.0.0:
4823
5086
  version "7.0.0"
4824
5087
  resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a"
@@ -4933,7 +5196,7 @@ yocto-queue@^0.1.0:
4933
5196
  resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
4934
5197
  integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
4935
5198
 
4936
- zustand@^5.0.3:
4937
- version "5.0.3"
4938
- resolved "https://registry.yarnpkg.com/zustand/-/zustand-5.0.3.tgz#b323435b73d06b2512e93c77239634374b0e407f"
4939
- integrity sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==
5199
+ zustand@^5.0.5:
5200
+ version "5.0.5"
5201
+ resolved "https://registry.yarnpkg.com/zustand/-/zustand-5.0.5.tgz#3e236f6a953142d975336d179bc735d97db17e84"
5202
+ integrity sha512-mILtRfKW9xM47hqxGIxCv12gXusoY/xTSHBYApXozR0HmQv299whhBeeAcRy+KrPPybzosvJBCOmVjq6x12fCg==
@@ -82,8 +82,9 @@ def react(
82
82
  the submit tool within the message. Alternatively, an async function
83
83
  to call to determine whether the loop should continue and what message
84
84
  to play back. Note that this function is called on _every_ iteration of
85
- the loop so if you only want to send a message back when the model fails
86
- to call tools you need to code that behavior explicitly.
85
+ the loop. If you return a `str` with a custom message it will be
86
+ sent to the model as a user message only in the case that no tool
87
+ calls were made.
87
88
  truncation: Truncate the conversation history in the event of a context
88
89
  window overflow. Defaults to "disabled" which does no truncation. Pass
89
90
  "auto" to use `trim_messages()` to reduce the context size. Pass a
@@ -245,11 +246,13 @@ def react(
245
246
  )
246
247
  )
247
248
  elif isinstance(do_continue, str):
248
- state.messages.append(
249
- ChatMessageUser(
250
- content=do_continue.format(submit=submit_tool.name)
249
+ # if there were no tool calls we need to send back the user message
250
+ if not state.output.message.tool_calls:
251
+ state.messages.append(
252
+ ChatMessageUser(
253
+ content=do_continue.format(submit=submit_tool.name)
254
+ )
251
255
  )
252
- )
253
256
  else: # do_continue is False
254
257
  break
255
258
 
@@ -327,7 +330,9 @@ def react_no_submit(
327
330
  if do_continue is True:
328
331
  do_continue = DEFAULT_CONTINUE_PROMOT_NO_SUBMIT
329
332
  if do_continue:
330
- state.messages.append(ChatMessageUser(content=do_continue))
333
+ # send back user message if there are no tool calls
334
+ if not state.output.message.tool_calls:
335
+ state.messages.append(ChatMessageUser(content=do_continue))
331
336
  else:
332
337
  break
333
338
  elif not state.output.message.tool_calls:
inspect_ai/agent/_run.py CHANGED
@@ -1,20 +1,43 @@
1
1
  from copy import copy
2
- from typing import Any
2
+ from typing import Any, overload
3
3
 
4
4
  from inspect_ai._util.registry import registry_unqualified_name
5
5
  from inspect_ai.model._chat_message import ChatMessage, ChatMessageUser
6
- from inspect_ai.util._limit import Limit, apply_limits
6
+ from inspect_ai.util._limit import Limit, LimitExceededError, apply_limits
7
7
  from inspect_ai.util._span import span
8
8
 
9
9
  from ._agent import Agent, AgentState
10
10
 
11
11
 
12
+ @overload
12
13
  async def run(
13
14
  agent: Agent,
14
15
  input: str | list[ChatMessage] | AgentState,
15
16
  limits: list[Limit] = [],
17
+ *,
18
+ name: str | None = None,
16
19
  **agent_kwargs: Any,
17
- ) -> AgentState:
20
+ ) -> tuple[AgentState, LimitExceededError | None]: ...
21
+
22
+
23
+ @overload
24
+ async def run(
25
+ agent: Agent,
26
+ input: str | list[ChatMessage] | AgentState,
27
+ *,
28
+ name: str | None = None,
29
+ **agent_kwargs: Any,
30
+ ) -> AgentState: ...
31
+
32
+
33
+ async def run(
34
+ agent: Agent,
35
+ input: str | list[ChatMessage] | AgentState,
36
+ limits: list[Limit] = [],
37
+ *,
38
+ name: str | None = None,
39
+ **agent_kwargs: Any,
40
+ ) -> AgentState | tuple[AgentState, LimitExceededError | None]:
18
41
  """Run an agent.
19
42
 
20
43
  The input messages(s) will be copied prior to running so are
@@ -23,13 +46,18 @@ async def run(
23
46
  Args:
24
47
  agent: Agent to run.
25
48
  input: Agent input (string, list of messages, or an `AgentState`).
26
- limits: List of limits to apply to the agent. Should a limit be
27
- exceeded, a LimitExceededError is raised which the caller may
28
- handle as appropriate.
49
+ limits: List of limits to apply to the agent. Should one of these limits be
50
+ exceeded, the `LimitExceededError` is caught and returned.
51
+ name: Optional display name for the transcript entry. If not provided, the
52
+ agent's name as defined in the registry will be used.
29
53
  **agent_kwargs: Additional arguments to pass to agent.
30
54
 
31
55
  Returns:
32
- AgentState: Messages and generated output.
56
+ AgentState: Messages and generated output. This is all that is returned if no
57
+ limits are supplied.
58
+ LimitExceededError | None: If a non-empty limits list is supplied, a tuple is
59
+ returned. If a limit was exceeded, the second value in the tuple is the
60
+ exception instance. If no limit was exceeded, the second element is None.
33
61
  """
34
62
  # copy input so we don't mutate it in place
35
63
  input = copy(input)
@@ -52,9 +80,16 @@ async def run(
52
80
  # create state
53
81
  state = AgentState(messages=input_messages)
54
82
 
55
- # run the agent with limits
56
- with apply_limits(limits):
83
+ # run the agent with limits, catching errors which are a direct result of our limits
84
+ with apply_limits(limits, catch_errors=True) as limit_scope:
57
85
  # run the agent
58
- agent_name = registry_unqualified_name(agent)
86
+ agent_name = name or registry_unqualified_name(agent)
59
87
  async with span(name=agent_name, type="agent"):
60
- return await agent(state, **agent_kwargs)
88
+ state = await agent(state, **agent_kwargs)
89
+ if limits:
90
+ return state, None
91
+ else:
92
+ return state
93
+
94
+ # execution reaches this point iff one of "our" limits was exceeded
95
+ return state, limit_scope.limit_error
@@ -356,26 +356,27 @@ def _read_samples_df_serial(
356
356
  details_table.drop_duplicates(
357
357
  f"{detail.name}_id", keep="first", inplace=True, ignore_index=True
358
358
  )
359
- samples_table = details_table.merge(
360
- samples_table,
361
- on=SAMPLE_ID,
362
- how="left",
363
- suffixes=(f"_{detail.name}", SAMPLE_SUFFIX),
364
- )
359
+ if len(details_table) > 0:
360
+ samples_table = details_table.merge(
361
+ samples_table,
362
+ on=SAMPLE_ID,
363
+ how="left",
364
+ suffixes=(f"_{detail.name}", SAMPLE_SUFFIX),
365
+ )
365
366
 
366
367
  # join eval_records
367
- samples_table = samples_table.merge(
368
- evals_table, on=EVAL_ID, how="left", suffixes=(SAMPLE_SUFFIX, EVAL_SUFFIX)
369
- )
370
-
371
- # re-order based on original specification
372
- samples_table = reorder_samples_df_columns(
373
- samples_table,
374
- columns_eval,
375
- columns_sample,
376
- columns_detail,
377
- detail.name if detail else "",
378
- )
368
+ if len(samples_table) > 0:
369
+ samples_table = samples_table.merge(
370
+ evals_table, on=EVAL_ID, how="left", suffixes=(SAMPLE_SUFFIX, EVAL_SUFFIX)
371
+ )
372
+ # re-order based on original specification
373
+ samples_table = reorder_samples_df_columns(
374
+ samples_table,
375
+ columns_eval,
376
+ columns_sample,
377
+ columns_detail,
378
+ detail.name if detail else "",
379
+ )
379
380
 
380
381
  # return
381
382
  if strict:
inspect_ai/log/_bundle.py CHANGED
@@ -146,7 +146,7 @@ def copy_log_files(
146
146
  log_fs = filesystem(log_dir, fs_options)
147
147
  if log_fs.exists(log_dir):
148
148
  eval_logs = log_files_from_ls(
149
- log_fs.ls(log_dir, recursive=True), ["json", "eval"], True
149
+ log_fs.ls(log_dir, recursive=True), ["json", "eval"], False
150
150
  )
151
151
  if len(eval_logs) == 0:
152
152
  raise PrerequisiteError(
@@ -201,8 +201,10 @@ def move_output(
201
201
  output_fs.mkdir(dir_path)
202
202
  tick()
203
203
 
204
- # Copy the files
205
- for working_file in files:
204
+ # Copy the files, preserving relative mtime ordering
205
+ for _, working_file in sorted(
206
+ (os.stat(os.path.join(root, f)).st_mtime, f) for f in files
207
+ ):
206
208
  target_path = (
207
209
  os.path.join(relative_dir, working_file)
208
210
  if relative_dir != "."
inspect_ai/log/_log.py CHANGED
@@ -158,14 +158,14 @@ class EvalConfig(BaseModel):
158
158
 
159
159
 
160
160
  class EvalSampleLimit(BaseModel):
161
- """Limit encontered by sample."""
161
+ """Limit encountered by sample."""
162
162
 
163
163
  type: Literal[
164
164
  "context", "time", "working", "message", "token", "operator", "custom"
165
165
  ]
166
166
  """The type of limit"""
167
167
 
168
- limit: int
168
+ limit: float
169
169
  """The limit value"""
170
170
 
171
171
 
@@ -694,7 +694,7 @@ class EvalSpec(BaseModel):
694
694
  task_id: str = Field(default_factory=str)
695
695
  """Unique task id."""
696
696
 
697
- task_version: int = Field(default=0)
697
+ task_version: int | str = Field(default=0)
698
698
  """Task version."""
699
699
 
700
700
  task_file: str | None = Field(default=None)
@@ -67,16 +67,9 @@ class FileRecorder(Recorder):
67
67
  async def read_log_sample_summaries(cls, location: str) -> list[EvalSampleSummary]:
68
68
  # establish the log to read from (might be cached)
69
69
  eval_log = await cls._log_file_maybe_cached(location)
70
-
71
- # throw if no samples
72
70
  if not eval_log.samples:
73
- raise IndexError(f"No samples found in log {location}")
74
-
75
- summaries: list[EvalSampleSummary] = []
76
- for sample in eval_log.samples:
77
- summaries.append(sample.summary())
78
-
79
- return summaries
71
+ return []
72
+ return [sample.summary() for sample in eval_log.samples]
80
73
 
81
74
  @classmethod
82
75
  async def _log_file_maybe_cached(cls, location: str) -> EvalLog:
@@ -111,7 +111,7 @@ class SampleLimitEvent(BaseEvent):
111
111
  message: str
112
112
  """A message associated with this limit"""
113
113
 
114
- limit: int | None = Field(default=None)
114
+ limit: float | None = Field(default=None)
115
115
  """The limit value (if any)"""
116
116
 
117
117