tactus 0.31.2__tar.gz → 0.32.1__tar.gz

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 (598) hide show
  1. {tactus-0.31.2 → tactus-0.32.1}/.gitignore +3 -0
  2. tactus-0.32.1/.tactus/config.yml.example +12 -0
  3. {tactus-0.31.2 → tactus-0.32.1}/CHANGELOG.md +21 -0
  4. {tactus-0.31.2 → tactus-0.32.1}/PKG-INFO +3 -1
  5. tactus-0.32.1/examples/.tactus/config.yml.example +12 -0
  6. {tactus-0.31.2 → tactus-0.32.1}/pyproject.toml +4 -1
  7. {tactus-0.31.2 → tactus-0.32.1}/tactus/__init__.py +1 -1
  8. {tactus-0.31.2 → tactus-0.32.1}/tactus/dspy/agent.py +21 -0
  9. tactus-0.32.1/tactus/ide/config_server.py +536 -0
  10. {tactus-0.31.2 → tactus-0.32.1}/tactus/ide/server.py +45 -12
  11. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/backend/tactus_backend.spec +2 -0
  12. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/package.json +2 -3
  13. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/preload/preload.ts +6 -1
  14. tactus-0.31.2/tactus-desktop/scripts/build-backend.js → tactus-0.32.1/tactus-desktop/scripts/build-backend.mjs +22 -8
  15. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/src/main.ts +28 -4
  16. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/src/menu.ts +15 -1
  17. tactus-0.32.1/tactus-desktop/src/preferences-window.ts +47 -0
  18. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/backend/config_server.py +18 -1
  19. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/App.tsx +100 -5
  20. tactus-0.32.1/tactus-ide/frontend/src/components/AuthErrorDialog.tsx +69 -0
  21. tactus-0.31.2/.tactus/config.yml.example +0 -41
  22. {tactus-0.31.2 → tactus-0.32.1}/.claude/agents.md +0 -0
  23. {tactus-0.31.2 → tactus-0.32.1}/.github/workflows/release.yml +0 -0
  24. {tactus-0.31.2 → tactus-0.32.1}/AGENTS.md +0 -0
  25. {tactus-0.31.2 → tactus-0.32.1}/IMPLEMENTATION.md +0 -0
  26. {tactus-0.31.2 → tactus-0.32.1}/LICENSE +0 -0
  27. {tactus-0.31.2 → tactus-0.32.1}/Makefile +0 -0
  28. {tactus-0.31.2 → tactus-0.32.1}/README.md +0 -0
  29. {tactus-0.31.2 → tactus-0.32.1}/SPECIFICATION.md +0 -0
  30. {tactus-0.31.2 → tactus-0.32.1}/TECHNICAL_DEBT.md +0 -0
  31. {tactus-0.31.2 → tactus-0.32.1}/behave.ini +0 -0
  32. {tactus-0.31.2 → tactus-0.32.1}/docs/AGENTS.md +0 -0
  33. {tactus-0.31.2 → tactus-0.32.1}/docs/BDD_TESTING.md +0 -0
  34. {tactus-0.31.2 → tactus-0.32.1}/docs/CONFIGURATION.md +0 -0
  35. {tactus-0.31.2 → tactus-0.32.1}/docs/DURABILITY.md +0 -0
  36. {tactus-0.31.2 → tactus-0.32.1}/docs/FILE_IO.md +0 -0
  37. {tactus-0.31.2 → tactus-0.32.1}/docs/SANDBOXING.md +0 -0
  38. {tactus-0.31.2 → tactus-0.32.1}/docs/STREAMING.md +0 -0
  39. {tactus-0.31.2 → tactus-0.32.1}/docs/TOOLS.md +0 -0
  40. {tactus-0.31.2 → tactus-0.32.1}/docs/TOOL_ROADMAP.md +0 -0
  41. {tactus-0.31.2 → tactus-0.32.1}/docs/development-mode.md +0 -0
  42. {tactus-0.31.2 → tactus-0.32.1}/examples/.tactus/config.yml +0 -0
  43. {tactus-0.31.2 → tactus-0.32.1}/examples/01-basics-hello-world.tac +0 -0
  44. {tactus-0.31.2 → tactus-0.32.1}/examples/02-basics-simple-logic.tac +0 -0
  45. {tactus-0.31.2 → tactus-0.32.1}/examples/03-basics-parameters.tac +0 -0
  46. {tactus-0.31.2 → tactus-0.32.1}/examples/04-basics-simple-agent.tac +0 -0
  47. {tactus-0.31.2 → tactus-0.32.1}/examples/05-basics-multi-model.tac +0 -0
  48. {tactus-0.31.2 → tactus-0.32.1}/examples/06-basics-streaming.tac +0 -0
  49. {tactus-0.31.2 → tactus-0.32.1}/examples/07-basics-bedrock.tac +0 -0
  50. {tactus-0.31.2 → tactus-0.32.1}/examples/08-basics-models.tac +0 -0
  51. {tactus-0.31.2 → tactus-0.32.1}/examples/09-basics-google-gemini.tac +0 -0
  52. {tactus-0.31.2 → tactus-0.32.1}/examples/10-feature-state.tac +0 -0
  53. {tactus-0.31.2 → tactus-0.32.1}/examples/11-feature-message-history.tac +0 -0
  54. {tactus-0.31.2 → tactus-0.32.1}/examples/12-feature-structured-output.tac +0 -0
  55. {tactus-0.31.2 → tactus-0.32.1}/examples/13-feature-session.tac +0 -0
  56. {tactus-0.31.2 → tactus-0.32.1}/examples/14-feature-per-turn-tools-simple.tac +0 -0
  57. {tactus-0.31.2 → tactus-0.32.1}/examples/14-feature-per-turn-tools.tac +0 -0
  58. {tactus-0.31.2 → tactus-0.32.1}/examples/15-feature-local-tools.tac +0 -0
  59. {tactus-0.31.2 → tactus-0.32.1}/examples/16-feature-toolsets-advanced.tac +0 -0
  60. {tactus-0.31.2 → tactus-0.32.1}/examples/17-feature-toolsets-dsl.tac +0 -0
  61. {tactus-0.31.2 → tactus-0.32.1}/examples/18-feature-lua-tools-individual.tac +0 -0
  62. {tactus-0.31.2 → tactus-0.32.1}/examples/18-feature-lua-tools-inline.tac +0 -0
  63. {tactus-0.31.2 → tactus-0.32.1}/examples/18-feature-lua-tools-toolset.tac +0 -0
  64. {tactus-0.31.2 → tactus-0.32.1}/examples/19-feature-direct-tool-calls.tac +0 -0
  65. {tactus-0.31.2 → tactus-0.32.1}/examples/20-bdd-complete.tac +0 -0
  66. {tactus-0.31.2 → tactus-0.32.1}/examples/21-bdd-passing.tac +0 -0
  67. {tactus-0.31.2 → tactus-0.32.1}/examples/22-bdd-fuzzy-matching.tac +0 -0
  68. {tactus-0.31.2 → tactus-0.32.1}/examples/30-eval-simple.tac +0 -0
  69. {tactus-0.31.2 → tactus-0.32.1}/examples/31-eval-demo.tac +0 -0
  70. {tactus-0.31.2 → tactus-0.32.1}/examples/32-eval-success-rate.tac +0 -0
  71. {tactus-0.31.2 → tactus-0.32.1}/examples/33-eval-thresholds.tac +0 -0
  72. {tactus-0.31.2 → tactus-0.32.1}/examples/34-eval-dataset.jsonl +0 -0
  73. {tactus-0.31.2 → tactus-0.32.1}/examples/34-eval-dataset.tac +0 -0
  74. {tactus-0.31.2 → tactus-0.32.1}/examples/35-eval-trace.tac +0 -0
  75. {tactus-0.31.2 → tactus-0.32.1}/examples/36-eval-advanced.tac +0 -0
  76. {tactus-0.31.2 → tactus-0.32.1}/examples/37-eval-comprehensive.tac +0 -0
  77. {tactus-0.31.2 → tactus-0.32.1}/examples/39-model-simple.tac +0 -0
  78. {tactus-0.31.2 → tactus-0.32.1}/examples/40-mcp-test.tac +0 -0
  79. {tactus-0.31.2 → tactus-0.32.1}/examples/40-model-text-classifier.tac +0 -0
  80. {tactus-0.31.2 → tactus-0.32.1}/examples/41-mcp-simple.tac +0 -0
  81. {tactus-0.31.2 → tactus-0.32.1}/examples/41-model-pytorch.tac +0 -0
  82. {tactus-0.31.2 → tactus-0.32.1}/examples/43-sub-procedure-simple.tac +0 -0
  83. {tactus-0.31.2 → tactus-0.32.1}/examples/44-sub-procedure-composition.tac +0 -0
  84. {tactus-0.31.2 → tactus-0.32.1}/examples/45-sub-procedure-recursive.tac +0 -0
  85. {tactus-0.31.2 → tactus-0.32.1}/examples/46-checkpoint-explicit.tac +0 -0
  86. {tactus-0.31.2 → tactus-0.32.1}/examples/47-checkpoint-expensive-ops.tac +0 -0
  87. {tactus-0.31.2 → tactus-0.32.1}/examples/48-script-mode-simple.tac +0 -0
  88. {tactus-0.31.2 → tactus-0.32.1}/examples/50-inputs-showcase.tac +0 -0
  89. {tactus-0.31.2 → tactus-0.32.1}/examples/51-inputs-calculator.tac +0 -0
  90. {tactus-0.31.2 → tactus-0.32.1}/examples/52-file-io-basics.tac +0 -0
  91. {tactus-0.31.2 → tactus-0.32.1}/examples/53-tsv-file-io.tac +0 -0
  92. {tactus-0.31.2 → tactus-0.32.1}/examples/54-json-file-io.tac +0 -0
  93. {tactus-0.31.2 → tactus-0.32.1}/examples/55-parquet-file-io.tac +0 -0
  94. {tactus-0.31.2 → tactus-0.32.1}/examples/56-hdf5-file-io.tac +0 -0
  95. {tactus-0.31.2 → tactus-0.32.1}/examples/57-excel-file-io.tac +0 -0
  96. {tactus-0.31.2 → tactus-0.32.1}/examples/58-text-file-io.tac +0 -0
  97. {tactus-0.31.2 → tactus-0.32.1}/examples/60-tool-sources.tac +0 -0
  98. {tactus-0.31.2 → tactus-0.32.1}/examples/61-inline-toolset-lua.tac +0 -0
  99. {tactus-0.31.2 → tactus-0.32.1}/examples/62-mcp-toolset-by-server.tac +0 -0
  100. {tactus-0.31.2 → tactus-0.32.1}/examples/63-toolset-import-from-file.tac +0 -0
  101. {tactus-0.31.2 → tactus-0.32.1}/examples/64-require-modules.tac +0 -0
  102. {tactus-0.31.2 → tactus-0.32.1}/examples/65-optional-state-demo.tac +0 -0
  103. {tactus-0.31.2 → tactus-0.32.1}/examples/66-host-tools-via-broker.tac +0 -0
  104. {tactus-0.31.2 → tactus-0.32.1}/examples/67-host-tool-source.tac +0 -0
  105. {tactus-0.31.2 → tactus-0.32.1}/examples/70-mocking-static.tac +0 -0
  106. {tactus-0.31.2 → tactus-0.32.1}/examples/71-mocking-temporal.tac +0 -0
  107. {tactus-0.31.2 → tactus-0.32.1}/examples/72-mocking-conditional.tac +0 -0
  108. {tactus-0.31.2 → tactus-0.32.1}/examples/99-misc-test-loading.tac +0 -0
  109. {tactus-0.31.2 → tactus-0.32.1}/examples/README.md +0 -0
  110. {tactus-0.31.2 → tactus-0.32.1}/examples/app_config.ini +0 -0
  111. {tactus-0.31.2 → tactus-0.32.1}/examples/data/sample.csv +0 -0
  112. {tactus-0.31.2 → tactus-0.32.1}/examples/demo_output.json +0 -0
  113. {tactus-0.31.2 → tactus-0.32.1}/examples/helpers/math_module.tac +0 -0
  114. {tactus-0.31.2 → tactus-0.32.1}/examples/helpers/product.tac +0 -0
  115. {tactus-0.31.2 → tactus-0.32.1}/examples/helpers/string_module.tac +0 -0
  116. {tactus-0.31.2 → tactus-0.32.1}/examples/helpers/sum.tac +0 -0
  117. {tactus-0.31.2 → tactus-0.32.1}/examples/helpers/text_tools.tac +0 -0
  118. {tactus-0.31.2 → tactus-0.32.1}/examples/inventory_summary.tsv +0 -0
  119. {tactus-0.31.2 → tactus-0.32.1}/examples/mock-config.json +0 -0
  120. {tactus-0.31.2 → tactus-0.32.1}/examples/models/README.md +0 -0
  121. {tactus-0.31.2 → tactus-0.32.1}/examples/models/create_sentiment_model.py +0 -0
  122. {tactus-0.31.2 → tactus-0.32.1}/examples/output_summary.txt +0 -0
  123. {tactus-0.31.2 → tactus-0.32.1}/examples/test-raw-module.tac +0 -0
  124. {tactus-0.31.2 → tactus-0.32.1}/examples/test-raw-streaming.tac +0 -0
  125. {tactus-0.31.2 → tactus-0.32.1}/examples/tools/calculations.py +0 -0
  126. {tactus-0.31.2 → tactus-0.32.1}/examples/tools/data_analysis.py +0 -0
  127. {tactus-0.31.2 → tactus-0.32.1}/examples/tools/search.py +0 -0
  128. {tactus-0.31.2 → tactus-0.32.1}/examples/with_dependencies/README.md +0 -0
  129. {tactus-0.31.2 → tactus-0.32.1}/examples/with_dependencies/simple_http_test.tac +0 -0
  130. {tactus-0.31.2 → tactus-0.32.1}/examples/with_dependencies/time_lookup.tac +0 -0
  131. {tactus-0.31.2 → tactus-0.32.1}/features/01_state_management.feature +0 -0
  132. {tactus-0.31.2 → tactus-0.32.1}/features/02_checkpointing.feature +0 -0
  133. {tactus-0.31.2 → tactus-0.32.1}/features/03_human_in_the_loop.feature +0 -0
  134. {tactus-0.31.2 → tactus-0.32.1}/features/04_control_flow.feature +0 -0
  135. {tactus-0.31.2 → tactus-0.32.1}/features/05_tool_integration.feature +0 -0
  136. {tactus-0.31.2 → tactus-0.32.1}/features/06_retry_logic.feature +0 -0
  137. {tactus-0.31.2 → tactus-0.32.1}/features/07_file_operations.feature +0 -0
  138. {tactus-0.31.2 → tactus-0.32.1}/features/08_agent_primitives.feature +0 -0
  139. {tactus-0.31.2 → tactus-0.32.1}/features/09_workflow_execution.feature +0 -0
  140. {tactus-0.31.2 → tactus-0.32.1}/features/10_lua_integration.feature +0 -0
  141. {tactus-0.31.2 → tactus-0.32.1}/features/11_storage_backends.feature +0 -0
  142. {tactus-0.31.2 → tactus-0.32.1}/features/12_json_operations.feature +0 -0
  143. {tactus-0.31.2 → tactus-0.32.1}/features/13_logging.feature +0 -0
  144. {tactus-0.31.2 → tactus-0.32.1}/features/15_procedure_calls.feature +0 -0
  145. {tactus-0.31.2 → tactus-0.32.1}/features/16_session_management.feature +0 -0
  146. {tactus-0.31.2 → tactus-0.32.1}/features/17_lua_dsl_validation.feature +0 -0
  147. {tactus-0.31.2 → tactus-0.32.1}/features/18_example_procedures.feature +0 -0
  148. {tactus-0.31.2 → tactus-0.32.1}/features/19_ide_server.feature +0 -0
  149. {tactus-0.31.2 → tactus-0.32.1}/features/20_parameters.feature +0 -0
  150. {tactus-0.31.2 → tactus-0.32.1}/features/21_outputs.feature +0 -0
  151. {tactus-0.31.2 → tactus-0.32.1}/features/23_prompts.feature +0 -0
  152. {tactus-0.31.2 → tactus-0.32.1}/features/24_bdd_specifications.feature +0 -0
  153. {tactus-0.31.2 → tactus-0.32.1}/features/25_bdd_custom_steps.feature +0 -0
  154. {tactus-0.31.2 → tactus-0.32.1}/features/26_bdd_evaluation.feature +0 -0
  155. {tactus-0.31.2 → tactus-0.32.1}/features/27_default_settings.feature +0 -0
  156. {tactus-0.31.2 → tactus-0.32.1}/features/28_custom_prompts.feature +0 -0
  157. {tactus-0.31.2 → tactus-0.32.1}/features/29_execution_settings.feature +0 -0
  158. {tactus-0.31.2 → tactus-0.32.1}/features/30_session_filters.feature +0 -0
  159. {tactus-0.31.2 → tactus-0.32.1}/features/31_matchers.feature +0 -0
  160. {tactus-0.31.2 → tactus-0.32.1}/features/32_result_object.feature +0 -0
  161. {tactus-0.31.2 → tactus-0.32.1}/features/33_output_type.feature +0 -0
  162. {tactus-0.31.2 → tactus-0.32.1}/features/42_model_primitive.feature +0 -0
  163. {tactus-0.31.2 → tactus-0.32.1}/features/43_sub_procedure_checkpointing.feature +0 -0
  164. {tactus-0.31.2 → tactus-0.32.1}/features/46_explicit_checkpoint.feature +0 -0
  165. {tactus-0.31.2 → tactus-0.32.1}/features/48_script_mode.feature +0 -0
  166. {tactus-0.31.2 → tactus-0.32.1}/features/51_dspy_lm_config.feature +0 -0
  167. {tactus-0.31.2 → tactus-0.32.1}/features/52_dspy_signature.feature +0 -0
  168. {tactus-0.31.2 → tactus-0.32.1}/features/53_dspy_module.feature +0 -0
  169. {tactus-0.31.2 → tactus-0.32.1}/features/54_dspy_history.feature +0 -0
  170. {tactus-0.31.2 → tactus-0.32.1}/features/55_dspy_prediction.feature +0 -0
  171. {tactus-0.31.2 → tactus-0.32.1}/features/56_dspy_agent.feature +0 -0
  172. {tactus-0.31.2 → tactus-0.32.1}/features/57_chat_assistant.feature +0 -0
  173. {tactus-0.31.2 → tactus-0.32.1}/features/60_formatting.feature +0 -0
  174. {tactus-0.31.2 → tactus-0.32.1}/features/documentation/IDE_SERVER_BEHAVIOR.md +0 -0
  175. {tactus-0.31.2 → tactus-0.32.1}/features/documentation/Lua DSL/README.md +0 -0
  176. {tactus-0.31.2 → tactus-0.32.1}/features/environment.py +0 -0
  177. {tactus-0.31.2 → tactus-0.32.1}/features/steps/agent_primitives_steps.py +0 -0
  178. {tactus-0.31.2 → tactus-0.32.1}/features/steps/chat_assistant_steps.py +0 -0
  179. {tactus-0.31.2 → tactus-0.32.1}/features/steps/checkpointing_steps.py +0 -0
  180. {tactus-0.31.2 → tactus-0.32.1}/features/steps/control_flow_steps.py +0 -0
  181. {tactus-0.31.2 → tactus-0.32.1}/features/steps/dspy_agent_steps.py +0 -0
  182. {tactus-0.31.2 → tactus-0.32.1}/features/steps/dspy_history_steps.py +0 -0
  183. {tactus-0.31.2 → tactus-0.32.1}/features/steps/dspy_lm_steps.py +0 -0
  184. {tactus-0.31.2 → tactus-0.32.1}/features/steps/dspy_module_steps.py +0 -0
  185. {tactus-0.31.2 → tactus-0.32.1}/features/steps/dspy_prediction_steps.py +0 -0
  186. {tactus-0.31.2 → tactus-0.32.1}/features/steps/dspy_signature_steps.py +0 -0
  187. {tactus-0.31.2 → tactus-0.32.1}/features/steps/example_procedures_steps.py +0 -0
  188. {tactus-0.31.2 → tactus-0.32.1}/features/steps/file_operations_steps.py +0 -0
  189. {tactus-0.31.2 → tactus-0.32.1}/features/steps/formatting_steps.py +0 -0
  190. {tactus-0.31.2 → tactus-0.32.1}/features/steps/human_in_the_loop_steps.py +0 -0
  191. {tactus-0.31.2 → tactus-0.32.1}/features/steps/ide_server_steps.py +0 -0
  192. {tactus-0.31.2 → tactus-0.32.1}/features/steps/json_operations_steps.py +0 -0
  193. {tactus-0.31.2 → tactus-0.32.1}/features/steps/logging_steps.py +0 -0
  194. {tactus-0.31.2 → tactus-0.32.1}/features/steps/lua_dsl_validation_steps.py +0 -0
  195. {tactus-0.31.2 → tactus-0.32.1}/features/steps/lua_integration_steps.py +0 -0
  196. {tactus-0.31.2 → tactus-0.32.1}/features/steps/mocking_steps.py +0 -0
  197. {tactus-0.31.2 → tactus-0.32.1}/features/steps/procedure_calls_steps.py +0 -0
  198. {tactus-0.31.2 → tactus-0.32.1}/features/steps/result_and_output_steps.py +0 -0
  199. {tactus-0.31.2 → tactus-0.32.1}/features/steps/retry_logic_steps.py +0 -0
  200. {tactus-0.31.2 → tactus-0.32.1}/features/steps/session_management_steps.py +0 -0
  201. {tactus-0.31.2 → tactus-0.32.1}/features/steps/state_management_steps.py +0 -0
  202. {tactus-0.31.2 → tactus-0.32.1}/features/steps/storage_backend_steps.py +0 -0
  203. {tactus-0.31.2 → tactus-0.32.1}/features/steps/support/__init__.py +0 -0
  204. {tactus-0.31.2 → tactus-0.32.1}/features/steps/support/harnesses.py +0 -0
  205. {tactus-0.31.2 → tactus-0.32.1}/features/steps/tool_integration_steps.py +0 -0
  206. {tactus-0.31.2 → tactus-0.32.1}/features/steps/workflow_execution_steps.py +0 -0
  207. {tactus-0.31.2 → tactus-0.32.1}/planning/BROKER_AND_TOOL_RUNNERS.md +0 -0
  208. {tactus-0.31.2 → tactus-0.32.1}/planning/FORMATTER.md +0 -0
  209. {tactus-0.31.2 → tactus-0.32.1}/scripts/audit_examples_mocking.py +0 -0
  210. {tactus-0.31.2 → tactus-0.32.1}/scripts/convert_examples.py +0 -0
  211. {tactus-0.31.2 → tactus-0.32.1}/scripts/run_precommit_suite.sh +0 -0
  212. {tactus-0.31.2 → tactus-0.32.1}/scripts/timeout.py +0 -0
  213. {tactus-0.31.2 → tactus-0.32.1}/start-web-ide.sh +0 -0
  214. {tactus-0.31.2 → tactus-0.32.1}/tactus/adapters/__init__.py +0 -0
  215. {tactus-0.31.2 → tactus-0.32.1}/tactus/adapters/broker_log.py +0 -0
  216. {tactus-0.31.2 → tactus-0.32.1}/tactus/adapters/cli_hitl.py +0 -0
  217. {tactus-0.31.2 → tactus-0.32.1}/tactus/adapters/cli_log.py +0 -0
  218. {tactus-0.31.2 → tactus-0.32.1}/tactus/adapters/cost_collector_log.py +0 -0
  219. {tactus-0.31.2 → tactus-0.32.1}/tactus/adapters/file_storage.py +0 -0
  220. {tactus-0.31.2 → tactus-0.32.1}/tactus/adapters/http_callback_log.py +0 -0
  221. {tactus-0.31.2 → tactus-0.32.1}/tactus/adapters/ide_log.py +0 -0
  222. {tactus-0.31.2 → tactus-0.32.1}/tactus/adapters/lua_tools.py +0 -0
  223. {tactus-0.31.2 → tactus-0.32.1}/tactus/adapters/mcp.py +0 -0
  224. {tactus-0.31.2 → tactus-0.32.1}/tactus/adapters/mcp_manager.py +0 -0
  225. {tactus-0.31.2 → tactus-0.32.1}/tactus/adapters/memory.py +0 -0
  226. {tactus-0.31.2 → tactus-0.32.1}/tactus/adapters/plugins.py +0 -0
  227. {tactus-0.31.2 → tactus-0.32.1}/tactus/backends/http_backend.py +0 -0
  228. {tactus-0.31.2 → tactus-0.32.1}/tactus/backends/model_backend.py +0 -0
  229. {tactus-0.31.2 → tactus-0.32.1}/tactus/backends/pytorch_backend.py +0 -0
  230. {tactus-0.31.2 → tactus-0.32.1}/tactus/broker/__init__.py +0 -0
  231. {tactus-0.31.2 → tactus-0.32.1}/tactus/broker/client.py +0 -0
  232. {tactus-0.31.2 → tactus-0.32.1}/tactus/broker/protocol.py +0 -0
  233. {tactus-0.31.2 → tactus-0.32.1}/tactus/broker/server.py +0 -0
  234. {tactus-0.31.2 → tactus-0.32.1}/tactus/broker/stdio.py +0 -0
  235. {tactus-0.31.2 → tactus-0.32.1}/tactus/cli/__init__.py +0 -0
  236. {tactus-0.31.2 → tactus-0.32.1}/tactus/cli/app.py +0 -0
  237. {tactus-0.31.2 → tactus-0.32.1}/tactus/cli/commands/__init__.py +0 -0
  238. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/__init__.py +0 -0
  239. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/config_manager.py +0 -0
  240. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/dependencies/__init__.py +0 -0
  241. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/dependencies/registry.py +0 -0
  242. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/dsl_stubs.py +0 -0
  243. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/exceptions.py +0 -0
  244. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/execution_context.py +0 -0
  245. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/lua_sandbox.py +0 -0
  246. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/message_history_manager.py +0 -0
  247. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/mocking.py +0 -0
  248. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/output_validator.py +0 -0
  249. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/registry.py +0 -0
  250. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/runtime.py +0 -0
  251. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/template_resolver.py +0 -0
  252. {tactus-0.31.2 → tactus-0.32.1}/tactus/core/yaml_parser.py +0 -0
  253. {tactus-0.31.2 → tactus-0.32.1}/tactus/docker/Dockerfile +0 -0
  254. {tactus-0.31.2 → tactus-0.32.1}/tactus/docker/entrypoint.sh +0 -0
  255. {tactus-0.31.2 → tactus-0.32.1}/tactus/dspy/__init__.py +0 -0
  256. {tactus-0.31.2 → tactus-0.32.1}/tactus/dspy/broker_lm.py +0 -0
  257. {tactus-0.31.2 → tactus-0.32.1}/tactus/dspy/config.py +0 -0
  258. {tactus-0.31.2 → tactus-0.32.1}/tactus/dspy/history.py +0 -0
  259. {tactus-0.31.2 → tactus-0.32.1}/tactus/dspy/module.py +0 -0
  260. {tactus-0.31.2 → tactus-0.32.1}/tactus/dspy/prediction.py +0 -0
  261. {tactus-0.31.2 → tactus-0.32.1}/tactus/dspy/signature.py +0 -0
  262. {tactus-0.31.2 → tactus-0.32.1}/tactus/formatting/__init__.py +0 -0
  263. {tactus-0.31.2 → tactus-0.32.1}/tactus/formatting/formatter.py +0 -0
  264. {tactus-0.31.2 → tactus-0.32.1}/tactus/ide/__init__.py +0 -0
  265. {tactus-0.31.2 → tactus-0.32.1}/tactus/ide/coding_assistant.py +0 -0
  266. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/__init__.py +0 -0
  267. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/control.py +0 -0
  268. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/file.py +0 -0
  269. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/handles.py +0 -0
  270. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/host.py +0 -0
  271. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/human.py +0 -0
  272. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/json.py +0 -0
  273. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/log.py +0 -0
  274. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/message_history.py +0 -0
  275. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/model.py +0 -0
  276. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/procedure.py +0 -0
  277. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/procedure_callable.py +0 -0
  278. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/retry.py +0 -0
  279. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/session.py +0 -0
  280. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/state.py +0 -0
  281. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/step.py +0 -0
  282. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/system.py +0 -0
  283. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/tool.py +0 -0
  284. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/tool_handle.py +0 -0
  285. {tactus-0.31.2 → tactus-0.32.1}/tactus/primitives/toolset.py +0 -0
  286. {tactus-0.31.2 → tactus-0.32.1}/tactus/protocols/__init__.py +0 -0
  287. {tactus-0.31.2 → tactus-0.32.1}/tactus/protocols/chat_recorder.py +0 -0
  288. {tactus-0.31.2 → tactus-0.32.1}/tactus/protocols/config.py +0 -0
  289. {tactus-0.31.2 → tactus-0.32.1}/tactus/protocols/cost.py +0 -0
  290. {tactus-0.31.2 → tactus-0.32.1}/tactus/protocols/hitl.py +0 -0
  291. {tactus-0.31.2 → tactus-0.32.1}/tactus/protocols/log_handler.py +0 -0
  292. {tactus-0.31.2 → tactus-0.32.1}/tactus/protocols/models.py +0 -0
  293. {tactus-0.31.2 → tactus-0.32.1}/tactus/protocols/result.py +0 -0
  294. {tactus-0.31.2 → tactus-0.32.1}/tactus/protocols/storage.py +0 -0
  295. {tactus-0.31.2 → tactus-0.32.1}/tactus/providers/__init__.py +0 -0
  296. {tactus-0.31.2 → tactus-0.32.1}/tactus/providers/base.py +0 -0
  297. {tactus-0.31.2 → tactus-0.32.1}/tactus/providers/bedrock.py +0 -0
  298. {tactus-0.31.2 → tactus-0.32.1}/tactus/providers/google.py +0 -0
  299. {tactus-0.31.2 → tactus-0.32.1}/tactus/providers/openai.py +0 -0
  300. {tactus-0.31.2 → tactus-0.32.1}/tactus/sandbox/__init__.py +0 -0
  301. {tactus-0.31.2 → tactus-0.32.1}/tactus/sandbox/config.py +0 -0
  302. {tactus-0.31.2 → tactus-0.32.1}/tactus/sandbox/container_runner.py +0 -0
  303. {tactus-0.31.2 → tactus-0.32.1}/tactus/sandbox/docker_manager.py +0 -0
  304. {tactus-0.31.2 → tactus-0.32.1}/tactus/sandbox/entrypoint.py +0 -0
  305. {tactus-0.31.2 → tactus-0.32.1}/tactus/sandbox/protocol.py +0 -0
  306. {tactus-0.31.2 → tactus-0.32.1}/tactus/stdlib/__init__.py +0 -0
  307. {tactus-0.31.2 → tactus-0.32.1}/tactus/stdlib/io/__init__.py +0 -0
  308. {tactus-0.31.2 → tactus-0.32.1}/tactus/stdlib/io/csv.py +0 -0
  309. {tactus-0.31.2 → tactus-0.32.1}/tactus/stdlib/io/excel.py +0 -0
  310. {tactus-0.31.2 → tactus-0.32.1}/tactus/stdlib/io/file.py +0 -0
  311. {tactus-0.31.2 → tactus-0.32.1}/tactus/stdlib/io/fs.py +0 -0
  312. {tactus-0.31.2 → tactus-0.32.1}/tactus/stdlib/io/hdf5.py +0 -0
  313. {tactus-0.31.2 → tactus-0.32.1}/tactus/stdlib/io/json.py +0 -0
  314. {tactus-0.31.2 → tactus-0.32.1}/tactus/stdlib/io/parquet.py +0 -0
  315. {tactus-0.31.2 → tactus-0.32.1}/tactus/stdlib/io/tsv.py +0 -0
  316. {tactus-0.31.2 → tactus-0.32.1}/tactus/stdlib/loader.py +0 -0
  317. {tactus-0.31.2 → tactus-0.32.1}/tactus/stdlib/tac/tactus/tools/done.tac +0 -0
  318. {tactus-0.31.2 → tactus-0.32.1}/tactus/stdlib/tac/tactus/tools/log.tac +0 -0
  319. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/README.md +0 -0
  320. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/__init__.py +0 -0
  321. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/behave_integration.py +0 -0
  322. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/context.py +0 -0
  323. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/eval_models.py +0 -0
  324. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/evaluation_runner.py +0 -0
  325. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/evaluators.py +0 -0
  326. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/events.py +0 -0
  327. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/gherkin_parser.py +0 -0
  328. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/mock_agent.py +0 -0
  329. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/mock_dependencies.py +0 -0
  330. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/mock_hitl.py +0 -0
  331. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/mock_registry.py +0 -0
  332. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/mock_tools.py +0 -0
  333. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/models.py +0 -0
  334. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/pydantic_eval_runner.py +0 -0
  335. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/steps/__init__.py +0 -0
  336. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/steps/builtin.py +0 -0
  337. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/steps/custom.py +0 -0
  338. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/steps/registry.py +0 -0
  339. {tactus-0.31.2 → tactus-0.32.1}/tactus/testing/test_runner.py +0 -0
  340. {tactus-0.31.2 → tactus-0.32.1}/tactus/tracing/__init__.py +0 -0
  341. {tactus-0.31.2 → tactus-0.32.1}/tactus/tracing/trace_manager.py +0 -0
  342. {tactus-0.31.2 → tactus-0.32.1}/tactus/utils/__init__.py +0 -0
  343. {tactus-0.31.2 → tactus-0.32.1}/tactus/utils/cost_calculator.py +0 -0
  344. {tactus-0.31.2 → tactus-0.32.1}/tactus/utils/model_pricing.py +0 -0
  345. {tactus-0.31.2 → tactus-0.32.1}/tactus/utils/safe_file_library.py +0 -0
  346. {tactus-0.31.2 → tactus-0.32.1}/tactus/utils/safe_libraries.py +0 -0
  347. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/LuaLexerBase.py +0 -0
  348. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/LuaParserBase.py +0 -0
  349. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/README.md +0 -0
  350. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/__init__.py +0 -0
  351. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/error_listener.py +0 -0
  352. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/generated/LuaLexer.interp +0 -0
  353. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/generated/LuaLexer.py +0 -0
  354. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/generated/LuaLexer.tokens +0 -0
  355. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/generated/LuaLexerBase.py +0 -0
  356. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/generated/LuaParser.interp +0 -0
  357. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/generated/LuaParser.py +0 -0
  358. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/generated/LuaParser.tokens +0 -0
  359. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/generated/LuaParserBase.py +0 -0
  360. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/generated/LuaParserVisitor.py +0 -0
  361. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/generated/__init__.py +0 -0
  362. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/grammar/LuaLexer.g4 +0 -0
  363. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/grammar/LuaParser.g4 +0 -0
  364. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/semantic_visitor.py +0 -0
  365. {tactus-0.31.2 → tactus-0.32.1}/tactus/validation/validator.py +0 -0
  366. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/.gitignore +0 -0
  367. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/BUILD_GUIDE.md +0 -0
  368. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/ELECTRON_INTEGRATION.md +0 -0
  369. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/README.md +0 -0
  370. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/RUN_ELECTRON.md +0 -0
  371. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/SETUP_COMPLETE.md +0 -0
  372. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/backend/hook-lupa.py +0 -0
  373. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/package-lock.json +0 -0
  374. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/preload/tsconfig.json +0 -0
  375. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/rebuild-and-test.sh +0 -0
  376. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/resources/app-icon.icns +0 -0
  377. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/resources/app-icon.ico +0 -0
  378. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/resources/app-icon.png +0 -0
  379. /tactus-0.31.2/tactus-desktop/scripts/build-frontend.js → /tactus-0.32.1/tactus-desktop/scripts/build-frontend.mjs +0 -0
  380. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/scripts/generate-icons.sh +0 -0
  381. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/src/backend-manager.ts +0 -0
  382. {tactus-0.31.2 → tactus-0.32.1}/tactus-desktop/tsconfig.json +0 -0
  383. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/ARCHITECTURE.md +0 -0
  384. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/CHANGELOG.md +0 -0
  385. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/DEV_MODE.md +0 -0
  386. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/QUICK_START.md +0 -0
  387. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/README.md +0 -0
  388. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/RESTART_INSTRUCTIONS.md +0 -0
  389. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/TROUBLESHOOTING.md +0 -0
  390. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/backend/README.md +0 -0
  391. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/backend/assistant_service.py +0 -0
  392. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/backend/assistant_tools.py +0 -0
  393. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/backend/chat_server.py +0 -0
  394. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/backend/events.py +0 -0
  395. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/backend/logging_capture.py +0 -0
  396. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/backend/lsp_server.py +0 -0
  397. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/backend/requirements.txt +0 -0
  398. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/backend/tactus_lsp_handler.py +0 -0
  399. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/backend/test_lsp_server.py +0 -0
  400. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/backend/text_editor_tool.py +0 -0
  401. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/dev.sh +0 -0
  402. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/.storybook/main.ts +0 -0
  403. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/.storybook/preview.ts +0 -0
  404. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/.storybook/vitest.setup.ts +0 -0
  405. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/README.md +0 -0
  406. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/demo.ts +0 -0
  407. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/index.html +0 -0
  408. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/jest.config.js +0 -0
  409. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/package-lock.json +0 -0
  410. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/package.json +0 -0
  411. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/postcss.config.js +0 -0
  412. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/Editor.tsx +0 -0
  413. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/LSPClient.ts +0 -0
  414. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/LSPClientHTTP.ts +0 -0
  415. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/TactusLanguage.ts +0 -0
  416. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/commands/registry.ts +0 -0
  417. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/AboutDialog.tsx +0 -0
  418. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ChatSidebar.tsx +0 -0
  419. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/CheckpointSummary.tsx +0 -0
  420. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/CollapsibleRun.tsx +0 -0
  421. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/Duration.stories.tsx +0 -0
  422. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/Duration.tsx +0 -0
  423. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/FileTree.stories.tsx +0 -0
  424. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/FileTree.tsx +0 -0
  425. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/MessageFeed.tsx +0 -0
  426. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/PreferencesView.tsx +0 -0
  427. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ProcedureInputsDisplay.stories.tsx +0 -0
  428. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ProcedureInputsDisplay.tsx +0 -0
  429. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ProcedureInputsModal.stories.tsx +0 -0
  430. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ProcedureInputsModal.tsx +0 -0
  431. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ProcedureTab.stories.tsx +0 -0
  432. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ProcedureTab.tsx +0 -0
  433. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ResizeHandle.tsx +0 -0
  434. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ResultsSidebar.stories.tsx +0 -0
  435. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ResultsSidebar.tsx +0 -0
  436. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/TestOptionsModal.tsx +0 -0
  437. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/Timestamp.stories.tsx +0 -0
  438. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/Timestamp.tsx +0 -0
  439. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/TopMenuBar.stories.tsx +0 -0
  440. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/chat/ChatInterface.tsx +0 -0
  441. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/chat/MessageInput.tsx +0 -0
  442. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/chat/MessageList.tsx +0 -0
  443. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/debugger/CheckpointDetails.stories.tsx +0 -0
  444. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/debugger/CheckpointDetails.tsx +0 -0
  445. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/debugger/CheckpointList.stories.tsx +0 -0
  446. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/debugger/CheckpointList.tsx +0 -0
  447. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/debugger/DebuggerPanel.stories.tsx +0 -0
  448. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/debugger/DebuggerPanel.tsx +0 -0
  449. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/debugger/RunSelector.stories.tsx +0 -0
  450. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/debugger/RunSelector.tsx +0 -0
  451. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/debugger/StatisticsPanel.stories.tsx +0 -0
  452. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/debugger/StatisticsPanel.tsx +0 -0
  453. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/AgentStreamingComponent.tsx +0 -0
  454. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/BaseEventComponent.tsx +0 -0
  455. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/CheckpointEventComponent.tsx +0 -0
  456. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/CollapsibleTestScenario.tsx +0 -0
  457. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/ContainerStatusEventComponent.tsx +0 -0
  458. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/CostEventComponent.stories.tsx +0 -0
  459. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/CostEventComponent.tsx +0 -0
  460. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/EvaluationEventComponent.stories.tsx +0 -0
  461. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/EvaluationEventComponent.tsx +0 -0
  462. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/EventRenderer.tsx +0 -0
  463. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/ExecutionEventComponent.stories.tsx +0 -0
  464. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/ExecutionEventComponent.tsx +0 -0
  465. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/ExecutionSummaryEventComponent.stories.tsx +0 -0
  466. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/ExecutionSummaryEventComponent.tsx +0 -0
  467. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/LoadingEventComponent.stories.tsx +0 -0
  468. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/LoadingEventComponent.tsx +0 -0
  469. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/LogCluster.tsx +0 -0
  470. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/LogEventComponent.stories.tsx +0 -0
  471. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/LogEventComponent.tsx +0 -0
  472. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/OutputEventComponent.stories.tsx +0 -0
  473. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/OutputEventComponent.tsx +0 -0
  474. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/TestEventComponent.stories.tsx +0 -0
  475. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/TestEventComponent.tsx +0 -0
  476. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/TestProgressContainer.tsx +0 -0
  477. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/ToolCallEventComponent.tsx +0 -0
  478. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/ValidationEventComponent.stories.tsx +0 -0
  479. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/events/ValidationEventComponent.tsx +0 -0
  480. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/metadata/AgentsSection.tsx +0 -0
  481. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/metadata/EvaluationsSection.tsx +0 -0
  482. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/metadata/MetadataSections.stories.tsx +0 -0
  483. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/metadata/OutputsSection.tsx +0 -0
  484. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/metadata/ParametersSection.tsx +0 -0
  485. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/metadata/SpecificationsSection.tsx +0 -0
  486. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/metadata/StagesSection.tsx +0 -0
  487. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/metadata/ToolsSection.tsx +0 -0
  488. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/preferences/ConfigFieldView.tsx +0 -0
  489. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/preferences/SourceBadge.tsx +0 -0
  490. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/preferences/YamlCodeEditor.tsx +0 -0
  491. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/scenarios/EvaluateScenarios.stories.tsx +0 -0
  492. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/scenarios/RunScenarios.stories.tsx +0 -0
  493. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/scenarios/TestScenarios.stories.tsx +0 -0
  494. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/scenarios/ValidationScenarios.stories.tsx +0 -0
  495. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/theme-provider.tsx +0 -0
  496. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/ai/conversation.tsx +0 -0
  497. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/ai/message.tsx +0 -0
  498. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/ai/prompt-input.tsx +0 -0
  499. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/badge.tsx +0 -0
  500. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/button.tsx +0 -0
  501. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/dialog.tsx +0 -0
  502. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/dropdown-menu.tsx +0 -0
  503. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/input.tsx +0 -0
  504. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/label.tsx +0 -0
  505. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/logo.stories.tsx +0 -0
  506. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/logo.tsx +0 -0
  507. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/menubar.tsx +0 -0
  508. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/scroll-area.tsx +0 -0
  509. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/select.tsx +0 -0
  510. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/separator.tsx +0 -0
  511. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/switch.tsx +0 -0
  512. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/tabs.tsx +0 -0
  513. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/components/ui/tooltip.tsx +0 -0
  514. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/hooks/useChatSSE.ts +0 -0
  515. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/hooks/useEventStream.ts +0 -0
  516. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/hooks/useTracing.ts +0 -0
  517. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/index.css +0 -0
  518. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/lib/utils.ts +0 -0
  519. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/main.tsx +0 -0
  520. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/types/events.ts +0 -0
  521. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/types/metadata.ts +0 -0
  522. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/types/preferences.ts +0 -0
  523. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/types/results.ts +0 -0
  524. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/types/tracing.ts +0 -0
  525. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/utils/yamlSync.ts +0 -0
  526. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/validation/TactusValidator.ts +0 -0
  527. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/validation/generated/LuaParser.interp +0 -0
  528. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/validation/generated/LuaParser.tokens +0 -0
  529. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/validation/types.ts +0 -0
  530. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/src/vite-env.d.ts +0 -0
  531. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/tailwind.config.js +0 -0
  532. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/tsconfig.json +0 -0
  533. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/tsconfig.node.json +0 -0
  534. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/vite.config.ts +0 -0
  535. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/frontend/vitest.shims.d.ts +0 -0
  536. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/package.json +0 -0
  537. {tactus-0.31.2 → tactus-0.32.1}/tactus-ide/start-dev.sh +0 -0
  538. {tactus-0.31.2 → tactus-0.32.1}/test-ci.sh +0 -0
  539. {tactus-0.31.2 → tactus-0.32.1}/tests/__init__.py +0 -0
  540. {tactus-0.31.2 → tactus-0.32.1}/tests/adapters/__init__.py +0 -0
  541. {tactus-0.31.2 → tactus-0.32.1}/tests/adapters/test_lua_tools_adapter.py +0 -0
  542. {tactus-0.31.2 → tactus-0.32.1}/tests/adapters/test_plugins.py +0 -0
  543. {tactus-0.31.2 → tactus-0.32.1}/tests/broker/test_broker_host_tool_source.py +0 -0
  544. {tactus-0.31.2 → tactus-0.32.1}/tests/broker/test_broker_integration.py +0 -0
  545. {tactus-0.31.2 → tactus-0.32.1}/tests/broker/test_broker_tcp_integration.py +0 -0
  546. {tactus-0.31.2 → tactus-0.32.1}/tests/broker/test_broker_tcp_unit.py +0 -0
  547. {tactus-0.31.2 → tactus-0.32.1}/tests/broker/test_brokered_lm_unit.py +0 -0
  548. {tactus-0.31.2 → tactus-0.32.1}/tests/cli/__init__.py +0 -0
  549. {tactus-0.31.2 → tactus-0.32.1}/tests/cli/test_cli.py +0 -0
  550. {tactus-0.31.2 → tactus-0.32.1}/tests/cli/test_cli_inputs.py +0 -0
  551. {tactus-0.31.2 → tactus-0.32.1}/tests/conftest.py +0 -0
  552. {tactus-0.31.2 → tactus-0.32.1}/tests/core/__init__.py +0 -0
  553. {tactus-0.31.2 → tactus-0.32.1}/tests/core/test_config_manager.py +0 -0
  554. {tactus-0.31.2 → tactus-0.32.1}/tests/core/test_determinism_safety.py +0 -0
  555. {tactus-0.31.2 → tactus-0.32.1}/tests/core/test_lua_sandbox_security.py +0 -0
  556. {tactus-0.31.2 → tactus-0.32.1}/tests/core/test_runtime_inputs.py +0 -0
  557. {tactus-0.31.2 → tactus-0.32.1}/tests/core/test_script_mode.py +0 -0
  558. {tactus-0.31.2 → tactus-0.32.1}/tests/dspy/__init__.py +0 -0
  559. {tactus-0.31.2 → tactus-0.32.1}/tests/dspy/test_mock_field_normalization.py +0 -0
  560. {tactus-0.31.2 → tactus-0.32.1}/tests/dspy/test_module_parameter.py +0 -0
  561. {tactus-0.31.2 → tactus-0.32.1}/tests/dspy/test_prediction_messages.py +0 -0
  562. {tactus-0.31.2 → tactus-0.32.1}/tests/dspy/test_streaming.py +0 -0
  563. {tactus-0.31.2 → tactus-0.32.1}/tests/fixtures/__init__.py +0 -0
  564. {tactus-0.31.2 → tactus-0.32.1}/tests/fixtures/brave_search_mcp_server.py +0 -0
  565. {tactus-0.31.2 → tactus-0.32.1}/tests/fixtures/filesystem_mcp_server.py +0 -0
  566. {tactus-0.31.2 → tactus-0.32.1}/tests/fixtures/test_mcp_server.py +0 -0
  567. {tactus-0.31.2 → tactus-0.32.1}/tests/integration/test_named_procedures.py +0 -0
  568. {tactus-0.31.2 → tactus-0.32.1}/tests/mocks/__init__.py +0 -0
  569. {tactus-0.31.2 → tactus-0.32.1}/tests/mocks/llm_mocks.py +0 -0
  570. {tactus-0.31.2 → tactus-0.32.1}/tests/primitives/test_checkpoint_primitive.py +0 -0
  571. {tactus-0.31.2 → tactus-0.32.1}/tests/primitives/test_host_primitive.py +0 -0
  572. {tactus-0.31.2 → tactus-0.32.1}/tests/primitives/test_retry_primitive.py +0 -0
  573. {tactus-0.31.2 → tactus-0.32.1}/tests/primitives/test_state_primitive.py +0 -0
  574. {tactus-0.31.2 → tactus-0.32.1}/tests/primitives/test_system_alert.py +0 -0
  575. {tactus-0.31.2 → tactus-0.32.1}/tests/primitives/test_tool_primitive.py +0 -0
  576. {tactus-0.31.2 → tactus-0.32.1}/tests/primitives/test_toolset_dsl.py +0 -0
  577. {tactus-0.31.2 → tactus-0.32.1}/tests/sandbox/test_container_runner.py +0 -0
  578. {tactus-0.31.2 → tactus-0.32.1}/tests/sandbox/test_docker_sandbox_smoke.py +0 -0
  579. {tactus-0.31.2 → tactus-0.32.1}/tests/stdlib/__init__.py +0 -0
  580. {tactus-0.31.2 → tactus-0.32.1}/tests/stdlib/test_loader.py +0 -0
  581. {tactus-0.31.2 → tactus-0.32.1}/tests/stdlib/test_require_python.py +0 -0
  582. {tactus-0.31.2 → tactus-0.32.1}/tests/test_checkpoints_integration.py +0 -0
  583. {tactus-0.31.2 → tactus-0.32.1}/tests/test_formatter.py +0 -0
  584. {tactus-0.31.2 → tactus-0.32.1}/tests/test_mcp_integration.py +0 -0
  585. {tactus-0.31.2 → tactus-0.32.1}/tests/test_tracing.py +0 -0
  586. {tactus-0.31.2 → tactus-0.32.1}/tests/testing/__init__.py +0 -0
  587. {tactus-0.31.2 → tactus-0.32.1}/tests/testing/conftest.py +0 -0
  588. {tactus-0.31.2 → tactus-0.32.1}/tests/testing/test_all_examples.py +0 -0
  589. {tactus-0.31.2 → tactus-0.32.1}/tests/testing/test_e2e.py +0 -0
  590. {tactus-0.31.2 → tactus-0.32.1}/tests/testing/test_gherkin_parser.py +0 -0
  591. {tactus-0.31.2 → tactus-0.32.1}/tests/testing/test_integration.py +0 -0
  592. {tactus-0.31.2 → tactus-0.32.1}/tests/testing/test_models.py +0 -0
  593. {tactus-0.31.2 → tactus-0.32.1}/tests/testing/test_runtime_integration.py +0 -0
  594. {tactus-0.31.2 → tactus-0.32.1}/tests/testing/test_step_registry.py +0 -0
  595. {tactus-0.31.2 → tactus-0.32.1}/tests/utils/__init__.py +0 -0
  596. {tactus-0.31.2 → tactus-0.32.1}/tests/utils/test_safe_file_library.py +0 -0
  597. {tactus-0.31.2 → tactus-0.32.1}/tests/validation/__init__.py +0 -0
  598. {tactus-0.31.2 → tactus-0.32.1}/tests/validation/test_tool_curried_syntax_disallowed.py +0 -0
