tactus 0.26.0__tar.gz → 0.27.0__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.
- {tactus-0.26.0 → tactus-0.27.0}/.gitignore +2 -0
- {tactus-0.26.0 → tactus-0.27.0}/CHANGELOG.md +9 -0
- {tactus-0.26.0 → tactus-0.27.0}/Makefile +9 -0
- {tactus-0.26.0 → tactus-0.27.0}/PKG-INFO +1 -1
- {tactus-0.26.0 → tactus-0.27.0}/docs/DURABILITY.md +2 -2
- {tactus-0.26.0 → tactus-0.27.0}/docs/SANDBOXING.md +3 -2
- {tactus-0.26.0 → tactus-0.27.0}/docs/TOOLS.md +92 -13
- {tactus-0.26.0 → tactus-0.27.0}/docs/TOOL_ROADMAP.md +1 -1
- tactus-0.27.0/examples/01-basics-hello-world.tac +23 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/05-basics-multi-model.tac +2 -2
- {tactus-0.26.0 → tactus-0.27.0}/examples/06-basics-streaming.tac +8 -1
- {tactus-0.26.0 → tactus-0.27.0}/examples/07-basics-bedrock.tac +3 -3
- {tactus-0.26.0 → tactus-0.27.0}/examples/08-basics-models.tac +3 -3
- {tactus-0.26.0 → tactus-0.27.0}/examples/09-basics-google-gemini.tac +4 -4
- {tactus-0.26.0 → tactus-0.27.0}/examples/12-feature-structured-output.tac +20 -8
- {tactus-0.26.0 → tactus-0.27.0}/examples/14-feature-per-turn-tools-simple.tac +10 -1
- {tactus-0.26.0 → tactus-0.27.0}/examples/15-feature-local-tools.tac +11 -1
- {tactus-0.26.0 → tactus-0.27.0}/examples/16-feature-toolsets-advanced.tac +2 -2
- {tactus-0.26.0 → tactus-0.27.0}/examples/17-feature-toolsets-dsl.tac +1 -2
- {tactus-0.26.0 → tactus-0.27.0}/examples/18-feature-lua-tools-individual.tac +1 -1
- {tactus-0.26.0 → tactus-0.27.0}/examples/18-feature-lua-tools-inline.tac +1 -1
- {tactus-0.26.0 → tactus-0.27.0}/examples/18-feature-lua-tools-toolset.tac +1 -1
- {tactus-0.26.0 → tactus-0.27.0}/examples/40-model-text-classifier.tac +9 -18
- {tactus-0.26.0 → tactus-0.27.0}/examples/41-model-pytorch.tac +9 -20
- {tactus-0.26.0 → tactus-0.27.0}/examples/44-sub-procedure-composition.tac +11 -19
- {tactus-0.26.0 → tactus-0.27.0}/examples/60-tool-sources.tac +2 -1
- {tactus-0.26.0 → tactus-0.27.0}/examples/61-inline-toolset-lua.tac +2 -2
- {tactus-0.26.0 → tactus-0.27.0}/examples/62-mcp-toolset-by-server.tac +2 -2
- {tactus-0.26.0 → tactus-0.27.0}/examples/63-toolset-import-from-file.tac +3 -3
- {tactus-0.26.0 → tactus-0.27.0}/examples/65-optional-state-demo.tac +4 -6
- tactus-0.27.0/examples/66-host-tools-via-broker.tac +36 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/99-misc-test-loading.tac +2 -2
- {tactus-0.26.0 → tactus-0.27.0}/features/18_example_procedures.feature +1 -1
- {tactus-0.26.0 → tactus-0.27.0}/features/32_result_object.feature +8 -6
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/example_procedures_steps.py +15 -10
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/result_and_output_steps.py +7 -7
- tactus-0.27.0/planning/BROKER_AND_TOOL_RUNNERS.md +617 -0
- {tactus-0.26.0 → tactus-0.27.0}/pyproject.toml +9 -1
- {tactus-0.26.0 → tactus-0.27.0}/tactus/__init__.py +1 -1
- tactus-0.27.0/tactus/adapters/broker_log.py +55 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/adapters/cli_log.py +0 -25
- tactus-0.27.0/tactus/broker/__init__.py +12 -0
- tactus-0.27.0/tactus/broker/client.py +260 -0
- tactus-0.27.0/tactus/broker/server.py +505 -0
- tactus-0.27.0/tactus/broker/stdio.py +12 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/cli/app.py +38 -2
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/dsl_stubs.py +2 -1
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/output_validator.py +6 -3
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/registry.py +8 -1
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/runtime.py +15 -1
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/yaml_parser.py +1 -11
- {tactus-0.26.0 → tactus-0.27.0}/tactus/dspy/agent.py +190 -102
- tactus-0.27.0/tactus/dspy/broker_lm.py +181 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/dspy/config.py +21 -8
- {tactus-0.26.0 → tactus-0.27.0}/tactus/dspy/prediction.py +71 -5
- {tactus-0.26.0 → tactus-0.27.0}/tactus/ide/server.py +37 -142
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/__init__.py +2 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/handles.py +34 -7
- tactus-0.27.0/tactus/primitives/host.py +94 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/log.py +4 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/model.py +20 -2
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/procedure.py +106 -51
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/tool.py +0 -2
- {tactus-0.26.0 → tactus-0.27.0}/tactus/protocols/__init__.py +0 -7
- {tactus-0.26.0 → tactus-0.27.0}/tactus/protocols/log_handler.py +2 -2
- {tactus-0.26.0 → tactus-0.27.0}/tactus/protocols/models.py +1 -1
- {tactus-0.26.0 → tactus-0.27.0}/tactus/sandbox/config.py +33 -5
- tactus-0.27.0/tactus/sandbox/container_runner.py +1022 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/sandbox/entrypoint.py +30 -17
- {tactus-0.26.0 → tactus-0.27.0}/tactus/sandbox/protocol.py +0 -9
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/README.md +0 -4
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/mock_agent.py +80 -23
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/test_runner.py +0 -18
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/backend/test_lsp_server.py +4 -4
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/MessageFeed.tsx +1 -27
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/EventRenderer.tsx +3 -9
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/types/events.ts +0 -8
- tactus-0.27.0/tests/broker/test_broker_integration.py +108 -0
- tactus-0.27.0/tests/broker/test_broker_tcp_integration.py +109 -0
- tactus-0.27.0/tests/broker/test_broker_tcp_unit.py +160 -0
- tactus-0.27.0/tests/broker/test_brokered_lm_unit.py +72 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/cli/test_cli.py +2 -1
- {tactus-0.26.0 → tactus-0.27.0}/tests/cli/test_cli_inputs.py +11 -10
- tactus-0.27.0/tests/dspy/test_agent_messages.py +187 -0
- tactus-0.27.0/tests/dspy/test_mock_field_normalization.py +120 -0
- tactus-0.27.0/tests/dspy/test_prediction_messages.py +114 -0
- tactus-0.27.0/tests/primitives/test_host_primitive.py +32 -0
- tactus-0.27.0/tests/sandbox/test_container_runner.py +98 -0
- tactus-0.27.0/tests/sandbox/test_docker_sandbox_smoke.py +98 -0
- tactus-0.27.0/tests/test_checkpoints_integration.py +59 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/test_mcp_integration.py +5 -2
- tactus-0.26.0/examples/01-basics-hello-world.tac +0 -8
- tactus-0.26.0/tactus/sandbox/container_runner.py +0 -584
- tactus-0.26.0/tests/test_checkpoints_integration.py +0 -104
- {tactus-0.26.0 → tactus-0.27.0}/.claude/agents.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/.github/workflows/desktop-release.yml +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/.github/workflows/release.yml +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/.tactus/config.yml.example +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/AGENTS.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/IMPLEMENTATION.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/LICENSE +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/README.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/SPECIFICATION.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/TECHNICAL_DEBT.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/behave.ini +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/docs/AGENTS.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/docs/BDD_TESTING.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/docs/CONFIGURATION.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/docs/FILE_IO.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/docs/STREAMING.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/.tactus/config.yml +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/02-basics-simple-logic.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/03-basics-parameters.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/04-basics-simple-agent.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/10-feature-state.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/11-feature-message-history.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/13-feature-session.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/14-feature-per-turn-tools.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/19-feature-direct-tool-calls.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/20-bdd-complete.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/20-bdd-complete.tac.bak2 +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/21-bdd-passing.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/21-bdd-passing.tac.bak2 +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/30-eval-simple.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/31-eval-demo.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/32-eval-success-rate.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/33-eval-thresholds.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/34-eval-dataset.jsonl +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/34-eval-dataset.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/35-eval-trace.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/35-eval-trace.tac.bak2 +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/36-eval-advanced.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/37-eval-comprehensive.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/37-eval-comprehensive.tac.bak2 +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/39-model-simple.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/40-mcp-test.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/41-mcp-simple.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/43-sub-procedure-simple.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/45-sub-procedure-recursive.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/46-checkpoint-explicit.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/47-checkpoint-expensive-ops.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/48-script-mode-simple.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/50-inputs-showcase.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/51-inputs-calculator.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/52-file-io-basics.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/53-tsv-file-io.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/54-json-file-io.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/55-parquet-file-io.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/56-hdf5-file-io.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/57-excel-file-io.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/58-text-file-io.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/64-require-modules.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/70-mocking-static.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/71-mocking-temporal.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/72-mocking-conditional.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/README.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/app_config.ini +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/data/sample.csv +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/demo_output.json +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/helpers/math_module.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/helpers/product.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/helpers/string_module.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/helpers/sum.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/helpers/text_tools.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/inventory_summary.tsv +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/mock-config.json +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/models/README.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/models/create_sentiment_model.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/output_summary.txt +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/test-raw-module.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/test-raw-streaming.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/tools/calculations.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/tools/data_analysis.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/tools/search.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/with_dependencies/README.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/with_dependencies/simple_http_test.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/examples/with_dependencies/time_lookup.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/01_state_management.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/02_checkpointing.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/03_human_in_the_loop.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/04_control_flow.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/05_tool_integration.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/06_retry_logic.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/07_file_operations.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/08_agent_primitives.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/09_workflow_execution.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/10_lua_integration.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/11_storage_backends.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/12_json_operations.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/13_logging.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/14_stage_and_step_tracking.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/15_procedure_calls.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/16_session_management.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/17_lua_dsl_validation.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/19_ide_server.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/20_parameters.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/21_outputs.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/23_prompts.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/24_bdd_specifications.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/25_bdd_custom_steps.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/26_bdd_evaluation.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/27_default_settings.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/28_custom_prompts.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/29_execution_settings.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/30_session_filters.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/31_matchers.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/33_output_type.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/42_model_primitive.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/43_sub_procedure_checkpointing.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/46_explicit_checkpoint.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/48_script_mode.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/51_dspy_lm_config.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/52_dspy_signature.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/53_dspy_module.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/54_dspy_history.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/55_dspy_prediction.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/56_dspy_agent.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/57_chat_assistant.feature +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/documentation/IDE_SERVER_BEHAVIOR.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/documentation/Lua DSL/README.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/environment.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/agent_primitives_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/chat_assistant_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/checkpointing_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/control_flow_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/dspy_agent_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/dspy_history_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/dspy_lm_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/dspy_module_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/dspy_prediction_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/dspy_signature_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/file_operations_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/human_in_the_loop_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/ide_server_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/json_operations_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/logging_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/lua_dsl_validation_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/lua_integration_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/mocking_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/procedure_calls_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/retry_logic_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/session_management_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/stage_tracking_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/state_management_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/storage_backend_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/support/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/support/harnesses.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/tool_integration_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/features/steps/workflow_execution_steps.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/scripts/audit_examples_mocking.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/scripts/convert_examples.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/start-web-ide.sh +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/adapters/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/adapters/cli_hitl.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/adapters/cost_collector_log.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/adapters/file_storage.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/adapters/http_callback_log.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/adapters/ide_log.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/adapters/lua_tools.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/adapters/mcp.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/adapters/mcp_manager.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/adapters/memory.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/adapters/plugins.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/backends/http_backend.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/backends/model_backend.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/backends/pytorch_backend.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/cli/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/cli/commands/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/config_manager.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/dependencies/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/dependencies/registry.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/exceptions.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/execution_context.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/lua_sandbox.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/message_history_manager.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/mocking.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/core/template_resolver.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/docker/Dockerfile +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/docker/entrypoint.sh +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/dspy/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/dspy/history.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/dspy/module.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/dspy/signature.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/ide/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/ide/coding_assistant.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/control.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/file.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/human.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/json.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/message_history.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/procedure_callable.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/retry.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/session.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/stage.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/state.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/step.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/system.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/tool_handle.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/primitives/toolset.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/protocols/chat_recorder.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/protocols/config.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/protocols/cost.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/protocols/hitl.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/protocols/result.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/protocols/storage.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/providers/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/providers/base.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/providers/bedrock.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/providers/google.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/providers/openai.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/sandbox/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/sandbox/docker_manager.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/stdlib/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/stdlib/io/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/stdlib/io/csv.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/stdlib/io/excel.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/stdlib/io/file.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/stdlib/io/fs.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/stdlib/io/hdf5.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/stdlib/io/json.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/stdlib/io/parquet.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/stdlib/io/tsv.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/stdlib/loader.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/stdlib/tac/tactus/tools/done.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/stdlib/tac/tactus/tools/log.tac +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/behave_integration.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/context.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/eval_models.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/evaluation_runner.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/evaluators.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/events.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/gherkin_parser.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/mock_dependencies.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/mock_hitl.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/mock_registry.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/mock_tools.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/models.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/pydantic_eval_runner.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/steps/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/steps/builtin.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/steps/custom.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/testing/steps/registry.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/tracing/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/tracing/trace_manager.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/utils/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/utils/cost_calculator.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/utils/model_pricing.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/utils/safe_file_library.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/utils/safe_libraries.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/LuaLexerBase.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/LuaParserBase.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/README.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/error_listener.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/generated/LuaLexer.interp +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/generated/LuaLexer.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/generated/LuaLexer.tokens +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/generated/LuaLexerBase.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/generated/LuaParser.interp +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/generated/LuaParser.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/generated/LuaParser.tokens +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/generated/LuaParserBase.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/generated/LuaParserVisitor.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/generated/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/grammar/LuaLexer.g4 +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/grammar/LuaParser.g4 +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/semantic_visitor.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus/validation/validator.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/.gitignore +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/README.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/RUN_ELECTRON.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/SETUP_COMPLETE.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/backend/hook-lupa.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/backend/tactus_backend.spec +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/package-lock.json +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/package.json +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/preload/preload.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/preload/tsconfig.json +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/rebuild-and-test.sh +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/scripts/build-backend.js +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/scripts/build-frontend.js +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/src/backend-manager.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/src/main.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/src/menu.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-desktop/tsconfig.json +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/ARCHITECTURE.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/CHANGELOG.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/DEV_MODE.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/QUICK_START.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/README.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/RESTART_INSTRUCTIONS.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/TROUBLESHOOTING.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/backend/README.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/backend/assistant_service.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/backend/assistant_tools.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/backend/chat_server.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/backend/config_server.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/backend/events.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/backend/logging_capture.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/backend/lsp_server.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/backend/requirements.txt +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/backend/tactus_lsp_handler.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/backend/text_editor_tool.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/dev.sh +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/.storybook/main.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/.storybook/preview.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/.storybook/vitest.setup.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/README.md +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/demo.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/index.html +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/jest.config.js +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/package-lock.json +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/package.json +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/postcss.config.js +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/App.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/Editor.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/LSPClient.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/LSPClientHTTP.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/TactusLanguage.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/commands/registry.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/AboutDialog.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ChatSidebar.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/CheckpointSummary.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/CollapsibleRun.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/Duration.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/Duration.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/FileTree.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/FileTree.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/PreferencesView.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ProcedureInputsDisplay.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ProcedureInputsDisplay.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ProcedureInputsModal.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ProcedureInputsModal.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ProcedureTab.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ProcedureTab.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ResizeHandle.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ResultsSidebar.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ResultsSidebar.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/TestOptionsModal.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/Timestamp.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/Timestamp.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/TopMenuBar.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/chat/ChatInterface.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/chat/MessageInput.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/chat/MessageList.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/debugger/CheckpointDetails.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/debugger/CheckpointDetails.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/debugger/CheckpointList.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/debugger/CheckpointList.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/debugger/DebuggerPanel.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/debugger/DebuggerPanel.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/debugger/RunSelector.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/debugger/RunSelector.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/debugger/StatisticsPanel.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/debugger/StatisticsPanel.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/AgentStreamingComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/BaseEventComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/CheckpointEventComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/CollapsibleTestScenario.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/ContainerStatusEventComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/CostEventComponent.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/CostEventComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/EvaluationEventComponent.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/EvaluationEventComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/ExecutionEventComponent.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/ExecutionEventComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/ExecutionSummaryEventComponent.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/ExecutionSummaryEventComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/LoadingEventComponent.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/LoadingEventComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/LogCluster.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/LogEventComponent.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/LogEventComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/OutputEventComponent.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/OutputEventComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/TestEventComponent.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/TestEventComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/TestProgressContainer.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/ToolCallEventComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/ValidationEventComponent.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/events/ValidationEventComponent.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/metadata/AgentsSection.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/metadata/EvaluationsSection.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/metadata/MetadataSections.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/metadata/OutputsSection.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/metadata/ParametersSection.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/metadata/SpecificationsSection.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/metadata/StagesSection.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/metadata/ToolsSection.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/preferences/ConfigFieldView.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/preferences/SourceBadge.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/preferences/YamlCodeEditor.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/scenarios/EvaluateScenarios.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/scenarios/RunScenarios.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/scenarios/TestScenarios.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/scenarios/ValidationScenarios.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/theme-provider.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/ai/conversation.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/ai/message.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/ai/prompt-input.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/badge.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/button.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/dialog.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/dropdown-menu.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/input.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/label.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/logo.stories.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/logo.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/menubar.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/scroll-area.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/select.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/separator.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/switch.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/tabs.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/components/ui/tooltip.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/hooks/useChatSSE.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/hooks/useEventStream.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/hooks/useTracing.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/index.css +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/lib/utils.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/main.tsx +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/types/metadata.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/types/preferences.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/types/results.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/types/tracing.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/utils/yamlSync.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/validation/TactusValidator.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/validation/generated/LuaParser.interp +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/validation/generated/LuaParser.tokens +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/validation/types.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/src/vite-env.d.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/tailwind.config.js +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/tsconfig.json +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/tsconfig.node.json +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/vite.config.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/frontend/vitest.shims.d.ts +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/package.json +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tactus-ide/start-dev.sh +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/adapters/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/adapters/test_lua_tools_adapter.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/adapters/test_plugins.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/cli/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/conftest.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/core/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/core/test_config_manager.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/core/test_determinism_safety.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/core/test_lua_sandbox_security.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/core/test_runtime_inputs.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/core/test_script_mode.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/dspy/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/dspy/test_module_parameter.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/dspy/test_streaming.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/fixtures/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/fixtures/test_mcp_server.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/integration/test_named_procedures.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/mocks/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/mocks/llm_mocks.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/primitives/test_checkpoint_primitive.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/primitives/test_retry_primitive.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/primitives/test_state_primitive.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/primitives/test_system_alert.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/primitives/test_tool_primitive.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/primitives/test_toolset_dsl.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/stdlib/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/stdlib/test_loader.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/stdlib/test_require_python.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/test_tracing.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/testing/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/testing/conftest.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/testing/test_all_examples.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/testing/test_e2e.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/testing/test_gherkin_parser.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/testing/test_integration.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/testing/test_models.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/testing/test_runtime_integration.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/testing/test_step_registry.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/utils/__init__.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/utils/test_safe_file_library.py +0 -0
- {tactus-0.26.0 → tactus-0.27.0}/tests/validation/__init__.py +0 -0
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- version list -->
|
|
4
4
|
|
|
5
|
+
## v0.27.0 (2026-01-11)
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- **broker**: Brokered sandbox runtime MVP (secretless runtime container) (#24)
|
|
10
|
+
([#24](https://github.com/AnthusAI/Tactus/pull/24),
|
|
11
|
+
[`f922432`](https://github.com/AnthusAI/Tactus/commit/f922432da5a881c5eceb7c1410276ab45264ddaa))
|
|
12
|
+
|
|
13
|
+
|
|
5
14
|
## v0.26.0 (2026-01-11)
|
|
6
15
|
|
|
7
16
|
### Features
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
.PHONY: help generate-parsers generate-python-parser generate-typescript-parser test-parsers clean-generated dev-ide test-examples test-examples-fast test-examples-parallel test-examples-bdd
|
|
2
|
+
.PHONY: test-docker-sandbox
|
|
2
3
|
|
|
3
4
|
help:
|
|
4
5
|
@echo "Tactus Parser Generation and Testing"
|
|
@@ -17,6 +18,9 @@ help:
|
|
|
17
18
|
@echo " test-examples-parallel - Test examples in parallel for speed"
|
|
18
19
|
@echo " test-examples-bdd - Test only examples with BDD specifications"
|
|
19
20
|
@echo ""
|
|
21
|
+
@echo "Docker Sandbox Testing:"
|
|
22
|
+
@echo " test-docker-sandbox - Run opt-in Docker sandbox smoke tests"
|
|
23
|
+
@echo ""
|
|
20
24
|
@echo "Requirements:"
|
|
21
25
|
@echo " - Docker must be running (for parser generation)"
|
|
22
26
|
@echo " - Python 3.11+ with dependencies installed"
|
|
@@ -113,6 +117,11 @@ test-examples-bdd:
|
|
|
113
117
|
@echo "Testing examples with BDD specifications..."
|
|
114
118
|
pytest tests/testing/test_all_examples.py::TestAllExamples::test_example_bdd_specs -v --tb=short
|
|
115
119
|
|
|
120
|
+
# Docker sandbox integration tests (dev-only, opt-in)
|
|
121
|
+
test-docker-sandbox:
|
|
122
|
+
@echo "Running Docker sandbox integration tests (opt-in)..."
|
|
123
|
+
@echo "Pre-req: tactus sandbox rebuild --force"
|
|
124
|
+
TACTUS_RUN_DOCKER_TESTS=1 pytest -m docker -v --tb=short
|
|
116
125
|
|
|
117
126
|
|
|
118
127
|
|
|
@@ -1097,7 +1097,7 @@ class AgentPrimitive:
|
|
|
1097
1097
|
)
|
|
1098
1098
|
return {
|
|
1099
1099
|
"output": result.output,
|
|
1100
|
-
"messages": self.messages
|
|
1100
|
+
"messages": self.messages + result.new_messages()
|
|
1101
1101
|
}
|
|
1102
1102
|
```
|
|
1103
1103
|
|
|
@@ -1390,4 +1390,4 @@ result = await runtime.execute(
|
|
|
1390
1390
|
|
|
1391
1391
|
4. **Observability**: Integration with Logfire/OpenTelemetry for tracing?
|
|
1392
1392
|
|
|
1393
|
-
5. **Error recovery**: Retry policies, dead letter queues, manual intervention?
|
|
1393
|
+
5. **Error recovery**: Retry policies, dead letter queues, manual intervention?
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Sandboxing & Security
|
|
2
2
|
|
|
3
|
-
Tactus provides **three layers of sandboxing** to protect against different threat models. This defense-in-depth approach makes Tactus safe for user-contributed code, secure for local development, and
|
|
3
|
+
Tactus provides **three layers of sandboxing** to protect against different threat models. This defense-in-depth approach makes Tactus safe for user-contributed code, secure for local development, and designed to support secure multi-tenant AI systems.
|
|
4
4
|
|
|
5
5
|
## Overview: Three Layers of Protection
|
|
6
6
|
|
|
@@ -458,6 +458,7 @@ logger.info(f"Tool call: {tool_name}", extra={
|
|
|
458
458
|
## Development
|
|
459
459
|
- [ ] Docker Desktop installed and running
|
|
460
460
|
- [ ] Sandbox enabled in config (default)
|
|
461
|
+
- [ ] Run opt-in Docker sandbox tests (dev-only): `tactus sandbox rebuild --force` then `make test-docker-sandbox` (or `TACTUS_RUN_DOCKER_TESTS=1 pytest -m docker -v`)
|
|
461
462
|
- [ ] MCP servers reviewed for security issues
|
|
462
463
|
- [ ] Tool calls logged for debugging
|
|
463
464
|
- [ ] Resource limits configured appropriately
|
|
@@ -485,7 +486,7 @@ logger.info(f"Tool call: {tool_name}", extra={
|
|
|
485
486
|
2. **Default security:** Sandbox enabled by default, opt-out requires explicit acknowledgment
|
|
486
487
|
3. **AI-native design:** Built from the ground up to prevent session leakage
|
|
487
488
|
4. **Embeddable safety:** Lua sandboxing makes Tactus safe for user-contributed code
|
|
488
|
-
5. **
|
|
489
|
+
5. **Multi-tenant isolation:** Cloud sandboxing provides per-invocation isolation at scale
|
|
489
490
|
6. **Information security DNA:** Per-invocation sandboxing prevents AI session leakage, a critical requirement for multi-tenant AI systems
|
|
490
491
|
|
|
491
492
|
---
|
|
@@ -1,23 +1,33 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Tools in Tactus
|
|
2
2
|
|
|
3
|
-
This guide explains
|
|
3
|
+
This guide explains the major tool types in Tactus, where they run, and how to keep secrets out of sandboxed runs.
|
|
4
4
|
|
|
5
5
|
## Table of Contents
|
|
6
6
|
|
|
7
7
|
1. [Overview](#overview)
|
|
8
|
-
2. [
|
|
9
|
-
3. [
|
|
10
|
-
4. [
|
|
11
|
-
5. [
|
|
12
|
-
6. [
|
|
13
|
-
7. [Tool
|
|
14
|
-
8. [
|
|
15
|
-
9. [
|
|
16
|
-
10. [
|
|
8
|
+
2. [Trust Zones](#trust-zones)
|
|
9
|
+
3. [Brokered Host Tools](#brokered-host-tools)
|
|
10
|
+
4. [Quick Start](#quick-start)
|
|
11
|
+
5. [Three Approaches](#three-approaches)
|
|
12
|
+
6. [Parameter Specifications](#parameter-specifications)
|
|
13
|
+
7. [Tool Implementation Patterns](#tool-implementation-patterns)
|
|
14
|
+
8. [Error Handling](#error-handling)
|
|
15
|
+
9. [Tool Call Tracking](#tool-call-tracking)
|
|
16
|
+
10. [Advanced Examples](#advanced-examples)
|
|
17
|
+
11. [Comparison with Plugin Tools](#comparison-with-plugin-tools)
|
|
18
|
+
12. [Best Practices](#best-practices)
|
|
17
19
|
|
|
18
20
|
## Overview
|
|
19
21
|
|
|
20
|
-
Tactus supports
|
|
22
|
+
Tactus supports several tool types:
|
|
23
|
+
|
|
24
|
+
- **Built-in Tactus tools** (shipped with Tactus): e.g. `tactus.tools.done`
|
|
25
|
+
- **Lua function tools** (defined inside `.tac`): simple, fast, co-located with the workflow
|
|
26
|
+
- **Python plugin tools** (loaded from `tool_paths`): run Python code from your repo without MCP
|
|
27
|
+
- **MCP tools** (Model Context Protocol): tools provided by external stdio servers
|
|
28
|
+
- **Brokered host tools** (Phase 1B): privileged “host-side” tools executed by the broker and invoked from the sandbox via `Host.call(...)`
|
|
29
|
+
|
|
30
|
+
Lua function tools support three ways to define tools:
|
|
21
31
|
|
|
22
32
|
1. **Individual `tool()` declarations** - Define single tools globally
|
|
23
33
|
2. **`toolset()` with `type="lua"`** - Group multiple related tools
|
|
@@ -33,6 +43,53 @@ All three approaches are powered by Pydantic AI's function toolset feature and i
|
|
|
33
43
|
- **Tracked**: Full integration with `Tool.called()` and `Tool.last_call()`
|
|
34
44
|
- **Fast**: Minimal overhead for simple operations
|
|
35
45
|
|
|
46
|
+
## Trust Zones
|
|
47
|
+
|
|
48
|
+
Tactus aims to keep the **runtime container** (when using `--sandbox`) both:
|
|
49
|
+
|
|
50
|
+
- **Networkless** by default (`--network none`)
|
|
51
|
+
- **Secretless** (no long-lived API keys in the container env, mounts, or request payload)
|
|
52
|
+
|
|
53
|
+
That means not all “tools” are equal: different tool types run in different trust zones.
|
|
54
|
+
|
|
55
|
+
At a high level:
|
|
56
|
+
|
|
57
|
+
- **Lua tools** run inside the runtime (and therefore inside the sandbox container when `--sandbox` is enabled).
|
|
58
|
+
- **MCP servers** run as subprocesses of the runtime (so they share the runtime’s trust zone unless explicitly isolated).
|
|
59
|
+
- **Brokered host tools** run on the trusted host-side broker and can hold secrets without exposing them to the sandbox.
|
|
60
|
+
|
|
61
|
+
For the broader architecture (including future isolated tool runners), see `planning/BROKER_AND_TOOL_RUNNERS.md`.
|
|
62
|
+
|
|
63
|
+
## Brokered Host Tools
|
|
64
|
+
|
|
65
|
+
Brokered host tools are allowlisted operations executed by the **host-side broker** and invoked from the runtime via the `Host` primitive.
|
|
66
|
+
|
|
67
|
+
This is the core mechanism for “remote tools with secrets” (e.g., a Tab search API key) while keeping the sandbox container secretless.
|
|
68
|
+
|
|
69
|
+
### Running the Example
|
|
70
|
+
|
|
71
|
+
Run the example:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
tactus sandbox rebuild --force
|
|
75
|
+
tactus run examples/66-host-tools-via-broker.tac --sandbox --verbose
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Call a host tool from Lua:
|
|
79
|
+
|
|
80
|
+
```lua
|
|
81
|
+
local result = Host.call("host.ping", {value = 1})
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Default Allowlist (Phase 1B)
|
|
85
|
+
|
|
86
|
+
The default broker allowlist intentionally starts small:
|
|
87
|
+
|
|
88
|
+
- `host.ping`
|
|
89
|
+
- `host.echo`
|
|
90
|
+
|
|
91
|
+
To add real host tools, extend the broker’s allowlist (see `tactus/broker/server.py:HostToolRegistry`).
|
|
92
|
+
|
|
36
93
|
## Quick Start
|
|
37
94
|
|
|
38
95
|
Here's the simplest example:
|
|
@@ -652,7 +709,7 @@ content_editor = Agent {
|
|
|
652
709
|
- Lua language constraints
|
|
653
710
|
- No async operations
|
|
654
711
|
- Limited to Lua ecosystem
|
|
655
|
-
- Can't
|
|
712
|
+
- Can't safely hold secrets (use brokered host tools instead)
|
|
656
713
|
|
|
657
714
|
**Best for:**
|
|
658
715
|
- Data transformations
|
|
@@ -683,6 +740,23 @@ content_editor = Agent {
|
|
|
683
740
|
- Shared across projects
|
|
684
741
|
- Complex algorithms
|
|
685
742
|
|
|
743
|
+
### Brokered Host Tools (via Host.call)
|
|
744
|
+
|
|
745
|
+
**Pros:**
|
|
746
|
+
- Secrets stay out of the sandbox container
|
|
747
|
+
- Can perform network calls without giving the runtime network access
|
|
748
|
+
- Centralized allowlist and auditing point (the broker)
|
|
749
|
+
|
|
750
|
+
**Cons:**
|
|
751
|
+
- Requires a broker transport (`--sandbox` uses broker by default)
|
|
752
|
+
- Must be explicitly allowlisted (deny-by-default)
|
|
753
|
+
- Privileged by design; treat host tools as trusted code
|
|
754
|
+
|
|
755
|
+
**Best for:**
|
|
756
|
+
- Remote API tools that require API keys
|
|
757
|
+
- “Host-integrated” capabilities (e.g., talking to a local index, keychain, or daemon)
|
|
758
|
+
- Anything that must be kept out of the untrusted runtime container
|
|
759
|
+
|
|
686
760
|
### When to Use Which?
|
|
687
761
|
|
|
688
762
|
Use **Lua Function Tools** when:
|
|
@@ -705,6 +779,11 @@ Use **MCP Tools** when:
|
|
|
705
779
|
- Tool is maintained separately
|
|
706
780
|
- Multiple procedures share it
|
|
707
781
|
|
|
782
|
+
Use **Brokered Host Tools** when:
|
|
783
|
+
- A tool needs secrets but the runtime container must remain secretless
|
|
784
|
+
- The runtime container must remain networkless (`--network none`)
|
|
785
|
+
- You want a narrow, allowlisted capability surface area
|
|
786
|
+
|
|
708
787
|
## Best Practices
|
|
709
788
|
|
|
710
789
|
### 1. Clear Descriptions
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
World = Agent {
|
|
2
|
+
provider = "openai",
|
|
3
|
+
model = "gpt-4o-mini",
|
|
4
|
+
system_prompt = "Your name is World.",
|
|
5
|
+
module = "Raw" -- No DSPy delimiter formatting
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
Procedure {
|
|
9
|
+
output = {
|
|
10
|
+
message = field.string{required = true}
|
|
11
|
+
},
|
|
12
|
+
function(_)
|
|
13
|
+
local result = World({message = "Hello, World!"})
|
|
14
|
+
return {message = result.response}
|
|
15
|
+
end
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
Mocks {
|
|
19
|
+
World = {
|
|
20
|
+
tool_calls = {},
|
|
21
|
+
message = "Hello, World!"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -45,7 +45,7 @@ Procedure {
|
|
|
45
45
|
if done.called() then
|
|
46
46
|
research = done.last_result() or "Task completed"
|
|
47
47
|
else
|
|
48
|
-
research =
|
|
48
|
+
research = result.message or "Research not completed"
|
|
49
49
|
Log.warn("Researcher did not call done within max turns")
|
|
50
50
|
end
|
|
51
51
|
state.research = research
|
|
@@ -66,7 +66,7 @@ Procedure {
|
|
|
66
66
|
if done.called() then
|
|
67
67
|
summary = done.last_result() or "Task completed"
|
|
68
68
|
else
|
|
69
|
-
summary =
|
|
69
|
+
summary = result.message or "Summary not completed"
|
|
70
70
|
Log.warn("Summarizer did not call done within max turns")
|
|
71
71
|
end
|
|
72
72
|
|
|
@@ -26,8 +26,15 @@ Procedure {
|
|
|
26
26
|
local result = storyteller({message = input.prompt})
|
|
27
27
|
|
|
28
28
|
return {
|
|
29
|
-
story = result.
|
|
29
|
+
story = result.response,
|
|
30
30
|
success = true
|
|
31
31
|
}
|
|
32
32
|
end
|
|
33
33
|
}
|
|
34
|
+
|
|
35
|
+
Mocks {
|
|
36
|
+
storyteller = {
|
|
37
|
+
tool_calls = {},
|
|
38
|
+
message = "A curious robot dipped its brush into blue paint and discovered joy in every stroke."
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -36,9 +36,9 @@ Procedure {
|
|
|
36
36
|
local response = haiku_assistant()
|
|
37
37
|
turn_count = turn_count + 1
|
|
38
38
|
|
|
39
|
-
-- Accumulate the response
|
|
40
|
-
if response.
|
|
41
|
-
response_text = response_text .. response.
|
|
39
|
+
-- Accumulate the response message from each turn using .message property
|
|
40
|
+
if response.message and response.message ~= "" then
|
|
41
|
+
response_text = response_text .. response.message
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
-- Safety check: exit if too many turns
|
|
@@ -137,8 +137,8 @@ Procedure {
|
|
|
137
137
|
local response = agent_ref()
|
|
138
138
|
turn_count = turn_count + 1
|
|
139
139
|
|
|
140
|
-
if response.
|
|
141
|
-
response_text = response_text .. response.
|
|
140
|
+
if response.message and response.message ~= "" then
|
|
141
|
+
response_text = response_text .. response.message
|
|
142
142
|
end
|
|
143
143
|
|
|
144
144
|
if turn_count >= max_turns then
|
|
@@ -175,7 +175,7 @@ Procedure {
|
|
|
175
175
|
local success, result = pcall(function(input)
|
|
176
176
|
local response = agent_ref()
|
|
177
177
|
return {
|
|
178
|
-
response = response.
|
|
178
|
+
response = response.message or "",
|
|
179
179
|
turns = 1,
|
|
180
180
|
success = true,
|
|
181
181
|
error = nil
|
|
@@ -56,8 +56,8 @@ Procedure {
|
|
|
56
56
|
pro_turns = pro_turns + 1
|
|
57
57
|
|
|
58
58
|
-- Accumulate the response text
|
|
59
|
-
if response.
|
|
60
|
-
pro_response = pro_response .. response.
|
|
59
|
+
if response.message and response.message ~= "" then
|
|
60
|
+
pro_response = pro_response .. response.message
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
-- Safety check
|
|
@@ -86,8 +86,8 @@ Procedure {
|
|
|
86
86
|
flash_turns = flash_turns + 1
|
|
87
87
|
|
|
88
88
|
-- Accumulate the response text
|
|
89
|
-
if response.
|
|
90
|
-
flash_response = flash_response .. response.
|
|
89
|
+
if response.message and response.message ~= "" then
|
|
90
|
+
flash_response = flash_response .. response.message
|
|
91
91
|
end
|
|
92
92
|
|
|
93
93
|
-- Safety check
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
-- Structured Output Demo
|
|
2
2
|
-- Demonstrates using output for structured data extraction
|
|
3
|
-
-- and accessing result.
|
|
3
|
+
-- and accessing result.data, result.usage
|
|
4
4
|
|
|
5
5
|
extractor = Agent {
|
|
6
6
|
provider = "openai",
|
|
7
7
|
model = "gpt-4o-mini",
|
|
8
|
-
system_prompt = [[You extract city information. Return ONLY
|
|
8
|
+
system_prompt = [[You extract city information. Return ONLY structured data with these fields:
|
|
9
9
|
- city: city name
|
|
10
10
|
- country: country name
|
|
11
11
|
- population: estimated population (number, optional)
|
|
@@ -32,14 +32,14 @@ Procedure {
|
|
|
32
32
|
function(input)
|
|
33
33
|
Log.info("Starting structured output demo", {query = input.query})
|
|
34
34
|
|
|
35
|
-
-- Agent returns
|
|
35
|
+
-- Agent returns ResultPrimitive (not raw data)
|
|
36
36
|
local result = extractor()
|
|
37
37
|
|
|
38
|
-
-- Access structured data via result.
|
|
38
|
+
-- Access structured data via result.data
|
|
39
39
|
Log.info("Extracted city information", {
|
|
40
|
-
city = result.
|
|
41
|
-
country = result.
|
|
42
|
-
population = result.
|
|
40
|
+
city = result.data.city,
|
|
41
|
+
country = result.data.country,
|
|
42
|
+
population = result.data.population or "unknown"
|
|
43
43
|
})
|
|
44
44
|
|
|
45
45
|
-- Access token usage stats
|
|
@@ -49,8 +49,20 @@ Procedure {
|
|
|
49
49
|
total_tokens = result.usage.total_tokens
|
|
50
50
|
})
|
|
51
51
|
|
|
52
|
+
-- Access messages from this turn
|
|
53
|
+
local new_msgs = result.new_messages()
|
|
54
|
+
Log.info("Messages generated in this turn", {count = #new_msgs})
|
|
55
|
+
|
|
56
|
+
-- Log first message (if any)
|
|
57
|
+
if #new_msgs > 0 then
|
|
58
|
+
Log.info("First message", {
|
|
59
|
+
role = new_msgs[1].role,
|
|
60
|
+
content_preview = string.sub(new_msgs[1].content, 1, 100)
|
|
61
|
+
})
|
|
62
|
+
end
|
|
63
|
+
|
|
52
64
|
return {
|
|
53
|
-
city_data = result.
|
|
65
|
+
city_data = result.data,
|
|
54
66
|
tokens_used = result.usage.total_tokens
|
|
55
67
|
}
|
|
56
68
|
end
|
|
@@ -83,7 +83,7 @@ Procedure {
|
|
|
83
83
|
end
|
|
84
84
|
else
|
|
85
85
|
-- Max turns reached - use last response
|
|
86
|
-
answer =
|
|
86
|
+
answer = result.message
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
return {
|
|
@@ -92,3 +92,13 @@ Procedure {
|
|
|
92
92
|
}
|
|
93
93
|
end
|
|
94
94
|
}
|
|
95
|
+
|
|
96
|
+
Mocks {
|
|
97
|
+
assistant = {
|
|
98
|
+
tool_calls = {
|
|
99
|
+
{tool = "calculate_mortgage", args = {principal = 300000, annual_interest_rate = 0.065, years = 30}},
|
|
100
|
+
{tool = "done", args = {reason = "Monthly payment is $1,896.20 (mocked)."}}
|
|
101
|
+
},
|
|
102
|
+
message = "Monthly payment is $1,896.20 (mocked)."
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -103,7 +103,7 @@ Procedure {
|
|
|
103
103
|
turn_count = turn_count + 1
|
|
104
104
|
until done.called() or turn_count >= max_turns
|
|
105
105
|
|
|
106
|
-
local response =
|
|
106
|
+
local response = result.message
|
|
107
107
|
Log.info(agent_name .. " response", {text = response})
|
|
108
108
|
return response
|
|
109
109
|
end
|
|
@@ -123,7 +123,7 @@ Procedure {
|
|
|
123
123
|
-- Test Agent 5: No tools (explicitly empty) - only needs 1 turn
|
|
124
124
|
Log.info("Testing Agent 5: No tools")
|
|
125
125
|
local observer_result = observer()
|
|
126
|
-
local observer_response =
|
|
126
|
+
local observer_response = observer_result.message
|
|
127
127
|
Log.info("Observer response", {text = observer_response})
|
|
128
128
|
|
|
129
129
|
return {
|
|
@@ -94,8 +94,7 @@ Procedure {
|
|
|
94
94
|
else
|
|
95
95
|
Log.warn("Agent did not call done within max turns")
|
|
96
96
|
return {
|
|
97
|
-
calculation_result =
|
|
98
|
-
or "Agent did not complete",
|
|
97
|
+
calculation_result = result.message or "Agent did not complete",
|
|
99
98
|
completed = false
|
|
100
99
|
}
|
|
101
100
|
end
|
|
@@ -47,29 +47,17 @@ Procedure {
|
|
|
47
47
|
},
|
|
48
48
|
function(input)
|
|
49
49
|
|
|
50
|
-
--
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
State.sentiment = "positive"
|
|
55
|
-
elseif string.find(msg_lower, "hate") or string.find(msg_lower, "terrible") or string.find(msg_lower, "awful") then
|
|
56
|
-
State.sentiment = "negative"
|
|
57
|
-
else
|
|
58
|
-
State.sentiment = "neutral"
|
|
59
|
-
end
|
|
50
|
+
-- 1. Classify sentiment with ML model (checkpointed)
|
|
51
|
+
State.sentiment = Model("sentiment_classifier").predict({
|
|
52
|
+
text = input.customer_message
|
|
53
|
+
})
|
|
60
54
|
|
|
61
|
-
-- Agent responds based on sentiment (checkpointed)
|
|
55
|
+
-- 2. Agent responds based on sentiment (checkpointed)
|
|
62
56
|
support_agent({message = input.customer_message})
|
|
63
57
|
|
|
64
|
-
-- Get response from done tool
|
|
65
|
-
local response = "Thank you for your message."
|
|
66
|
-
if done.called() then
|
|
67
|
-
response = done.last_result() or "I'm here to help."
|
|
68
|
-
end
|
|
69
|
-
|
|
70
58
|
return {
|
|
71
59
|
sentiment = State.sentiment,
|
|
72
|
-
response =
|
|
60
|
+
response = support_agent.output
|
|
73
61
|
}
|
|
74
62
|
|
|
75
63
|
-- BDD Specifications
|
|
@@ -78,6 +66,9 @@ Procedure {
|
|
|
78
66
|
|
|
79
67
|
-- Agent Mocks for CI testing
|
|
80
68
|
Mocks {
|
|
69
|
+
sentiment_classifier = {
|
|
70
|
+
returns = "positive"
|
|
71
|
+
},
|
|
81
72
|
support_agent = {
|
|
82
73
|
tool_calls = {
|
|
83
74
|
{tool = "done", args = {reason = "I'm happy to help! Thank you for your positive feedback."}}
|
|
@@ -13,7 +13,7 @@ local done = require("tactus.tools.done")
|
|
|
13
13
|
|
|
14
14
|
-- Define a PyTorch sentiment classifier
|
|
15
15
|
-- (This requires the .pt file to exist and PyTorch to be installed)
|
|
16
|
-
|
|
16
|
+
Model "sentiment_classifier" { type = "pytorch", path = "models/sentiment.pt" }
|
|
17
17
|
|
|
18
18
|
support_agent = Agent {
|
|
19
19
|
provider = "openai",
|
|
@@ -31,7 +31,7 @@ Call done when finished.
|
|
|
31
31
|
|
|
32
32
|
Procedure {
|
|
33
33
|
input = {
|
|
34
|
-
customer_message = field.string{
|
|
34
|
+
customer_message = field.string{default = "I love this product!", description = "Customer message to analyze"}
|
|
35
35
|
},
|
|
36
36
|
output = {
|
|
37
37
|
sentiment = field.string{required = true, description = "Detected sentiment label"},
|
|
@@ -39,29 +39,16 @@ Procedure {
|
|
|
39
39
|
},
|
|
40
40
|
function(input)
|
|
41
41
|
|
|
42
|
-
--
|
|
43
|
-
--
|
|
44
|
-
|
|
45
|
-
if string.find(msg_lower, "love") or string.find(msg_lower, "great") then
|
|
46
|
-
State.sentiment = "positive"
|
|
47
|
-
elseif string.find(msg_lower, "hate") or string.find(msg_lower, "bad") then
|
|
48
|
-
State.sentiment = "negative"
|
|
49
|
-
else
|
|
50
|
-
State.sentiment = "neutral"
|
|
51
|
-
end
|
|
42
|
+
-- Classify sentiment with PyTorch model
|
|
43
|
+
-- Input: tensor of word indices (for demo, just pass a simple tensor)
|
|
44
|
+
State.sentiment = Model("sentiment_classifier").predict({1, 2, 3, 4, 5})
|
|
52
45
|
|
|
53
46
|
-- Agent responds based on sentiment
|
|
54
47
|
support_agent({message = input.customer_message})
|
|
55
48
|
|
|
56
|
-
-- Get response from done tool
|
|
57
|
-
local response = "I'm here to help."
|
|
58
|
-
if done.called() then
|
|
59
|
-
response = done.last_result() or "Thank you for your message."
|
|
60
|
-
end
|
|
61
|
-
|
|
62
49
|
return {
|
|
63
50
|
sentiment = State.sentiment,
|
|
64
|
-
response =
|
|
51
|
+
response = support_agent.output
|
|
65
52
|
}
|
|
66
53
|
|
|
67
54
|
-- BDD Specifications
|
|
@@ -70,6 +57,9 @@ Procedure {
|
|
|
70
57
|
|
|
71
58
|
-- Agent Mocks for CI testing
|
|
72
59
|
Mocks {
|
|
60
|
+
sentiment_classifier = {
|
|
61
|
+
returns = "positive"
|
|
62
|
+
},
|
|
73
63
|
support_agent = {
|
|
74
64
|
tool_calls = {
|
|
75
65
|
{tool = "done", args = {reason = "Based on the sentiment analysis, I've provided an appropriate response."}}
|
|
@@ -82,7 +72,6 @@ Specifications([[
|
|
|
82
72
|
Feature: PyTorch Model Integration
|
|
83
73
|
Scenario: PyTorch model performs inference
|
|
84
74
|
Given the procedure has started
|
|
85
|
-
And the input customer_message is "I love this product!"
|
|
86
75
|
When the procedure runs
|
|
87
76
|
Then the done tool should be called
|
|
88
77
|
And the output sentiment should exist
|