@bolt-foundry/gambit 0.8.6-rc.3 → 0.8.6-rc.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (338) hide show
  1. package/CHANGELOG.md +20 -1
  2. package/esm/gambit/simulator-ui/dist/bundle.js +2435 -620
  3. package/esm/gambit/simulator-ui/dist/bundle.js.map +4 -4
  4. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/entrypoint.d.ts +7 -0
  5. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/entrypoint.d.ts.map +1 -0
  6. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/entrypoint.js +22 -0
  7. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/normalization_ast.d.ts +4 -0
  8. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/normalization_ast.d.ts.map +1 -0
  9. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/normalization_ast.js +456 -0
  10. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/output_type.d.ts +3 -0
  11. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/output_type.d.ts.map +1 -0
  12. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/output_type.js +1 -0
  13. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/param_type.d.ts +110 -0
  14. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/param_type.d.ts.map +1 -0
  15. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/param_type.js +1 -0
  16. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/parameters_type.d.ts +10 -0
  17. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/parameters_type.d.ts.map +1 -0
  18. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/parameters_type.js +1 -0
  19. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/query_text.d.ts +3 -0
  20. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/query_text.d.ts.map +1 -0
  21. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/query_text.js +96 -0
  22. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/raw_response_type.d.ts +91 -0
  23. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/raw_response_type.d.ts.map +1 -0
  24. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/raw_response_type.js +1 -0
  25. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/resolver_reader.d.ts +6 -0
  26. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/resolver_reader.d.ts.map +1 -0
  27. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/resolver_reader.js +610 -0
  28. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/normalization_ast.d.ts.map +1 -1
  29. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/normalization_ast.js +86 -0
  30. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/param_type.d.ts +18 -0
  31. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/param_type.d.ts.map +1 -1
  32. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/query_text.d.ts +1 -1
  33. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/query_text.d.ts.map +1 -1
  34. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/query_text.js +18 -0
  35. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/raw_response_type.d.ts +18 -0
  36. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/raw_response_type.d.ts.map +1 -1
  37. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/resolver_reader.d.ts.map +1 -1
  38. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/resolver_reader.js +120 -0
  39. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/normalization_ast.d.ts.map +1 -1
  40. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/normalization_ast.js +43 -0
  41. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/param_type.d.ts +9 -0
  42. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/param_type.d.ts.map +1 -1
  43. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/query_text.d.ts +1 -1
  44. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/query_text.d.ts.map +1 -1
  45. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/query_text.js +9 -0
  46. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/raw_response_type.d.ts +9 -0
  47. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/raw_response_type.d.ts.map +1 -1
  48. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/resolver_reader.d.ts.map +1 -1
  49. package/esm/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/resolver_reader.js +60 -0
  50. package/esm/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/normalization_ast.d.ts.map +1 -1
  51. package/esm/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/normalization_ast.js +43 -0
  52. package/esm/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/query_text.d.ts +1 -1
  53. package/esm/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/query_text.d.ts.map +1 -1
  54. package/esm/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/query_text.js +9 -0
  55. package/esm/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/raw_response_type.d.ts +9 -0
  56. package/esm/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/raw_response_type.d.ts.map +1 -1
  57. package/esm/simulator-ui/__generated__/__isograph/Workspace/TestTab/param_type.d.ts +9 -0
  58. package/esm/simulator-ui/__generated__/__isograph/Workspace/TestTab/param_type.d.ts.map +1 -1
  59. package/esm/simulator-ui/__generated__/__isograph/Workspace/TestTab/resolver_reader.d.ts.map +1 -1
  60. package/esm/simulator-ui/__generated__/__isograph/Workspace/TestTab/resolver_reader.js +60 -0
  61. package/esm/simulator-ui/__generated__/__isograph/iso.d.ts +4 -0
  62. package/esm/simulator-ui/__generated__/__isograph/iso.d.ts.map +1 -1
  63. package/esm/simulator-ui/__generated__/__isograph/iso.js +3 -0
  64. package/esm/simulator-ui/__generated__/builtRoutes.d.ts +2 -0
  65. package/esm/simulator-ui/__generated__/builtRoutes.d.ts.map +1 -1
  66. package/esm/simulator-ui/__generated__/builtRoutes.js +3 -0
  67. package/esm/simulator-ui/isograph/components/Query/SimulatorTestPage.d.ts.map +1 -1
  68. package/esm/simulator-ui/isograph/components/Query/SimulatorTestPage.js +141 -4
  69. package/esm/simulator-ui/isograph/entrypoints/EntrypointSimulatorWorkspaceShell.d.ts.map +1 -1
  70. package/esm/simulator-ui/isograph/entrypoints/EntrypointSimulatorWorkspaceShell.js +3 -1
  71. package/esm/simulator-ui/mutations/GambitWorkspaceFeedbackSave.d.ts +93 -0
  72. package/esm/simulator-ui/mutations/GambitWorkspaceFeedbackSave.d.ts.map +1 -0
  73. package/esm/simulator-ui/mutations/GambitWorkspaceFeedbackSave.js +101 -0
  74. package/esm/simulator-ui/mutations/GambitWorkspaceFeedbackSaveMutation.d.ts +93 -0
  75. package/esm/simulator-ui/mutations/GambitWorkspaceFeedbackSaveMutation.d.ts.map +1 -0
  76. package/esm/simulator-ui/mutations/GambitWorkspaceFeedbackSaveMutation.js +7 -0
  77. package/esm/simulator-ui/mutations/GambitWorkspaceScenarioRunSend.d.ts +18 -0
  78. package/esm/simulator-ui/mutations/GambitWorkspaceScenarioRunSend.d.ts.map +1 -1
  79. package/esm/simulator-ui/mutations/GambitWorkspaceScenarioRunSend.js +18 -0
  80. package/esm/simulator-ui/mutations/GambitWorkspaceScenarioRunSendMutation.d.ts +18 -0
  81. package/esm/simulator-ui/mutations/GambitWorkspaceScenarioRunSendMutation.d.ts.map +1 -1
  82. package/esm/simulator-ui/mutations/GambitWorkspaceScenarioRunStart.d.ts +9 -0
  83. package/esm/simulator-ui/mutations/GambitWorkspaceScenarioRunStart.d.ts.map +1 -1
  84. package/esm/simulator-ui/mutations/GambitWorkspaceScenarioRunStart.js +9 -0
  85. package/esm/simulator-ui/mutations/GambitWorkspaceScenarioRunStartMutation.d.ts +9 -0
  86. package/esm/simulator-ui/mutations/GambitWorkspaceScenarioRunStartMutation.d.ts.map +1 -1
  87. package/esm/simulator-ui/src/AppIsoMinimal.d.ts +3 -0
  88. package/esm/simulator-ui/src/AppIsoMinimal.d.ts.map +1 -1
  89. package/esm/simulator-ui/src/AppIsoMinimal.js +7 -4
  90. package/esm/simulator-ui/src/AppShell.d.ts.map +1 -1
  91. package/esm/simulator-ui/src/AppShell.js +2 -2
  92. package/esm/simulator-ui/src/MinimalRouterRoot.js +4 -2
  93. package/esm/simulator-ui/src/RouterContext.d.ts.map +1 -1
  94. package/esm/simulator-ui/src/RouterContext.js +7 -3
  95. package/esm/simulator-ui/src/shared.d.ts.map +1 -1
  96. package/esm/simulator-ui/src/shared.js +3 -3
  97. package/esm/src/server/request_handler.d.ts +210 -0
  98. package/esm/src/server/request_handler.d.ts.map +1 -0
  99. package/esm/src/server/request_handler.js +416 -0
  100. package/esm/src/server/workspace/build.d.ts +57 -0
  101. package/esm/src/server/workspace/build.d.ts.map +1 -0
  102. package/esm/src/server/workspace/build.js +377 -0
  103. package/esm/src/server/workspace/conversation_sessions.d.ts +83 -0
  104. package/esm/src/server/workspace/conversation_sessions.d.ts.map +1 -0
  105. package/esm/src/server/workspace/conversation_sessions.js +163 -0
  106. package/esm/src/server/workspace/grading.d.ts +52 -0
  107. package/esm/src/server/workspace/grading.d.ts.map +1 -0
  108. package/esm/src/server/workspace/grading.js +488 -0
  109. package/esm/src/server/workspace/helpers.d.ts +46 -0
  110. package/esm/src/server/workspace/helpers.d.ts.map +1 -0
  111. package/esm/src/server/workspace/helpers.js +340 -0
  112. package/esm/src/server/workspace/read_model.d.ts +35 -0
  113. package/esm/src/server/workspace/read_model.d.ts.map +1 -0
  114. package/esm/src/server/workspace/read_model.js +121 -0
  115. package/esm/src/server/workspace/response_events.d.ts +28 -0
  116. package/esm/src/server/workspace/response_events.d.ts.map +1 -0
  117. package/esm/src/server/workspace/response_events.js +178 -0
  118. package/esm/src/server/workspace/run_deck.d.ts +23 -0
  119. package/esm/src/server/workspace/run_deck.d.ts.map +1 -0
  120. package/esm/src/server/workspace/run_deck.js +79 -0
  121. package/esm/src/server/workspace/scenario_history.d.ts +8 -0
  122. package/esm/src/server/workspace/scenario_history.d.ts.map +1 -0
  123. package/esm/src/server/workspace/scenario_history.js +269 -0
  124. package/esm/src/server/workspace/scenarios.d.ts +93 -0
  125. package/esm/src/server/workspace/scenarios.d.ts.map +1 -0
  126. package/esm/src/server/workspace/scenarios.js +1052 -0
  127. package/esm/src/server/workspace/schema.d.ts +35 -0
  128. package/esm/src/server/workspace/schema.d.ts.map +1 -0
  129. package/esm/src/server/workspace/schema.js +427 -0
  130. package/esm/src/server/workspace/sessions.d.ts +38 -0
  131. package/esm/src/server/workspace/sessions.d.ts.map +1 -0
  132. package/esm/src/server/workspace/sessions.js +232 -0
  133. package/esm/src/server/workspace/types.d.ts +128 -0
  134. package/esm/src/server/workspace/types.d.ts.map +1 -0
  135. package/esm/src/server/workspace/types.js +1 -0
  136. package/esm/src/server/workspace/verify.d.ts +52 -0
  137. package/esm/src/server/workspace/verify.d.ts.map +1 -0
  138. package/esm/src/server/workspace/verify.js +449 -0
  139. package/esm/src/server.d.ts +0 -3
  140. package/esm/src/server.d.ts.map +1 -1
  141. package/esm/src/server.js +324 -6732
  142. package/esm/src/server_isograph_environment.d.ts +12 -1
  143. package/esm/src/server_isograph_environment.d.ts.map +1 -1
  144. package/esm/src/server_legacy_api_routes.d.ts +137 -0
  145. package/esm/src/server_legacy_api_routes.d.ts.map +1 -0
  146. package/esm/src/server_legacy_api_routes.js +629 -0
  147. package/esm/src/server_openresponses.d.ts +6 -0
  148. package/esm/src/server_openresponses.d.ts.map +1 -0
  149. package/esm/src/server_openresponses.js +687 -0
  150. package/esm/src/server_session_store.d.ts +4 -0
  151. package/esm/src/server_session_store.d.ts.map +1 -1
  152. package/esm/src/server_session_store.js +196 -1
  153. package/esm/src/server_simulator_ui.d.ts +27 -0
  154. package/esm/src/server_simulator_ui.d.ts.map +1 -0
  155. package/esm/src/server_simulator_ui.js +501 -0
  156. package/esm/src/server_types.d.ts +22 -0
  157. package/esm/src/server_types.d.ts.map +1 -1
  158. package/esm/src/server_workspace_decks.d.ts +31 -0
  159. package/esm/src/server_workspace_decks.d.ts.map +1 -0
  160. package/esm/src/server_workspace_decks.js +98 -0
  161. package/esm/src/server_workspace_graphql.d.ts +17 -0
  162. package/esm/src/server_workspace_graphql.d.ts.map +1 -0
  163. package/esm/src/server_workspace_graphql.js +52 -0
  164. package/esm/src/server_workspace_runtime.d.ts +55 -0
  165. package/esm/src/server_workspace_runtime.d.ts.map +1 -0
  166. package/esm/src/server_workspace_runtime.js +358 -0
  167. package/esm/src/simulator_graphql.d.ts +14 -1
  168. package/esm/src/simulator_graphql.d.ts.map +1 -1
  169. package/esm/src/simulator_graphql.js +77 -0
  170. package/package.json +1 -1
  171. package/script/gambit/simulator-ui/dist/bundle.js +2435 -620
  172. package/script/gambit/simulator-ui/dist/bundle.js.map +4 -4
  173. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/entrypoint.d.ts +7 -0
  174. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/entrypoint.d.ts.map +1 -0
  175. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/entrypoint.js +27 -0
  176. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/normalization_ast.d.ts +4 -0
  177. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/normalization_ast.d.ts.map +1 -0
  178. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/normalization_ast.js +458 -0
  179. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/output_type.d.ts +3 -0
  180. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/output_type.d.ts.map +1 -0
  181. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/output_type.js +2 -0
  182. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/param_type.d.ts +110 -0
  183. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/param_type.d.ts.map +1 -0
  184. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/param_type.js +2 -0
  185. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/parameters_type.d.ts +10 -0
  186. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/parameters_type.d.ts.map +1 -0
  187. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/parameters_type.js +2 -0
  188. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/query_text.d.ts +3 -0
  189. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/query_text.d.ts.map +1 -0
  190. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/query_text.js +98 -0
  191. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/raw_response_type.d.ts +91 -0
  192. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/raw_response_type.d.ts.map +1 -0
  193. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/raw_response_type.js +2 -0
  194. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/resolver_reader.d.ts +6 -0
  195. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/resolver_reader.d.ts.map +1 -0
  196. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceFeedbackSave/resolver_reader.js +615 -0
  197. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/normalization_ast.d.ts.map +1 -1
  198. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/normalization_ast.js +86 -0
  199. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/param_type.d.ts +18 -0
  200. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/param_type.d.ts.map +1 -1
  201. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/query_text.d.ts +1 -1
  202. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/query_text.d.ts.map +1 -1
  203. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/query_text.js +18 -0
  204. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/raw_response_type.d.ts +18 -0
  205. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/raw_response_type.d.ts.map +1 -1
  206. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/resolver_reader.d.ts.map +1 -1
  207. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunSend/resolver_reader.js +120 -0
  208. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/normalization_ast.d.ts.map +1 -1
  209. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/normalization_ast.js +43 -0
  210. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/param_type.d.ts +9 -0
  211. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/param_type.d.ts.map +1 -1
  212. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/query_text.d.ts +1 -1
  213. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/query_text.d.ts.map +1 -1
  214. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/query_text.js +9 -0
  215. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/raw_response_type.d.ts +9 -0
  216. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/raw_response_type.d.ts.map +1 -1
  217. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/resolver_reader.d.ts.map +1 -1
  218. package/script/simulator-ui/__generated__/__isograph/Mutation/GambitWorkspaceScenarioRunStart/resolver_reader.js +60 -0
  219. package/script/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/normalization_ast.d.ts.map +1 -1
  220. package/script/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/normalization_ast.js +43 -0
  221. package/script/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/query_text.d.ts +1 -1
  222. package/script/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/query_text.d.ts.map +1 -1
  223. package/script/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/query_text.js +9 -0
  224. package/script/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/raw_response_type.d.ts +9 -0
  225. package/script/simulator-ui/__generated__/__isograph/Query/EntrypointSimulatorTestPage/raw_response_type.d.ts.map +1 -1
  226. package/script/simulator-ui/__generated__/__isograph/Workspace/TestTab/param_type.d.ts +9 -0
  227. package/script/simulator-ui/__generated__/__isograph/Workspace/TestTab/param_type.d.ts.map +1 -1
  228. package/script/simulator-ui/__generated__/__isograph/Workspace/TestTab/resolver_reader.d.ts.map +1 -1
  229. package/script/simulator-ui/__generated__/__isograph/Workspace/TestTab/resolver_reader.js +60 -0
  230. package/script/simulator-ui/__generated__/__isograph/iso.d.ts +4 -0
  231. package/script/simulator-ui/__generated__/__isograph/iso.d.ts.map +1 -1
  232. package/script/simulator-ui/__generated__/__isograph/iso.js +45 -42
  233. package/script/simulator-ui/__generated__/builtRoutes.d.ts +2 -0
  234. package/script/simulator-ui/__generated__/builtRoutes.d.ts.map +1 -1
  235. package/script/simulator-ui/__generated__/builtRoutes.js +18 -15
  236. package/script/simulator-ui/isograph/components/Query/SimulatorTestPage.d.ts.map +1 -1
  237. package/script/simulator-ui/isograph/components/Query/SimulatorTestPage.js +141 -4
  238. package/script/simulator-ui/isograph/entrypoints/EntrypointSimulatorWorkspaceShell.d.ts.map +1 -1
  239. package/script/simulator-ui/isograph/entrypoints/EntrypointSimulatorWorkspaceShell.js +3 -1
  240. package/script/simulator-ui/mutations/GambitWorkspaceFeedbackSave.d.ts +93 -0
  241. package/script/simulator-ui/mutations/GambitWorkspaceFeedbackSave.d.ts.map +1 -0
  242. package/script/simulator-ui/mutations/GambitWorkspaceFeedbackSave.js +104 -0
  243. package/script/simulator-ui/mutations/GambitWorkspaceFeedbackSaveMutation.d.ts +93 -0
  244. package/script/simulator-ui/mutations/GambitWorkspaceFeedbackSaveMutation.d.ts.map +1 -0
  245. package/script/simulator-ui/mutations/GambitWorkspaceFeedbackSaveMutation.js +13 -0
  246. package/script/simulator-ui/mutations/GambitWorkspaceScenarioRunSend.d.ts +18 -0
  247. package/script/simulator-ui/mutations/GambitWorkspaceScenarioRunSend.d.ts.map +1 -1
  248. package/script/simulator-ui/mutations/GambitWorkspaceScenarioRunSend.js +18 -0
  249. package/script/simulator-ui/mutations/GambitWorkspaceScenarioRunSendMutation.d.ts +18 -0
  250. package/script/simulator-ui/mutations/GambitWorkspaceScenarioRunSendMutation.d.ts.map +1 -1
  251. package/script/simulator-ui/mutations/GambitWorkspaceScenarioRunStart.d.ts +9 -0
  252. package/script/simulator-ui/mutations/GambitWorkspaceScenarioRunStart.d.ts.map +1 -1
  253. package/script/simulator-ui/mutations/GambitWorkspaceScenarioRunStart.js +9 -0
  254. package/script/simulator-ui/mutations/GambitWorkspaceScenarioRunStartMutation.d.ts +9 -0
  255. package/script/simulator-ui/mutations/GambitWorkspaceScenarioRunStartMutation.d.ts.map +1 -1
  256. package/script/simulator-ui/src/AppIsoMinimal.d.ts +3 -0
  257. package/script/simulator-ui/src/AppIsoMinimal.d.ts.map +1 -1
  258. package/script/simulator-ui/src/AppIsoMinimal.js +7 -4
  259. package/script/simulator-ui/src/AppShell.d.ts.map +1 -1
  260. package/script/simulator-ui/src/AppShell.js +1 -1
  261. package/script/simulator-ui/src/MinimalRouterRoot.js +4 -2
  262. package/script/simulator-ui/src/RouterContext.d.ts.map +1 -1
  263. package/script/simulator-ui/src/RouterContext.js +6 -2
  264. package/script/simulator-ui/src/shared.d.ts.map +1 -1
  265. package/script/simulator-ui/src/shared.js +3 -3
  266. package/script/src/server/request_handler.d.ts +210 -0
  267. package/script/src/server/request_handler.d.ts.map +1 -0
  268. package/script/src/server/request_handler.js +453 -0
  269. package/script/src/server/workspace/build.d.ts +57 -0
  270. package/script/src/server/workspace/build.d.ts.map +1 -0
  271. package/script/src/server/workspace/build.js +381 -0
  272. package/script/src/server/workspace/conversation_sessions.d.ts +83 -0
  273. package/script/src/server/workspace/conversation_sessions.d.ts.map +1 -0
  274. package/script/src/server/workspace/conversation_sessions.js +167 -0
  275. package/script/src/server/workspace/grading.d.ts +52 -0
  276. package/script/src/server/workspace/grading.d.ts.map +1 -0
  277. package/script/src/server/workspace/grading.js +492 -0
  278. package/script/src/server/workspace/helpers.d.ts +46 -0
  279. package/script/src/server/workspace/helpers.d.ts.map +1 -0
  280. package/script/src/server/workspace/helpers.js +353 -0
  281. package/script/src/server/workspace/read_model.d.ts +35 -0
  282. package/script/src/server/workspace/read_model.d.ts.map +1 -0
  283. package/script/src/server/workspace/read_model.js +125 -0
  284. package/script/src/server/workspace/response_events.d.ts +28 -0
  285. package/script/src/server/workspace/response_events.d.ts.map +1 -0
  286. package/script/src/server/workspace/response_events.js +182 -0
  287. package/script/src/server/workspace/run_deck.d.ts +23 -0
  288. package/script/src/server/workspace/run_deck.d.ts.map +1 -0
  289. package/script/src/server/workspace/run_deck.js +84 -0
  290. package/script/src/server/workspace/scenario_history.d.ts +8 -0
  291. package/script/src/server/workspace/scenario_history.d.ts.map +1 -0
  292. package/script/src/server/workspace/scenario_history.js +310 -0
  293. package/script/src/server/workspace/scenarios.d.ts +93 -0
  294. package/script/src/server/workspace/scenarios.d.ts.map +1 -0
  295. package/script/src/server/workspace/scenarios.js +1089 -0
  296. package/script/src/server/workspace/schema.d.ts +35 -0
  297. package/script/src/server/workspace/schema.d.ts.map +1 -0
  298. package/script/src/server/workspace/schema.js +478 -0
  299. package/script/src/server/workspace/sessions.d.ts +38 -0
  300. package/script/src/server/workspace/sessions.d.ts.map +1 -0
  301. package/script/src/server/workspace/sessions.js +269 -0
  302. package/script/src/server/workspace/types.d.ts +128 -0
  303. package/script/src/server/workspace/types.d.ts.map +1 -0
  304. package/script/src/server/workspace/types.js +2 -0
  305. package/script/src/server/workspace/verify.d.ts +52 -0
  306. package/script/src/server/workspace/verify.d.ts.map +1 -0
  307. package/script/src/server/workspace/verify.js +453 -0
  308. package/script/src/server.d.ts +0 -3
  309. package/script/src/server.d.ts.map +1 -1
  310. package/script/src/server.js +391 -6799
  311. package/script/src/server_isograph_environment.d.ts +12 -1
  312. package/script/src/server_isograph_environment.d.ts.map +1 -1
  313. package/script/src/server_legacy_api_routes.d.ts +137 -0
  314. package/script/src/server_legacy_api_routes.d.ts.map +1 -0
  315. package/script/src/server_legacy_api_routes.js +666 -0
  316. package/script/src/server_openresponses.d.ts +6 -0
  317. package/script/src/server_openresponses.d.ts.map +1 -0
  318. package/script/src/server_openresponses.js +690 -0
  319. package/script/src/server_session_store.d.ts +4 -0
  320. package/script/src/server_session_store.d.ts.map +1 -1
  321. package/script/src/server_session_store.js +196 -1
  322. package/script/src/server_simulator_ui.d.ts +27 -0
  323. package/script/src/server_simulator_ui.d.ts.map +1 -0
  324. package/script/src/server_simulator_ui.js +544 -0
  325. package/script/src/server_types.d.ts +22 -0
  326. package/script/src/server_types.d.ts.map +1 -1
  327. package/script/src/server_workspace_decks.d.ts +31 -0
  328. package/script/src/server_workspace_decks.d.ts.map +1 -0
  329. package/script/src/server_workspace_decks.js +142 -0
  330. package/script/src/server_workspace_graphql.d.ts +17 -0
  331. package/script/src/server_workspace_graphql.d.ts.map +1 -0
  332. package/script/src/server_workspace_graphql.js +56 -0
  333. package/script/src/server_workspace_runtime.d.ts +55 -0
  334. package/script/src/server_workspace_runtime.d.ts.map +1 -0
  335. package/script/src/server_workspace_runtime.js +395 -0
  336. package/script/src/simulator_graphql.d.ts +14 -1
  337. package/script/src/simulator_graphql.d.ts.map +1 -1
  338. package/script/src/simulator_graphql.js +77 -0
