superacli 1.1.5 → 1.1.7

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 (1081) hide show
  1. package/README.md +77 -53
  2. package/__tests__/azd-plugin.test.js +109 -0
  3. package/__tests__/config.test.js +4 -3
  4. package/__tests__/discover.test.js +59 -0
  5. package/__tests__/goose-plugin.test.js +149 -0
  6. package/__tests__/help-json.test.js +2 -0
  7. package/__tests__/openhands-plugin.test.js +106 -0
  8. package/__tests__/plugin-cocoindex-code-uninstall.test.js +19 -0
  9. package/__tests__/plugin-cocoindex-code.test.js +37 -0
  10. package/__tests__/plugin-install-guidance.test.js +81 -0
  11. package/__tests__/plugins-registry.test.js +44 -0
  12. package/__tests__/plugins-store.test.js +40 -5
  13. package/__tests__/process-adapter.test.js +50 -1
  14. package/__tests__/resend-plugin.test.js +22 -1
  15. package/__tests__/server-app.test.js +1 -0
  16. package/__tests__/server-routes-commands.test.js +20 -2
  17. package/__tests__/server-routes-plugins.test.js +130 -0
  18. package/__tests__/skills.test.js +26 -0
  19. package/__tests__/squirrelscan-plugin.test.js +129 -0
  20. package/__tests__/uipath-plugin.test.js +104 -0
  21. package/__tests__/uipathcli-plugin.test.js +95 -0
  22. package/cli/adapters/mcp.js +2 -0
  23. package/cli/adapters/process.js +49 -2
  24. package/cli/config.js +240 -3
  25. package/cli/discover.js +157 -0
  26. package/cli/help-json.js +16 -1
  27. package/cli/plugin-install-guidance.js +92 -37
  28. package/cli/plugins-manager.js +1 -0
  29. package/cli/plugins-registry.js +74 -8
  30. package/cli/plugins-store.js +78 -17
  31. package/cli/skills-mcp.js +1 -1
  32. package/cli/skills.js +39 -2
  33. package/cli/supercli.js +87 -11
  34. package/docs/feature-gaps.md +8 -8
  35. package/docs/features/azd-uipath-plugins.md +43 -0
  36. package/docs/features/server-plugins.md +62 -0
  37. package/docs/features/skills.md +9 -5
  38. package/docs/{supported-harnesses.md → plugins-available.md} +4 -3
  39. package/docs/{plugin-harness-guide.md → plugins-how-to.md} +1 -1
  40. package/docs/plugins.md +26 -20
  41. package/docs/server-plugins-usage-guide.md +182 -0
  42. package/docs/skills-catalog.md +12 -10
  43. package/package.json +1 -1
  44. package/plugins/agent-browser/README.md +69 -0
  45. package/plugins/agent-browser/plugin.json +111 -0
  46. package/plugins/agent-browser/skills/quickstart/SKILL.md +66 -0
  47. package/plugins/aider/README.md +53 -0
  48. package/plugins/aider/plugin.json +105 -0
  49. package/plugins/aider/scripts/aider-wrapper.js +243 -0
  50. package/plugins/aider/scripts/setup-aider.js +37 -0
  51. package/plugins/aider/skills/dry-run-review.md +24 -0
  52. package/plugins/aider/skills/model-and-provider.md +24 -0
  53. package/plugins/aider/skills/one-shot-edits.md +30 -0
  54. package/plugins/aider/skills/quickstart/SKILL.md +51 -0
  55. package/plugins/azd/README.md +28 -0
  56. package/plugins/azd/plugin.json +87 -0
  57. package/plugins/azd/skills/quickstart/SKILL.md +41 -0
  58. package/plugins/blogwatcher/README.md +3 -3
  59. package/plugins/boxlite/Dockerfile +9 -0
  60. package/plugins/boxlite/README.md +62 -0
  61. package/plugins/boxlite/plugin.json +201 -0
  62. package/plugins/boxlite/scripts/run-boxlite.js +106 -0
  63. package/plugins/boxlite/skills/quickstart/SKILL.md +40 -0
  64. package/plugins/cass/plugin.json +150 -0
  65. package/plugins/cass/scripts/setup-cass.js +47 -0
  66. package/plugins/cass/skills/quickstart/SKILL.md +46 -0
  67. package/plugins/clever/README.md +46 -0
  68. package/plugins/clever/plugin.json +119 -0
  69. package/plugins/clever/scripts/setup-clever.js +28 -0
  70. package/plugins/clever/skills/auth-and-profile.md +29 -0
  71. package/plugins/clever/skills/passthrough-safety.md +21 -0
  72. package/plugins/clever/skills/quickstart/SKILL.md +45 -0
  73. package/plugins/clever/skills/resource-inventory.md +24 -0
  74. package/plugins/clix/README.md +4 -4
  75. package/plugins/cocoindex-code/README.md +64 -0
  76. package/plugins/cocoindex-code/plugin.json +81 -0
  77. package/plugins/cocoindex-code/scripts/__pycache__/query.cpython-310.pyc +0 -0
  78. package/plugins/cocoindex-code/scripts/__pycache__/query.cpython-311.pyc +0 -0
  79. package/plugins/cocoindex-code/scripts/post-install.js +61 -0
  80. package/plugins/cocoindex-code/scripts/post-uninstall.js +25 -0
  81. package/plugins/cocoindex-code/scripts/query.py +88 -0
  82. package/plugins/cocoindex-code/scripts/run-query.js +50 -0
  83. package/plugins/cocoindex-code/skills/quickstart/SKILL.md +73 -0
  84. package/plugins/copilot/README.md +24 -0
  85. package/plugins/copilot/plugin.json +80 -0
  86. package/plugins/copilot/skills/quickstart/SKILL.md +44 -0
  87. package/plugins/gemini/README.md +24 -0
  88. package/plugins/gemini/plugin.json +98 -0
  89. package/plugins/gemini/skills/quickstart/SKILL.md +44 -0
  90. package/plugins/gifcap/plugin.json +119 -0
  91. package/plugins/gifcap/scripts/setup-gifcap.js +44 -0
  92. package/plugins/gifcap/skills/quickstart/SKILL.md +34 -0
  93. package/plugins/gifcap/test-record-quiet.gif +0 -0
  94. package/plugins/gifcap/test-record.gif +0 -0
  95. package/plugins/goose/README.md +36 -0
  96. package/plugins/goose/plugin.json +183 -0
  97. package/plugins/goose/skills/quickstart/SKILL.md +44 -0
  98. package/plugins/json-server/README.md +58 -0
  99. package/plugins/json-server/plugin.json +113 -0
  100. package/plugins/json-server/skills/quickstart/SKILL.md +57 -0
  101. package/plugins/lightpanda/README.md +145 -0
  102. package/plugins/lightpanda/package-lock.json +1375 -0
  103. package/plugins/lightpanda/package.json +12 -0
  104. package/plugins/lightpanda/plugin.json +116 -0
  105. package/plugins/lightpanda/scripts/lightpanda-contacts.js +494 -0
  106. package/plugins/lightpanda/scripts/lightpanda-generic-extract.js +403 -0
  107. package/plugins/lightpanda/scripts/lightpanda-wrapper.js +480 -0
  108. package/plugins/lightpanda/scripts/setup-lightpanda.js +39 -0
  109. package/plugins/lightpanda/skills/contact-discovery.md +51 -0
  110. package/plugins/lightpanda/skills/generic-extraction.md +66 -0
  111. package/plugins/lightpanda/skills/quickstart/SKILL.md +103 -0
  112. package/plugins/lightpanda/skills/resilient-navigation.md +42 -0
  113. package/plugins/monty/README.md +2 -2
  114. package/plugins/nullclaw/README.md +3 -3
  115. package/plugins/offline-ai/README.md +23 -0
  116. package/plugins/offline-ai/plugin.json +82 -0
  117. package/plugins/offline-ai/skills/quickstart/SKILL.md +43 -0
  118. package/plugins/openhands/README.md +25 -0
  119. package/plugins/openhands/plugin.json +116 -0
  120. package/plugins/openhands/skills/quickstart/SKILL.md +26 -0
  121. package/plugins/plandex/README.md +25 -0
  122. package/plugins/plandex/plugin.json +130 -0
  123. package/plugins/plandex/skills/quickstart/SKILL.md +50 -0
  124. package/plugins/plugins.json +190 -2
  125. package/plugins/resend/plugin.json +279 -2
  126. package/plugins/resend/skills/quickstart/SKILL.md +32 -13
  127. package/plugins/squirrelscan/Dockerfile +5 -0
  128. package/plugins/squirrelscan/README.md +47 -0
  129. package/plugins/squirrelscan/plugin.json +493 -0
  130. package/plugins/squirrelscan/scripts/post-install.js +33 -0
  131. package/plugins/squirrelscan/scripts/post-uninstall.js +25 -0
  132. package/plugins/squirrelscan/scripts/run-squirrel.js +73 -0
  133. package/plugins/squirrelscan/skills/audit-workflow/SKILL.md +33 -0
  134. package/plugins/squirrelscan/skills/publish-report/SKILL.md +33 -0
  135. package/plugins/squirrelscan/skills/quickstart/SKILL.md +41 -0
  136. package/plugins/uipath/README.md +27 -0
  137. package/plugins/uipath/plugin.json +86 -0
  138. package/plugins/uipath/skills/quickstart/SKILL.md +47 -0
  139. package/plugins/uipathcli/README.md +28 -0
  140. package/plugins/uipathcli/plugin.json +120 -0
  141. package/plugins/uipathcli/scripts/run-uipath-cli.js +49 -0
  142. package/plugins/uipathcli/skills/quickstart/SKILL.md +22 -0
  143. package/plugins/xurl/README.md +4 -4
  144. package/server/app.js +5 -2
  145. package/server/public/app.js +3 -0
  146. package/server/routes/commands.js +95 -12
  147. package/server/routes/plugins.js +262 -0
  148. package/server/services/pluginsService.js +303 -0
  149. package/server/views/command-edit.ejs +196 -14
  150. package/server/views/partials/head.ejs +1 -0
  151. package/server/views/plugins.ejs +264 -0
  152. package/tests/test-plugins-registry.js +30 -0
  153. package/tests/test-resend-smoke.sh +7 -3
  154. package/.beads/.br_history/issues.20260308_200823_636718328.jsonl +0 -20
  155. package/.beads/.br_history/issues.20260308_200823_636718328.jsonl.meta.json +0 -1
  156. package/.beads/.br_history/issues.20260308_200827_033159453.jsonl +0 -21
  157. package/.beads/.br_history/issues.20260308_200827_033159453.jsonl.meta.json +0 -1
  158. package/.beads/.br_history/issues.20260308_200829_595900053.jsonl +0 -22
  159. package/.beads/.br_history/issues.20260308_200829_595900053.jsonl.meta.json +0 -1
  160. package/.beads/.br_history/issues.20260308_200834_079930100.jsonl +0 -23
  161. package/.beads/.br_history/issues.20260308_200834_079930100.jsonl.meta.json +0 -1
  162. package/.beads/.br_history/issues.20260308_200858_370924996.jsonl +0 -24
  163. package/.beads/.br_history/issues.20260308_200858_370924996.jsonl.meta.json +0 -1
  164. package/.beads/.br_history/issues.20260308_201031_019730855.jsonl +0 -24
  165. package/.beads/.br_history/issues.20260308_201031_019730855.jsonl.meta.json +0 -1
  166. package/.beads/.br_history/issues.20260308_201031_578974884.jsonl +0 -24
  167. package/.beads/.br_history/issues.20260308_201031_578974884.jsonl.meta.json +0 -1
  168. package/.beads/.br_history/issues.20260308_201054_780345548.jsonl +0 -24
  169. package/.beads/.br_history/issues.20260308_201054_780345548.jsonl.meta.json +0 -1
  170. package/.beads/.br_history/issues.20260308_201054_896980019.jsonl +0 -24
  171. package/.beads/.br_history/issues.20260308_201054_896980019.jsonl.meta.json +0 -1
  172. package/.beads/.br_history/issues.20260308_201128_599819688.jsonl +0 -24
  173. package/.beads/.br_history/issues.20260308_201128_599819688.jsonl.meta.json +0 -1
  174. package/.beads/.br_history/issues.20260308_201128_710221699.jsonl +0 -24
  175. package/.beads/.br_history/issues.20260308_201128_710221699.jsonl.meta.json +0 -1
  176. package/.beads/.br_history/issues.20260308_201204_745649213.jsonl +0 -24
  177. package/.beads/.br_history/issues.20260308_201204_745649213.jsonl.meta.json +0 -1
  178. package/.beads/.br_history/issues.20260308_201338_908436144.jsonl +0 -24
  179. package/.beads/.br_history/issues.20260308_201338_908436144.jsonl.meta.json +0 -1
  180. package/.beads/.br_history/issues.20260308_201344_734860714.jsonl +0 -25
  181. package/.beads/.br_history/issues.20260308_201344_734860714.jsonl.meta.json +0 -1
  182. package/.beads/.br_history/issues.20260308_201630_819282295.jsonl +0 -25
  183. package/.beads/.br_history/issues.20260308_201630_819282295.jsonl.meta.json +0 -1
  184. package/.beads/.br_history/issues.20260308_203538_054279699.jsonl +0 -25
  185. package/.beads/.br_history/issues.20260308_203538_054279699.jsonl.meta.json +0 -1
  186. package/.beads/.br_history/issues.20260308_203547_597113070.jsonl +0 -26
  187. package/.beads/.br_history/issues.20260308_203547_597113070.jsonl.meta.json +0 -1
  188. package/.beads/.br_history/issues.20260308_203547_775139216.jsonl +0 -27
  189. package/.beads/.br_history/issues.20260308_203547_775139216.jsonl.meta.json +0 -1
  190. package/.beads/.br_history/issues.20260308_203547_950724773.jsonl +0 -28
  191. package/.beads/.br_history/issues.20260308_203547_950724773.jsonl.meta.json +0 -1
  192. package/.beads/.br_history/issues.20260308_203548_107684523.jsonl +0 -29
  193. package/.beads/.br_history/issues.20260308_203548_107684523.jsonl.meta.json +0 -1
  194. package/.beads/.br_history/issues.20260308_203548_310389993.jsonl +0 -30
  195. package/.beads/.br_history/issues.20260308_203548_310389993.jsonl.meta.json +0 -1
  196. package/.beads/.br_history/issues.20260308_203825_953337320.jsonl +0 -31
  197. package/.beads/.br_history/issues.20260308_203825_953337320.jsonl.meta.json +0 -1
  198. package/.beads/.br_history/issues.20260308_204056_071377736.jsonl +0 -32
  199. package/.beads/.br_history/issues.20260308_204056_071377736.jsonl.meta.json +0 -1
  200. package/.beads/.br_history/issues.20260308_205141_517616844.jsonl +0 -32
  201. package/.beads/.br_history/issues.20260308_205141_517616844.jsonl.meta.json +0 -1
  202. package/.beads/.br_history/issues.20260308_205141_648994024.jsonl +0 -32
  203. package/.beads/.br_history/issues.20260308_205141_648994024.jsonl.meta.json +0 -1
  204. package/.beads/.br_history/issues.20260308_205141_867598036.jsonl +0 -32
  205. package/.beads/.br_history/issues.20260308_205141_867598036.jsonl.meta.json +0 -1
  206. package/.beads/.br_history/issues.20260308_205142_094157355.jsonl +0 -32
  207. package/.beads/.br_history/issues.20260308_205142_094157355.jsonl.meta.json +0 -1
  208. package/.beads/.br_history/issues.20260308_205142_327315677.jsonl +0 -32
  209. package/.beads/.br_history/issues.20260308_205142_327315677.jsonl.meta.json +0 -1
  210. package/.beads/.br_history/issues.20260308_205142_545563822.jsonl +0 -32
  211. package/.beads/.br_history/issues.20260308_205142_545563822.jsonl.meta.json +0 -1
  212. package/.beads/.br_history/issues.20260308_205213_061989333.jsonl +0 -32
  213. package/.beads/.br_history/issues.20260308_205213_061989333.jsonl.meta.json +0 -1
  214. package/.beads/.br_history/issues.20260308_205213_181103364.jsonl +0 -32
  215. package/.beads/.br_history/issues.20260308_205213_181103364.jsonl.meta.json +0 -1
  216. package/.beads/.br_history/issues.20260308_205213_408872234.jsonl +0 -32
  217. package/.beads/.br_history/issues.20260308_205213_408872234.jsonl.meta.json +0 -1
  218. package/.beads/.br_history/issues.20260308_205213_616681652.jsonl +0 -32
  219. package/.beads/.br_history/issues.20260308_205213_616681652.jsonl.meta.json +0 -1
  220. package/.beads/.br_history/issues.20260308_205213_821507069.jsonl +0 -32
  221. package/.beads/.br_history/issues.20260308_205213_821507069.jsonl.meta.json +0 -1
  222. package/.beads/.br_history/issues.20260308_205214_026661112.jsonl +0 -32
  223. package/.beads/.br_history/issues.20260308_205214_026661112.jsonl.meta.json +0 -1
  224. package/.beads/.br_history/issues.20260308_205454_955250554.jsonl +0 -32
  225. package/.beads/.br_history/issues.20260308_205454_955250554.jsonl.meta.json +0 -1
  226. package/.beads/.br_history/issues.20260308_205556_337800392.jsonl +0 -33
  227. package/.beads/.br_history/issues.20260308_205556_337800392.jsonl.meta.json +0 -1
  228. package/.beads/.br_history/issues.20260308_205824_274686694.jsonl +0 -33
  229. package/.beads/.br_history/issues.20260308_205824_274686694.jsonl.meta.json +0 -1
  230. package/.beads/.br_history/issues.20260308_210240_583768328.jsonl +0 -34
  231. package/.beads/.br_history/issues.20260308_210240_583768328.jsonl.meta.json +0 -1
  232. package/.beads/.br_history/issues.20260308_212223_641541494.jsonl +0 -34
  233. package/.beads/.br_history/issues.20260308_212223_641541494.jsonl.meta.json +0 -1
  234. package/.beads/.br_history/issues.20260308_212227_735550996.jsonl +0 -35
  235. package/.beads/.br_history/issues.20260308_212227_735550996.jsonl.meta.json +0 -1
  236. package/.beads/.br_history/issues.20260308_212232_547298548.jsonl +0 -36
  237. package/.beads/.br_history/issues.20260308_212232_547298548.jsonl.meta.json +0 -1
  238. package/.beads/.br_history/issues.20260308_212528_843628125.jsonl +0 -37
  239. package/.beads/.br_history/issues.20260308_212528_843628125.jsonl.meta.json +0 -1
  240. package/.beads/.br_history/issues.20260308_212529_094530502.jsonl +0 -38
  241. package/.beads/.br_history/issues.20260308_212529_094530502.jsonl.meta.json +0 -1
  242. package/.beads/.br_history/issues.20260308_212529_331000853.jsonl +0 -39
  243. package/.beads/.br_history/issues.20260308_212529_331000853.jsonl.meta.json +0 -1
  244. package/.beads/.br_history/issues.20260308_212529_587925652.jsonl +0 -40
  245. package/.beads/.br_history/issues.20260308_212529_587925652.jsonl.meta.json +0 -1
  246. package/.beads/.br_history/issues.20260308_212804_927764103.jsonl +0 -41
  247. package/.beads/.br_history/issues.20260308_212804_927764103.jsonl.meta.json +0 -1
  248. package/.beads/.br_history/issues.20260308_212805_153673453.jsonl +0 -42
  249. package/.beads/.br_history/issues.20260308_212805_153673453.jsonl.meta.json +0 -1
  250. package/.beads/.br_history/issues.20260308_212805_415982363.jsonl +0 -43
  251. package/.beads/.br_history/issues.20260308_212805_415982363.jsonl.meta.json +0 -1
  252. package/.beads/.br_history/issues.20260308_212805_657497741.jsonl +0 -44
  253. package/.beads/.br_history/issues.20260308_212805_657497741.jsonl.meta.json +0 -1
  254. package/.beads/.br_history/issues.20260308_212805_952838724.jsonl +0 -45
  255. package/.beads/.br_history/issues.20260308_212805_952838724.jsonl.meta.json +0 -1
  256. package/.beads/.br_history/issues.20260308_212806_325433779.jsonl +0 -46
  257. package/.beads/.br_history/issues.20260308_212806_325433779.jsonl.meta.json +0 -1
  258. package/.beads/.br_history/issues.20260308_212806_584685598.jsonl +0 -47
  259. package/.beads/.br_history/issues.20260308_212806_584685598.jsonl.meta.json +0 -1
  260. package/.beads/.br_history/issues.20260308_212806_827817208.jsonl +0 -48
  261. package/.beads/.br_history/issues.20260308_212806_827817208.jsonl.meta.json +0 -1
  262. package/.beads/.br_history/issues.20260308_212807_111320451.jsonl +0 -49
  263. package/.beads/.br_history/issues.20260308_212807_111320451.jsonl.meta.json +0 -1
  264. package/.beads/.br_history/issues.20260308_212807_409545536.jsonl +0 -50
  265. package/.beads/.br_history/issues.20260308_212807_409545536.jsonl.meta.json +0 -1
  266. package/.beads/.br_history/issues.20260308_212807_625063294.jsonl +0 -51
  267. package/.beads/.br_history/issues.20260308_212807_625063294.jsonl.meta.json +0 -1
  268. package/.beads/.br_history/issues.20260308_212807_843906551.jsonl +0 -52
  269. package/.beads/.br_history/issues.20260308_212807_843906551.jsonl.meta.json +0 -1
  270. package/.beads/.br_history/issues.20260308_212808_100304073.jsonl +0 -53
  271. package/.beads/.br_history/issues.20260308_212808_100304073.jsonl.meta.json +0 -1
  272. package/.beads/.br_history/issues.20260308_212808_324723976.jsonl +0 -54
  273. package/.beads/.br_history/issues.20260308_212808_324723976.jsonl.meta.json +0 -1
  274. package/.beads/.br_history/issues.20260308_212808_557513104.jsonl +0 -55
  275. package/.beads/.br_history/issues.20260308_212808_557513104.jsonl.meta.json +0 -1
  276. package/.beads/.br_history/issues.20260308_212808_788048322.jsonl +0 -56
  277. package/.beads/.br_history/issues.20260308_212808_788048322.jsonl.meta.json +0 -1
  278. package/.beads/.br_history/issues.20260308_213702_613249728.jsonl +0 -57
  279. package/.beads/.br_history/issues.20260308_213702_613249728.jsonl.meta.json +0 -1
  280. package/.beads/.br_history/issues.20260308_213715_115792063.jsonl +0 -57
  281. package/.beads/.br_history/issues.20260308_213715_115792063.jsonl.meta.json +0 -1
  282. package/.beads/.br_history/issues.20260308_213715_462220666.jsonl +0 -57
  283. package/.beads/.br_history/issues.20260308_213715_462220666.jsonl.meta.json +0 -1
  284. package/.beads/.br_history/issues.20260308_213727_191258923.jsonl +0 -57
  285. package/.beads/.br_history/issues.20260308_213727_191258923.jsonl.meta.json +0 -1
  286. package/.beads/.br_history/issues.20260308_213727_684383652.jsonl +0 -57
  287. package/.beads/.br_history/issues.20260308_213727_684383652.jsonl.meta.json +0 -1
  288. package/.beads/.br_history/issues.20260308_213735_751882991.jsonl +0 -57
  289. package/.beads/.br_history/issues.20260308_213735_751882991.jsonl.meta.json +0 -1
  290. package/.beads/.br_history/issues.20260308_222052_279844960.jsonl +0 -57
  291. package/.beads/.br_history/issues.20260308_222052_279844960.jsonl.meta.json +0 -1
  292. package/.beads/.br_history/issues.20260308_222056_873282114.jsonl +0 -57
  293. package/.beads/.br_history/issues.20260308_222056_873282114.jsonl.meta.json +0 -1
  294. package/.beads/.br_history/issues.20260308_222103_402410761.jsonl +0 -57
  295. package/.beads/.br_history/issues.20260308_222103_402410761.jsonl.meta.json +0 -1
  296. package/.beads/.br_history/issues.20260308_235202_180577215.jsonl +0 -57
  297. package/.beads/.br_history/issues.20260308_235202_180577215.jsonl.meta.json +0 -1
  298. package/.beads/.br_history/issues.20260308_235202_387414163.jsonl +0 -57
  299. package/.beads/.br_history/issues.20260308_235202_387414163.jsonl.meta.json +0 -1
  300. package/.beads/.br_history/issues.20260308_235202_564422794.jsonl +0 -57
  301. package/.beads/.br_history/issues.20260308_235202_564422794.jsonl.meta.json +0 -1
  302. package/.beads/.br_history/issues.20260308_235202_742600597.jsonl +0 -57
  303. package/.beads/.br_history/issues.20260308_235202_742600597.jsonl.meta.json +0 -1
  304. package/.beads/.br_history/issues.20260308_235208_133360069.jsonl +0 -57
  305. package/.beads/.br_history/issues.20260308_235208_133360069.jsonl.meta.json +0 -1
  306. package/.beads/.br_history/issues.20260308_235505_473406307.jsonl +0 -57
  307. package/.beads/.br_history/issues.20260308_235505_473406307.jsonl.meta.json +0 -1
  308. package/.beads/.br_history/issues.20260308_235505_662360489.jsonl +0 -57
  309. package/.beads/.br_history/issues.20260308_235505_662360489.jsonl.meta.json +0 -1
  310. package/.beads/.br_history/issues.20260308_235505_843935624.jsonl +0 -57
  311. package/.beads/.br_history/issues.20260308_235505_843935624.jsonl.meta.json +0 -1
  312. package/.beads/.br_history/issues.20260308_235506_044530221.jsonl +0 -57
  313. package/.beads/.br_history/issues.20260308_235506_044530221.jsonl.meta.json +0 -1
  314. package/.beads/.br_history/issues.20260309_002618_115728731.jsonl +0 -57
  315. package/.beads/.br_history/issues.20260309_002618_115728731.jsonl.meta.json +0 -1
  316. package/.beads/.br_history/issues.20260309_003748_878174586.jsonl +0 -57
  317. package/.beads/.br_history/issues.20260309_003748_878174586.jsonl.meta.json +0 -1
  318. package/.beads/.br_history/issues.20260309_004057_868755623.jsonl +0 -57
  319. package/.beads/.br_history/issues.20260309_004057_868755623.jsonl.meta.json +0 -1
  320. package/.beads/.br_history/issues.20260309_004058_512842163.jsonl +0 -57
  321. package/.beads/.br_history/issues.20260309_004058_512842163.jsonl.meta.json +0 -1
  322. package/.beads/.br_history/issues.20260309_004058_994445226.jsonl +0 -57
  323. package/.beads/.br_history/issues.20260309_004058_994445226.jsonl.meta.json +0 -1
  324. package/.beads/.br_history/issues.20260309_004059_475988596.jsonl +0 -57
  325. package/.beads/.br_history/issues.20260309_004059_475988596.jsonl.meta.json +0 -1
  326. package/.beads/.br_history/issues.20260309_161902_566857851.jsonl +0 -57
  327. package/.beads/.br_history/issues.20260309_161902_566857851.jsonl.meta.json +0 -1
  328. package/.beads/.br_history/issues.20260309_170512_277017739.jsonl +0 -57
  329. package/.beads/.br_history/issues.20260309_170512_277017739.jsonl.meta.json +0 -1
  330. package/.beads/.br_history/issues.20260309_170512_477876921.jsonl +0 -57
  331. package/.beads/.br_history/issues.20260309_170512_477876921.jsonl.meta.json +0 -1
  332. package/.beads/.br_history/issues.20260309_170512_664382701.jsonl +0 -57
  333. package/.beads/.br_history/issues.20260309_170512_664382701.jsonl.meta.json +0 -1
  334. package/.beads/.br_history/issues.20260309_170512_859400333.jsonl +0 -57
  335. package/.beads/.br_history/issues.20260309_170512_859400333.jsonl.meta.json +0 -1
  336. package/.beads/.br_history/issues.20260309_212326_082771164.jsonl +0 -57
  337. package/.beads/.br_history/issues.20260309_212326_082771164.jsonl.meta.json +0 -1
  338. package/.beads/.br_history/issues.20260309_212326_245619716.jsonl +0 -58
  339. package/.beads/.br_history/issues.20260309_212326_245619716.jsonl.meta.json +0 -1
  340. package/.beads/.br_history/issues.20260309_212326_403198317.jsonl +0 -59
  341. package/.beads/.br_history/issues.20260309_212326_403198317.jsonl.meta.json +0 -1
  342. package/.beads/.br_history/issues.20260309_212332_539197678.jsonl +0 -60
  343. package/.beads/.br_history/issues.20260309_212332_539197678.jsonl.meta.json +0 -1
  344. package/.beads/.br_history/issues.20260309_212332_731373599.jsonl +0 -60
  345. package/.beads/.br_history/issues.20260309_212332_731373599.jsonl.meta.json +0 -1
  346. package/.beads/.br_history/issues.20260309_212332_928710953.jsonl +0 -60
  347. package/.beads/.br_history/issues.20260309_212332_928710953.jsonl.meta.json +0 -1
  348. package/.beads/.br_history/issues.20260309_213021_341505240.jsonl +0 -60
  349. package/.beads/.br_history/issues.20260309_213021_341505240.jsonl.meta.json +0 -1
  350. package/.beads/.br_history/issues.20260309_213022_023136934.jsonl +0 -60
  351. package/.beads/.br_history/issues.20260309_213022_023136934.jsonl.meta.json +0 -1
  352. package/.beads/.br_history/issues.20260309_213022_400050719.jsonl +0 -60
  353. package/.beads/.br_history/issues.20260309_213022_400050719.jsonl.meta.json +0 -1
  354. package/.beads/config.yaml +0 -4
  355. package/.beads/issues.jsonl +0 -60
  356. package/.beads/metadata.json +0 -4
  357. package/docs/mcp-cheatsheet.md +0 -324
  358. package/docs/visual-overview.md +0 -21
  359. package/ref-monty/.cargo/config.toml +0 -3
  360. package/ref-monty/.claude/settings.json +0 -60
  361. package/ref-monty/.claude/skills/fastmod/SKILL.md +0 -22
  362. package/ref-monty/.claude/skills/python-playground/SKILL.md +0 -47
  363. package/ref-monty/.codecov.yml +0 -12
  364. package/ref-monty/.github/actions/build-pgo-wheel/action.yml +0 -72
  365. package/ref-monty/.github/workflows/ci.yml +0 -776
  366. package/ref-monty/.github/workflows/codspeed.yml +0 -45
  367. package/ref-monty/.github/workflows/init-npm-packages.yml +0 -82
  368. package/ref-monty/.pre-commit-config.yaml +0 -47
  369. package/ref-monty/.python-version +0 -1
  370. package/ref-monty/.rustfmt.toml +0 -4
  371. package/ref-monty/.zed/settings.json +0 -11
  372. package/ref-monty/CLAUDE.md +0 -535
  373. package/ref-monty/Cargo.lock +0 -3798
  374. package/ref-monty/Cargo.toml +0 -87
  375. package/ref-monty/LICENSE +0 -21
  376. package/ref-monty/Makefile +0 -216
  377. package/ref-monty/README.md +0 -430
  378. package/ref-monty/RELEASING.md +0 -47
  379. package/ref-monty/crates/fuzz/Cargo.toml +0 -30
  380. package/ref-monty/crates/fuzz/fuzz_targets/string_input_panic.rs +0 -37
  381. package/ref-monty/crates/fuzz/fuzz_targets/tokens_input_panic.rs +0 -552
  382. package/ref-monty/crates/monty/Cargo.toml +0 -68
  383. package/ref-monty/crates/monty/benches/main.rs +0 -247
  384. package/ref-monty/crates/monty/build.rs +0 -10
  385. package/ref-monty/crates/monty/src/args.rs +0 -733
  386. package/ref-monty/crates/monty/src/asyncio.rs +0 -179
  387. package/ref-monty/crates/monty/src/builtins/abs.rs +0 -55
  388. package/ref-monty/crates/monty/src/builtins/all.rs +0 -30
  389. package/ref-monty/crates/monty/src/builtins/any.rs +0 -30
  390. package/ref-monty/crates/monty/src/builtins/bin.rs +0 -59
  391. package/ref-monty/crates/monty/src/builtins/chr.rs +0 -46
  392. package/ref-monty/crates/monty/src/builtins/divmod.rs +0 -164
  393. package/ref-monty/crates/monty/src/builtins/enumerate.rs +0 -52
  394. package/ref-monty/crates/monty/src/builtins/filter.rs +0 -67
  395. package/ref-monty/crates/monty/src/builtins/getattr.rs +0 -65
  396. package/ref-monty/crates/monty/src/builtins/hash.rs +0 -28
  397. package/ref-monty/crates/monty/src/builtins/hex.rs +0 -58
  398. package/ref-monty/crates/monty/src/builtins/id.rs +0 -24
  399. package/ref-monty/crates/monty/src/builtins/isinstance.rs +0 -68
  400. package/ref-monty/crates/monty/src/builtins/len.rs +0 -25
  401. package/ref-monty/crates/monty/src/builtins/map.rs +0 -98
  402. package/ref-monty/crates/monty/src/builtins/min_max.rs +0 -113
  403. package/ref-monty/crates/monty/src/builtins/mod.rs +0 -246
  404. package/ref-monty/crates/monty/src/builtins/next.rs +0 -21
  405. package/ref-monty/crates/monty/src/builtins/oct.rs +0 -59
  406. package/ref-monty/crates/monty/src/builtins/ord.rs +0 -67
  407. package/ref-monty/crates/monty/src/builtins/pow.rs +0 -365
  408. package/ref-monty/crates/monty/src/builtins/print.rs +0 -141
  409. package/ref-monty/crates/monty/src/builtins/repr.rs +0 -16
  410. package/ref-monty/crates/monty/src/builtins/reversed.rs +0 -28
  411. package/ref-monty/crates/monty/src/builtins/round.rs +0 -174
  412. package/ref-monty/crates/monty/src/builtins/sorted.rs +0 -151
  413. package/ref-monty/crates/monty/src/builtins/sum.rs +0 -66
  414. package/ref-monty/crates/monty/src/builtins/type_.rs +0 -16
  415. package/ref-monty/crates/monty/src/builtins/zip.rs +0 -77
  416. package/ref-monty/crates/monty/src/bytecode/builder.rs +0 -699
  417. package/ref-monty/crates/monty/src/bytecode/code.rs +0 -310
  418. package/ref-monty/crates/monty/src/bytecode/compiler.rs +0 -3206
  419. package/ref-monty/crates/monty/src/bytecode/mod.rs +0 -24
  420. package/ref-monty/crates/monty/src/bytecode/op.rs +0 -617
  421. package/ref-monty/crates/monty/src/bytecode/vm/async_exec.rs +0 -1058
  422. package/ref-monty/crates/monty/src/bytecode/vm/attr.rs +0 -63
  423. package/ref-monty/crates/monty/src/bytecode/vm/binary.rs +0 -487
  424. package/ref-monty/crates/monty/src/bytecode/vm/call.rs +0 -767
  425. package/ref-monty/crates/monty/src/bytecode/vm/collections.rs +0 -741
  426. package/ref-monty/crates/monty/src/bytecode/vm/compare.rs +0 -147
  427. package/ref-monty/crates/monty/src/bytecode/vm/exceptions.rs +0 -297
  428. package/ref-monty/crates/monty/src/bytecode/vm/format.rs +0 -132
  429. package/ref-monty/crates/monty/src/bytecode/vm/mod.rs +0 -1958
  430. package/ref-monty/crates/monty/src/bytecode/vm/scheduler.rs +0 -620
  431. package/ref-monty/crates/monty/src/exception_private.rs +0 -1513
  432. package/ref-monty/crates/monty/src/exception_public.rs +0 -346
  433. package/ref-monty/crates/monty/src/expressions.rs +0 -694
  434. package/ref-monty/crates/monty/src/fstring.rs +0 -854
  435. package/ref-monty/crates/monty/src/function.rs +0 -119
  436. package/ref-monty/crates/monty/src/heap.rs +0 -1073
  437. package/ref-monty/crates/monty/src/heap_data.rs +0 -985
  438. package/ref-monty/crates/monty/src/heap_traits.rs +0 -312
  439. package/ref-monty/crates/monty/src/intern.rs +0 -837
  440. package/ref-monty/crates/monty/src/io.rs +0 -106
  441. package/ref-monty/crates/monty/src/lib.rs +0 -52
  442. package/ref-monty/crates/monty/src/modules/asyncio.rs +0 -144
  443. package/ref-monty/crates/monty/src/modules/math.rs +0 -1453
  444. package/ref-monty/crates/monty/src/modules/mod.rs +0 -120
  445. package/ref-monty/crates/monty/src/modules/os.rs +0 -116
  446. package/ref-monty/crates/monty/src/modules/pathlib.rs +0 -33
  447. package/ref-monty/crates/monty/src/modules/re.rs +0 -606
  448. package/ref-monty/crates/monty/src/modules/sys.rs +0 -60
  449. package/ref-monty/crates/monty/src/modules/typing.rs +0 -70
  450. package/ref-monty/crates/monty/src/namespace.rs +0 -21
  451. package/ref-monty/crates/monty/src/object.rs +0 -1040
  452. package/ref-monty/crates/monty/src/os.rs +0 -215
  453. package/ref-monty/crates/monty/src/parse.rs +0 -1730
  454. package/ref-monty/crates/monty/src/prepare.rs +0 -3015
  455. package/ref-monty/crates/monty/src/repl.rs +0 -1109
  456. package/ref-monty/crates/monty/src/resource.rs +0 -559
  457. package/ref-monty/crates/monty/src/run.rs +0 -457
  458. package/ref-monty/crates/monty/src/run_progress.rs +0 -821
  459. package/ref-monty/crates/monty/src/signature.rs +0 -651
  460. package/ref-monty/crates/monty/src/sorting.rs +0 -100
  461. package/ref-monty/crates/monty/src/types/bytes.rs +0 -2356
  462. package/ref-monty/crates/monty/src/types/dataclass.rs +0 -345
  463. package/ref-monty/crates/monty/src/types/dict.rs +0 -879
  464. package/ref-monty/crates/monty/src/types/dict_view.rs +0 -619
  465. package/ref-monty/crates/monty/src/types/iter.rs +0 -799
  466. package/ref-monty/crates/monty/src/types/list.rs +0 -929
  467. package/ref-monty/crates/monty/src/types/long_int.rs +0 -211
  468. package/ref-monty/crates/monty/src/types/mod.rs +0 -48
  469. package/ref-monty/crates/monty/src/types/module.rs +0 -146
  470. package/ref-monty/crates/monty/src/types/namedtuple.rs +0 -261
  471. package/ref-monty/crates/monty/src/types/path.rs +0 -596
  472. package/ref-monty/crates/monty/src/types/property.rs +0 -35
  473. package/ref-monty/crates/monty/src/types/py_trait.rs +0 -322
  474. package/ref-monty/crates/monty/src/types/range.rs +0 -285
  475. package/ref-monty/crates/monty/src/types/re_match.rs +0 -522
  476. package/ref-monty/crates/monty/src/types/re_pattern.rs +0 -726
  477. package/ref-monty/crates/monty/src/types/set.rs +0 -1373
  478. package/ref-monty/crates/monty/src/types/slice.rs +0 -257
  479. package/ref-monty/crates/monty/src/types/str.rs +0 -2051
  480. package/ref-monty/crates/monty/src/types/tuple.rs +0 -376
  481. package/ref-monty/crates/monty/src/types/type.rs +0 -407
  482. package/ref-monty/crates/monty/src/value.rs +0 -2558
  483. package/ref-monty/crates/monty/test_cases/args__dict_get_no_args.py +0 -3
  484. package/ref-monty/crates/monty/test_cases/args__dict_get_too_many.py +0 -3
  485. package/ref-monty/crates/monty/test_cases/args__dict_items_with_args.py +0 -3
  486. package/ref-monty/crates/monty/test_cases/args__dict_keys_with_args.py +0 -3
  487. package/ref-monty/crates/monty/test_cases/args__dict_pop_no_args.py +0 -3
  488. package/ref-monty/crates/monty/test_cases/args__dict_pop_too_many.py +0 -3
  489. package/ref-monty/crates/monty/test_cases/args__dict_values_with_args.py +0 -3
  490. package/ref-monty/crates/monty/test_cases/args__id_too_many.py +0 -2
  491. package/ref-monty/crates/monty/test_cases/args__len_no_args.py +0 -2
  492. package/ref-monty/crates/monty/test_cases/args__len_too_many.py +0 -2
  493. package/ref-monty/crates/monty/test_cases/args__len_type_error_int.py +0 -9
  494. package/ref-monty/crates/monty/test_cases/args__len_type_error_none.py +0 -9
  495. package/ref-monty/crates/monty/test_cases/args__list_append_no_args.py +0 -3
  496. package/ref-monty/crates/monty/test_cases/args__list_append_too_many.py +0 -3
  497. package/ref-monty/crates/monty/test_cases/args__list_insert_too_few.py +0 -3
  498. package/ref-monty/crates/monty/test_cases/args__list_insert_too_many.py +0 -3
  499. package/ref-monty/crates/monty/test_cases/args__repr_no_args.py +0 -2
  500. package/ref-monty/crates/monty/test_cases/arith__div_zero_float.py +0 -2
  501. package/ref-monty/crates/monty/test_cases/arith__div_zero_int.py +0 -2
  502. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_float.py +0 -2
  503. package/ref-monty/crates/monty/test_cases/arith__floordiv_zero_int.py +0 -2
  504. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg.py +0 -2
  505. package/ref-monty/crates/monty/test_cases/arith__pow_zero_neg_builtin.py +0 -9
  506. package/ref-monty/crates/monty/test_cases/assert__expr_fail.py +0 -2
  507. package/ref-monty/crates/monty/test_cases/assert__fail.py +0 -2
  508. package/ref-monty/crates/monty/test_cases/assert__fail_msg.py +0 -2
  509. package/ref-monty/crates/monty/test_cases/assert__fn_fail.py +0 -3
  510. package/ref-monty/crates/monty/test_cases/assert__ops.py +0 -11
  511. package/ref-monty/crates/monty/test_cases/async__asyncio_run.py +0 -47
  512. package/ref-monty/crates/monty/test_cases/async__basic.py +0 -10
  513. package/ref-monty/crates/monty/test_cases/async__closure.py +0 -14
  514. package/ref-monty/crates/monty/test_cases/async__double_await_coroutine.py +0 -16
  515. package/ref-monty/crates/monty/test_cases/async__exception.py +0 -10
  516. package/ref-monty/crates/monty/test_cases/async__ext_call.py +0 -73
  517. package/ref-monty/crates/monty/test_cases/async__gather_all.py +0 -85
  518. package/ref-monty/crates/monty/test_cases/async__nested_await.py +0 -15
  519. package/ref-monty/crates/monty/test_cases/async__nested_gather_ext.py +0 -37
  520. package/ref-monty/crates/monty/test_cases/async__not_awaitable.py +0 -10
  521. package/ref-monty/crates/monty/test_cases/async__not_imported.py +0 -14
  522. package/ref-monty/crates/monty/test_cases/async__recursion_depth_isolation.py +0 -27
  523. package/ref-monty/crates/monty/test_cases/async__return_types.py +0 -31
  524. package/ref-monty/crates/monty/test_cases/async__sequential.py +0 -16
  525. package/ref-monty/crates/monty/test_cases/async__traceback.py +0 -19
  526. package/ref-monty/crates/monty/test_cases/async__with_args.py +0 -14
  527. package/ref-monty/crates/monty/test_cases/attr__get_int_error.py +0 -9
  528. package/ref-monty/crates/monty/test_cases/attr__get_list_error.py +0 -9
  529. package/ref-monty/crates/monty/test_cases/attr__set_frozen_nonfield.py +0 -12
  530. package/ref-monty/crates/monty/test_cases/attr__set_int_error.py +0 -10
  531. package/ref-monty/crates/monty/test_cases/attr__set_list_error.py +0 -10
  532. package/ref-monty/crates/monty/test_cases/bench__kitchen_sink.py +0 -68
  533. package/ref-monty/crates/monty/test_cases/bool__ops.py +0 -20
  534. package/ref-monty/crates/monty/test_cases/builtin__add_type_error.py +0 -2
  535. package/ref-monty/crates/monty/test_cases/builtin__filter.py +0 -62
  536. package/ref-monty/crates/monty/test_cases/builtin__filter_not_iterable.py +0 -11
  537. package/ref-monty/crates/monty/test_cases/builtin__getattr.py +0 -84
  538. package/ref-monty/crates/monty/test_cases/builtin__iter_funcs.py +0 -42
  539. package/ref-monty/crates/monty/test_cases/builtin__iter_next.py +0 -66
  540. package/ref-monty/crates/monty/test_cases/builtin__map.py +0 -74
  541. package/ref-monty/crates/monty/test_cases/builtin__map_not_iterable.py +0 -11
  542. package/ref-monty/crates/monty/test_cases/builtin__math_funcs.py +0 -154
  543. package/ref-monty/crates/monty/test_cases/builtin__more_iter_funcs.py +0 -148
  544. package/ref-monty/crates/monty/test_cases/builtin__next_stop_iteration.py +0 -10
  545. package/ref-monty/crates/monty/test_cases/builtin__print_invalid_kwarg.py +0 -9
  546. package/ref-monty/crates/monty/test_cases/builtin__print_kwargs.py +0 -12
  547. package/ref-monty/crates/monty/test_cases/builtin__repr.py +0 -3
  548. package/ref-monty/crates/monty/test_cases/builtin__string_funcs.py +0 -73
  549. package/ref-monty/crates/monty/test_cases/bytes__decode_invalid_utf8.py +0 -18
  550. package/ref-monty/crates/monty/test_cases/bytes__endswith_str_error.py +0 -10
  551. package/ref-monty/crates/monty/test_cases/bytes__getitem_index_error.py +0 -10
  552. package/ref-monty/crates/monty/test_cases/bytes__index_start_gt_end.py +0 -10
  553. package/ref-monty/crates/monty/test_cases/bytes__methods.py +0 -394
  554. package/ref-monty/crates/monty/test_cases/bytes__negative_count.py +0 -9
  555. package/ref-monty/crates/monty/test_cases/bytes__ops.py +0 -90
  556. package/ref-monty/crates/monty/test_cases/bytes__startswith_str_error.py +0 -10
  557. package/ref-monty/crates/monty/test_cases/call_object.py +0 -3
  558. package/ref-monty/crates/monty/test_cases/chain_comparison__all.py +0 -79
  559. package/ref-monty/crates/monty/test_cases/closure__param_shadows_outer.py +0 -81
  560. package/ref-monty/crates/monty/test_cases/closure__pep448.py +0 -203
  561. package/ref-monty/crates/monty/test_cases/closure__undefined_nonlocal.py +0 -13
  562. package/ref-monty/crates/monty/test_cases/compare__mixed_types.py +0 -120
  563. package/ref-monty/crates/monty/test_cases/comprehension__all.py +0 -208
  564. package/ref-monty/crates/monty/test_cases/comprehension__scope.py +0 -7
  565. package/ref-monty/crates/monty/test_cases/comprehension__unbound_local.py +0 -14
  566. package/ref-monty/crates/monty/test_cases/dataclass__basic.py +0 -238
  567. package/ref-monty/crates/monty/test_cases/dataclass__call_field_error.py +0 -12
  568. package/ref-monty/crates/monty/test_cases/dataclass__frozen_set_error.py +0 -12
  569. package/ref-monty/crates/monty/test_cases/dataclass__get_missing_attr_error.py +0 -11
  570. package/ref-monty/crates/monty/test_cases/dict__get_unhashable_key.py +0 -3
  571. package/ref-monty/crates/monty/test_cases/dict__literal_unhashable_key.py +0 -2
  572. package/ref-monty/crates/monty/test_cases/dict__method_pop_missing_error.py +0 -3
  573. package/ref-monty/crates/monty/test_cases/dict__methods.py +0 -151
  574. package/ref-monty/crates/monty/test_cases/dict__ops.py +0 -133
  575. package/ref-monty/crates/monty/test_cases/dict__pop_unhashable_key.py +0 -4
  576. package/ref-monty/crates/monty/test_cases/dict__popitem_empty.py +0 -9
  577. package/ref-monty/crates/monty/test_cases/dict__subscript_missing_key.py +0 -3
  578. package/ref-monty/crates/monty/test_cases/dict__unhashable_dict_key.py +0 -2
  579. package/ref-monty/crates/monty/test_cases/dict__unhashable_list_key.py +0 -2
  580. package/ref-monty/crates/monty/test_cases/dict__unpack_type_error.py +0 -2
  581. package/ref-monty/crates/monty/test_cases/dict__views.py +0 -165
  582. package/ref-monty/crates/monty/test_cases/edge__all.py +0 -26
  583. package/ref-monty/crates/monty/test_cases/edge__float_int_mod.py +0 -2
  584. package/ref-monty/crates/monty/test_cases/edge__int_float_mod.py +0 -2
  585. package/ref-monty/crates/monty/test_cases/exc__args.py +0 -16
  586. package/ref-monty/crates/monty/test_cases/exc__str.py +0 -15
  587. package/ref-monty/crates/monty/test_cases/execute_ok__all.py +0 -54
  588. package/ref-monty/crates/monty/test_cases/execute_raise__error_instance_str.py +0 -2
  589. package/ref-monty/crates/monty/test_cases/execute_raise__error_no_args.py +0 -2
  590. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg.py +0 -2
  591. package/ref-monty/crates/monty/test_cases/execute_raise__error_string_arg_quotes.py +0 -2
  592. package/ref-monty/crates/monty/test_cases/execute_raise__error_type.py +0 -2
  593. package/ref-monty/crates/monty/test_cases/execute_raise__raise_instance_via_var.py +0 -4
  594. package/ref-monty/crates/monty/test_cases/execute_raise__raise_list.py +0 -2
  595. package/ref-monty/crates/monty/test_cases/execute_raise__raise_number.py +0 -2
  596. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_call_via_var.py +0 -4
  597. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_direct.py +0 -3
  598. package/ref-monty/crates/monty/test_cases/execute_raise__raise_type_via_var.py +0 -4
  599. package/ref-monty/crates/monty/test_cases/ext_call__arg_side_effect_bug.py +0 -22
  600. package/ref-monty/crates/monty/test_cases/ext_call__augmented.py +0 -17
  601. package/ref-monty/crates/monty/test_cases/ext_call__augmented_refcount_bug.py +0 -7
  602. package/ref-monty/crates/monty/test_cases/ext_call__bare_raise_after_resume.py +0 -34
  603. package/ref-monty/crates/monty/test_cases/ext_call__basic.py +0 -99
  604. package/ref-monty/crates/monty/test_cases/ext_call__boolean.py +0 -37
  605. package/ref-monty/crates/monty/test_cases/ext_call__boolean_side_effect_hang.py +0 -17
  606. package/ref-monty/crates/monty/test_cases/ext_call__closure_bug.py +0 -16
  607. package/ref-monty/crates/monty/test_cases/ext_call__comparison.py +0 -26
  608. package/ref-monty/crates/monty/test_cases/ext_call__deep_call_stack.py +0 -18
  609. package/ref-monty/crates/monty/test_cases/ext_call__elif.py +0 -171
  610. package/ref-monty/crates/monty/test_cases/ext_call__exc.py +0 -4
  611. package/ref-monty/crates/monty/test_cases/ext_call__exc_deep_stack.py +0 -39
  612. package/ref-monty/crates/monty/test_cases/ext_call__exc_in_function.py +0 -17
  613. package/ref-monty/crates/monty/test_cases/ext_call__exc_nested_functions.py +0 -31
  614. package/ref-monty/crates/monty/test_cases/ext_call__ext_exc.py +0 -171
  615. package/ref-monty/crates/monty/test_cases/ext_call__for.py +0 -114
  616. package/ref-monty/crates/monty/test_cases/ext_call__fstring.py +0 -12
  617. package/ref-monty/crates/monty/test_cases/ext_call__if.py +0 -135
  618. package/ref-monty/crates/monty/test_cases/ext_call__if_condition.py +0 -37
  619. package/ref-monty/crates/monty/test_cases/ext_call__in_closure.py +0 -14
  620. package/ref-monty/crates/monty/test_cases/ext_call__in_function.py +0 -40
  621. package/ref-monty/crates/monty/test_cases/ext_call__in_function_simple.py +0 -7
  622. package/ref-monty/crates/monty/test_cases/ext_call__literals.py +0 -17
  623. package/ref-monty/crates/monty/test_cases/ext_call__multi_in_func.py +0 -32
  624. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup.py +0 -69
  625. package/ref-monty/crates/monty/test_cases/ext_call__name_lookup_undefined.py +0 -4
  626. package/ref-monty/crates/monty/test_cases/ext_call__nested_calls.py +0 -14
  627. package/ref-monty/crates/monty/test_cases/ext_call__recursion_bug.py +0 -19
  628. package/ref-monty/crates/monty/test_cases/ext_call__return.py +0 -28
  629. package/ref-monty/crates/monty/test_cases/ext_call__side_effects.py +0 -25
  630. package/ref-monty/crates/monty/test_cases/ext_call__subscript.py +0 -7
  631. package/ref-monty/crates/monty/test_cases/ext_call__ternary.py +0 -28
  632. package/ref-monty/crates/monty/test_cases/ext_call__try.py +0 -280
  633. package/ref-monty/crates/monty/test_cases/ext_call__try_simple.py +0 -10
  634. package/ref-monty/crates/monty/test_cases/ext_call__unary.py +0 -13
  635. package/ref-monty/crates/monty/test_cases/frozenset__ops.py +0 -178
  636. package/ref-monty/crates/monty/test_cases/fstring__all.py +0 -236
  637. package/ref-monty/crates/monty/test_cases/fstring__error_eq_align_on_str.py +0 -3
  638. package/ref-monty/crates/monty/test_cases/fstring__error_float_f_on_str.py +0 -3
  639. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_float.py +0 -3
  640. package/ref-monty/crates/monty/test_cases/fstring__error_int_d_on_str.py +0 -3
  641. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec.py +0 -4
  642. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_dynamic.py +0 -4
  643. package/ref-monty/crates/monty/test_cases/fstring__error_invalid_spec_str.py +0 -4
  644. package/ref-monty/crates/monty/test_cases/fstring__error_str_s_on_int.py +0 -3
  645. package/ref-monty/crates/monty/test_cases/function__call_duplicate_kwargs.py +0 -6
  646. package/ref-monty/crates/monty/test_cases/function__call_unpack.py +0 -42
  647. package/ref-monty/crates/monty/test_cases/function__defaults.py +0 -117
  648. package/ref-monty/crates/monty/test_cases/function__err_duplicate_arg.py +0 -7
  649. package/ref-monty/crates/monty/test_cases/function__err_duplicate_first_arg.py +0 -7
  650. package/ref-monty/crates/monty/test_cases/function__err_duplicate_kwarg_cleanup.py +0 -9
  651. package/ref-monty/crates/monty/test_cases/function__err_kwonly_as_positional.py +0 -7
  652. package/ref-monty/crates/monty/test_cases/function__err_missing_all_posonly.py +0 -7
  653. package/ref-monty/crates/monty/test_cases/function__err_missing_heap_cleanup.py +0 -9
  654. package/ref-monty/crates/monty/test_cases/function__err_missing_kwonly.py +0 -7
  655. package/ref-monty/crates/monty/test_cases/function__err_missing_posonly_with_kwarg.py +0 -7
  656. package/ref-monty/crates/monty/test_cases/function__err_missing_with_posonly.py +0 -7
  657. package/ref-monty/crates/monty/test_cases/function__err_posonly_as_kwarg.py +0 -7
  658. package/ref-monty/crates/monty/test_cases/function__err_posonly_first_as_kwarg.py +0 -7
  659. package/ref-monty/crates/monty/test_cases/function__err_too_many_posonly.py +0 -7
  660. package/ref-monty/crates/monty/test_cases/function__err_too_many_with_kwonly.py +0 -7
  661. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg.py +0 -7
  662. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_cleanup.py +0 -9
  663. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_quote.py +0 -13
  664. package/ref-monty/crates/monty/test_cases/function__err_unexpected_kwarg_simple.py +0 -7
  665. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_arg.py +0 -6
  666. package/ref-monty/crates/monty/test_cases/function__err_unpack_duplicate_heap.py +0 -8
  667. package/ref-monty/crates/monty/test_cases/function__err_unpack_int.py +0 -6
  668. package/ref-monty/crates/monty/test_cases/function__err_unpack_nonstring_key.py +0 -6
  669. package/ref-monty/crates/monty/test_cases/function__err_unpack_not_mapping.py +0 -6
  670. package/ref-monty/crates/monty/test_cases/function__kwargs_unpacking.py +0 -173
  671. package/ref-monty/crates/monty/test_cases/function__ops.py +0 -294
  672. package/ref-monty/crates/monty/test_cases/function__return_none.py +0 -42
  673. package/ref-monty/crates/monty/test_cases/function__signatures.py +0 -47
  674. package/ref-monty/crates/monty/test_cases/function__too_few_args_all.py +0 -6
  675. package/ref-monty/crates/monty/test_cases/function__too_few_args_one.py +0 -6
  676. package/ref-monty/crates/monty/test_cases/function__too_few_args_two.py +0 -6
  677. package/ref-monty/crates/monty/test_cases/function__too_many_args_one.py +0 -6
  678. package/ref-monty/crates/monty/test_cases/function__too_many_args_two.py +0 -6
  679. package/ref-monty/crates/monty/test_cases/function__too_many_args_zero.py +0 -6
  680. package/ref-monty/crates/monty/test_cases/global__error_assigned_before.py +0 -7
  681. package/ref-monty/crates/monty/test_cases/global__ops.py +0 -163
  682. package/ref-monty/crates/monty/test_cases/hash__dict_unhashable.py +0 -2
  683. package/ref-monty/crates/monty/test_cases/hash__list_unhashable.py +0 -2
  684. package/ref-monty/crates/monty/test_cases/hash__ops.py +0 -153
  685. package/ref-monty/crates/monty/test_cases/id__bytes_literals_distinct.py +0 -3
  686. package/ref-monty/crates/monty/test_cases/id__int_copy_distinct.py +0 -5
  687. package/ref-monty/crates/monty/test_cases/id__is_number_is_number.py +0 -3
  688. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_distinct_types.py +0 -10
  689. package/ref-monty/crates/monty/test_cases/id__non_overlapping_lifetimes_same_types.py +0 -6
  690. package/ref-monty/crates/monty/test_cases/id__ops.py +0 -97
  691. package/ref-monty/crates/monty/test_cases/id__str_literals_same.py +0 -3
  692. package/ref-monty/crates/monty/test_cases/if__elif_else.py +0 -207
  693. package/ref-monty/crates/monty/test_cases/if__raise_elif.py +0 -11
  694. package/ref-monty/crates/monty/test_cases/if__raise_else.py +0 -13
  695. package/ref-monty/crates/monty/test_cases/if__raise_if.py +0 -9
  696. package/ref-monty/crates/monty/test_cases/if__raise_in_elif_condition.py +0 -18
  697. package/ref-monty/crates/monty/test_cases/if__raise_in_if_condition.py +0 -16
  698. package/ref-monty/crates/monty/test_cases/if_else_expr__all.py +0 -55
  699. package/ref-monty/crates/monty/test_cases/import__error_cannot_import.py +0 -9
  700. package/ref-monty/crates/monty/test_cases/import__error_module_not_found.py +0 -9
  701. package/ref-monty/crates/monty/test_cases/import__local_scope.py +0 -68
  702. package/ref-monty/crates/monty/test_cases/import__os.py +0 -25
  703. package/ref-monty/crates/monty/test_cases/import__relative_error.py +0 -9
  704. package/ref-monty/crates/monty/test_cases/import__relative_no_module_error.py +0 -9
  705. package/ref-monty/crates/monty/test_cases/import__runtime_error_when_executed.py +0 -14
  706. package/ref-monty/crates/monty/test_cases/import__star_error.py +0 -11
  707. package/ref-monty/crates/monty/test_cases/import__sys.py +0 -47
  708. package/ref-monty/crates/monty/test_cases/import__sys_monty.py +0 -28
  709. package/ref-monty/crates/monty/test_cases/import__type_checking_guard.py +0 -37
  710. package/ref-monty/crates/monty/test_cases/import__typing.py +0 -25
  711. package/ref-monty/crates/monty/test_cases/import__typing_type_ignore.py +0 -4
  712. package/ref-monty/crates/monty/test_cases/int__bigint.py +0 -467
  713. package/ref-monty/crates/monty/test_cases/int__bigint_errors.py +0 -260
  714. package/ref-monty/crates/monty/test_cases/int__ops.py +0 -219
  715. package/ref-monty/crates/monty/test_cases/int__overflow_division.py +0 -84
  716. package/ref-monty/crates/monty/test_cases/is_variant__all.py +0 -36
  717. package/ref-monty/crates/monty/test_cases/isinstance__arg2_list_error.py +0 -2
  718. package/ref-monty/crates/monty/test_cases/isinstance__arg2_type_error.py +0 -2
  719. package/ref-monty/crates/monty/test_cases/iter__dict_mutation.py +0 -4
  720. package/ref-monty/crates/monty/test_cases/iter__for.py +0 -243
  721. package/ref-monty/crates/monty/test_cases/iter__for_loop_unpacking.py +0 -66
  722. package/ref-monty/crates/monty/test_cases/iter__generator_expr.py +0 -20
  723. package/ref-monty/crates/monty/test_cases/iter__generator_expr_type.py +0 -7
  724. package/ref-monty/crates/monty/test_cases/iter__not_iterable.py +0 -3
  725. package/ref-monty/crates/monty/test_cases/lambda__all.py +0 -145
  726. package/ref-monty/crates/monty/test_cases/list__extend_not_iterable.py +0 -7
  727. package/ref-monty/crates/monty/test_cases/list__getitem_out_of_bounds.py +0 -3
  728. package/ref-monty/crates/monty/test_cases/list__index_not_found.py +0 -9
  729. package/ref-monty/crates/monty/test_cases/list__index_start_gt_end.py +0 -10
  730. package/ref-monty/crates/monty/test_cases/list__ops.py +0 -473
  731. package/ref-monty/crates/monty/test_cases/list__pop_empty.py +0 -9
  732. package/ref-monty/crates/monty/test_cases/list__pop_out_of_range.py +0 -9
  733. package/ref-monty/crates/monty/test_cases/list__pop_type_error.py +0 -9
  734. package/ref-monty/crates/monty/test_cases/list__remove_not_found.py +0 -9
  735. package/ref-monty/crates/monty/test_cases/list__setitem_dict_index.py +0 -13
  736. package/ref-monty/crates/monty/test_cases/list__setitem_huge_int_index.py +0 -13
  737. package/ref-monty/crates/monty/test_cases/list__setitem_index_error.py +0 -10
  738. package/ref-monty/crates/monty/test_cases/list__setitem_type_error.py +0 -10
  739. package/ref-monty/crates/monty/test_cases/list__unpack_type_error.py +0 -2
  740. package/ref-monty/crates/monty/test_cases/longint__index_error.py +0 -3
  741. package/ref-monty/crates/monty/test_cases/longint__repeat_error.py +0 -3
  742. package/ref-monty/crates/monty/test_cases/loop__break_continue.py +0 -113
  743. package/ref-monty/crates/monty/test_cases/loop__break_finally.py +0 -69
  744. package/ref-monty/crates/monty/test_cases/loop__break_in_function_error.py +0 -13
  745. package/ref-monty/crates/monty/test_cases/loop__break_in_if_error.py +0 -11
  746. package/ref-monty/crates/monty/test_cases/loop__break_nested_except_clears.py +0 -55
  747. package/ref-monty/crates/monty/test_cases/loop__break_outside_error.py +0 -9
  748. package/ref-monty/crates/monty/test_cases/loop__continue_finally.py +0 -81
  749. package/ref-monty/crates/monty/test_cases/loop__continue_in_function_error.py +0 -13
  750. package/ref-monty/crates/monty/test_cases/loop__continue_in_if_error.py +0 -11
  751. package/ref-monty/crates/monty/test_cases/loop__continue_nested_except_clears.py +0 -60
  752. package/ref-monty/crates/monty/test_cases/loop__continue_outside_error.py +0 -9
  753. package/ref-monty/crates/monty/test_cases/math__acos_domain_error.py +0 -11
  754. package/ref-monty/crates/monty/test_cases/math__acosh_domain_error.py +0 -11
  755. package/ref-monty/crates/monty/test_cases/math__asin_domain_error.py +0 -11
  756. package/ref-monty/crates/monty/test_cases/math__atanh_domain_error.py +0 -11
  757. package/ref-monty/crates/monty/test_cases/math__cos_inf_error.py +0 -11
  758. package/ref-monty/crates/monty/test_cases/math__cosh_overflow_error.py +0 -11
  759. package/ref-monty/crates/monty/test_cases/math__exp_overflow_error.py +0 -11
  760. package/ref-monty/crates/monty/test_cases/math__factorial_float_error.py +0 -11
  761. package/ref-monty/crates/monty/test_cases/math__factorial_negative_error.py +0 -11
  762. package/ref-monty/crates/monty/test_cases/math__floor_inf_error.py +0 -11
  763. package/ref-monty/crates/monty/test_cases/math__floor_nan_error.py +0 -11
  764. package/ref-monty/crates/monty/test_cases/math__floor_str_error.py +0 -11
  765. package/ref-monty/crates/monty/test_cases/math__fmod_inf_error.py +0 -11
  766. package/ref-monty/crates/monty/test_cases/math__gamma_neg_int_error.py +0 -11
  767. package/ref-monty/crates/monty/test_cases/math__gcd_float_error.py +0 -11
  768. package/ref-monty/crates/monty/test_cases/math__isqrt_negative_error.py +0 -11
  769. package/ref-monty/crates/monty/test_cases/math__ldexp_overflow_error.py +0 -11
  770. package/ref-monty/crates/monty/test_cases/math__log1p_domain_error.py +0 -11
  771. package/ref-monty/crates/monty/test_cases/math__log_base1_error.py +0 -11
  772. package/ref-monty/crates/monty/test_cases/math__log_zero_error.py +0 -11
  773. package/ref-monty/crates/monty/test_cases/math__module.py +0 -1432
  774. package/ref-monty/crates/monty/test_cases/math__pow_domain_error.py +0 -11
  775. package/ref-monty/crates/monty/test_cases/math__sin_inf_error.py +0 -11
  776. package/ref-monty/crates/monty/test_cases/math__sqrt_negative_error.py +0 -11
  777. package/ref-monty/crates/monty/test_cases/math__tan_inf_error.py +0 -11
  778. package/ref-monty/crates/monty/test_cases/math__trunc_str_error.py +0 -11
  779. package/ref-monty/crates/monty/test_cases/method__args_kwargs_unpacking.py +0 -259
  780. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_func.py +0 -19
  781. package/ref-monty/crates/monty/test_cases/name_error__unbound_local_module.py +0 -12
  782. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_chained.py +0 -9
  783. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_expr.py +0 -9
  784. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_in_function.py +0 -16
  785. package/ref-monty/crates/monty/test_cases/name_error__undefined_call_with_args.py +0 -9
  786. package/ref-monty/crates/monty/test_cases/name_error__undefined_global.py +0 -10
  787. package/ref-monty/crates/monty/test_cases/namedtuple__missing_attr.py +0 -11
  788. package/ref-monty/crates/monty/test_cases/namedtuple__ops.py +0 -34
  789. package/ref-monty/crates/monty/test_cases/nonlocal__error_module_level.py +0 -3
  790. package/ref-monty/crates/monty/test_cases/nonlocal__ops.py +0 -353
  791. package/ref-monty/crates/monty/test_cases/os__environ.py +0 -40
  792. package/ref-monty/crates/monty/test_cases/os__getenv_key_list_error.py +0 -5
  793. package/ref-monty/crates/monty/test_cases/os__getenv_key_type_error.py +0 -5
  794. package/ref-monty/crates/monty/test_cases/parse_error__complex.py +0 -3
  795. package/ref-monty/crates/monty/test_cases/pathlib__import.py +0 -11
  796. package/ref-monty/crates/monty/test_cases/pathlib__os.py +0 -136
  797. package/ref-monty/crates/monty/test_cases/pathlib__os_read_error.py +0 -12
  798. package/ref-monty/crates/monty/test_cases/pathlib__pure.py +0 -81
  799. package/ref-monty/crates/monty/test_cases/pyobject__cycle_dict_self.py +0 -5
  800. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_dict.py +0 -6
  801. package/ref-monty/crates/monty/test_cases/pyobject__cycle_list_self.py +0 -5
  802. package/ref-monty/crates/monty/test_cases/pyobject__cycle_multiple_refs.py +0 -6
  803. package/ref-monty/crates/monty/test_cases/range__error_no_args.py +0 -2
  804. package/ref-monty/crates/monty/test_cases/range__error_step_zero.py +0 -2
  805. package/ref-monty/crates/monty/test_cases/range__error_too_many_args.py +0 -2
  806. package/ref-monty/crates/monty/test_cases/range__getitem_index_error.py +0 -10
  807. package/ref-monty/crates/monty/test_cases/range__ops.py +0 -236
  808. package/ref-monty/crates/monty/test_cases/re__basic.py +0 -756
  809. package/ref-monty/crates/monty/test_cases/re__grouping.py +0 -241
  810. package/ref-monty/crates/monty/test_cases/re__match.py +0 -148
  811. package/ref-monty/crates/monty/test_cases/recursion__deep_drop.py +0 -26
  812. package/ref-monty/crates/monty/test_cases/recursion__deep_eq.py +0 -23
  813. package/ref-monty/crates/monty/test_cases/recursion__deep_hash.py +0 -46
  814. package/ref-monty/crates/monty/test_cases/recursion__deep_repr.py +0 -12
  815. package/ref-monty/crates/monty/test_cases/recursion__function_depth.py +0 -13
  816. package/ref-monty/crates/monty/test_cases/refcount__cycle_mutual_reference.py +0 -18
  817. package/ref-monty/crates/monty/test_cases/refcount__cycle_self_reference.py +0 -12
  818. package/ref-monty/crates/monty/test_cases/refcount__dict_basic.py +0 -5
  819. package/ref-monty/crates/monty/test_cases/refcount__dict_get.py +0 -5
  820. package/ref-monty/crates/monty/test_cases/refcount__dict_keys_and.py +0 -14
  821. package/ref-monty/crates/monty/test_cases/refcount__dict_overwrite.py +0 -6
  822. package/ref-monty/crates/monty/test_cases/refcount__gather_cleanup.py +0 -16
  823. package/ref-monty/crates/monty/test_cases/refcount__gather_exception.py +0 -18
  824. package/ref-monty/crates/monty/test_cases/refcount__gather_nested_cancel.py +0 -25
  825. package/ref-monty/crates/monty/test_cases/refcount__immediate_skipped.py +0 -4
  826. package/ref-monty/crates/monty/test_cases/refcount__kwargs_unpacking.py +0 -27
  827. package/ref-monty/crates/monty/test_cases/refcount__list_append_multiple.py +0 -6
  828. package/ref-monty/crates/monty/test_cases/refcount__list_append_ref.py +0 -5
  829. package/ref-monty/crates/monty/test_cases/refcount__list_concat.py +0 -5
  830. package/ref-monty/crates/monty/test_cases/refcount__list_getitem.py +0 -5
  831. package/ref-monty/crates/monty/test_cases/refcount__list_iadd.py +0 -5
  832. package/ref-monty/crates/monty/test_cases/refcount__nested_list.py +0 -4
  833. package/ref-monty/crates/monty/test_cases/refcount__re_pattern_sub_error_paths.py +0 -37
  834. package/ref-monty/crates/monty/test_cases/refcount__re_search_match.py +0 -34
  835. package/ref-monty/crates/monty/test_cases/refcount__re_sub_error_paths.py +0 -31
  836. package/ref-monty/crates/monty/test_cases/refcount__shared_reference.py +0 -4
  837. package/ref-monty/crates/monty/test_cases/refcount__single_list.py +0 -3
  838. package/ref-monty/crates/monty/test_cases/repr__cycle_detection.py +0 -24
  839. package/ref-monty/crates/monty/test_cases/set__ops.py +0 -191
  840. package/ref-monty/crates/monty/test_cases/set__review_bugs.py +0 -35
  841. package/ref-monty/crates/monty/test_cases/set__unpack_type_error.py +0 -2
  842. package/ref-monty/crates/monty/test_cases/slice__invalid_indices.py +0 -2
  843. package/ref-monty/crates/monty/test_cases/slice__kwargs.py +0 -9
  844. package/ref-monty/crates/monty/test_cases/slice__no_args.py +0 -9
  845. package/ref-monty/crates/monty/test_cases/slice__ops.py +0 -149
  846. package/ref-monty/crates/monty/test_cases/slice__step_zero.py +0 -9
  847. package/ref-monty/crates/monty/test_cases/slice__step_zero_bytes.py +0 -9
  848. package/ref-monty/crates/monty/test_cases/slice__step_zero_range.py +0 -9
  849. package/ref-monty/crates/monty/test_cases/slice__step_zero_str.py +0 -9
  850. package/ref-monty/crates/monty/test_cases/slice__step_zero_tuple.py +0 -9
  851. package/ref-monty/crates/monty/test_cases/slice__too_many_args.py +0 -9
  852. package/ref-monty/crates/monty/test_cases/str__getitem_index_error.py +0 -10
  853. package/ref-monty/crates/monty/test_cases/str__index_not_found.py +0 -9
  854. package/ref-monty/crates/monty/test_cases/str__join_no_args.py +0 -9
  855. package/ref-monty/crates/monty/test_cases/str__join_non_string.py +0 -9
  856. package/ref-monty/crates/monty/test_cases/str__join_not_iterable.py +0 -9
  857. package/ref-monty/crates/monty/test_cases/str__join_too_many_args.py +0 -9
  858. package/ref-monty/crates/monty/test_cases/str__methods.py +0 -327
  859. package/ref-monty/crates/monty/test_cases/str__ops.py +0 -162
  860. package/ref-monty/crates/monty/test_cases/str__partition_empty.py +0 -9
  861. package/ref-monty/crates/monty/test_cases/str__rsplit_empty_sep.py +0 -9
  862. package/ref-monty/crates/monty/test_cases/str__split_empty_sep.py +0 -9
  863. package/ref-monty/crates/monty/test_cases/sys__types.py +0 -7
  864. package/ref-monty/crates/monty/test_cases/traceback__division_error.py +0 -30
  865. package/ref-monty/crates/monty/test_cases/traceback__index_error.py +0 -17
  866. package/ref-monty/crates/monty/test_cases/traceback__insert_as_int.py +0 -10
  867. package/ref-monty/crates/monty/test_cases/traceback__nested_call.py +0 -29
  868. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_module_scope.py +0 -10
  869. package/ref-monty/crates/monty/test_cases/traceback__nonlocal_unbound.py +0 -24
  870. package/ref-monty/crates/monty/test_cases/traceback__range_as_int.py +0 -9
  871. package/ref-monty/crates/monty/test_cases/traceback__recursion_error.py +0 -23
  872. package/ref-monty/crates/monty/test_cases/traceback__set_mutation.py +0 -11
  873. package/ref-monty/crates/monty/test_cases/traceback__undefined_attr_call.py +0 -16
  874. package/ref-monty/crates/monty/test_cases/traceback__undefined_call.py +0 -16
  875. package/ref-monty/crates/monty/test_cases/traceback__undefined_raise.py +0 -16
  876. package/ref-monty/crates/monty/test_cases/try_except__all.py +0 -472
  877. package/ref-monty/crates/monty/test_cases/try_except__bare_raise_no_context.py +0 -2
  878. package/ref-monty/crates/monty/test_cases/try_except__invalid_type.py +0 -5
  879. package/ref-monty/crates/monty/test_cases/tuple__getitem_out_of_bounds.py +0 -3
  880. package/ref-monty/crates/monty/test_cases/tuple__index_not_found.py +0 -9
  881. package/ref-monty/crates/monty/test_cases/tuple__index_start_gt_end.py +0 -10
  882. package/ref-monty/crates/monty/test_cases/tuple__methods.py +0 -19
  883. package/ref-monty/crates/monty/test_cases/tuple__ops.py +0 -133
  884. package/ref-monty/crates/monty/test_cases/tuple__unpack_type_error.py +0 -2
  885. package/ref-monty/crates/monty/test_cases/type__builtin_attr_error.py +0 -9
  886. package/ref-monty/crates/monty/test_cases/type__bytes_negative.py +0 -2
  887. package/ref-monty/crates/monty/test_cases/type__cell_not_builtin.py +0 -9
  888. package/ref-monty/crates/monty/test_cases/type__exception_attr_error.py +0 -11
  889. package/ref-monty/crates/monty/test_cases/type__float_conversion_error.py +0 -2
  890. package/ref-monty/crates/monty/test_cases/type__float_repr_both_quotes.py +0 -9
  891. package/ref-monty/crates/monty/test_cases/type__float_repr_newline.py +0 -9
  892. package/ref-monty/crates/monty/test_cases/type__float_repr_single_quote.py +0 -9
  893. package/ref-monty/crates/monty/test_cases/type__int_conversion_error.py +0 -2
  894. package/ref-monty/crates/monty/test_cases/type__list_not_iterable.py +0 -2
  895. package/ref-monty/crates/monty/test_cases/type__non_builtin_name_error.py +0 -9
  896. package/ref-monty/crates/monty/test_cases/type__ops.py +0 -200
  897. package/ref-monty/crates/monty/test_cases/type__shadow_exc.py +0 -3
  898. package/ref-monty/crates/monty/test_cases/type__shadow_int.py +0 -9
  899. package/ref-monty/crates/monty/test_cases/type__shadow_len.py +0 -3
  900. package/ref-monty/crates/monty/test_cases/type__tuple_not_iterable.py +0 -2
  901. package/ref-monty/crates/monty/test_cases/type_error__int_add_list.py +0 -2
  902. package/ref-monty/crates/monty/test_cases/type_error__int_div_str.py +0 -2
  903. package/ref-monty/crates/monty/test_cases/type_error__int_floordiv_str.py +0 -2
  904. package/ref-monty/crates/monty/test_cases/type_error__int_iadd_str.py +0 -3
  905. package/ref-monty/crates/monty/test_cases/type_error__int_mod_str.py +0 -2
  906. package/ref-monty/crates/monty/test_cases/type_error__int_pow_str.py +0 -2
  907. package/ref-monty/crates/monty/test_cases/type_error__int_sub_str.py +0 -2
  908. package/ref-monty/crates/monty/test_cases/type_error__list_add_int.py +0 -2
  909. package/ref-monty/crates/monty/test_cases/type_error__list_add_str.py +0 -2
  910. package/ref-monty/crates/monty/test_cases/type_error__list_iadd_int.py +0 -6
  911. package/ref-monty/crates/monty/test_cases/type_error__str_add_int.py +0 -2
  912. package/ref-monty/crates/monty/test_cases/type_error__str_iadd_int.py +0 -3
  913. package/ref-monty/crates/monty/test_cases/type_error__unary_invert_str.py +0 -3
  914. package/ref-monty/crates/monty/test_cases/type_error__unary_minus_str.py +0 -4
  915. package/ref-monty/crates/monty/test_cases/type_error__unary_neg_str.py +0 -3
  916. package/ref-monty/crates/monty/test_cases/type_error__unary_plus_str.py +0 -4
  917. package/ref-monty/crates/monty/test_cases/typing__types.py +0 -24
  918. package/ref-monty/crates/monty/test_cases/unpack__nested.py +0 -48
  919. package/ref-monty/crates/monty/test_cases/unpack__non_sequence.py +0 -9
  920. package/ref-monty/crates/monty/test_cases/unpack__not_enough.py +0 -9
  921. package/ref-monty/crates/monty/test_cases/unpack__ops.py +0 -153
  922. package/ref-monty/crates/monty/test_cases/unpack__star_not_enough.py +0 -9
  923. package/ref-monty/crates/monty/test_cases/unpack__too_many.py +0 -9
  924. package/ref-monty/crates/monty/test_cases/version__cpython.py +0 -4
  925. package/ref-monty/crates/monty/test_cases/walrus__all.py +0 -178
  926. package/ref-monty/crates/monty/test_cases/while__all.py +0 -206
  927. package/ref-monty/crates/monty/tests/asyncio.rs +0 -764
  928. package/ref-monty/crates/monty/tests/binary_serde.rs +0 -185
  929. package/ref-monty/crates/monty/tests/bytecode_limits.rs +0 -248
  930. package/ref-monty/crates/monty/tests/datatest_runner.rs +0 -2029
  931. package/ref-monty/crates/monty/tests/inputs.rs +0 -420
  932. package/ref-monty/crates/monty/tests/json_serde.rs +0 -250
  933. package/ref-monty/crates/monty/tests/main.rs +0 -71
  934. package/ref-monty/crates/monty/tests/math_module.rs +0 -114
  935. package/ref-monty/crates/monty/tests/name_lookup.rs +0 -482
  936. package/ref-monty/crates/monty/tests/os_tests.rs +0 -459
  937. package/ref-monty/crates/monty/tests/parse_errors.rs +0 -441
  938. package/ref-monty/crates/monty/tests/print_writer.rs +0 -238
  939. package/ref-monty/crates/monty/tests/py_object.rs +0 -121
  940. package/ref-monty/crates/monty/tests/regex.rs +0 -90
  941. package/ref-monty/crates/monty/tests/repl.rs +0 -344
  942. package/ref-monty/crates/monty/tests/resource_limits.rs +0 -1826
  943. package/ref-monty/crates/monty/tests/try_from.rs +0 -167
  944. package/ref-monty/crates/monty-cli/Cargo.toml +0 -25
  945. package/ref-monty/crates/monty-cli/src/main.rs +0 -541
  946. package/ref-monty/crates/monty-js/.cargo/config.toml +0 -2
  947. package/ref-monty/crates/monty-js/.prettierignore +0 -8
  948. package/ref-monty/crates/monty-js/Cargo.toml +0 -32
  949. package/ref-monty/crates/monty-js/README.md +0 -207
  950. package/ref-monty/crates/monty-js/__test__/async.spec.ts +0 -350
  951. package/ref-monty/crates/monty-js/__test__/basic.spec.ts +0 -114
  952. package/ref-monty/crates/monty-js/__test__/exceptions.spec.ts +0 -427
  953. package/ref-monty/crates/monty-js/__test__/external.spec.ts +0 -354
  954. package/ref-monty/crates/monty-js/__test__/inputs.spec.ts +0 -143
  955. package/ref-monty/crates/monty-js/__test__/limits.spec.ts +0 -162
  956. package/ref-monty/crates/monty-js/__test__/package.json +0 -3
  957. package/ref-monty/crates/monty-js/__test__/print.spec.ts +0 -229
  958. package/ref-monty/crates/monty-js/__test__/repl.spec.ts +0 -34
  959. package/ref-monty/crates/monty-js/__test__/serialize.spec.ts +0 -205
  960. package/ref-monty/crates/monty-js/__test__/start.spec.ts +0 -443
  961. package/ref-monty/crates/monty-js/__test__/type_check.spec.ts +0 -147
  962. package/ref-monty/crates/monty-js/__test__/types.spec.ts +0 -319
  963. package/ref-monty/crates/monty-js/build.rs +0 -61
  964. package/ref-monty/crates/monty-js/index-header.d.ts +0 -3
  965. package/ref-monty/crates/monty-js/package-lock.json +0 -4694
  966. package/ref-monty/crates/monty-js/package.json +0 -100
  967. package/ref-monty/crates/monty-js/scripts/smoke-test.sh +0 -69
  968. package/ref-monty/crates/monty-js/smoke-test/package.json +0 -17
  969. package/ref-monty/crates/monty-js/smoke-test/test.ts +0 -171
  970. package/ref-monty/crates/monty-js/smoke-test/tsconfig.json +0 -11
  971. package/ref-monty/crates/monty-js/src/convert.rs +0 -648
  972. package/ref-monty/crates/monty-js/src/exceptions.rs +0 -293
  973. package/ref-monty/crates/monty-js/src/lib.rs +0 -41
  974. package/ref-monty/crates/monty-js/src/limits.rs +0 -53
  975. package/ref-monty/crates/monty-js/src/monty_cls.rs +0 -1407
  976. package/ref-monty/crates/monty-js/tsconfig.json +0 -17
  977. package/ref-monty/crates/monty-js/wrapper.ts +0 -701
  978. package/ref-monty/crates/monty-python/Cargo.toml +0 -38
  979. package/ref-monty/crates/monty-python/README.md +0 -134
  980. package/ref-monty/crates/monty-python/build.rs +0 -4
  981. package/ref-monty/crates/monty-python/example.py +0 -40
  982. package/ref-monty/crates/monty-python/exercise.py +0 -46
  983. package/ref-monty/crates/monty-python/pyproject.toml +0 -57
  984. package/ref-monty/crates/monty-python/python/pydantic_monty/__init__.py +0 -281
  985. package/ref-monty/crates/monty-python/python/pydantic_monty/_monty.pyi +0 -677
  986. package/ref-monty/crates/monty-python/python/pydantic_monty/os_access.py +0 -933
  987. package/ref-monty/crates/monty-python/python/pydantic_monty/py.typed +0 -0
  988. package/ref-monty/crates/monty-python/src/convert.rs +0 -273
  989. package/ref-monty/crates/monty-python/src/dataclass.rs +0 -461
  990. package/ref-monty/crates/monty-python/src/exceptions.rs +0 -557
  991. package/ref-monty/crates/monty-python/src/external.rs +0 -165
  992. package/ref-monty/crates/monty-python/src/lib.rs +0 -77
  993. package/ref-monty/crates/monty-python/src/limits.rs +0 -142
  994. package/ref-monty/crates/monty-python/src/monty_cls.rs +0 -1650
  995. package/ref-monty/crates/monty-python/src/repl.rs +0 -470
  996. package/ref-monty/crates/monty-python/src/serialization.rs +0 -761
  997. package/ref-monty/crates/monty-python/tests/test_async.py +0 -1201
  998. package/ref-monty/crates/monty-python/tests/test_basic.py +0 -66
  999. package/ref-monty/crates/monty-python/tests/test_dataclasses.py +0 -971
  1000. package/ref-monty/crates/monty-python/tests/test_exceptions.py +0 -361
  1001. package/ref-monty/crates/monty-python/tests/test_external.py +0 -367
  1002. package/ref-monty/crates/monty-python/tests/test_inputs.py +0 -126
  1003. package/ref-monty/crates/monty-python/tests/test_limits.py +0 -257
  1004. package/ref-monty/crates/monty-python/tests/test_os_access.py +0 -1286
  1005. package/ref-monty/crates/monty-python/tests/test_os_access_compat.py +0 -731
  1006. package/ref-monty/crates/monty-python/tests/test_os_access_raw.py +0 -483
  1007. package/ref-monty/crates/monty-python/tests/test_os_calls.py +0 -819
  1008. package/ref-monty/crates/monty-python/tests/test_print.py +0 -208
  1009. package/ref-monty/crates/monty-python/tests/test_re.py +0 -170
  1010. package/ref-monty/crates/monty-python/tests/test_readme_examples.py +0 -20
  1011. package/ref-monty/crates/monty-python/tests/test_repl.py +0 -749
  1012. package/ref-monty/crates/monty-python/tests/test_serialize.py +0 -284
  1013. package/ref-monty/crates/monty-python/tests/test_start.py +0 -346
  1014. package/ref-monty/crates/monty-python/tests/test_threading.py +0 -163
  1015. package/ref-monty/crates/monty-python/tests/test_type_check.py +0 -344
  1016. package/ref-monty/crates/monty-python/tests/test_types.py +0 -553
  1017. package/ref-monty/crates/monty-type-checking/Cargo.toml +0 -32
  1018. package/ref-monty/crates/monty-type-checking/src/db.rs +0 -116
  1019. package/ref-monty/crates/monty-type-checking/src/lib.rs +0 -4
  1020. package/ref-monty/crates/monty-type-checking/src/type_check.rs +0 -280
  1021. package/ref-monty/crates/monty-type-checking/tests/bad_types.py +0 -109
  1022. package/ref-monty/crates/monty-type-checking/tests/bad_types_output.txt +0 -21
  1023. package/ref-monty/crates/monty-type-checking/tests/good_types.py +0 -475
  1024. package/ref-monty/crates/monty-type-checking/tests/main.rs +0 -205
  1025. package/ref-monty/crates/monty-type-checking/tests/reveal_types.py +0 -56
  1026. package/ref-monty/crates/monty-type-checking/tests/reveal_types_output.txt +0 -41
  1027. package/ref-monty/crates/monty-typeshed/Cargo.toml +0 -29
  1028. package/ref-monty/crates/monty-typeshed/README.md +0 -11
  1029. package/ref-monty/crates/monty-typeshed/build.rs +0 -101
  1030. package/ref-monty/crates/monty-typeshed/custom/README.md +0 -1
  1031. package/ref-monty/crates/monty-typeshed/custom/asyncio.pyi +0 -138
  1032. package/ref-monty/crates/monty-typeshed/custom/os.pyi +0 -87
  1033. package/ref-monty/crates/monty-typeshed/custom/sys.pyi +0 -33
  1034. package/ref-monty/crates/monty-typeshed/src/lib.rs +0 -56
  1035. package/ref-monty/crates/monty-typeshed/update.py +0 -321
  1036. package/ref-monty/crates/monty-typeshed/vendor/typeshed/source_commit.txt +0 -1
  1037. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/VERSIONS +0 -20
  1038. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_collections_abc.pyi +0 -105
  1039. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/_typeshed/__init__.pyi +0 -394
  1040. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/asyncio.pyi +0 -138
  1041. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/builtins.pyi +0 -1434
  1042. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/__init__.pyi +0 -527
  1043. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/collections/abc.pyi +0 -2
  1044. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/dataclasses.pyi +0 -502
  1045. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/enum.pyi +0 -376
  1046. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/math.pyi +0 -149
  1047. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/os.pyi +0 -87
  1048. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/__init__.pyi +0 -395
  1049. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/pathlib/types.pyi +0 -8
  1050. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/re.pyi +0 -337
  1051. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/sys.pyi +0 -33
  1052. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/types.pyi +0 -741
  1053. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing.pyi +0 -1217
  1054. package/ref-monty/crates/monty-typeshed/vendor/typeshed/stdlib/typing_extensions.pyi +0 -716
  1055. package/ref-monty/docs/usage-guide.md +0 -117
  1056. package/ref-monty/examples/README.md +0 -3
  1057. package/ref-monty/examples/expense_analysis/README.md +0 -3
  1058. package/ref-monty/examples/expense_analysis/data.py +0 -124
  1059. package/ref-monty/examples/expense_analysis/main.py +0 -115
  1060. package/ref-monty/examples/sql_playground/README.md +0 -20
  1061. package/ref-monty/examples/sql_playground/external_functions.py +0 -129
  1062. package/ref-monty/examples/sql_playground/main.py +0 -81
  1063. package/ref-monty/examples/sql_playground/sandbox_code.py +0 -82
  1064. package/ref-monty/examples/sql_playground/type_stubs.pyi +0 -14
  1065. package/ref-monty/examples/web_scraper/README.md +0 -15
  1066. package/ref-monty/examples/web_scraper/browser.py +0 -56
  1067. package/ref-monty/examples/web_scraper/example_code.py +0 -59
  1068. package/ref-monty/examples/web_scraper/external_functions.py +0 -324
  1069. package/ref-monty/examples/web_scraper/main.py +0 -193
  1070. package/ref-monty/examples/web_scraper/sub_agent.py +0 -79
  1071. package/ref-monty/monty-npm.md +0 -235
  1072. package/ref-monty/pyproject.toml +0 -162
  1073. package/ref-monty/scripts/check_imports.py +0 -91
  1074. package/ref-monty/scripts/codecov_diff.py +0 -412
  1075. package/ref-monty/scripts/complete_tests.py +0 -146
  1076. package/ref-monty/scripts/flamegraph_to_text.py +0 -208
  1077. package/ref-monty/scripts/iter_test_methods.py +0 -540
  1078. package/ref-monty/scripts/run_traceback.py +0 -180
  1079. package/ref-monty/scripts/startup_performance.py +0 -130
  1080. package/ref-monty/uv.lock +0 -1779
  1081. /package/docs/{plugin-examples.md → plugins-examples.md} +0 -0