@@ -1,3 +1,6 @@
1
+ # macOS
2
+ .DS_Store
3
+
1
4
  # Python
2
5
  __pycache__/
3
6
  *.pyc
@@ -0,0 +1,12 @@
1
+ # Tactus Configuration File
2
+ # Copy this file to config.yml and add your actual API keys
3
+
4
+ aws:
5
+ profile: default
6
+ region: us-west-2
7
+
8
+ google:
9
+ api_key:
10
+
11
+ openai:
12
+ api_key:
@@ -2,6 +2,27 @@
2
2
 
3
3
  <!-- version list -->
4
4
 
5
+ ## v0.32.1 (2026-01-17)
6
+
7
+ ### Bug Fixes
8
+
9
+ - Add Flask and Flask-CORS to package dependencies for IDE server
10
+ ([`a7ccb69`](https://github.com/AnthusAI/Tactus/commit/a7ccb6957c77628601407f53b8a41d074c6d5568))
11
+
12
+
13
+ ## v0.32.0 (2026-01-17)
14
+
15
+ ### Code Style
16
+
17
+ - Apply Black formatting to IDE server and config files
18
+ ([`65641cc`](https://github.com/AnthusAI/Tactus/commit/65641cc4b806230c086dff071853d1527f82781d))
19
+
20
+ ### Features
21
+
22
+ - Add authentication error dialog and automatic config reload
23
+ ([`5f3dd95`](https://github.com/AnthusAI/Tactus/commit/5f3dd9572e545cfeb94c26af656ad1d36723cc43))
24
+
25
+
5
26
  ## v0.31.2 (2026-01-16)
6
27
 
7
28
  ### Bug Fixes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tactus
3
- Version: 0.31.2
3
+ Version: 0.32.1
4
4
  Summary: Tactus: Lua-based DSL for agentic workflows
5
5
  Project-URL: Homepage, https://github.com/AnthusAI/Tactus
6
6
  Project-URL: Documentation, https://github.com/AnthusAI/Tactus/tree/main/docs
@@ -24,6 +24,8 @@ Requires-Dist: behave>=1.2.6
24
24
  Requires-Dist: boto3>=1.28.0
25
25
  Requires-Dist: dotyaml>=0.1.0
26
26
  Requires-Dist: dspy>=2.5
27
+ Requires-Dist: flask-cors>=4.0.0
28
+ Requires-Dist: flask>=3.0.0
27
29
  Requires-Dist: gherkin-official>=28.0.0
28
30
  Requires-Dist: h5py>=3.10
29
31
  Requires-Dist: lupa>=2.6
@@ -0,0 +1,12 @@
1
+ # Tactus Configuration File
2
+ # Copy this file to config.yml and add your actual API keys
3
+
4
+ aws:
5
+ profile: default
6
+ region: us-west-2
7
+
8
+ google:
9
+ api_key:
10
+
11
+ openai:
12
+ api_key:
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "tactus"
7
- version = "0.31.2"
7
+ version = "0.32.1"
8
8
  description = "Tactus: Lua-based DSL for agentic workflows"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -45,6 +45,9 @@ dependencies = [
45
45
  "openpyxl>=3.1",
46
46
  # DSPy for prompt optimization and LLM abstraction
47
47
  "dspy>=2.5",
48
+ # IDE server dependencies
49
+ "flask>=3.0.0",
50
+ "flask-cors>=4.0.0",
48
51
  ]
49
52
 
50
53
  [project.optional-dependencies]
@@ -5,7 +5,7 @@ Tactus provides a declarative workflow engine for AI agents with pluggable
5
5
  backends for storage, HITL, and chat recording.
6
6
  """
7
7
 
8
- __version__ = "0.31.2"
8
+ __version__ = "0.32.1"
9
9
 
10
10
  # Core exports
11
11
  from tactus.core.runtime import TactusRuntime
@@ -599,6 +599,27 @@ class DSPyAgentHandle:
599
599
 
600
600
  # Check for errors
601
601
  if result_holder["error"] is not None:
602
+ error = result_holder["error"]
603
+
604
+ # Unwrap ExceptionGroup to find the real error
605
+ original_error = error
606
+ if hasattr(error, "__class__") and error.__class__.__name__ == "ExceptionGroup":
607
+ # Python 3.11+ ExceptionGroup
608
+ if hasattr(error, "exceptions") and error.exceptions:
609
+ original_error = error.exceptions[0]
610
+
611
+ # Check if it's an authentication error (in original or wrapped)
612
+ error_str = str(original_error).lower()
613
+ error_type = str(type(original_error).__name__)
614
+
615
+ if "authenticationerror" in error_type.lower() or "api_key" in error_str:
616
+ from tactus.core.exceptions import TactusRuntimeError
617
+
618
+ raise TactusRuntimeError(
619
+ f"API authentication failed for agent '{self.name}': "
620
+ f"Missing or invalid API key. Please configure your API key in Settings (Cmd+,)."
621
+ ) from error
622
+
602
623
  raise result_holder["error"]
603
624
 
604
625
  # If streaming failed to produce a result, fall back to non-streaming
@@ -0,0 +1,536 @@
1
+ """
2
+ Configuration API endpoints for Tactus IDE.
3
+
4
+ Provides RESTful API for loading and saving configuration files,
5
+ with support for the configuration cascade system.
6
+ """
7
+
8
+ import logging
9
+ import shutil
10
+ import yaml
11
+ from pathlib import Path
12
+ from flask import Blueprint, request, jsonify
13
+ from typing import Dict, Any, List, Tuple, Optional
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+ config_bp = Blueprint("config", __name__, url_prefix="/api/config")
18
+
19
+
20
+ def build_cascade_map(loaded_configs: List[Tuple[str, Dict[str, Any]]]) -> Dict[str, str]:
21
+ """
22
+ Build a map of config path -> source for cascade visualization.
23
+
24
+ Args:
25
+ loaded_configs: List of (source_name, config_dict) tuples
26
+
27
+ Returns:
28
+ Dictionary mapping config paths to their source
29
+ """
30
+ cascade_map = {}
31
+
32
+ def add_paths(obj: Any, prefix: str = "", source: str = ""):
33
+ """Recursively add paths from nested config structure."""
34
+ if isinstance(obj, dict):
35
+ for key, value in obj.items():
36
+ path = f"{prefix}.{key}" if prefix else key
37
+ cascade_map[path] = source
38
+ add_paths(value, path, source)
39
+ elif isinstance(obj, list):
40
+ for i, item in enumerate(obj):
41
+ path = f"{prefix}[{i}]"
42
+ add_paths(item, path, source)
43
+
44
+ # Process configs in order (later ones override)
45
+ for source, config in loaded_configs:
46
+ # Extract simple source name (e.g., "user" from "user:/path/to/config.yml")
47
+ source_name = source.split(":")[0] if ":" in source else source
48
+ add_paths(config, "", source_name)
49
+
50
+ return cascade_map
51
+
52
+
53
+ def load_yaml_file(path: Path) -> Optional[Dict[str, Any]]:
54
+ """
55
+ Load YAML file safely.
56
+
57
+ Args:
58
+ path: Path to YAML file
59
+
60
+ Returns:
61
+ Configuration dictionary or None if file doesn't exist or fails to load
62
+ """
63
+ if not path.exists():
64
+ return None
65
+
66
+ try:
67
+ with open(path, "r") as f:
68
+ config = yaml.safe_load(f)
69
+ return config if isinstance(config, dict) else {}
70
+ except Exception as e:
71
+ logger.warning(f"Failed to load config from {path}: {e}")
72
+ return None
73
+
74
+
75
+ def save_yaml_file(path: Path, config: Dict[str, Any], create_backup: bool = True):
76
+ """
77
+ Save configuration to YAML file.
78
+
79
+ Args:
80
+ path: Path to save config
81
+ config: Configuration dictionary
82
+ create_backup: Whether to create backup of existing file
83
+ """
84
+ # Create .tactus directory if needed
85
+ path.parent.mkdir(parents=True, exist_ok=True)
86
+
87
+ # Create backup if requested and file exists
88
+ if create_backup and path.exists():
89
+ backup_path = path.with_suffix(".yml.bak")
90
+ shutil.copy2(path, backup_path)
91
+ logger.info(f"Created backup: {backup_path}")
92
+
93
+ # Save config
94
+ with open(path, "w") as f:
95
+ yaml.safe_dump(
96
+ config,
97
+ f,
98
+ default_flow_style=False,
99
+ sort_keys=False,
100
+ allow_unicode=True,
101
+ indent=2,
102
+ )
103
+
104
+ logger.info(f"Saved config to: {path}")
105
+
106
+
107
+ @config_bp.route("", methods=["GET"])
108
+ def get_config():
109
+ """
110
+ Get configuration with cascade information.
111
+
112
+ Returns:
113
+ JSON response with:
114
+ - config: Merged effective configuration
115
+ - project_config: Project .tactus/config.yml
116
+ - user_config: User ~/.tactus/config.yml
117
+ - system_config: System config if exists
118
+ - cascade: Map of config paths to their source (legacy)
119
+ - source_details: Detailed source tracking with override chains
120
+ - writable_configs: Which configs can be edited
121
+ - config_paths: Full paths to all config files
122
+ """
123
+ try:
124
+ from tactus.core.config_manager import ConfigManager
125
+
126
+ # Create config manager
127
+ config_manager = ConfigManager()
128
+
129
+ # For IDE purposes, we load config without a specific procedure
130
+ # Use a dummy path to trigger the cascade from project/user/system
131
+ dummy_path = Path.cwd() / "dummy.tac"
132
+
133
+ # Load cascade with source tracking
134
+ effective_config, source_map = config_manager.load_cascade_with_sources(dummy_path)
135
+
136
+ # Build legacy cascade map from loaded configs (for backward compatibility)
137
+ cascade_map = build_cascade_map(config_manager.loaded_configs)
138
+
139
+ # Convert source_map to JSON-serializable format
140
+ source_details = {path: config_value.to_dict() for path, config_value in source_map.items()}
141
+
142
+ # Load individual config files for editing
143
+ project_config_path = Path.cwd() / ".tactus" / "config.yml"
144
+ project_config = load_yaml_file(project_config_path)
145
+
146
+ # Check if we should initialize from example template
147
+ # This happens when:
148
+ # 1. No config.yml exists, OR
149
+ # 2. Config exists but has no API keys configured (openai_api_key is empty/missing)
150
+ should_initialize_from_example = False
151
+
152
+ if project_config is None:
153
+ should_initialize_from_example = True
154
+ elif isinstance(project_config, dict):
155
+ # Check if API keys are configured
156
+ # Support both old flat format (openai_api_key) and new nested format (openai.api_key)
157
+ openai_key = None
158
+ if "openai" in project_config and isinstance(project_config["openai"], dict):
159
+ openai_key = project_config["openai"].get("api_key")
160
+ else:
161
+ openai_key = project_config.get("openai_api_key")
162
+
163
+ aws_key = None
164
+ if "aws" in project_config and isinstance(project_config["aws"], dict):
165
+ aws_key = project_config["aws"].get("profile") or project_config["aws"].get(
166
+ "access_key_id"
167
+ )
168
+ else:
169
+ aws_key = project_config.get("aws_access_key_id")
170
+
171
+ google_key = None
172
+ if "google" in project_config and isinstance(project_config["google"], dict):
173
+ google_key = project_config["google"].get("api_key")
174
+
175
+ # Check if keys are present and not placeholder values
176
+ # Empty strings or None mean not configured
177
+ has_openai_key = (
178
+ openai_key
179
+ and str(openai_key).strip() != ""
180
+ and not str(openai_key).startswith("your-")
181
+ )
182
+ has_aws_keys = (
183
+ aws_key
184
+ and str(aws_key).strip() != ""
185
+ and str(aws_key) != "default"
186
+ and not str(aws_key).startswith("your-")
187
+ )
188
+ has_google_key = (
189
+ google_key
190
+ and str(google_key).strip() != ""
191
+ and not str(google_key).startswith("your-")
192
+ )
193
+
194
+ # If no API keys are configured, initialize from example
195
+ if not has_openai_key and not has_aws_keys and not has_google_key:
196
+ should_initialize_from_example = True
197
+ else:
198
+ project_config = {}
199
+
200
+ if should_initialize_from_example:
201
+ example_config_path = Path.cwd() / ".tactus" / "config.yml.example"
202
+ if example_config_path.exists():
203
+ example_config = load_yaml_file(example_config_path) or {}
204
+ # Merge with existing config (keeps existing values, adds missing fields from example)
205
+ if project_config and isinstance(project_config, dict):
206
+ # Deep merge: example provides defaults, existing values are kept
207
+ merged_config = {**example_config, **project_config}
208
+ else:
209
+ merged_config = example_config
210
+ project_config = merged_config
211
+ # Save the merged config
212
+ try:
213
+ save_yaml_file(project_config_path, project_config, create_backup=True)
214
+ logger.info(
215
+ f"Initialized/merged config with example template: {example_config_path}"
216
+ )
217
+ except Exception as e:
218
+ logger.warning(f"Failed to save merged config: {e}")
219
+ elif not project_config:
220
+ # No example found and no existing config, use empty
221
+ project_config = {}
222
+
223
+ user_config_path = Path.home() / ".tactus" / "config.yml"
224
+ user_config = load_yaml_file(user_config_path) or {}
225
+
226
+ # Try to find system config
227
+ system_config_path = Path("/etc/tactus/config.yml")
228
+ system_config = load_yaml_file(system_config_path) or {}
229
+
230
+ # Determine which configs are writable
231
+ writable_configs = {
232
+ "system": False, # System config is never writable from IDE
233
+ "user": user_config_path.parent.exists() or True, # Can create user config
234
+ "project": True, # Can always write to project config
235
+ }
236
+
237
+ return jsonify(
238
+ {
239
+ "config": effective_config,
240
+ "project_config": project_config,
241
+ "user_config": user_config,
242
+ "system_config": system_config,
243
+ "cascade": cascade_map,
244
+ "source_details": source_details,
245
+ "writable_configs": writable_configs,
246
+ "config_paths": {
247
+ "system": str(system_config_path),
248
+ "user": str(user_config_path),
249
+ "project": str(project_config_path),
250
+ },
251
+ # Keep old fields for backward compatibility
252
+ "project_config_path": str(project_config_path),
253
+ "user_config_path": str(user_config_path),
254
+ }
255
+ )
256
+
257
+ except Exception as e:
258
+ logger.error(f"Error loading config: {e}", exc_info=True)
259
+ return jsonify({"error": str(e)}), 500
260
+
261
+
262
+ @config_bp.route("", methods=["POST"])
263
+ def save_config():
264
+ """
265
+ Save configuration to specified target file.
266
+
267
+ Request body:
268
+ {
269
+ "config": {...},
270
+ "targetFile": "project" | "user",
271
+ "createBackup": true
272
+ }
273
+
274
+ Returns:
275
+ JSON response with success status and saved path
276
+ """
277
+ try:
278
+ data = request.json
279
+
280
+ if not data:
281
+ return jsonify({"error": "Missing request body"}), 400
282
+
283
+ config = data.get("config")
284
+ target = data.get("targetFile", "project")
285
+ create_backup = data.get("createBackup", True)
286
+
287
+ if not config:
288
+ return jsonify({"error": "Missing config"}), 400
289
+
290
+ if not isinstance(config, dict):
291
+ return jsonify({"error": "Config must be an object"}), 400
292
+
293
+ # Determine target path
294
+ if target == "project":
295
+ config_path = Path.cwd() / ".tactus" / "config.yml"
296
+ elif target == "user":
297
+ config_path = Path.home() / ".tactus" / "config.yml"
298
+ else:
299
+ return jsonify({"error": f"Invalid target: {target}"}), 400
300
+
301
+ # Save config
302
+ save_yaml_file(config_path, config, create_backup)
303
+
304
+ # Trigger a runtime reload by emitting an event or clearing caches
305
+ # This ensures the new config is picked up without requiring a restart
306
+ try:
307
+ from tactus.ide.server import clear_runtime_caches
308
+
309
+ clear_runtime_caches()
310
+ logger.info("Cleared runtime caches after config save")
311
+ except (ImportError, AttributeError):
312
+ # If function doesn't exist yet, that's okay - just log it
313
+ logger.debug("Runtime cache clearing not available")
314
+
315
+ return jsonify({"success": True, "path": str(config_path)})
316
+
317
+ except Exception as e:
318
+ logger.error(f"Error saving config: {e}", exc_info=True)
319
+ return jsonify({"error": str(e)}), 500
320
+
321
+
322
+ @config_bp.route("/save-by-source", methods=["POST"])
323
+ def save_config_by_source():
324
+ """
325
+ Save configuration changes to the appropriate file based on source tracking.
326
+
327
+ This endpoint intelligently routes config changes to the correct file based on
328
+ where each value is currently sourced from, or uses a fallback strategy.
329
+
330
+ Request body:
331
+ {
332
+ "changes": {
333
+ "aws.region": "us-west-2",
334
+ "default_model": "gpt-4o"
335
+ },
336
+ "target_strategy": "source_aware" | "force_user" | "force_project"
337
+ }
338
+
339
+ Returns:
340
+ JSON response with:
341
+ - success: Boolean
342
+ - saved_to: Dict mapping change paths to files they were saved to
343
+ - errors: List of any errors (e.g., trying to override env var)
344
+ """
345
+ try:
346
+ from tactus.core.config_manager import ConfigManager
347
+
348
+ data = request.json
349
+
350
+ if not data:
351
+ return jsonify({"error": "Missing request body"}), 400
352
+
353
+ changes = data.get("changes")
354
+ strategy = data.get("target_strategy", "source_aware")
355
+
356
+ if not changes:
357
+ return jsonify({"error": "Missing changes"}), 400
358
+
359
+ if not isinstance(changes, dict):
360
+ return jsonify({"error": "Changes must be an object"}), 400
361
+
362
+ # Load current config with sources
363
+ config_manager = ConfigManager()
364
+ dummy_path = Path.cwd() / "dummy.tac"
365
+ effective_config, source_map = config_manager.load_cascade_with_sources(dummy_path)
366
+
367
+ # Load current project and user configs
368
+ project_config_path = Path.cwd() / ".tactus" / "config.yml"
369
+ project_config = load_yaml_file(project_config_path) or {}
370
+
371
+ user_config_path = Path.home() / ".tactus" / "config.yml"
372
+ user_config = load_yaml_file(user_config_path) or {}
373
+
374
+ saved_to = {}
375
+ errors = []
376
+
377
+ # Process each change
378
+ for path, new_value in changes.items():
379
+ # Determine target file based on strategy
380
+ if strategy == "force_user":
381
+ target_file = "user"
382
+ target_config = user_config
383
+ elif strategy == "force_project":
384
+ target_file = "project"
385
+ target_config = project_config
386
+ else: # source_aware
387
+ # Check current source
388
+ if path in source_map:
389
+ source_info = source_map[path]
390
+
391
+ # Check if sourced from environment variable
392
+ if source_info.is_env_override:
393
+ errors.append(
394
+ f"{path}: Cannot override environment variable "
395
+ f"{source_info.original_env_var} in config file"
396
+ )
397
+ continue
398
+
399
+ # Route to the source file
400
+ if source_info.source_type == "user":
401
+ target_file = "user"
402
+ target_config = user_config
403
+ elif source_info.source_type == "project":
404
+ target_file = "project"
405
+ target_config = project_config
406
+ else:
407
+ # For system or other sources, default to user config
408
+ target_file = "user"
409
+ target_config = user_config
410
+ else:
411
+ # New value, default to user config
412
+ target_file = "user"
413
+ target_config = user_config
414
+
415
+ # Update the target config dict
416
+ _set_nested_value(target_config, path, new_value)
417
+ saved_to[path] = target_file
418
+
419
+ # Save modified configs
420
+ if any(v == "user" for v in saved_to.values()):
421
+ save_yaml_file(user_config_path, user_config, create_backup=True)
422
+
423
+ if any(v == "project" for v in saved_to.values()):
424
+ save_yaml_file(project_config_path, project_config, create_backup=True)
425
+
426
+ return jsonify(
427
+ {
428
+ "success": len(errors) == 0,
429
+ "saved_to": saved_to,
430
+ "errors": errors,
431
+ }
432
+ )
433
+
434
+ except Exception as e:
435
+ logger.error(f"Error saving config by source: {e}", exc_info=True)
436
+ return jsonify({"error": str(e)}), 500
437
+
438
+
439
+ def _set_nested_value(config: Dict[str, Any], path: str, value: Any) -> None:
440
+ """
441
+ Set a nested value in a config dict using dot notation path.
442
+
443
+ Args:
444
+ config: Configuration dictionary to modify
445
+ path: Dot-separated path (e.g., "aws.region")
446
+ value: Value to set
447
+ """
448
+ keys = path.split(".")
449
+ current = config
450
+
451
+ # Navigate to the parent of the target key
452
+ for key in keys[:-1]:
453
+ if key not in current:
454
+ current[key] = {}
455
+ elif not isinstance(current[key], dict):
456
+ # Path conflicts with existing non-dict value
457
+ raise ValueError(f"Cannot set nested value: {key} is not a dict")
458
+ current = current[key]
459
+
460
+ # Set the final value
461
+ current[keys[-1]] = value
462
+
463
+
464
+ @config_bp.route("/validate", methods=["POST"])
465
+ def validate_config():
466
+ """
467
+ Validate configuration structure without saving.
468
+
469
+ Request body:
470
+ {
471
+ "config": {...}
472
+ }
473
+
474
+ Returns:
475
+ JSON response with validation results
476
+ """
477
+ try:
478
+ data = request.json
479
+
480
+ if not data:
481
+ return jsonify({"error": "Missing request body"}), 400
482
+
483
+ config = data.get("config")
484
+
485
+ if not config:
486
+ return jsonify({"error": "Missing config"}), 400
487
+
488
+ errors = []
489
+ warnings = []
490
+
491
+ # Basic validation
492
+ if not isinstance(config, dict):
493
+ errors.append("Config must be an object")
494
+ return jsonify({"valid": False, "errors": errors, "warnings": warnings})
495
+
496
+ # Validate known structure (optional - can be expanded)
497
+ # Check for common mistakes
498
+ if "default_provider" in config:
499
+ if config["default_provider"] not in ["openai", "bedrock", "google"]:
500
+ warnings.append(
501
+ f"Unknown provider: {config['default_provider']}. Expected openai, bedrock, or google."
502
+ )
503
+
504
+ if "ide" in config:
505
+ ide_config = config["ide"]
506
+ if not isinstance(ide_config, dict):
507
+ errors.append("ide config must be an object")
508
+
509
+ # Try to serialize to YAML (validation)
510
+ try:
511
+ yaml.safe_dump(config)
512
+ except Exception as e:
513
+ errors.append(f"Config cannot be serialized to YAML: {str(e)}")
514
+
515
+ return jsonify(
516
+ {
517
+ "valid": len(errors) == 0,
518
+ "errors": errors,
519
+ "warnings": warnings,
520
+ }
521
+ )
522
+
523
+ except Exception as e:
524
+ logger.error(f"Error validating config: {e}", exc_info=True)
525
+ return jsonify({"error": str(e)}), 500
526
+
527
+
528
+ def register_config_routes(app):
529
+ """
530
+ Register config routes with Flask app.
531
+
532
+ Args:
533
+ app: Flask application instance
534
+ """
535
+ app.register_blueprint(config_bp)
536
+ logger.info("Registered config API routes")