@@ -0,0 +1,1052 @@
1
+ import * as dntShim from "../../../_dnt.shims.js";
2
+ import * as path from "../../../deps/jsr.io/@std/path/1.1.4/mod.js";
3
+ import { isGambitEndSignal, isRunCanceledError, runDeck, } from "@bolt-foundry/gambit-core";
4
+ import { sanitizeNumber } from "../../test_bot.js";
5
+ import { cloneValue, deriveInitialFromSchema } from "./schema.js";
6
+ import { applyUserMessageRefSource, buildTestBotSnapshot, stringifyContent, syncTestBotRunFromState, } from "./helpers.js";
7
+ import { resolveWorkerSandboxForSignalAwareRun, runDeckWithFallback, stringifyOutput, } from "./run_deck.js";
8
+ import { isFeedbackEligibleMessageRef, isFeedbackEligiblePersistedTestRunMessageRef, listPersistedTestRunStatuses, listScenarioRunStatusesFromStateMeta, readPersistedTestRunStatusById, } from "./scenario_history.js";
9
+ const DEFAULT_TEST_BOT_SEED_PROMPT = "Start the conversation as the user. Do not wait for the assistant to speak first.";
10
+ const traceCategory = (type) => {
11
+ switch (type) {
12
+ case "message.user":
13
+ case "model.result":
14
+ return "turn";
15
+ case "tool.call":
16
+ case "tool.result":
17
+ return "tool";
18
+ case "log":
19
+ case "monolog":
20
+ return "status";
21
+ case "run.start":
22
+ case "run.end":
23
+ case "deck.start":
24
+ case "deck.end":
25
+ case "action.start":
26
+ case "action.end":
27
+ case "model.call":
28
+ return "lifecycle";
29
+ default:
30
+ return "trace";
31
+ }
32
+ };
33
+ export const createWorkspaceScenarioService = (deps) => {
34
+ const testBotRuns = new Map();
35
+ const shouldPersistTestWorkspaceEvent = (payload) => {
36
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
37
+ return false;
38
+ }
39
+ const type = payload.type;
40
+ return type === "testBotStatus" || type === "gambit.test.status";
41
+ };
42
+ const broadcastTestBot = (payload, workspaceId) => {
43
+ if (workspaceId && shouldPersistTestWorkspaceEvent(payload)) {
44
+ const state = deps.readSessionState(workspaceId);
45
+ if (state) {
46
+ deps.appendWorkspaceEnvelope(state, "test", payload);
47
+ }
48
+ }
49
+ deps.appendDurableStreamEvent(deps.workspaceStreamId, payload);
50
+ deps.appendDurableStreamEvent(deps.testStreamId, payload);
51
+ };
52
+ const findTestRunByWorkspaceId = (workspaceId) => {
53
+ for (const candidate of testBotRuns.values()) {
54
+ if (candidate.run.workspaceId === workspaceId ||
55
+ candidate.run.sessionId === workspaceId) {
56
+ return candidate;
57
+ }
58
+ }
59
+ return undefined;
60
+ };
61
+ const startTestBotRun = (runOpts = {}) => {
62
+ const botDeckPath = typeof runOpts.botDeckPath === "string"
63
+ ? runOpts.botDeckPath
64
+ : undefined;
65
+ if (!botDeckPath) {
66
+ throw new Error("Missing scenario deck path");
67
+ }
68
+ const defaultMaxTurns = 12;
69
+ const maxTurns = Math.round(sanitizeNumber(runOpts.maxTurnsOverride ?? defaultMaxTurns, defaultMaxTurns, { min: 1, max: 200 }));
70
+ const deckInput = runOpts.deckInput;
71
+ const hasDeckInput = deckInput !== undefined;
72
+ const botInput = runOpts.botInput;
73
+ const initialUserMessage = typeof runOpts.initialUserMessage === "string"
74
+ ? runOpts.initialUserMessage.trim()
75
+ : "";
76
+ const botConfigPath = botDeckPath;
77
+ const testBotName = path.basename(botConfigPath).replace(/\.deck\.(md|ts)$/i, "");
78
+ const selectedScenarioDeckId = runOpts.botDeckId ?? testBotName;
79
+ const selectedScenarioDeckLabel = runOpts.botDeckLabel ?? testBotName;
80
+ const runId = typeof runOpts.runId === "string" &&
81
+ runOpts.runId.trim().length > 0
82
+ ? runOpts.runId.trim()
83
+ : deps.randomId("testbot");
84
+ const startedAt = new Date().toISOString();
85
+ const controller = new AbortController();
86
+ const entry = {
87
+ run: {
88
+ id: runId,
89
+ status: "running",
90
+ startedAt,
91
+ maxTurns,
92
+ messages: [],
93
+ traces: [],
94
+ toolInserts: [],
95
+ },
96
+ state: null,
97
+ promise: null,
98
+ abort: controller,
99
+ };
100
+ testBotRuns.set(runId, entry);
101
+ const run = entry.run;
102
+ if (runOpts.workspaceId) {
103
+ run.workspaceId = runOpts.workspaceId;
104
+ run.sessionId = runOpts.workspaceId;
105
+ }
106
+ const emitTestBot = (payload) => broadcastTestBot(payload, run.workspaceId ?? runOpts.workspaceId);
107
+ if (runOpts.initFill)
108
+ run.initFill = runOpts.initFill;
109
+ let savedState = undefined;
110
+ const openResponsesStartIndex = runOpts.workspaceId
111
+ ? (deps.readSessionState(runOpts.workspaceId)?.messages?.length ?? 0)
112
+ : 0;
113
+ const baseMeta = runOpts.baseMeta ?? {};
114
+ const workspaceMeta = runOpts.workspaceRecord
115
+ ? deps.buildWorkspaceMeta(runOpts.workspaceRecord, baseMeta)
116
+ : baseMeta;
117
+ let lastCount = 0;
118
+ const capturedTraces = [];
119
+ if (runOpts.initFillTrace) {
120
+ const actionCallId = deps.randomId("initfill");
121
+ capturedTraces.push({
122
+ type: "tool.call",
123
+ runId,
124
+ actionCallId,
125
+ name: "gambit_test_bot_init_fill",
126
+ args: runOpts.initFillTrace.args,
127
+ toolKind: "internal",
128
+ }, {
129
+ type: "tool.result",
130
+ runId,
131
+ actionCallId,
132
+ name: "gambit_test_bot_init_fill",
133
+ result: runOpts.initFillTrace.result,
134
+ toolKind: "internal",
135
+ });
136
+ }
137
+ const setWorkspaceId = (state) => {
138
+ const workspaceId = typeof state?.meta?.workspaceId === "string"
139
+ ? state.meta.workspaceId
140
+ : typeof state?.meta?.sessionId === "string"
141
+ ? state.meta.sessionId
142
+ : undefined;
143
+ if (workspaceId) {
144
+ run.workspaceId = workspaceId;
145
+ run.sessionId = workspaceId;
146
+ }
147
+ };
148
+ const appendFromState = (state) => {
149
+ const snapshot = buildTestBotSnapshot(state);
150
+ const rawLength = state.messages?.length ?? 0;
151
+ const toolCount = snapshot.toolInserts.length;
152
+ const shouldBroadcast = rawLength !== lastCount ||
153
+ (run.toolInserts?.length ?? 0) !== toolCount;
154
+ run.messages = snapshot.messages;
155
+ run.toolInserts = snapshot.toolInserts;
156
+ lastCount = rawLength;
157
+ setWorkspaceId(state);
158
+ run.traces = Array.isArray(state.traces) ? [...state.traces] : undefined;
159
+ if (shouldBroadcast) {
160
+ emitTestBot({ type: "testBotStatus", run });
161
+ }
162
+ };
163
+ const pendingTraceEvents = [];
164
+ const flushPendingTraceEvents = (state) => {
165
+ if (!pendingTraceEvents.length)
166
+ return;
167
+ for (const pending of pendingTraceEvents) {
168
+ deps.persistOpenResponsesTraceEvent(state, pending, runId);
169
+ deps.appendSessionEvent(state, {
170
+ ...pending,
171
+ kind: "trace",
172
+ category: traceCategory(pending.type),
173
+ });
174
+ }
175
+ pendingTraceEvents.length = 0;
176
+ };
177
+ const tracer = (event) => {
178
+ const stamped = event.ts ? event : { ...event, ts: Date.now() };
179
+ capturedTraces.push(stamped);
180
+ deps.consoleTracer?.(stamped);
181
+ if (savedState?.meta?.sessionId) {
182
+ deps.persistOpenResponsesTraceEvent(savedState, stamped, runId);
183
+ deps.appendSessionEvent(savedState, {
184
+ ...stamped,
185
+ kind: "trace",
186
+ category: traceCategory(stamped.type),
187
+ });
188
+ }
189
+ else {
190
+ pendingTraceEvents.push(stamped);
191
+ }
192
+ };
193
+ let deckBotState = undefined;
194
+ let sessionEnded = false;
195
+ const getLastAssistantMessage = (history) => {
196
+ for (let i = history.length - 1; i >= 0; i--) {
197
+ const msg = history[i];
198
+ if (msg?.role === "assistant") {
199
+ return stringifyContent(msg.content);
200
+ }
201
+ }
202
+ return undefined;
203
+ };
204
+ const generateDeckBotUserMessage = async (history, streamOptions) => {
205
+ const assistantMessage = getLastAssistantMessage(history)?.trim() || "";
206
+ const seedPrompt = !assistantMessage && streamOptions?.allowEmptyAssistant
207
+ ? DEFAULT_TEST_BOT_SEED_PROMPT
208
+ : undefined;
209
+ if (!assistantMessage && !seedPrompt)
210
+ return "";
211
+ const result = await runDeckWithFallback({
212
+ path: botDeckPath,
213
+ input: botInput,
214
+ inputProvided: botInput !== undefined,
215
+ modelProvider: deps.modelProvider,
216
+ state: deckBotState,
217
+ allowRootStringInput: true,
218
+ initialUserMessage: assistantMessage || seedPrompt,
219
+ onStateUpdate: (state) => {
220
+ deckBotState = state;
221
+ },
222
+ stream: Boolean(streamOptions?.onStreamText),
223
+ onStreamText: streamOptions?.onStreamText,
224
+ responsesMode: deps.responsesMode,
225
+ workerSandbox: deps.workerSandbox,
226
+ signal: controller.signal,
227
+ });
228
+ if (isGambitEndSignal(result)) {
229
+ sessionEnded = true;
230
+ return "";
231
+ }
232
+ const text = stringifyOutput(result);
233
+ return text.trim();
234
+ };
235
+ const loop = async () => {
236
+ try {
237
+ const effectiveStartMode = deps.getRootStartMode() ?? "assistant";
238
+ const shouldRunInitial = effectiveStartMode !== "user" ||
239
+ Boolean(initialUserMessage);
240
+ if (!controller.signal.aborted && shouldRunInitial) {
241
+ const initialResult = await runDeck({
242
+ path: deps.getResolvedDeckPath(),
243
+ input: deckInput,
244
+ inputProvided: hasDeckInput,
245
+ modelProvider: deps.modelProvider,
246
+ defaultModel: deps.model,
247
+ modelOverride: deps.modelForce,
248
+ trace: tracer,
249
+ stream: false,
250
+ state: savedState,
251
+ allowRootStringInput: true,
252
+ initialUserMessage: initialUserMessage || undefined,
253
+ responsesMode: deps.responsesMode,
254
+ workerSandbox: resolveWorkerSandboxForSignalAwareRun({
255
+ workerSandbox: deps.workerSandbox,
256
+ signal: controller.signal,
257
+ }),
258
+ signal: controller.signal,
259
+ onStateUpdate: (state) => {
260
+ const nextStateWithSource = applyUserMessageRefSource(savedState, state, "scenario");
261
+ const nextMeta = {
262
+ ...workspaceMeta,
263
+ ...(nextStateWithSource.meta ?? {}),
264
+ testBot: true,
265
+ testBotRunId: runId,
266
+ testBotConfigPath: botConfigPath,
267
+ testBotName,
268
+ scenarioRunId: runId,
269
+ selectedScenarioDeckId,
270
+ selectedScenarioDeckLabel,
271
+ scenarioConfigPath: botConfigPath,
272
+ ...(run.initFill ? { testBotInitFill: run.initFill } : {}),
273
+ ...(runOpts.workspaceId
274
+ ? { workspaceId: runOpts.workspaceId }
275
+ : {}),
276
+ };
277
+ const enriched = deps.persistSessionState({
278
+ ...nextStateWithSource,
279
+ meta: nextMeta,
280
+ traces: capturedTraces,
281
+ });
282
+ savedState = enriched;
283
+ entry.state = enriched;
284
+ flushPendingTraceEvents(enriched);
285
+ appendFromState(enriched);
286
+ },
287
+ });
288
+ if (isGambitEndSignal(initialResult)) {
289
+ sessionEnded = true;
290
+ }
291
+ }
292
+ for (let turn = 0; turn < maxTurns; turn++) {
293
+ if (sessionEnded)
294
+ break;
295
+ if (controller.signal.aborted)
296
+ break;
297
+ const history = savedState?.messages ?? [];
298
+ const userMessage = await generateDeckBotUserMessage(history, {
299
+ onStreamText: (chunk) => emitTestBot({
300
+ type: "testBotStream",
301
+ workspaceId: run.workspaceId ?? runOpts.workspaceId,
302
+ runId,
303
+ role: "user",
304
+ chunk,
305
+ turn,
306
+ ts: Date.now(),
307
+ }),
308
+ allowEmptyAssistant: effectiveStartMode === "user" &&
309
+ !getLastAssistantMessage(history),
310
+ });
311
+ emitTestBot({
312
+ type: "testBotStreamEnd",
313
+ workspaceId: run.workspaceId ?? runOpts.workspaceId,
314
+ runId,
315
+ role: "user",
316
+ turn,
317
+ ts: Date.now(),
318
+ });
319
+ if (!userMessage)
320
+ break;
321
+ const rootResult = await runDeck({
322
+ path: deps.getResolvedDeckPath(),
323
+ input: deckInput,
324
+ inputProvided: hasDeckInput,
325
+ modelProvider: deps.modelProvider,
326
+ defaultModel: deps.model,
327
+ modelOverride: deps.modelForce,
328
+ trace: tracer,
329
+ stream: true,
330
+ state: savedState,
331
+ allowRootStringInput: true,
332
+ initialUserMessage: userMessage,
333
+ responsesMode: deps.responsesMode,
334
+ workerSandbox: resolveWorkerSandboxForSignalAwareRun({
335
+ workerSandbox: deps.workerSandbox,
336
+ signal: controller.signal,
337
+ }),
338
+ signal: controller.signal,
339
+ onStateUpdate: (state) => {
340
+ const nextStateWithSource = applyUserMessageRefSource(savedState, state, "scenario");
341
+ const nextMeta = {
342
+ ...workspaceMeta,
343
+ ...(nextStateWithSource.meta ?? {}),
344
+ testBot: true,
345
+ testBotRunId: runId,
346
+ testBotConfigPath: botConfigPath,
347
+ testBotName,
348
+ scenarioRunId: runId,
349
+ selectedScenarioDeckId,
350
+ selectedScenarioDeckLabel,
351
+ scenarioConfigPath: botConfigPath,
352
+ ...(run.initFill ? { testBotInitFill: run.initFill } : {}),
353
+ ...(runOpts.workspaceId
354
+ ? { workspaceId: runOpts.workspaceId }
355
+ : {}),
356
+ };
357
+ const enriched = deps.persistSessionState({
358
+ ...nextStateWithSource,
359
+ meta: nextMeta,
360
+ traces: capturedTraces,
361
+ });
362
+ savedState = enriched;
363
+ entry.state = enriched;
364
+ flushPendingTraceEvents(enriched);
365
+ appendFromState(enriched);
366
+ },
367
+ onStreamText: (chunk) => emitTestBot({
368
+ type: "testBotStream",
369
+ workspaceId: run.workspaceId ?? runOpts.workspaceId,
370
+ runId,
371
+ role: "assistant",
372
+ chunk,
373
+ turn,
374
+ ts: Date.now(),
375
+ }),
376
+ });
377
+ if (isGambitEndSignal(rootResult)) {
378
+ sessionEnded = true;
379
+ break;
380
+ }
381
+ emitTestBot({
382
+ type: "testBotStreamEnd",
383
+ workspaceId: run.workspaceId ?? runOpts.workspaceId,
384
+ runId,
385
+ role: "assistant",
386
+ turn,
387
+ ts: Date.now(),
388
+ });
389
+ }
390
+ run.status = controller.signal.aborted ? "canceled" : "completed";
391
+ emitTestBot({ type: "testBotStatus", run });
392
+ }
393
+ catch (err) {
394
+ if (controller.signal.aborted || isRunCanceledError(err)) {
395
+ run.status = "canceled";
396
+ run.error = undefined;
397
+ }
398
+ else {
399
+ run.status = "error";
400
+ run.error = err instanceof Error ? err.message : String(err);
401
+ const stack = err instanceof Error ? err.stack : undefined;
402
+ deps.logger.error(`[sim] scenario run failed runId=${runId} workspaceId=${run.workspaceId ?? runOpts.workspaceId ?? "unknown"} rootDeck=${deps.getResolvedDeckPath()} scenarioDeck=${botDeckPath} error=${run.error}${stack ? `\n${stack}` : ""}`);
403
+ }
404
+ emitTestBot({ type: "testBotStatus", run });
405
+ }
406
+ finally {
407
+ if (savedState?.messages) {
408
+ const snapshot = buildTestBotSnapshot(savedState);
409
+ run.messages = snapshot.messages;
410
+ run.toolInserts = snapshot.toolInserts;
411
+ }
412
+ setWorkspaceId(savedState);
413
+ run.traces = Array.isArray(savedState?.traces)
414
+ ? [...(savedState?.traces ?? [])]
415
+ : undefined;
416
+ if (savedState) {
417
+ deps.persistCanonicalStateMessages({
418
+ state: savedState,
419
+ runId,
420
+ startIndex: openResponsesStartIndex,
421
+ source: "scenario",
422
+ });
423
+ entry.state = savedState;
424
+ }
425
+ run.finishedAt = new Date().toISOString();
426
+ entry.abort = null;
427
+ entry.promise = null;
428
+ emitTestBot({ type: "testBotStatus", run });
429
+ }
430
+ };
431
+ entry.promise = loop();
432
+ emitTestBot({ type: "testBotStatus", run });
433
+ return run;
434
+ };
435
+ const startWorkspaceScenarioRunForGraphql = async (args) => {
436
+ await deps.activateWorkspaceDeck(args.workspaceId, { forceReload: true });
437
+ const workspaceRecord = deps.resolveWorkspaceRecord(args.workspaceId);
438
+ if (!workspaceRecord) {
439
+ throw new Error("Workspace not found");
440
+ }
441
+ const deckState = deps.readWorkspaceDeckStateStrict(args.workspaceId);
442
+ const requestedDeckId = typeof args.scenarioDeckId === "string" &&
443
+ args.scenarioDeckId.trim().length > 0
444
+ ? args.scenarioDeckId.trim()
445
+ : null;
446
+ const fallbackScenarioDeck = deps.buildRootScenarioFallback(deckState);
447
+ const scenarioDeck = requestedDeckId
448
+ ? deps.resolveScenarioDeckFromState(deckState, requestedDeckId) ??
449
+ (requestedDeckId === deckState.assistantDeck.deck
450
+ ? fallbackScenarioDeck
451
+ : null)
452
+ : fallbackScenarioDeck;
453
+ if (requestedDeckId && !scenarioDeck) {
454
+ throw new Error("Unknown scenario deck selection");
455
+ }
456
+ if (!scenarioDeck) {
457
+ throw new Error("No scenario deck configured for this workspace.");
458
+ }
459
+ try {
460
+ const stat = await dntShim.Deno.stat(scenarioDeck.path);
461
+ if (!stat.isFile) {
462
+ throw new Error(`Scenario deck path is not a file: ${scenarioDeck.path}`);
463
+ }
464
+ }
465
+ catch (error) {
466
+ const message = error instanceof Error ? error.message : String(error);
467
+ deps.logger.error(`[sim] workspaceScenarioRunStart deck preflight failed workspaceId=${args.workspaceId} deckId=${scenarioDeck.id} deckPath=${scenarioDeck.path} error=${message}`);
468
+ throw new Error(`Scenario deck is unavailable (${scenarioDeck.label}): ${message}`);
469
+ }
470
+ const parseOptionalJsonInput = (value, label) => {
471
+ if (value === null || value === undefined)
472
+ return undefined;
473
+ if (typeof value !== "string")
474
+ return value;
475
+ const text = value.trim();
476
+ if (text.length === 0)
477
+ return undefined;
478
+ try {
479
+ return JSON.parse(text);
480
+ }
481
+ catch (error) {
482
+ const message = error instanceof Error ? error.message : "Invalid JSON";
483
+ throw new Error(`${label} must be valid JSON: ${message}`);
484
+ }
485
+ };
486
+ const parsedScenarioInput = parseOptionalJsonInput(args.scenarioInput, "scenarioInput");
487
+ const parsedAssistantInit = parseOptionalJsonInput(args.assistantInit, "assistantInit");
488
+ let assistantInit = parsedAssistantInit;
489
+ if (assistantInit === undefined) {
490
+ try {
491
+ const desc = await deps.getSchemaPromise();
492
+ assistantInit = desc.defaults !== undefined
493
+ ? cloneValue(desc.defaults)
494
+ : deriveInitialFromSchema(desc.schema);
495
+ }
496
+ catch {
497
+ // keep assistantInit undefined when schema introspection fails
498
+ }
499
+ }
500
+ if (!requestedDeckId) {
501
+ const startedAt = new Date().toISOString();
502
+ const manualRun = {
503
+ id: typeof args.runId === "string" && args.runId.trim().length > 0
504
+ ? args.runId.trim()
505
+ : deps.randomId("testbot"),
506
+ status: "idle",
507
+ workspaceId: args.workspaceId,
508
+ sessionId: args.workspaceId,
509
+ startedAt,
510
+ messages: [],
511
+ traces: [],
512
+ toolInserts: [],
513
+ };
514
+ const existing = deps.readSessionState(args.workspaceId);
515
+ const baseMeta = deps.buildWorkspaceMeta(workspaceRecord, existing?.meta);
516
+ const nextMeta = {
517
+ ...baseMeta,
518
+ testBot: true,
519
+ testBotRunId: manualRun.id,
520
+ testBotConfigPath: scenarioDeck.path,
521
+ testBotName: path.basename(scenarioDeck.path).replace(/\.deck\.(md|ts)$/i, ""),
522
+ scenarioRunId: manualRun.id,
523
+ selectedScenarioDeckId: scenarioDeck.id,
524
+ selectedScenarioDeckLabel: "Manual assistant chat",
525
+ scenarioConfigPath: scenarioDeck.path,
526
+ scenarioRunMode: "manual",
527
+ workspaceId: args.workspaceId,
528
+ };
529
+ const manualState = deps.persistSessionState({
530
+ ...(existing ?? {
531
+ runId: args.workspaceId,
532
+ messages: [],
533
+ }),
534
+ runId: manualRun.id,
535
+ messages: [],
536
+ messageRefs: [],
537
+ traces: [],
538
+ items: [],
539
+ meta: nextMeta,
540
+ });
541
+ testBotRuns.set(manualRun.id, {
542
+ run: manualRun,
543
+ state: manualState,
544
+ promise: null,
545
+ abort: null,
546
+ });
547
+ broadcastTestBot({ type: "testBotStatus", run: manualRun }, args.workspaceId);
548
+ return {
549
+ id: manualRun.id,
550
+ workspaceId: args.workspaceId,
551
+ status: manualRun.status,
552
+ error: manualRun.error,
553
+ startedAt: manualRun.startedAt,
554
+ finishedAt: manualRun.finishedAt,
555
+ messages: [],
556
+ traces: [],
557
+ toolInserts: [],
558
+ };
559
+ }
560
+ const run = startTestBotRun({
561
+ runId: args.runId,
562
+ workspaceId: args.workspaceId,
563
+ workspaceRecord,
564
+ botDeckPath: scenarioDeck.path,
565
+ botDeckId: scenarioDeck.id,
566
+ botDeckLabel: scenarioDeck.label,
567
+ maxTurnsOverride: scenarioDeck.maxTurns,
568
+ botInput: parsedScenarioInput,
569
+ deckInput: assistantInit,
570
+ baseMeta: {
571
+ scenarioRunMode: "scenario",
572
+ },
573
+ });
574
+ return {
575
+ id: run.id ?? deps.randomId("testbot"),
576
+ workspaceId: args.workspaceId,
577
+ status: run.status,
578
+ error: run.error,
579
+ startedAt: run.startedAt,
580
+ finishedAt: run.finishedAt,
581
+ messages: Array.isArray(run.messages) ? [...run.messages] : [],
582
+ traces: Array.isArray(run.traces) ? [...run.traces] : [],
583
+ toolInserts: Array.isArray(run.toolInserts) ? [...run.toolInserts] : [],
584
+ };
585
+ };
586
+ const sendWorkspaceScenarioRunForGraphql = async (args) => {
587
+ await deps.activateWorkspaceDeck(args.workspaceId, { forceReload: true });
588
+ const workspaceRecord = deps.resolveWorkspaceRecord(args.workspaceId);
589
+ if (!workspaceRecord) {
590
+ throw new Error("Workspace not found");
591
+ }
592
+ const active = testBotRuns.get(args.runId);
593
+ if (active &&
594
+ active.run.status === "running" &&
595
+ (active.run.workspaceId === args.workspaceId ||
596
+ active.run.sessionId === args.workspaceId)) {
597
+ throw new Error("Scenario run already in progress.");
598
+ }
599
+ const activeMatchesWorkspace = active
600
+ ? (active.run.workspaceId === args.workspaceId ||
601
+ active.run.sessionId === args.workspaceId)
602
+ : false;
603
+ let state = activeMatchesWorkspace
604
+ ? (active?.state ?? undefined)
605
+ : undefined;
606
+ if (!state) {
607
+ try {
608
+ state = deps.readSessionStateStrict(args.workspaceId, {
609
+ withTraces: true,
610
+ });
611
+ }
612
+ catch {
613
+ state = undefined;
614
+ }
615
+ }
616
+ if (!state) {
617
+ throw new Error("Workspace state unavailable for scenario send.");
618
+ }
619
+ const stateMeta = state.meta && typeof state.meta === "object"
620
+ ? state.meta
621
+ : {};
622
+ const stateRunId = typeof stateMeta.scenarioRunId === "string"
623
+ ? stateMeta.scenarioRunId
624
+ : typeof stateMeta.testBotRunId === "string"
625
+ ? stateMeta.testBotRunId
626
+ : null;
627
+ if (stateRunId !== args.runId) {
628
+ throw new Error("Scenario run is not the active run state. Open latest run first.");
629
+ }
630
+ const scenarioDeckPath = typeof stateMeta.scenarioConfigPath === "string"
631
+ ? stateMeta.scenarioConfigPath
632
+ : typeof stateMeta.testBotConfigPath === "string"
633
+ ? stateMeta.testBotConfigPath
634
+ : null;
635
+ if (!scenarioDeckPath) {
636
+ throw new Error("Scenario deck path unavailable for this run.");
637
+ }
638
+ const scenarioDeckId = typeof stateMeta.selectedScenarioDeckId === "string"
639
+ ? stateMeta.selectedScenarioDeckId
640
+ : undefined;
641
+ const scenarioDeckLabel = typeof stateMeta.selectedScenarioDeckLabel === "string"
642
+ ? stateMeta.selectedScenarioDeckLabel
643
+ : undefined;
644
+ const userMessageSource = stateMeta.scenarioRunMode === "manual"
645
+ ? "manual"
646
+ : "scenario";
647
+ const runMaxTurns = typeof stateMeta.testBotMaxTurns === "number" &&
648
+ Number.isFinite(stateMeta.testBotMaxTurns)
649
+ ? Math.round(stateMeta.testBotMaxTurns)
650
+ : undefined;
651
+ const existingRun = active?.run;
652
+ const openResponsesStartIndex = state.messages?.length ?? 0;
653
+ const run = {
654
+ id: args.runId,
655
+ status: "running",
656
+ workspaceId: args.workspaceId,
657
+ sessionId: args.workspaceId,
658
+ startedAt: existingRun?.startedAt ??
659
+ (typeof stateMeta.startedAt === "string"
660
+ ? stateMeta.startedAt
661
+ : null) ??
662
+ new Date().toISOString(),
663
+ finishedAt: undefined,
664
+ error: undefined,
665
+ maxTurns: existingRun?.maxTurns ?? runMaxTurns,
666
+ messages: existingRun?.messages ? [...existingRun.messages] : [],
667
+ traces: existingRun?.traces
668
+ ? [...existingRun.traces]
669
+ : Array.isArray(state.traces)
670
+ ? [...state.traces]
671
+ : [],
672
+ toolInserts: existingRun?.toolInserts ? [...existingRun.toolInserts] : [],
673
+ initFill: stateMeta.testBotInitFill ??
674
+ existingRun?.initFill,
675
+ };
676
+ const controller = new AbortController();
677
+ const entry = {
678
+ run,
679
+ state,
680
+ promise: null,
681
+ abort: controller,
682
+ };
683
+ testBotRuns.set(args.runId, entry);
684
+ const emitTestBot = (payload) => broadcastTestBot(payload, args.workspaceId);
685
+ const baseMeta = deps.buildWorkspaceMeta(workspaceRecord, stateMeta);
686
+ let savedState = state;
687
+ const capturedTraces = Array.isArray(state.traces)
688
+ ? [...state.traces]
689
+ : [];
690
+ const appendFromState = (nextState) => {
691
+ const snapshot = buildTestBotSnapshot(nextState);
692
+ run.messages = snapshot.messages;
693
+ run.toolInserts = snapshot.toolInserts;
694
+ run.traces = Array.isArray(nextState.traces)
695
+ ? [...nextState.traces]
696
+ : undefined;
697
+ emitTestBot({ type: "testBotStatus", run });
698
+ };
699
+ const tracer = (event) => {
700
+ const stamped = event.ts ? event : { ...event, ts: Date.now() };
701
+ capturedTraces.push(stamped);
702
+ if (savedState) {
703
+ deps.persistOpenResponsesTraceEvent(savedState, stamped, args.runId);
704
+ }
705
+ emitTestBot({
706
+ type: "testBotTrace",
707
+ workspaceId: args.workspaceId,
708
+ runId: args.runId,
709
+ event: stamped,
710
+ });
711
+ };
712
+ const trimmedMessage = args.message.trim();
713
+ const turn = run.messages.filter((message) => message.role === "user")
714
+ .length;
715
+ if (trimmedMessage.length > 0) {
716
+ run.messages = [
717
+ ...run.messages,
718
+ { role: "user", content: trimmedMessage },
719
+ ];
720
+ }
721
+ let hasStartedAssistantStreamMessage = false;
722
+ entry.promise = (async () => {
723
+ try {
724
+ emitTestBot({ type: "testBotStatus", run });
725
+ const rootResult = await runDeck({
726
+ path: scenarioDeckPath,
727
+ input: undefined,
728
+ inputProvided: false,
729
+ modelProvider: deps.modelProvider,
730
+ defaultModel: deps.model,
731
+ modelOverride: deps.modelForce,
732
+ trace: tracer,
733
+ stream: true,
734
+ state: savedState,
735
+ allowRootStringInput: true,
736
+ initialUserMessage: trimmedMessage,
737
+ responsesMode: deps.responsesMode,
738
+ workerSandbox: resolveWorkerSandboxForSignalAwareRun({
739
+ workerSandbox: deps.workerSandbox,
740
+ signal: controller.signal,
741
+ }),
742
+ signal: controller.signal,
743
+ onStateUpdate: (nextState) => {
744
+ const sourced = applyUserMessageRefSource(savedState, nextState, userMessageSource);
745
+ const nextMeta = {
746
+ ...baseMeta,
747
+ ...(sourced.meta ?? {}),
748
+ testBot: true,
749
+ testBotRunId: args.runId,
750
+ testBotConfigPath: scenarioDeckPath,
751
+ testBotName: path.basename(scenarioDeckPath).replace(/\.deck\.(md|ts)$/i, ""),
752
+ scenarioRunId: args.runId,
753
+ ...(scenarioDeckId
754
+ ? { selectedScenarioDeckId: scenarioDeckId }
755
+ : {}),
756
+ ...(scenarioDeckLabel
757
+ ? { selectedScenarioDeckLabel: scenarioDeckLabel }
758
+ : {}),
759
+ scenarioConfigPath: scenarioDeckPath,
760
+ scenarioRunMode: userMessageSource === "manual"
761
+ ? "manual"
762
+ : "scenario",
763
+ ...(run.initFill ? { testBotInitFill: run.initFill } : {}),
764
+ workspaceId: args.workspaceId,
765
+ ...(run.maxTurns ? { testBotMaxTurns: run.maxTurns } : {}),
766
+ };
767
+ const enriched = deps.persistSessionState({
768
+ ...sourced,
769
+ meta: nextMeta,
770
+ traces: capturedTraces,
771
+ });
772
+ savedState = enriched;
773
+ entry.state = enriched;
774
+ appendFromState(enriched);
775
+ },
776
+ onStreamText: (chunk) => {
777
+ if (typeof chunk === "string" && chunk.length > 0) {
778
+ if (!hasStartedAssistantStreamMessage) {
779
+ run.messages = [
780
+ ...run.messages,
781
+ { role: "assistant", content: chunk },
782
+ ];
783
+ hasStartedAssistantStreamMessage = true;
784
+ }
785
+ else {
786
+ const last = run.messages[run.messages.length - 1];
787
+ if (last?.role === "assistant") {
788
+ last.content += chunk;
789
+ }
790
+ }
791
+ }
792
+ emitTestBot({
793
+ type: "testBotStream",
794
+ workspaceId: args.workspaceId,
795
+ runId: args.runId,
796
+ role: "assistant",
797
+ chunk,
798
+ turn,
799
+ ts: Date.now(),
800
+ });
801
+ },
802
+ });
803
+ if (!isGambitEndSignal(rootResult)) {
804
+ emitTestBot({
805
+ type: "testBotStreamEnd",
806
+ workspaceId: args.workspaceId,
807
+ runId: args.runId,
808
+ role: "assistant",
809
+ turn,
810
+ ts: Date.now(),
811
+ });
812
+ }
813
+ run.status = controller.signal.aborted ? "canceled" : "completed";
814
+ run.error = undefined;
815
+ }
816
+ catch (err) {
817
+ if (controller.signal.aborted || isRunCanceledError(err)) {
818
+ run.status = "canceled";
819
+ run.error = undefined;
820
+ }
821
+ else {
822
+ run.status = "error";
823
+ run.error = err instanceof Error ? err.message : String(err);
824
+ }
825
+ }
826
+ finally {
827
+ if (savedState?.messages) {
828
+ const snapshot = buildTestBotSnapshot(savedState);
829
+ run.messages = snapshot.messages;
830
+ run.toolInserts = snapshot.toolInserts;
831
+ run.traces = Array.isArray(savedState.traces)
832
+ ? [...savedState.traces]
833
+ : run.traces;
834
+ }
835
+ if (savedState) {
836
+ deps.persistCanonicalStateMessages({
837
+ state: savedState,
838
+ runId: args.runId,
839
+ startIndex: openResponsesStartIndex,
840
+ source: userMessageSource,
841
+ });
842
+ entry.state = savedState;
843
+ }
844
+ run.finishedAt = new Date().toISOString();
845
+ entry.abort = null;
846
+ entry.promise = null;
847
+ emitTestBot({ type: "testBotStatus", run });
848
+ }
849
+ })();
850
+ return {
851
+ id: run.id,
852
+ workspaceId: args.workspaceId,
853
+ status: run.status,
854
+ error: run.error,
855
+ startedAt: run.startedAt,
856
+ finishedAt: run.finishedAt,
857
+ messages: Array.isArray(run.messages) ? [...run.messages] : [],
858
+ traces: Array.isArray(run.traces) ? [...run.traces] : [],
859
+ toolInserts: Array.isArray(run.toolInserts) ? [...run.toolInserts] : [],
860
+ };
861
+ };
862
+ const readWorkspaceScenarioRunsForGraphql = (workspaceId) => {
863
+ const latestByRunId = new Map();
864
+ const persistedState = deps.readSessionState(workspaceId);
865
+ if (persistedState) {
866
+ const metaRuns = listScenarioRunStatusesFromStateMeta(persistedState, workspaceId);
867
+ if (metaRuns.length > 0) {
868
+ for (const run of metaRuns) {
869
+ latestByRunId.set(run.id, run);
870
+ }
871
+ }
872
+ else {
873
+ for (const run of listPersistedTestRunStatuses(persistedState, workspaceId)) {
874
+ latestByRunId.set(run.id, run);
875
+ }
876
+ }
877
+ }
878
+ for (const entry of testBotRuns.values()) {
879
+ const run = entry.run;
880
+ if (run.workspaceId !== workspaceId &&
881
+ run.sessionId !== workspaceId) {
882
+ continue;
883
+ }
884
+ if (!run.id || run.id.trim().length === 0)
885
+ continue;
886
+ latestByRunId.set(run.id, run);
887
+ }
888
+ const records = [...latestByRunId.values()].map((run) => ({
889
+ id: run.id,
890
+ workspaceId,
891
+ status: run.status,
892
+ error: run.error,
893
+ startedAt: run.startedAt,
894
+ finishedAt: run.finishedAt,
895
+ messages: Array.isArray(run.messages) ? [...run.messages] : [],
896
+ traces: Array.isArray(run.traces) ? [...run.traces] : [],
897
+ toolInserts: Array.isArray(run.toolInserts) ? [...run.toolInserts] : [],
898
+ maxTurns: run.maxTurns,
899
+ initFill: run.initFill,
900
+ sessionId: run.sessionId,
901
+ }));
902
+ records.sort((a, b) => {
903
+ const aKey = a.startedAt ?? a.finishedAt ?? a.id;
904
+ const bKey = b.startedAt ?? b.finishedAt ?? b.id;
905
+ return bKey.localeCompare(aKey);
906
+ });
907
+ return records;
908
+ };
909
+ const stopWorkspaceScenarioRunForGraphql = async (args) => {
910
+ const active = testBotRuns.get(args.runId);
911
+ if (active &&
912
+ (active.run.workspaceId === args.workspaceId ||
913
+ active.run.sessionId === args.workspaceId)) {
914
+ active.abort?.abort();
915
+ try {
916
+ await active.promise;
917
+ }
918
+ catch {
919
+ // Abort path can reject internally; run projection remains authoritative.
920
+ }
921
+ }
922
+ const latest = readWorkspaceScenarioRunsForGraphql(args.workspaceId).find((run) => run.id === args.runId);
923
+ if (latest)
924
+ return latest;
925
+ throw new Error(`Scenario run ${args.runId} not found`);
926
+ };
927
+ const readWorkspaceScenarioRunForGraphql = (workspaceId, runId) => {
928
+ return readWorkspaceScenarioRunsForGraphql(workspaceId).find((run) => run.id === runId);
929
+ };
930
+ const saveWorkspaceFeedbackForGraphql = (args) => {
931
+ const workspaceId = args.workspaceId.trim();
932
+ if (!workspaceId)
933
+ throw new Error("Missing workspaceId");
934
+ const messageRefId = args.messageRefId.trim();
935
+ if (!messageRefId)
936
+ throw new Error("Missing messageRefId");
937
+ if (args.score !== null &&
938
+ (typeof args.score !== "number" || Number.isNaN(args.score))) {
939
+ throw new Error("Invalid score");
940
+ }
941
+ const state = deps.readSessionState(workspaceId);
942
+ if (!state)
943
+ throw new Error("Workspace not found");
944
+ const requestedRunId = typeof args.runId === "string" &&
945
+ args.runId.trim().length > 0
946
+ ? args.runId.trim()
947
+ : undefined;
948
+ const feedbackEligible = isFeedbackEligibleMessageRef(state, messageRefId) ||
949
+ (requestedRunId
950
+ ? isFeedbackEligiblePersistedTestRunMessageRef(state, requestedRunId, messageRefId)
951
+ : false);
952
+ if (!feedbackEligible) {
953
+ throw new Error("Feedback target is not eligible");
954
+ }
955
+ const existing = state.feedback ?? [];
956
+ const idx = existing.findIndex((entry) => entry.messageRefId === messageRefId);
957
+ let feedback = existing;
958
+ let entry;
959
+ let deleted = false;
960
+ if (args.score === null) {
961
+ if (idx >= 0) {
962
+ feedback = existing.filter((_, index) => index !== idx);
963
+ deleted = true;
964
+ }
965
+ }
966
+ else {
967
+ const clamped = Math.max(-3, Math.min(3, Math.round(args.score)));
968
+ const reason = typeof args.reason === "string"
969
+ ? args.reason
970
+ : idx >= 0
971
+ ? existing[idx]?.reason
972
+ : undefined;
973
+ const runId = requestedRunId ??
974
+ (typeof state.runId === "string" ? state.runId : "session");
975
+ const scenarioRunId = requestedRunId ??
976
+ (typeof state.meta?.scenarioRunId === "string"
977
+ ? state.meta.scenarioRunId
978
+ : runId);
979
+ const now = new Date().toISOString();
980
+ entry = idx >= 0
981
+ ? {
982
+ ...existing[idx],
983
+ score: clamped,
984
+ reason,
985
+ runId: existing[idx]?.runId ?? runId,
986
+ }
987
+ : {
988
+ id: deps.randomId("fb"),
989
+ runId,
990
+ messageRefId,
991
+ score: clamped,
992
+ reason,
993
+ createdAt: now,
994
+ };
995
+ if (entry) {
996
+ entry.workspaceId = workspaceId;
997
+ entry.scenarioRunId = scenarioRunId;
998
+ }
999
+ feedback = idx >= 0
1000
+ ? existing.map((item, index) => index === idx ? entry : item)
1001
+ : [...existing, entry];
1002
+ }
1003
+ const nextState = deps.persistSessionState({ ...state, feedback });
1004
+ deps.appendSessionEvent(nextState, {
1005
+ type: "feedback.update",
1006
+ kind: "artifact",
1007
+ category: "feedback",
1008
+ workspaceId,
1009
+ scenarioRunId: typeof nextState.meta?.scenarioRunId === "string"
1010
+ ? nextState.meta.scenarioRunId
1011
+ : nextState.runId,
1012
+ messageRefId,
1013
+ feedback: entry,
1014
+ deleted,
1015
+ });
1016
+ const liveRunId = typeof nextState.meta?.testBotRunId === "string"
1017
+ ? nextState.meta.testBotRunId
1018
+ : undefined;
1019
+ if (liveRunId) {
1020
+ const liveEntry = testBotRuns.get(liveRunId);
1021
+ if (liveEntry) {
1022
+ syncTestBotRunFromState(liveEntry.run, nextState);
1023
+ broadcastTestBot({ type: "testBotStatus", run: liveEntry.run }, workspaceId);
1024
+ }
1025
+ }
1026
+ const effectiveRunId = requestedRunId ??
1027
+ (entry?.runId ??
1028
+ (typeof nextState.meta?.scenarioRunId === "string"
1029
+ ? nextState.meta.scenarioRunId
1030
+ : nextState.runId));
1031
+ const run = readWorkspaceScenarioRunForGraphql(workspaceId, effectiveRunId);
1032
+ if (!run) {
1033
+ throw new Error(`Scenario run ${effectiveRunId} not found`);
1034
+ }
1035
+ return { feedback: entry, deleted, run };
1036
+ };
1037
+ return {
1038
+ broadcastTestBot,
1039
+ startWorkspaceScenarioRunForGraphql,
1040
+ sendWorkspaceScenarioRunForGraphql,
1041
+ readWorkspaceScenarioRunsForGraphql,
1042
+ readWorkspaceScenarioRunForGraphql,
1043
+ saveWorkspaceFeedbackForGraphql,
1044
+ stopWorkspaceScenarioRunForGraphql,
1045
+ getLiveTestRunEntry: (runId) => testBotRuns.get(runId),
1046
+ getLiveTestRunEntryByWorkspaceId: findTestRunByWorkspaceId,
1047
+ readPersistedTestRunStatusById,
1048
+ isFeedbackEligibleMessageRef,
1049
+ isFeedbackEligiblePersistedTestRunMessageRef,
1050
+ syncTestBotRunFromState,
1051
+ };
1052
+ };