@@ -1,1407 +0,0 @@
1
- //! The main `Monty` class and iterative execution support for the TypeScript/JavaScript bindings.
2
- //!
3
- //! Provides a sandboxed Python interpreter that can be configured with inputs
4
- //! and resource limits. External functions are provided at runtime via
5
- //! `RunOptions` or `StartOptions`. Supports both immediate execution
6
- //! via `run()` and iterative execution via `start()`/`resume()`.
7
- //!
8
- //! ## Quick Start
9
- //!
10
- //! ```typescript
11
- //! import { Monty } from 'monty';
12
- //!
13
- //! // Simple execution
14
- //! const m = new Monty('1 + 2');
15
- //! const result = m.run(); // returns 3
16
- //!
17
- //! // With inputs
18
- //! const m2 = new Monty('x + y', { inputs: ['x', 'y'] });
19
- //! const result2 = m2.run({ inputs: { x: 10, y: 20 } }); // returns 30
20
- //! ```
21
- //!
22
- //! ## Iterative Execution
23
- //!
24
- //! ```text
25
- //! Monty.start() -> MontySnapshot | MontyNameLookup | MontyComplete
26
- //! | |
27
- //! v v
28
- //! MontySnapshot.resume() / MontyNameLookup.resume()
29
- //! -> MontySnapshot | MontyNameLookup | MontyComplete
30
- //! | |
31
- //! v v
32
- //! (repeat until complete)
33
- //! ```
34
- //!
35
- //! ```typescript
36
- //! const m = new Monty('result = external_func(1, 2)');
37
- //!
38
- //! let progress = m.start();
39
- //! while (progress instanceof MontySnapshot) {
40
- //! console.log(`Calling ${progress.functionName} with args:`, progress.args);
41
- //! progress = progress.resume({ returnValue: 42 });
42
- //! }
43
- //! console.log('Final result:', progress.output);
44
- //! ```
45
-
46
- use std::borrow::Cow;
47
-
48
- use monty::{
49
- ExcType, ExtFunctionResult, FunctionCall, LimitedTracker, MontyException, MontyObject, MontyRepl as CoreMontyRepl,
50
- MontyRun, NameLookup, NameLookupResult, NoLimitTracker, OsCall, PrintWriter, PrintWriterCallback, ResourceTracker,
51
- RunProgress,
52
- };
53
- use monty_type_checking::{type_check, SourceFile};
54
- use napi::bindgen_prelude::*;
55
- use napi_derive::napi;
56
-
57
- use crate::{
58
- convert::{js_to_monty, monty_to_js, JsMontyObject},
59
- exceptions::{exc_js_to_monty, JsMontyException, MontyTypingError},
60
- limits::JsResourceLimits,
61
- };
62
-
63
- // =============================================================================
64
- // Monty - Main interpreter class
65
- // =============================================================================
66
-
67
- /// A sandboxed Python interpreter instance.
68
- ///
69
- /// Parses and compiles Python code on initialization, then can be run
70
- /// multiple times with different input values. This separates the parsing
71
- /// cost from execution, making repeated runs more efficient.
72
- #[napi]
73
- pub struct Monty {
74
- /// The compiled code runner, ready to execute.
75
- runner: MontyRun,
76
- /// The artificial name of the python code "file".
77
- script_name: String,
78
- /// Names of input variables expected by the code.
79
- input_names: Vec<String>,
80
- }
81
-
82
- /// Options for creating a new Monty instance.
83
- #[napi(object)]
84
- #[derive(Default)]
85
- pub struct MontyOptions {
86
- /// Name used in tracebacks and error messages. Default: 'main.py'
87
- pub script_name: Option<String>,
88
- /// List of input variable names available in the code.
89
- pub inputs: Option<Vec<String>>,
90
- /// Whether to perform type checking on the code. Default: false
91
- pub type_check: Option<bool>,
92
- /// Optional code to prepend before type checking.
93
- pub type_check_prefix_code: Option<String>,
94
- }
95
-
96
- /// Options for running code.
97
- #[napi(object)]
98
- #[derive(Default)]
99
- pub struct RunOptions<'env> {
100
- pub inputs: Option<Object<'env>>,
101
- /// Resource limits configuration.
102
- pub limits: Option<JsResourceLimits>,
103
- /// Optional print callback function.
104
- pub print_callback: Option<JsPrintCallback<'env>>,
105
- /// Dict of external function callbacks.
106
- /// Keys are function names, values are callable functions.
107
- pub external_functions: Option<Object<'env>>,
108
- }
109
-
110
- /// Options for starting execution.
111
- #[napi(object)]
112
- #[derive(Default)]
113
- pub struct StartOptions<'env> {
114
- /// Dict of input variable values.
115
- pub inputs: Option<Object<'env>>,
116
- /// Resource limits configuration.
117
- pub limits: Option<JsResourceLimits>,
118
- /// Optional print callback function.
119
- pub print_callback: Option<JsPrintCallback<'env>>,
120
- }
121
-
122
- #[napi]
123
- impl Monty {
124
- /// Creates a new Monty interpreter by parsing the given code.
125
- ///
126
- /// Returns either a Monty instance, a MontyException (for syntax errors), or a MontyTypingError.
127
- /// The wrapper should check the result type and throw the appropriate error.
128
- ///
129
- /// @param code - Python code to execute
130
- /// @param options - Configuration options
131
- /// @returns Monty instance on success, or error object on failure
132
- #[napi]
133
- pub fn create(
134
- code: String,
135
- options: Option<MontyOptions>,
136
- ) -> Result<Either3<Self, JsMontyException, MontyTypingError>> {
137
- let ResolvedMontyOptions {
138
- script_name,
139
- input_names,
140
- do_type_check,
141
- type_check_prefix_code,
142
- } = resolve_monty_options(options);
143
-
144
- // Perform type checking if requested
145
- if do_type_check {
146
- if let Some(error) = run_type_check_result(&code, &script_name, type_check_prefix_code.as_deref())? {
147
- return Ok(Either3::C(error));
148
- }
149
- }
150
-
151
- // Create the runner (parses the code)
152
- let runner = match MontyRun::new(code, &script_name, input_names.clone()) {
153
- Ok(r) => r,
154
- Err(exc) => return Ok(Either3::B(JsMontyException::new(exc))),
155
- };
156
-
157
- Ok(Either3::A(Self {
158
- runner,
159
- script_name,
160
- input_names,
161
- }))
162
- }
163
-
164
- /// Performs static type checking on the code.
165
- ///
166
- /// Returns either nothing (success) or a MontyTypingError.
167
- ///
168
- /// @param prefixCode - Optional code to prepend before type checking
169
- /// @returns null on success, or MontyTypingError on failure
170
- #[napi]
171
- pub fn type_check(&self, prefix_code: Option<String>) -> Result<Option<MontyTypingError>> {
172
- run_type_check_result(self.runner.code(), &self.script_name, prefix_code.as_deref())
173
- }
174
-
175
- /// Executes the code and returns the result, or an exception object if execution fails.
176
- ///
177
- /// If runtime `externalFunctions` are provided, the start/resume loop is used
178
- /// to dispatch external function calls and name lookups. Otherwise, code is
179
- /// executed directly.
180
- ///
181
- /// @param options - Execution options (inputs, limits, externalFunctions)
182
- /// @returns The result of the last expression, or a MontyException if execution fails
183
- #[napi]
184
- pub fn run<'env>(
185
- &self,
186
- env: &'env Env,
187
- options: Option<RunOptions<'env>>,
188
- ) -> Result<Either<JsMontyObject<'env>, JsMontyException>> {
189
- let options = options.unwrap_or_default();
190
- let input_values = self.extract_input_values(options.inputs, *env)?;
191
-
192
- let external_functions = options.external_functions;
193
-
194
- let mut print_cb;
195
- let print_writer = match &options.print_callback {
196
- Some(func) => {
197
- print_cb = CallbackStringPrint::new_js(env, func)?;
198
- PrintWriter::Callback(&mut print_cb)
199
- }
200
- None => PrintWriter::Stdout,
201
- };
202
-
203
- // If we have runtime external functions, use the start/resume loop
204
- // to handle both FunctionCall and NameLookup dispatching
205
- if external_functions.is_some() {
206
- return self.run_with_external_functions(
207
- env,
208
- input_values,
209
- options.limits,
210
- external_functions,
211
- print_writer,
212
- );
213
- }
214
-
215
- let result = if let Some(limits) = options.limits {
216
- let tracker = LimitedTracker::new(limits.into());
217
- self.runner.run(input_values, tracker, print_writer)
218
- } else {
219
- let tracker = NoLimitTracker;
220
- self.runner.run(input_values, tracker, print_writer)
221
- };
222
-
223
- match result {
224
- Ok(value) => Ok(Either::A(monty_to_js(&value, env)?)),
225
- Err(exc) => Ok(Either::B(JsMontyException::new(exc))),
226
- }
227
- }
228
-
229
- /// Internal helper to run code with external function callbacks.
230
- ///
231
- /// Handles both `FunctionCall` and `NameLookup` dispatch in a loop.
232
- /// For `NameLookup`, checks the runtime external functions map: if the name
233
- /// is found, resolves it as a `Function`; otherwise returns `Undefined`.
234
- fn run_with_external_functions<'env>(
235
- &self,
236
- env: &'env Env,
237
- input_values: Vec<MontyObject>,
238
- limits: Option<JsResourceLimits>,
239
- external_functions: Option<Object<'env>>,
240
- mut print_output: PrintWriter<'_>,
241
- ) -> Result<Either<JsMontyObject<'env>, JsMontyException>> {
242
- let runner = self.runner.clone();
243
-
244
- // Helper macro to handle the execution loop for both tracker types
245
- macro_rules! run_loop {
246
- ($tracker:expr) => {{
247
- let progress = runner.start(input_values, $tracker, print_output.reborrow());
248
-
249
- let mut progress = match progress {
250
- Ok(p) => p,
251
- Err(exc) => return Ok(Either::B(JsMontyException::new(exc))),
252
- };
253
-
254
- loop {
255
- match progress {
256
- RunProgress::Complete(result) => {
257
- return Ok(Either::A(monty_to_js(&result, env)?));
258
- }
259
- RunProgress::FunctionCall(call) => {
260
- let return_value = call_external_function(
261
- env,
262
- external_functions.as_ref(),
263
- &call.function_name,
264
- &call.args,
265
- &call.kwargs,
266
- )?;
267
-
268
- progress = match call.resume(return_value, print_output.reborrow()) {
269
- Ok(p) => p,
270
- Err(exc) => return Ok(Either::B(JsMontyException::new(exc))),
271
- };
272
- }
273
- RunProgress::NameLookup(lookup) => {
274
- let result = resolve_name_lookup(external_functions.as_ref(), &lookup.name)?;
275
- progress = match lookup.resume(result, print_output.reborrow()) {
276
- Ok(p) => p,
277
- Err(exc) => return Ok(Either::B(JsMontyException::new(exc))),
278
- };
279
- }
280
- RunProgress::ResolveFutures(_) => {
281
- return Err(Error::from_reason(
282
- "Async futures are not supported in synchronous run(). Use start() for async execution.",
283
- ));
284
- }
285
- RunProgress::OsCall(OsCall { function, .. }) => {
286
- return Ok(Either::B(JsMontyException::new(MontyException::new(
287
- ExcType::NotImplementedError,
288
- Some(format!("OS function '{function}' not implemented")),
289
- ))));
290
- }
291
- }
292
- }
293
- }};
294
- }
295
-
296
- if let Some(limits) = limits {
297
- let tracker = LimitedTracker::new(limits.into());
298
- run_loop!(tracker)
299
- } else {
300
- run_loop!(NoLimitTracker)
301
- }
302
- }
303
-
304
- /// Starts execution and returns a snapshot (paused at external call or name lookup),
305
- /// completion, or error.
306
- ///
307
- /// This method enables iterative execution where code pauses at external function
308
- /// calls or name lookups, allowing the host to provide return values before resuming.
309
- ///
310
- /// @param options - Execution options (inputs, limits)
311
- /// @returns MontySnapshot if paused at function call, MontyNameLookup if paused at
312
- /// name lookup, MontyComplete if done, or MontyException if failed
313
- #[napi]
314
- pub fn start<'env>(
315
- &self,
316
- env: &'env Env,
317
- options: Option<StartOptions<'env>>,
318
- ) -> Result<Either4<MontySnapshot, MontyNameLookup, MontyComplete, JsMontyException>> {
319
- let options = options.unwrap_or_default();
320
- let input_values = self.extract_input_values(options.inputs, *env)?;
321
-
322
- // Clone the runner since start() consumes it - allows reuse of the parsed code
323
- let runner = self.runner.clone();
324
-
325
- // Build print writer and capture the callback ref for the snapshot
326
- let mut print_cb;
327
- let print_writer = match &options.print_callback {
328
- Some(func) => {
329
- print_cb = CallbackStringPrint::new_js(env, func)?;
330
- PrintWriter::Callback(&mut print_cb)
331
- }
332
- None => PrintWriter::Stdout,
333
- };
334
- let print_callback_ref = options.print_callback.as_ref().map(Function::create_ref).transpose()?;
335
-
336
- // Start execution with appropriate tracker
337
- if let Some(limits) = options.limits {
338
- let tracker = LimitedTracker::new(limits.into());
339
- let progress = match runner.start(input_values, tracker, print_writer) {
340
- Ok(p) => p,
341
- Err(exc) => return Ok(Either4::D(JsMontyException::new(exc))),
342
- };
343
- Ok(progress_to_result(progress, print_callback_ref, self.script_name()))
344
- } else {
345
- let tracker = NoLimitTracker;
346
- let progress = match runner.start(input_values, tracker, print_writer) {
347
- Ok(p) => p,
348
- Err(exc) => return Ok(Either4::D(JsMontyException::new(exc))),
349
- };
350
- Ok(progress_to_result(progress, print_callback_ref, self.script_name()))
351
- }
352
- }
353
-
354
- /// Serializes the Monty instance to a binary format.
355
- ///
356
- /// The serialized data can be stored and later restored with `Monty.load()`.
357
- /// This allows caching parsed code to avoid re-parsing on subsequent runs.
358
- ///
359
- /// @returns Buffer containing the serialized Monty instance
360
- #[napi]
361
- pub fn dump(&self) -> Result<Buffer> {
362
- let serialized = SerializedMonty {
363
- runner: self.runner.clone(),
364
- script_name: self.script_name.clone(),
365
- input_names: self.input_names.clone(),
366
- };
367
- let bytes =
368
- postcard::to_allocvec(&serialized).map_err(|e| Error::from_reason(format!("Serialization failed: {e}")))?;
369
- Ok(Buffer::from(bytes))
370
- }
371
-
372
- /// Deserializes a Monty instance from binary format.
373
- ///
374
- /// @param data - The serialized Monty data from `dump()`
375
- /// @returns A new Monty instance
376
- #[napi(factory)]
377
- pub fn load(data: Buffer) -> Result<Self> {
378
- let serialized: SerializedMonty =
379
- postcard::from_bytes(&data).map_err(|e| Error::from_reason(format!("Deserialization failed: {e}")))?;
380
-
381
- Ok(Self {
382
- runner: serialized.runner,
383
- script_name: serialized.script_name,
384
- input_names: serialized.input_names,
385
- })
386
- }
387
-
388
- /// Returns the script name.
389
- #[napi(getter)]
390
- pub fn script_name(&self) -> String {
391
- self.script_name.clone()
392
- }
393
-
394
- /// Returns the input variable names.
395
- #[napi(getter)]
396
- pub fn inputs(&self) -> Vec<String> {
397
- self.input_names.clone()
398
- }
399
-
400
- /// Returns a string representation of the Monty instance.
401
- #[napi]
402
- pub fn repr(&self) -> String {
403
- use std::fmt::Write;
404
- let lines = self.runner.code().lines().count();
405
- let mut s = format!(
406
- "Monty(<{} line{} of code>, scriptName='{}'",
407
- lines,
408
- if lines == 1 { "" } else { "s" },
409
- self.script_name
410
- );
411
- if !self.input_names.is_empty() {
412
- write!(s, ", inputs={:?}", self.input_names).unwrap();
413
- }
414
- s.push(')');
415
- s
416
- }
417
-
418
- /// Extracts input values from the JS Object in the order they were declared.
419
- fn extract_input_values(&self, inputs: Option<Object<'_>>, env: Env) -> Result<Vec<MontyObject>> {
420
- extract_input_values_in_order(&self.input_names, inputs, env)
421
- }
422
- }
423
-
424
- /// Performs type checking on the code and returns the error object if there are type errors.
425
- ///
426
- /// Returns `None` if type checking passes, or `Some(MontyTypingError)` if there are errors.
427
- fn run_type_check_result(code: &str, script_name: &str, prefix_code: Option<&str>) -> Result<Option<MontyTypingError>> {
428
- let source_code: Cow<str> = if let Some(prefix_code) = prefix_code {
429
- format!("{prefix_code}\n{code}").into()
430
- } else {
431
- code.into()
432
- };
433
-
434
- let source_file = SourceFile::new(&source_code, script_name);
435
- let result =
436
- type_check(&source_file, None).map_err(|e| Error::from_reason(format!("Type checking failed: {e}")))?;
437
-
438
- Ok(result.map(MontyTypingError::from_failure))
439
- }
440
-
441
- // =============================================================================
442
- // MontyRepl - Incremental no-replay REPL session
443
- // =============================================================================
444
-
445
- /// REPL state holder for napi interoperability.
446
- ///
447
- /// `napi` classes cannot be generic, so this enum stores REPL sessions for both
448
- /// resource tracker variants.
449
- #[derive(Debug, serde::Serialize, serde::Deserialize)]
450
- enum EitherRepl {
451
- NoLimit(CoreMontyRepl<NoLimitTracker>),
452
- Limited(CoreMontyRepl<LimitedTracker>),
453
- }
454
-
455
- /// Options for creating a new `MontyRepl` instance.
456
- ///
457
- /// Controls the script name shown in tracebacks and optional resource limits
458
- /// that apply to all subsequent `feed()` calls.
459
- #[napi(object)]
460
- #[derive(Default)]
461
- pub struct MontyReplOptions {
462
- /// Name used in tracebacks and error messages. Default: 'main.py'
463
- pub script_name: Option<String>,
464
- /// Resource limits configuration applied to all snippet executions.
465
- pub limits: Option<JsResourceLimits>,
466
- }
467
-
468
- /// Stateful no-replay REPL session.
469
- ///
470
- /// Create with `new MontyRepl()` then call `feed()` to execute snippets
471
- /// incrementally against persistent heap and namespace state.
472
- #[napi]
473
- pub struct MontyRepl {
474
- repl: EitherRepl,
475
- script_name: String,
476
- }
477
-
478
- #[napi]
479
- impl MontyRepl {
480
- /// Creates an empty REPL session ready to receive snippets via `feed()`.
481
- ///
482
- /// No code is parsed or executed at construction time — all execution
483
- /// is driven through `feed()`.
484
- ///
485
- /// @param options - Optional configuration (scriptName, limits)
486
- #[napi(constructor)]
487
- #[must_use]
488
- pub fn new(options: Option<MontyReplOptions>) -> Self {
489
- let options = options.unwrap_or_default();
490
- let script_name = options.script_name.unwrap_or_else(|| "main.py".to_string());
491
-
492
- let repl = if let Some(limits) = options.limits {
493
- let tracker = LimitedTracker::new(limits.into());
494
- EitherRepl::Limited(CoreMontyRepl::new(&script_name, tracker))
495
- } else {
496
- EitherRepl::NoLimit(CoreMontyRepl::new(&script_name, NoLimitTracker))
497
- };
498
-
499
- Self { repl, script_name }
500
- }
501
-
502
- /// Returns the script name for this REPL session.
503
- #[napi(getter)]
504
- #[must_use]
505
- pub fn script_name(&self) -> String {
506
- self.script_name.clone()
507
- }
508
-
509
- /// Executes one incremental snippet against persistent REPL state.
510
- #[napi]
511
- pub fn feed<'env>(
512
- &mut self,
513
- env: &'env Env,
514
- code: String,
515
- ) -> Result<Either<JsMontyObject<'env>, JsMontyException>> {
516
- let output = match &mut self.repl {
517
- EitherRepl::NoLimit(repl) => repl.feed_run(&code, vec![], PrintWriter::Stdout),
518
- EitherRepl::Limited(repl) => repl.feed_run(&code, vec![], PrintWriter::Stdout),
519
- };
520
-
521
- match output {
522
- Ok(value) => Ok(Either::A(monty_to_js(&value, env)?)),
523
- Err(exc) => Ok(Either::B(JsMontyException::new(exc))),
524
- }
525
- }
526
-
527
- /// Serializes this REPL session to bytes.
528
- #[napi]
529
- pub fn dump(&self) -> Result<Buffer> {
530
- let serialized = SerializedRepl {
531
- repl: &self.repl,
532
- script_name: &self.script_name,
533
- };
534
- let bytes =
535
- postcard::to_allocvec(&serialized).map_err(|e| Error::from_reason(format!("Serialization failed: {e}")))?;
536
- Ok(Buffer::from(bytes))
537
- }
538
-
539
- /// Restores a REPL session from bytes produced by `dump()`.
540
- #[napi(factory)]
541
- pub fn load(data: Buffer) -> Result<Self> {
542
- let serialized: SerializedReplOwned =
543
- postcard::from_bytes(&data).map_err(|e| Error::from_reason(format!("Deserialization failed: {e}")))?;
544
- Ok(Self {
545
- repl: serialized.repl,
546
- script_name: serialized.script_name,
547
- })
548
- }
549
-
550
- /// Returns a string representation of the REPL session.
551
- #[napi]
552
- #[must_use]
553
- pub fn repr(&self) -> String {
554
- format!("MontyRepl(scriptName='{}')", self.script_name)
555
- }
556
- }
557
-
558
- /// Fully resolved creation options shared by `Monty` and `MontyRepl`.
559
- ///
560
- /// This keeps parsing/type-checking defaults consistent across non-REPL and
561
- /// REPL entry points.
562
- struct ResolvedMontyOptions {
563
- script_name: String,
564
- input_names: Vec<String>,
565
- do_type_check: bool,
566
- type_check_prefix_code: Option<String>,
567
- }
568
-
569
- /// Normalizes optional JS-facing creation options into concrete defaults.
570
- fn resolve_monty_options(options: Option<MontyOptions>) -> ResolvedMontyOptions {
571
- let options = options.unwrap_or(MontyOptions {
572
- script_name: None,
573
- inputs: None,
574
- type_check: None,
575
- type_check_prefix_code: None,
576
- });
577
-
578
- ResolvedMontyOptions {
579
- script_name: options.script_name.unwrap_or_else(|| "main.py".to_string()),
580
- input_names: options.inputs.unwrap_or_default(),
581
- do_type_check: options.type_check.unwrap_or(false),
582
- type_check_prefix_code: options.type_check_prefix_code,
583
- }
584
- }
585
-
586
- /// Extracts input values in declaration order from a JS object.
587
- ///
588
- /// This helper is shared by regular `Monty` execution and direct REPL creation
589
- /// so both paths perform identical input validation.
590
- fn extract_input_values_in_order(
591
- input_names: &[String],
592
- inputs: Option<Object<'_>>,
593
- env: Env,
594
- ) -> Result<Vec<MontyObject>> {
595
- if input_names.is_empty() {
596
- if inputs.is_some() {
597
- return Err(Error::from_reason(
598
- "No input variables declared but inputs object was provided",
599
- ));
600
- }
601
- return Ok(vec![]);
602
- }
603
-
604
- let Some(inputs) = inputs else {
605
- return Err(Error::from_reason(format!("Missing required inputs: {input_names:?}")));
606
- };
607
-
608
- input_names
609
- .iter()
610
- .map(|name| {
611
- if !inputs.has_named_property(name)? {
612
- return Err(Error::from_reason(format!("Missing required input: '{name}'")));
613
- }
614
- let value: Unknown = inputs.get_named_property(name)?;
615
- js_to_monty(value, env)
616
- })
617
- .collect()
618
- }
619
-
620
- // =============================================================================
621
- // EitherSnapshot - Internal enum to handle generic resource tracker types
622
- // =============================================================================
623
-
624
- /// Runtime execution snapshot, holds a `FunctionCall` for either resource tracker variant
625
- /// since napi structs can't be generic.
626
- ///
627
- /// Used internally by `MontySnapshot` to store execution state.
628
- /// The `Done` variant indicates the snapshot has been consumed.
629
- #[derive(Debug, serde::Serialize, serde::Deserialize)]
630
- enum EitherSnapshot {
631
- NoLimit(FunctionCall<NoLimitTracker>),
632
- Limited(FunctionCall<LimitedTracker>),
633
- /// Sentinel indicating the snapshot has been consumed via `resume()`.
634
- Done,
635
- }
636
-
637
- // =============================================================================
638
- // MontySnapshot - Paused execution at an external function call
639
- // =============================================================================
640
-
641
- /// Represents paused execution waiting for an external function call return value.
642
- ///
643
- /// Contains information about the pending external function call and allows
644
- /// resuming execution with the return value or an exception.
645
- #[napi]
646
- pub struct MontySnapshot {
647
- /// The execution state that can be resumed.
648
- snapshot: EitherSnapshot,
649
- /// Name of the script being executed.
650
- script_name: String,
651
- /// The name of the external function being called.
652
- function_name: String,
653
- /// The positional arguments passed to the function (stored as MontyObject for serialization).
654
- args: Vec<MontyObject>,
655
- /// The keyword arguments passed to the function (stored as MontyObject pairs for serialization).
656
- kwargs: Vec<(MontyObject, MontyObject)>,
657
- /// Optional print callback function.
658
- print_callback: Option<JsPrintCallbackRef>,
659
- }
660
-
661
- /// Options for resuming execution.
662
- #[napi(object)]
663
- pub struct ResumeOptions<'env> {
664
- /// The value to return from the external function call.
665
- pub return_value: Option<Unknown<'env>>,
666
- /// An exception to raise in the interpreter.
667
- /// Format: { type: string, message: string }
668
- pub exception: Option<ExceptionInput>,
669
- }
670
-
671
- /// Input for raising an exception during resume.
672
- #[napi(object)]
673
- pub struct ExceptionInput {
674
- /// The exception type name (e.g., "ValueError").
675
- pub r#type: String,
676
- /// The exception message.
677
- pub message: String,
678
- }
679
-
680
- /// Options for loading a serialized snapshot.
681
- #[napi(object)]
682
- pub struct SnapshotLoadOptions<'env> {
683
- /// Optional print callback function.
684
- pub print_callback: Option<JsPrintCallback<'env>>,
685
- // Future: could add dataclass-like registry support
686
- }
687
-
688
- #[napi]
689
- impl MontySnapshot {
690
- /// Returns the name of the script being executed.
691
- #[napi(getter)]
692
- pub fn script_name(&self) -> String {
693
- self.script_name.clone()
694
- }
695
-
696
- /// Returns the name of the external function being called.
697
- #[napi(getter)]
698
- pub fn function_name(&self) -> String {
699
- self.function_name.clone()
700
- }
701
-
702
- /// Returns the positional arguments passed to the external function.
703
- #[napi(getter)]
704
- pub fn args<'env>(&self, env: &'env Env) -> Result<Vec<JsMontyObject<'env>>> {
705
- self.args.iter().map(|obj| monty_to_js(obj, env)).collect()
706
- }
707
-
708
- /// Returns the keyword arguments passed to the external function as an object.
709
- #[napi(getter)]
710
- pub fn kwargs<'env>(&self, env: &'env Env) -> Result<Object<'env>> {
711
- let mut obj = Object::new(env)?;
712
- for (k, v) in &self.kwargs {
713
- // Keys should be strings
714
- let key = match k {
715
- MontyObject::String(s) => s.clone(),
716
- _ => format!("{k:?}"),
717
- };
718
- let js_value = monty_to_js(v, env)?;
719
- obj.set_named_property(&key, js_value)?;
720
- }
721
- Ok(obj)
722
- }
723
-
724
- /// Resumes execution with either a return value or an exception.
725
- ///
726
- /// Exactly one of `returnValue` or `exception` must be provided.
727
- ///
728
- /// @param options - Object with either `returnValue` or `exception`
729
- /// @returns MontySnapshot if paused at function call, MontyNameLookup if paused at
730
- /// name lookup, MontyComplete if done, or MontyException if failed
731
- #[napi]
732
- pub fn resume<'env>(
733
- &mut self,
734
- env: &'env Env,
735
- options: ResumeOptions<'env>,
736
- ) -> Result<Either4<Self, MontyNameLookup, MontyComplete, JsMontyException>> {
737
- // Validate that exactly one of returnValue or exception is provided
738
- let external_result = match (options.return_value, options.exception) {
739
- (Some(value), None) => {
740
- let monty_value = js_to_monty(value, *env)?;
741
- ExtFunctionResult::Return(monty_value)
742
- }
743
- (None, Some(exc)) => {
744
- let monty_exc = MontyException::new(string_to_exc_type(&exc.r#type)?, Some(exc.message));
745
- ExtFunctionResult::Error(monty_exc)
746
- }
747
- (Some(_), Some(_)) => {
748
- return Err(Error::from_reason(
749
- "resume() accepts either returnValue or exception, not both",
750
- ));
751
- }
752
- (None, None) => {
753
- return Err(Error::from_reason("resume() requires either returnValue or exception"));
754
- }
755
- };
756
-
757
- // Take the snapshot, replacing with Done
758
- let snapshot = std::mem::replace(&mut self.snapshot, EitherSnapshot::Done);
759
-
760
- // Take the print callback
761
- // This is necessary to move out of `&mut self` to please the borrow checker.
762
- // Unless the entire snapshot generator is refactored we have to do this.
763
- let print_callback = std::mem::take(&mut self.print_callback);
764
-
765
- // Build print writer from the callback ref
766
- let mut print_cb;
767
- let print_writer = match &print_callback {
768
- Some(func) => {
769
- print_cb = CallbackStringPrint::new_js_ref(env, func)?;
770
- PrintWriter::Callback(&mut print_cb)
771
- }
772
- None => PrintWriter::Stdout,
773
- };
774
-
775
- // Resume execution based on the snapshot type
776
- match snapshot {
777
- EitherSnapshot::NoLimit(call) => {
778
- let progress = match call.resume(external_result, print_writer) {
779
- Ok(p) => p,
780
- Err(exc) => return Ok(Either4::D(JsMontyException::new(exc))),
781
- };
782
- Ok(progress_to_result(progress, print_callback, self.script_name.clone()))
783
- }
784
- EitherSnapshot::Limited(call) => {
785
- let progress = match call.resume(external_result, print_writer) {
786
- Ok(p) => p,
787
- Err(exc) => return Ok(Either4::D(JsMontyException::new(exc))),
788
- };
789
- Ok(progress_to_result(progress, print_callback, self.script_name.clone()))
790
- }
791
- EitherSnapshot::Done => Err(Error::from_reason("Snapshot has already been resumed")),
792
- }
793
- }
794
-
795
- /// Serializes the MontySnapshot to a binary format.
796
- ///
797
- /// The serialized data can be stored and later restored with `MontySnapshot.load()`.
798
- /// This allows suspending execution and resuming later, potentially in a different process.
799
- ///
800
- /// @returns Buffer containing the serialized snapshot
801
- #[napi]
802
- pub fn dump(&self) -> Result<Buffer> {
803
- if matches!(self.snapshot, EitherSnapshot::Done) {
804
- return Err(Error::from_reason("Cannot dump snapshot that has already been resumed"));
805
- }
806
-
807
- let serialized = SerializedSnapshot {
808
- snapshot: &self.snapshot,
809
- script_name: &self.script_name,
810
- function_name: &self.function_name,
811
- args: &self.args,
812
- kwargs: &self.kwargs,
813
- };
814
-
815
- let bytes =
816
- postcard::to_allocvec(&serialized).map_err(|e| Error::from_reason(format!("Serialization failed: {e}")))?;
817
- Ok(Buffer::from(bytes))
818
- }
819
-
820
- /// Deserializes a MontySnapshot from binary format.
821
- ///
822
- /// @param data - The serialized snapshot data from `dump()`
823
- /// @param options - Optional load options (reserved for future use)
824
- /// @returns A new MontySnapshot instance
825
- #[napi(factory)]
826
- pub fn load(data: Buffer, options: Option<SnapshotLoadOptions>) -> Result<Self> {
827
- let serialized: SerializedSnapshotOwned =
828
- postcard::from_bytes(&data).map_err(|e| Error::from_reason(format!("Deserialization failed: {e}")))?;
829
-
830
- Ok(Self {
831
- snapshot: serialized.snapshot,
832
- script_name: serialized.script_name,
833
- function_name: serialized.function_name,
834
- args: serialized.args,
835
- kwargs: serialized.kwargs,
836
- print_callback: options
837
- .as_ref()
838
- .and_then(|t| t.print_callback.as_ref())
839
- .map(Function::create_ref)
840
- .transpose()?,
841
- })
842
- }
843
-
844
- /// Returns a string representation of the MontySnapshot.
845
- #[napi]
846
- pub fn repr(&self) -> String {
847
- format!(
848
- "MontySnapshot(scriptName='{}', functionName='{}', args={:?}, kwargs={:?})",
849
- self.script_name, self.function_name, self.args, self.kwargs
850
- )
851
- }
852
- }
853
-
854
- // =============================================================================
855
- // MontyComplete - Completed execution
856
- // =============================================================================
857
-
858
- /// Represents completed execution with a final output value.
859
- ///
860
- /// The output value is stored as a `MontyObject` internally and converted to JS on access.
861
- #[napi]
862
- pub struct MontyComplete {
863
- /// The final output value from the executed code.
864
- output_value: MontyObject,
865
- }
866
-
867
- #[napi]
868
- impl MontyComplete {
869
- /// Returns the final output value from the executed code.
870
- #[napi(getter)]
871
- pub fn output<'env>(&self, env: &'env Env) -> Result<JsMontyObject<'env>> {
872
- monty_to_js(&self.output_value, env)
873
- }
874
-
875
- /// Returns a string representation of the MontyComplete.
876
- #[napi]
877
- #[must_use]
878
- pub fn repr(&self) -> String {
879
- format!("MontyComplete(output={:?})", self.output_value)
880
- }
881
- }
882
-
883
- // =============================================================================
884
- // EitherLookupSnapshot - Internal enum for NameLookup tracker variants
885
- // =============================================================================
886
-
887
- /// Runtime execution snapshot, holds a `NameLookup` for either resource tracker variant
888
- /// since napi structs can't be generic.
889
- ///
890
- /// The `Done` variant indicates the snapshot has been consumed.
891
- #[derive(Debug, serde::Serialize, serde::Deserialize)]
892
- enum EitherLookupSnapshot {
893
- NoLimit(NameLookup<NoLimitTracker>),
894
- Limited(NameLookup<LimitedTracker>),
895
- /// Sentinel indicating the snapshot has been consumed via `resume()`.
896
- Done,
897
- }
898
-
899
- /// Trait to convert a typed `NameLookup` into `EitherLookupSnapshot`.
900
- trait FromLookupSnapshot<T: ResourceTracker> {
901
- /// Wraps a name-lookup snapshot.
902
- fn from_lookup(lookup: NameLookup<T>) -> Self;
903
- }
904
-
905
- impl FromLookupSnapshot<NoLimitTracker> for EitherLookupSnapshot {
906
- fn from_lookup(lookup: NameLookup<NoLimitTracker>) -> Self {
907
- Self::NoLimit(lookup)
908
- }
909
- }
910
-
911
- impl FromLookupSnapshot<LimitedTracker> for EitherLookupSnapshot {
912
- fn from_lookup(lookup: NameLookup<LimitedTracker>) -> Self {
913
- Self::Limited(lookup)
914
- }
915
- }
916
-
917
- // =============================================================================
918
- // MontyNameLookup - Paused execution at a name lookup
919
- // =============================================================================
920
-
921
- /// Represents paused execution waiting for a name to be resolved.
922
- ///
923
- /// The host should check if the variable name corresponds to a known value
924
- /// (e.g., an external function). Call `resume()` with the value to continue
925
- /// execution, or call `resume()` with no value to raise `NameError`.
926
- #[napi]
927
- pub struct MontyNameLookup {
928
- /// The execution state that can be resumed.
929
- snapshot: EitherLookupSnapshot,
930
- /// Name of the script being executed.
931
- script_name: String,
932
- /// The name of the variable being looked up.
933
- variable_name: String,
934
- /// Optional print callback function.
935
- print_callback: Option<JsPrintCallbackRef>,
936
- }
937
-
938
- /// Options for resuming execution from a name lookup.
939
- ///
940
- /// If `value` is provided, the name resolves to that value and execution continues.
941
- /// If `value` is omitted or undefined, the VM raises a `NameError`.
942
- #[napi(object)]
943
- pub struct NameLookupResumeOptions<'env> {
944
- /// The value to provide for the name.
945
- pub value: Option<Unknown<'env>>,
946
- }
947
-
948
- /// Options for loading a serialized name lookup snapshot.
949
- #[napi(object)]
950
- pub struct NameLookupLoadOptions<'env> {
951
- /// Optional print callback function.
952
- pub print_callback: Option<JsPrintCallback<'env>>,
953
- }
954
-
955
- #[napi]
956
- impl MontyNameLookup {
957
- /// Returns the name of the script being executed.
958
- #[napi(getter)]
959
- pub fn script_name(&self) -> String {
960
- self.script_name.clone()
961
- }
962
-
963
- /// Returns the name of the variable being looked up.
964
- #[napi(getter)]
965
- pub fn variable_name(&self) -> String {
966
- self.variable_name.clone()
967
- }
968
-
969
- /// Resumes execution after resolving the name lookup.
970
- ///
971
- /// If `value` is provided, the name resolves to that value and execution continues.
972
- /// If `value` is omitted or undefined, the VM raises a `NameError`.
973
- ///
974
- /// @param options - Optional object with `value` to resolve the name to
975
- /// @returns MontySnapshot if paused at function call, MontyNameLookup if paused at
976
- /// another name lookup, MontyComplete if done, or MontyException if failed
977
- #[napi]
978
- pub fn resume<'env>(
979
- &mut self,
980
- env: &'env Env,
981
- options: Option<NameLookupResumeOptions<'env>>,
982
- ) -> Result<Either4<MontySnapshot, Self, MontyComplete, JsMontyException>> {
983
- let lookup_result = match options.and_then(|opts| opts.value) {
984
- Some(value) => {
985
- let monty_value = js_to_monty(value, *env)?;
986
- NameLookupResult::Value(monty_value)
987
- }
988
- None => NameLookupResult::Undefined,
989
- };
990
-
991
- // Take the snapshot, replacing with Done
992
- let snapshot = std::mem::replace(&mut self.snapshot, EitherLookupSnapshot::Done);
993
-
994
- // Take the print callback
995
- let print_callback = std::mem::take(&mut self.print_callback);
996
-
997
- // Build print writer from the callback ref
998
- let mut print_cb;
999
- let print_writer = match &print_callback {
1000
- Some(func) => {
1001
- print_cb = CallbackStringPrint::new_js_ref(env, func)?;
1002
- PrintWriter::Callback(&mut print_cb)
1003
- }
1004
- None => PrintWriter::Stdout,
1005
- };
1006
-
1007
- match snapshot {
1008
- EitherLookupSnapshot::NoLimit(lookup) => {
1009
- let progress = match lookup.resume(lookup_result, print_writer) {
1010
- Ok(p) => p,
1011
- Err(exc) => return Ok(Either4::D(JsMontyException::new(exc))),
1012
- };
1013
- Ok(progress_to_result(progress, print_callback, self.script_name.clone()))
1014
- }
1015
- EitherLookupSnapshot::Limited(lookup) => {
1016
- let progress = match lookup.resume(lookup_result, print_writer) {
1017
- Ok(p) => p,
1018
- Err(exc) => return Ok(Either4::D(JsMontyException::new(exc))),
1019
- };
1020
- Ok(progress_to_result(progress, print_callback, self.script_name.clone()))
1021
- }
1022
- EitherLookupSnapshot::Done => Err(Error::from_reason("Name lookup has already been resumed")),
1023
- }
1024
- }
1025
-
1026
- /// Serializes the MontyNameLookup to a binary format.
1027
- ///
1028
- /// The serialized data can be stored and later restored with `MontyNameLookup.load()`.
1029
- ///
1030
- /// @returns Buffer containing the serialized name lookup snapshot
1031
- #[napi]
1032
- pub fn dump(&self) -> Result<Buffer> {
1033
- if matches!(self.snapshot, EitherLookupSnapshot::Done) {
1034
- return Err(Error::from_reason(
1035
- "Cannot dump name lookup that has already been resumed",
1036
- ));
1037
- }
1038
-
1039
- let serialized = SerializedNameLookup {
1040
- snapshot: &self.snapshot,
1041
- script_name: &self.script_name,
1042
- variable_name: &self.variable_name,
1043
- };
1044
-
1045
- let bytes =
1046
- postcard::to_allocvec(&serialized).map_err(|e| Error::from_reason(format!("Serialization failed: {e}")))?;
1047
- Ok(Buffer::from(bytes))
1048
- }
1049
-
1050
- /// Deserializes a MontyNameLookup from binary format.
1051
- ///
1052
- /// @param data - The serialized data from `dump()`
1053
- /// @param options - Optional load options
1054
- /// @returns A new MontyNameLookup instance
1055
- #[napi(factory)]
1056
- pub fn load(data: Buffer, options: Option<NameLookupLoadOptions>) -> Result<Self> {
1057
- let serialized: SerializedNameLookupOwned =
1058
- postcard::from_bytes(&data).map_err(|e| Error::from_reason(format!("Deserialization failed: {e}")))?;
1059
-
1060
- Ok(Self {
1061
- snapshot: serialized.snapshot,
1062
- script_name: serialized.script_name,
1063
- variable_name: serialized.variable_name,
1064
- print_callback: options
1065
- .as_ref()
1066
- .and_then(|t| t.print_callback.as_ref())
1067
- .map(Function::create_ref)
1068
- .transpose()?,
1069
- })
1070
- }
1071
-
1072
- /// Returns a string representation of the MontyNameLookup.
1073
- #[napi]
1074
- pub fn repr(&self) -> String {
1075
- format!(
1076
- "MontyNameLookup(scriptName='{}', variableName='{}')",
1077
- self.script_name, self.variable_name
1078
- )
1079
- }
1080
- }
1081
-
1082
- // Function type for JS callback used in `CallbackStringPrint`.
1083
- type JsPrintCallback<'env> = Function<'env, FnArgs<(&'static str, String)>, ()>;
1084
- type JsPrintCallbackRef = FunctionRef<FnArgs<(&'static str, String)>, ()>;
1085
-
1086
- /// A `PrintWriter` implementation that calls a javascript callback for each print output.
1087
- ///
1088
- /// This structure internally holds a `napi::Function`.
1089
- pub struct CallbackStringPrint<'env>(JsPrintCallback<'env>);
1090
-
1091
- impl<'env> CallbackStringPrint<'env> {
1092
- /// Creates a new `CallbackStringPrint` from a `JsFunction`.
1093
- pub fn new_js(env: &'env Env, func: &JsPrintCallback<'env>) -> napi::Result<Self> {
1094
- Ok(Self(func.create_ref()?.borrow_back(env)?))
1095
- }
1096
-
1097
- /// Creates a new printer from a function reference.
1098
- ///
1099
- /// This will re-borrow the function reference for use in printing.
1100
- pub fn new_js_ref(env: &'env Env, func: &JsPrintCallbackRef) -> napi::Result<Self> {
1101
- Ok(Self(func.borrow_back(env)?))
1102
- }
1103
- }
1104
-
1105
- impl PrintWriterCallback for CallbackStringPrint<'_> {
1106
- fn stdout_write(&mut self, output: Cow<'_, str>) -> std::result::Result<(), MontyException> {
1107
- self.0
1108
- .call(("stdout", output.as_ref().to_owned()).into())
1109
- .map_err(exc_js_to_monty)?;
1110
- Ok(())
1111
- }
1112
-
1113
- fn stdout_push(&mut self, end: char) -> std::result::Result<(), MontyException> {
1114
- self.0
1115
- .call(("stdout", end.to_string()).into())
1116
- .map_err(exc_js_to_monty)?;
1117
- Ok(())
1118
- }
1119
- }
1120
-
1121
- // =============================================================================
1122
- // Helper functions for progress conversion
1123
- // =============================================================================
1124
-
1125
- /// Converts a `RunProgress` to either a `MontySnapshot`, `MontyNameLookup`,
1126
- /// `MontyComplete`, or `JsMontyException`.
1127
- ///
1128
- /// `NameLookup` events are surfaced to the host as `MontyNameLookup` instances,
1129
- /// allowing the host to decide how to resolve each name (or let the VM raise `NameError`).
1130
- ///
1131
- /// For progress types that are not yet supported in the JS bindings (`ResolveFutures`, `OsCall`),
1132
- /// returns a `JsMontyException` with `NotImplementedError` instead of panicking, matching
1133
- /// the Python bindings behavior.
1134
- fn progress_to_result<T>(
1135
- progress: RunProgress<T>,
1136
- print_callback: Option<JsPrintCallbackRef>,
1137
- script_name: String,
1138
- ) -> Either4<MontySnapshot, MontyNameLookup, MontyComplete, JsMontyException>
1139
- where
1140
- T: ResourceTracker + serde::Serialize + serde::de::DeserializeOwned,
1141
- EitherSnapshot: FromSnapshot<T>,
1142
- EitherLookupSnapshot: FromLookupSnapshot<T>,
1143
- {
1144
- match progress {
1145
- RunProgress::Complete(result) => Either4::C(MontyComplete { output_value: result }),
1146
- RunProgress::FunctionCall(call) => {
1147
- let function_name = call.function_name.clone();
1148
- let args = call.args.clone();
1149
- let kwargs = call.kwargs.clone();
1150
- Either4::A(MontySnapshot {
1151
- snapshot: EitherSnapshot::from_snapshot(call),
1152
- script_name,
1153
- function_name,
1154
- args,
1155
- kwargs,
1156
- print_callback,
1157
- })
1158
- }
1159
- RunProgress::NameLookup(lookup) => {
1160
- let variable_name = lookup.name.clone();
1161
- Either4::B(MontyNameLookup {
1162
- snapshot: EitherLookupSnapshot::from_lookup(lookup),
1163
- script_name,
1164
- variable_name,
1165
- print_callback,
1166
- })
1167
- }
1168
- RunProgress::ResolveFutures(_) => Either4::D(JsMontyException::new(MontyException::new(
1169
- ExcType::NotImplementedError,
1170
- Some("Async futures (ResolveFutures) are not yet supported in the JS bindings".to_owned()),
1171
- ))),
1172
- RunProgress::OsCall(OsCall { function, .. }) => Either4::D(JsMontyException::new(MontyException::new(
1173
- ExcType::NotImplementedError,
1174
- Some(format!("OS function '{function}' not implemented")),
1175
- ))),
1176
- }
1177
- }
1178
-
1179
- /// Trait to convert a typed `FunctionCall` into `EitherSnapshot`.
1180
- trait FromSnapshot<T: ResourceTracker> {
1181
- /// Wraps a function-call snapshot.
1182
- fn from_snapshot(call: FunctionCall<T>) -> Self;
1183
- }
1184
-
1185
- impl FromSnapshot<NoLimitTracker> for EitherSnapshot {
1186
- fn from_snapshot(call: FunctionCall<NoLimitTracker>) -> Self {
1187
- Self::NoLimit(call)
1188
- }
1189
- }
1190
-
1191
- impl FromSnapshot<LimitedTracker> for EitherSnapshot {
1192
- fn from_snapshot(call: FunctionCall<LimitedTracker>) -> Self {
1193
- Self::Limited(call)
1194
- }
1195
- }
1196
-
1197
- /// Converts a string exception type to `ExcType`.
1198
- fn string_to_exc_type(type_name: &str) -> Result<ExcType> {
1199
- type_name
1200
- .parse()
1201
- .map_err(|_| Error::from_reason(format!("Invalid exception type: '{type_name}'")))
1202
- }
1203
-
1204
- // =============================================================================
1205
- // Serialization types
1206
- // =============================================================================
1207
-
1208
- /// Serialization wrapper for `Monty` that includes all fields needed for reconstruction.
1209
- #[derive(serde::Serialize, serde::Deserialize)]
1210
- struct SerializedMonty {
1211
- runner: MontyRun,
1212
- script_name: String,
1213
- input_names: Vec<String>,
1214
- }
1215
-
1216
- /// Serialization wrapper for `MontyRepl` using borrowed references.
1217
- #[derive(serde::Serialize)]
1218
- struct SerializedRepl<'a> {
1219
- repl: &'a EitherRepl,
1220
- script_name: &'a str,
1221
- }
1222
-
1223
- /// Owned version of `SerializedRepl` for deserialization.
1224
- #[derive(serde::Deserialize)]
1225
- struct SerializedReplOwned {
1226
- repl: EitherRepl,
1227
- script_name: String,
1228
- }
1229
-
1230
- /// Serialization wrapper for `MontySnapshot` using borrowed references.
1231
- #[derive(serde::Serialize)]
1232
- struct SerializedSnapshot<'a> {
1233
- snapshot: &'a EitherSnapshot,
1234
- script_name: &'a str,
1235
- function_name: &'a str,
1236
- args: &'a [MontyObject],
1237
- kwargs: &'a [(MontyObject, MontyObject)],
1238
- }
1239
-
1240
- /// Owned version of `SerializedSnapshot` for deserialization.
1241
- #[derive(serde::Deserialize)]
1242
- struct SerializedSnapshotOwned {
1243
- snapshot: EitherSnapshot,
1244
- script_name: String,
1245
- function_name: String,
1246
- args: Vec<MontyObject>,
1247
- kwargs: Vec<(MontyObject, MontyObject)>,
1248
- }
1249
-
1250
- /// Serialization wrapper for `MontyNameLookup` using borrowed references.
1251
- #[derive(serde::Serialize)]
1252
- struct SerializedNameLookup<'a> {
1253
- snapshot: &'a EitherLookupSnapshot,
1254
- script_name: &'a str,
1255
- variable_name: &'a str,
1256
- }
1257
-
1258
- /// Owned version of `SerializedNameLookup` for deserialization.
1259
- #[derive(serde::Deserialize)]
1260
- struct SerializedNameLookupOwned {
1261
- snapshot: EitherLookupSnapshot,
1262
- script_name: String,
1263
- variable_name: String,
1264
- }
1265
-
1266
- // =============================================================================
1267
- // External function support
1268
- // =============================================================================
1269
-
1270
- /// Calls a JavaScript external function and returns the result.
1271
- ///
1272
- /// Converts args/kwargs from Monty format, calls the JS function,
1273
- /// and converts the result back to Monty format (or an exception).
1274
- fn call_external_function(
1275
- env: &Env,
1276
- external_functions: Option<&Object<'_>>,
1277
- function_name: &str,
1278
- args: &[MontyObject],
1279
- kwargs: &[(MontyObject, MontyObject)],
1280
- ) -> Result<ExtFunctionResult> {
1281
- // Get the external functions dict, or error if not provided
1282
- let functions = external_functions.ok_or_else(|| {
1283
- Error::from_reason(format!(
1284
- "External function '{function_name}' called but no externalFunctions provided"
1285
- ))
1286
- })?;
1287
-
1288
- // Look up the function by name
1289
- if !functions.has_named_property(function_name)? {
1290
- // Return a NameError exception — matches Python's behavior for undefined names
1291
- let exc = MontyException::new(
1292
- ExcType::NameError,
1293
- Some(format!("name '{function_name}' is not defined")),
1294
- );
1295
- return Ok(ExtFunctionResult::Error(exc));
1296
- }
1297
-
1298
- let callable: Unknown = functions.get_named_property(function_name)?;
1299
-
1300
- // Convert positional arguments to JS
1301
- let mut js_args: Vec<sys::napi_value> = Vec::with_capacity(args.len() + 1);
1302
- for arg in args {
1303
- js_args.push(monty_to_js(arg, env)?.raw());
1304
- }
1305
-
1306
- // If we have kwargs, add them as a final object argument
1307
- if !kwargs.is_empty() {
1308
- let mut kwargs_obj = Object::new(env)?;
1309
- for (key, value) in kwargs {
1310
- let key_str = match key {
1311
- MontyObject::String(s) => s.clone(),
1312
- _ => format!("{key:?}"),
1313
- };
1314
- kwargs_obj.set_named_property(&key_str, monty_to_js(value, env)?)?;
1315
- }
1316
- js_args.push(kwargs_obj.raw());
1317
- }
1318
-
1319
- // Get undefined for the 'this' argument
1320
- let mut undefined_raw = std::ptr::null_mut();
1321
- // SAFETY: [DH] - all arguments are valid and result is valid on success
1322
- unsafe {
1323
- sys::napi_get_undefined(env.raw(), &raw mut undefined_raw);
1324
- }
1325
-
1326
- // Call the function using raw napi
1327
- let mut result_raw = std::ptr::null_mut();
1328
- // SAFETY: [DH] - all arguments are valid and result is valid on success
1329
- let status = unsafe {
1330
- sys::napi_call_function(
1331
- env.raw(),
1332
- undefined_raw, // this = undefined
1333
- callable.raw(),
1334
- js_args.len(),
1335
- js_args.as_ptr(),
1336
- &raw mut result_raw,
1337
- )
1338
- };
1339
-
1340
- if status != sys::Status::napi_ok {
1341
- // An error occurred - get the pending exception
1342
- let mut is_exception = false;
1343
- // SAFETY: [DH] - all arguments are valid
1344
- unsafe { sys::napi_is_exception_pending(env.raw(), &raw mut is_exception) };
1345
-
1346
- if is_exception {
1347
- let mut exception_raw = std::ptr::null_mut();
1348
- // SAFETY: [DH] - all arguments are valid and exception_raw is valid on success
1349
- let status = unsafe { sys::napi_get_and_clear_last_exception(env.raw(), &raw mut exception_raw) };
1350
-
1351
- if status != sys::Status::napi_ok {
1352
- // Failed to get the exception - return a generic error
1353
- let exc = MontyException::new(
1354
- ExcType::RuntimeError,
1355
- Some("External function call failed and exception could not be retrieved".to_string()),
1356
- );
1357
- return Ok(ExtFunctionResult::Error(exc));
1358
- }
1359
- let exception_obj = Object::from_raw(env.raw(), exception_raw);
1360
- let exc = extract_js_exception(exception_obj);
1361
- return Ok(ExtFunctionResult::Error(exc));
1362
- }
1363
-
1364
- // Generic error
1365
- let exc = MontyException::new(ExcType::RuntimeError, Some("External function call failed".to_string()));
1366
- return Ok(ExtFunctionResult::Error(exc));
1367
- }
1368
-
1369
- // Convert the result back to Monty format
1370
- // SAFETY: [DH] - result_raw is valid on success
1371
- let result = unsafe { Unknown::from_raw_unchecked(env.raw(), result_raw) };
1372
- let monty_result = js_to_monty(result, *env)?;
1373
- Ok(ExtFunctionResult::Return(monty_result))
1374
- }
1375
-
1376
- /// Extracts exception info from a JS exception object.
1377
- fn extract_js_exception(exception_obj: Object<'_>) -> MontyException {
1378
- // Try to get the 'name' property (e.g., "ValueError")
1379
- let name: std::result::Result<String, _> = exception_obj.get_named_property("name");
1380
- // Try to get the 'message' property
1381
- let message: std::result::Result<String, _> = exception_obj.get_named_property("message");
1382
-
1383
- let exc_type = name
1384
- .ok()
1385
- .and_then(|n| string_to_exc_type(&n).ok())
1386
- .unwrap_or(ExcType::RuntimeError);
1387
- let msg = message.ok();
1388
-
1389
- MontyException::new(exc_type, msg)
1390
- }
1391
-
1392
- /// Resolves a name lookup against the runtime external functions map.
1393
- ///
1394
- /// If the name exists as a property on the external functions object, returns
1395
- /// `NameLookupResult::Value` with a `Function` object. Otherwise returns
1396
- /// `NameLookupResult::Undefined` so the VM raises `NameError`.
1397
- fn resolve_name_lookup(external_functions: Option<&Object<'_>>, name: &str) -> Result<NameLookupResult> {
1398
- if let Some(functions) = external_functions {
1399
- if functions.has_named_property(name)? {
1400
- return Ok(NameLookupResult::Value(MontyObject::Function {
1401
- name: name.to_string(),
1402
- docstring: None, // TODO, can we do better?
1403
- }));
1404
- }
1405
- }
1406
- Ok(NameLookupResult::Undefined)
1407
- }