tactus 0.27.0__py3-none-any.whl → 0.28.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -33,6 +33,7 @@ class ToolHandle:
33
33
  impl_fn: Callable,
34
34
  tool_primitive: Optional["ToolPrimitive"] = None,
35
35
  is_async: bool = False,
36
+ record_calls: bool = True,
36
37
  ):
37
38
  """
38
39
  Initialize a tool handle.
@@ -47,6 +48,7 @@ class ToolHandle:
47
48
  self.impl_fn = impl_fn
48
49
  self.tool_primitive = tool_primitive
49
50
  self.is_async = is_async
51
+ self.record_calls = record_calls
50
52
 
51
53
  logger.debug(f"ToolHandle created for '{name}' (async={is_async})")
52
54
 
@@ -77,7 +79,7 @@ class ToolHandle:
77
79
  result = self.impl_fn(args)
78
80
 
79
81
  # Record the call for tracking
80
- if self.tool_primitive:
82
+ if self.tool_primitive and self.record_calls:
81
83
  self.tool_primitive.record_call(self.name, args, result)
82
84
 
83
85
  logger.debug(f"ToolHandle.call('{self.name}') returned: {result}")
tactus/sandbox/config.py CHANGED
@@ -7,7 +7,7 @@ Defines the SandboxConfig Pydantic model for controlling container execution.
7
7
  from pathlib import Path
8
8
  from typing import Dict, List, Optional
9
9
 
10
- from pydantic import BaseModel, Field
10
+ from pydantic import BaseModel, Field, model_validator
11
11
 
12
12
 
13
13
  class SandboxLimits(BaseModel):
@@ -52,6 +52,12 @@ class SandboxConfig(BaseModel):
52
52
  description="Additional environment variables to pass to the container",
53
53
  )
54
54
 
55
+ # Volume mount settings
56
+ mount_current_dir: bool = Field(
57
+ default=True,
58
+ description="Mount current directory to /workspace:rw by default. Set false to disable.",
59
+ )
60
+
55
61
  # Additional volume mounts
56
62
  volumes: List[str] = Field(
57
63
  default_factory=list,
@@ -60,16 +66,17 @@ class SandboxConfig(BaseModel):
60
66
 
61
67
  # Network mode
62
68
  network: str = Field(
63
- default="none",
64
- description="Docker network mode (bridge allows outbound, none blocks all)",
69
+ default="bridge",
70
+ description="Docker network mode (bridge for broker access, none blocks all network)",
65
71
  )
66
72
 
67
73
  # Broker transport (how the secretless runtime reaches the host broker)
68
- # - stdio: local Docker MVP (works on Docker Desktop with --network none)
69
- # - tcp/tls: remote-mode spike (for K8s/cloud; requires container networking)
74
+ # - tcp: Standard mode using TCP sockets (works locally and in K8s/cloud)
75
+ # - tls: TCP with TLS encryption (for production deployments)
76
+ # - stdio: Legacy mode using stdin/stdout (deprecated due to buffering issues)
70
77
  broker_transport: str = Field(
71
- default="stdio",
72
- description="Broker transport for the runtime container: stdio, tcp, or tls",
78
+ default="tcp",
79
+ description="Broker transport for the runtime container: tcp, tls, or stdio (deprecated)",
73
80
  )
74
81
  broker_host: str = Field(
75
82
  default="host.docker.internal",
@@ -143,6 +150,15 @@ class SandboxConfig(BaseModel):
143
150
 
144
151
  model_config = {"arbitrary_types_allowed": True}
145
152
 
153
+ @model_validator(mode="after")
154
+ def add_default_volumes(self):
155
+ """Add default volume mounts based on config flags."""
156
+ if self.mount_current_dir:
157
+ # Insert at beginning so user volumes can override
158
+ if ".:/workspace:rw" not in self.volumes:
159
+ self.volumes.insert(0, ".:/workspace:rw")
160
+ return self
161
+
146
162
 
147
163
  def get_default_sandbox_config() -> SandboxConfig:
148
164
  """Get the default sandbox configuration."""
@@ -419,12 +419,40 @@ class ContainerRunner:
419
419
  )
420
420
 
421
421
  # Run container
422
- result = await self._run_container(
423
- docker_cmd,
424
- request,
425
- timeout=self.config.timeout,
426
- event_handler=event_handler,
427
- )
422
+ # If TCP broker is active, run it concurrently with the container
423
+ if broker_transport in ("tcp", "tls") and broker_server is not None:
424
+
425
+ async def run_broker_server():
426
+ """Serve broker connections until explicitly closed."""
427
+ try:
428
+ await broker_server.serve()
429
+ except Exception:
430
+ # Broker server was closed (expected on cleanup)
431
+ pass
432
+
433
+ # Run broker and container concurrently
434
+ broker_task = asyncio.create_task(run_broker_server())
435
+ try:
436
+ result = await self._run_container(
437
+ docker_cmd,
438
+ request,
439
+ timeout=self.config.timeout,
440
+ event_handler=event_handler,
441
+ )
442
+ finally:
443
+ # Cancel broker task when container finishes
444
+ broker_task.cancel()
445
+ try:
446
+ await broker_task
447
+ except asyncio.CancelledError:
448
+ pass
449
+ else:
450
+ result = await self._run_container(
451
+ docker_cmd,
452
+ request,
453
+ timeout=self.config.timeout,
454
+ event_handler=event_handler,
455
+ )
428
456
 
429
457
  result.duration_seconds = time.time() - start_time
430
458
  return result
@@ -16,9 +16,9 @@ Usage:
16
16
  end
17
17
  ]]--
18
18
 
19
- -- Use named syntax so the tool has explicit name "done"
20
- -- (required for mock mode where tool calls are recorded by name)
21
- return Tool "done" {
19
+ -- Provide explicit name so the tool is recorded/mocked as "done"
20
+ return Tool {
21
+ name = "done",
22
22
  description = "Signal task completion",
23
23
  input = {
24
24
  reason = field.string{required = false, description = "Reason for completion"}
@@ -17,6 +17,7 @@ Note: For direct logging in procedures, use the Log global directly:
17
17
  ]]--
18
18
 
19
19
  local log_tool = Tool {
20
+ name = "log",
20
21
  description = "Log a message during procedure execution",
21
22
  input = {
22
23
  message = field.string{required = true, description = "Message to log"},
tactus/testing/context.py CHANGED
@@ -77,7 +77,6 @@ class TactusTestContext:
77
77
  storage_backend=storage,
78
78
  hitl_handler=hitl,
79
79
  tool_primitive=tool_primitive, # Inject mocked tool if configured
80
- skip_agents=bool(self.mock_tools), # Skip agents in mock mode
81
80
  openai_api_key=os.environ.get("OPENAI_API_KEY"), # Pass API key for real LLM calls
82
81
  log_handler=log_handler, # Enable cost tracking
83
82
  source_file_path=str(self.procedure_file.resolve()), # For require() path resolution
@@ -155,6 +155,23 @@ class TactusDSLVisitor(LuaParserVisitor):
155
155
  elif func_name == "Tool":
156
156
  # Extract config from Tool {...}
157
157
  config = self._extract_single_table_arg(func_call)
158
+ if (
159
+ config
160
+ and isinstance(config, dict)
161
+ and isinstance(config.get("name"), str)
162
+ and config.get("name") != var_name
163
+ ):
164
+ self.errors.append(
165
+ ValidationMessage(
166
+ level="error",
167
+ message=(
168
+ f"Tool name mismatch: '{var_name} = Tool {{ name = \"{config.get('name')}\" }}'. "
169
+ f"Remove the 'name' field or set it to '{var_name}'."
170
+ ),
171
+ location=(self.current_line, self.current_col),
172
+ declaration="Tool",
173
+ )
174
+ )
158
175
  self.builder.register_tool(var_name, config if config else {}, None)
159
176
  elif func_name == "Toolset":
160
177
  # Extract config from Toolset {...}
@@ -508,28 +525,21 @@ class TactusDSLVisitor(LuaParserVisitor):
508
525
  if args and len(args) >= 1 and isinstance(args[0], dict):
509
526
  self.builder.register_top_level_output(args[0])
510
527
  elif func_name == "Tool": # CamelCase only
511
- # Tool("name", {config}, function) - DEPRECATED curried syntax
512
- # New syntax: tool_name = Tool { config, function }
513
- if args and len(args) >= 1: # Support curried syntax
514
- # First arg must be name (string)
515
- if isinstance(args[0], str):
516
- tool_name = args[0]
517
- # Check for special stdlib import syntax: Tool "name" { use = "..." }
518
- # This is still allowed for backwards compatibility
519
- config = args[1] if len(args) >= 2 and isinstance(args[1], dict) else {}
520
- if config.get("use"):
521
- # This is a stdlib import, still allowed
522
- self.builder.register_tool(tool_name, config, None)
523
- else:
524
- # This is deprecated curried syntax
525
- self.errors.append(
526
- ValidationMessage(
527
- level="error",
528
- message=f'Curried syntax Tool "{tool_name}" {{...}} is deprecated. Use assignment syntax: {tool_name} = Tool {{...}}',
529
- location=(self.current_line, self.current_col),
530
- declaration="Tool",
531
- )
532
- )
528
+ # Curried syntax (Tool "name" {...} / Tool("name", ...)) is not supported.
529
+ # Use assignment syntax: my_tool = Tool { ... }.
530
+ if args and len(args) >= 1 and isinstance(args[0], str):
531
+ tool_name = args[0]
532
+ self.errors.append(
533
+ ValidationMessage(
534
+ level="error",
535
+ message=(
536
+ f'Curried Tool syntax is not supported: Tool "{tool_name}" {{...}}. '
537
+ f"Use assignment syntax: {tool_name} = Tool {{...}}."
538
+ ),
539
+ location=(self.current_line, self.current_col),
540
+ declaration="Tool",
541
+ )
542
+ )
533
543
  elif func_name == "Toolset": # CamelCase only
534
544
  # Toolset("name", {config})
535
545
  # or new curried syntax: Toolset "name" { config }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tactus
3
- Version: 0.27.0
3
+ Version: 0.28.0
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
@@ -636,6 +636,22 @@ researcher({
636
636
 
637
637
  See `examples/14-feature-per-turn-tools.tac` for a complete working example.
638
638
 
639
+ ### Checkpointed Steps (Determinism)
640
+
641
+ For durable execution, any operation that touches external state (randomness, time, APIs not in tools) must be checkpointed. Tactus provides `Step.checkpoint` for this:
642
+
643
+ ```lua
644
+ -- Non-deterministic operation wrapped in checkpoint
645
+ local data = Step.checkpoint(function()
646
+ return http_get("https://api.example.com/data")
647
+ end)
648
+
649
+ -- On replay, the function is NOT called again.
650
+ -- The previously saved 'data' is returned immediately.
651
+ ```
652
+
653
+ This ensures that when a procedure resumes after a pause (e.g. waiting for a human), it doesn't re-execute side effects or get different random values.
654
+
639
655
  ### File I/O Operations
640
656
 
641
657
  Tactus provides safe file I/O operations for reading and writing data files, with all operations restricted to the current working directory for security.
@@ -1085,6 +1101,60 @@ default_provider: openai
1085
1101
  default_model: gpt-4o
1086
1102
  ```
1087
1103
 
1104
+ ### DSPy Integration
1105
+
1106
+ Tactus provides first-class support for **DSPy Modules and Signatures**, enabling you to build declarative, self-optimizing AI components directly within your agent workflows.
1107
+
1108
+ **Modules & Signatures:**
1109
+
1110
+ Instead of hand-tuning prompts, define what you want the model to do using typed signatures:
1111
+
1112
+ ```lua
1113
+ -- Configure the Language Model for DSPy
1114
+ LM("openai/gpt-4o")
1115
+
1116
+ -- Define a module with a typed signature
1117
+ summarizer = Module {
1118
+ signature = "text -> summary",
1119
+ strategy = "chain_of_thought" -- Use Chain of Thought reasoning
1120
+ }
1121
+
1122
+ -- Or define complex signatures with specific fields
1123
+ classifier = Module {
1124
+ signature = Signature {
1125
+ input = {
1126
+ text = field.string{description = "The customer email to classify"}
1127
+ },
1128
+ output = {
1129
+ category = field.string{description = "Support category (Billing, Tech, Sales)"},
1130
+ priority = field.string{description = "Priority level (Low, High, Critical)"}
1131
+ }
1132
+ },
1133
+ strategy = "predict"
1134
+ }
1135
+ ```
1136
+
1137
+ **Using Modules:**
1138
+
1139
+ Modules are callable just like Agents or Tools:
1140
+
1141
+ ```lua
1142
+ Procedure {
1143
+ function(input)
1144
+ -- Call the module
1145
+ local result = classifier({text = input.email})
1146
+
1147
+ if result.priority == "Critical" then
1148
+ human_escalation({context = result})
1149
+ else
1150
+ auto_responder({category = result.category})
1151
+ end
1152
+ end
1153
+ }
1154
+ ```
1155
+
1156
+ This brings the power of DSPy's programmable LLM interfaces into Tactus's durable, orchestrated environment.
1157
+
1088
1158
  ### Asynchronous Execution
1089
1159
 
1090
1160
  Tactus is built on **async I/O** from the ground up, making it ideal for LLM-based workflows where you spend most of your time waiting for API responses.
@@ -1275,6 +1345,21 @@ Then reference them in your procedure:
1275
1345
  local approved = Human.approve("confirm_publish")
1276
1346
  ```
1277
1347
 
1348
+ **System Alerts:**
1349
+
1350
+ Send alerts to your monitoring infrastructure (Datadog, PagerDuty) directly from the workflow:
1351
+
1352
+ ```lua
1353
+ System.alert({
1354
+ message = "Failure rate exceeded threshold",
1355
+ level = "error", -- info, warning, error, critical
1356
+ context = {
1357
+ current_rate = 0.15,
1358
+ threshold = 0.05
1359
+ }
1360
+ })
1361
+ ```
1362
+
1278
1363
  ### Cost Tracking & Metrics
1279
1364
 
1280
1365
  Tactus provides **comprehensive cost and performance tracking** for all LLM calls. Every agent interaction is monitored with detailed metrics, giving you complete visibility into costs, performance, and behavior.
@@ -1360,20 +1445,37 @@ The AI agent space is crowded. This section explains how Tactus differs from alt
1360
1445
 
1361
1446
  ### DSPy
1362
1447
 
1363
- [DSPy](https://dspy.ai) (Declarative Self-improving Python) treats prompting as a compilation target. You define typed signatures and let optimizers automatically discover effective prompts, few-shot examples, or fine-tuning strategies. DSPy excels at tasks where you have training data and clear metrics—classification, RAG, information extraction—and want to programmatically iterate on prompt quality without manual tuning.
1448
+ [DSPy](https://dspy.ai) (Declarative Self-improving Python) is the engine that powers Tactus's intelligence layer. Tactus integrates DSPy directly, allowing you to define DSPy Modules, Signatures, and Optimizers within your `.tac` files using a clean Lua syntax.
1449
+
1450
+ While DSPy provides the primitives for programming with language models (optimizing prompts, few-shot examples, and reasoning steps), Tactus provides the **orchestration layer** that makes these components production-ready:
1364
1451
 
1365
- Tactus takes a different approach: rather than optimizing prompts automatically, it provides a token-efficient, sandboxed language that serves as a safe platform for user-contributed or AI-generated code. Where DSPy hides control flow behind module composition, Tactus makes it explicit—you write the loops, conditionals, and error handling while agents handle intelligence within each turn.
1452
+ - **Durability**: Tactus handles checkpointing and resuming DSPy module calls transparently.
1453
+ - **Orchestration**: Tactus manages the control flow (loops, conditionals) around your DSPy modules.
1454
+ - **Human-in-the-Loop**: Tactus allows humans to inspect, approve, or correct DSPy module outputs.
1455
+ - **Sandboxing**: Tactus runs DSPy components in a safe, sandboxed environment suitable for user-contributed code.
1456
+
1457
+ You can use Tactus to define standard DSPy modules:
1458
+
1459
+ ```lua
1460
+ -- Define a DSPy Module with a typed signature
1461
+ qa = Module {
1462
+ signature = "question -> answer",
1463
+ strategy = "chain_of_thought"
1464
+ }
1465
+
1466
+ -- Invoke it as part of a durable workflow
1467
+ local result = qa({question = "How does this work?"})
1468
+ ```
1366
1469
 
1367
- The frameworks are complementary: you could use DSPy to optimize the prompts that go into a Tactus agent's `system_prompt`, then use Tactus to orchestrate those optimized agents in a durable, human-in-the-loop workflow.
1470
+ Tactus and DSPy work together: DSPy handles the *thinking* (optimizing how to get the best answer), while Tactus handles the *doing* (ensuring the workflow completes reliably, even if it takes days).
1368
1471
 
1369
- | | DSPy | Tactus |
1370
- |-|------|--------|
1371
- | **Core idea** | Programming, not prompting | Token-efficient, AI-manipulable orchestration language |
1372
- | **Optimization** | Automatic (optimizers) | Manual or agent-driven self-evolution |
1373
- | **Control flow** | Declarative composition | Imperative Lua DSL |
1374
- | **Human-in-the-loop** | Not built-in | First-class citizen |
1375
- | **Durability** | Caching | Checkpointing + replay |
1376
- | **Target** | Researchers optimizing prompts | Engineers building production workflows |
1472
+ | | DSPy (Python) | Tactus (Lua) |
1473
+ |---|---|---|
1474
+ | **Role** | Intelligence Engine | Orchestration Engine |
1475
+ | **Focus** | Prompt optimization, reasoning | Durability, HITL, Sandboxing |
1476
+ | **Definition** | Python classes | Lua DSL primitives |
1477
+ | **State** | In-memory | Persisted & Resumable |
1478
+ | **Optimization** | Automatic (Teleprompters) | Agent-driven or Manual |
1377
1479
 
1378
1480
  ### LangGraph
1379
1481
 
@@ -1409,17 +1511,18 @@ The major AI companies have released their own agent frameworks:
1409
1511
 
1410
1512
  - **[Meta Llama Stack](https://ai.meta.com/blog/meta-llama-3-1/)** — Standardized interfaces for building agentic applications with Llama models. More of an API specification than a workflow framework.
1411
1513
 
1412
- These frameworks are valuable if you're committed to a specific vendor's ecosystem. Tactus is model-agnostic (via Pydantic-AI) and designed to run anywhere—local, cloud, or AWS Lambda Durable Functions.
1514
+ These frameworks are valuable if you're committed to a specific vendor's ecosystem. Tactus is model-agnostic (via [DSPy](https://dspy.ai)) and designed to run anywhere—local, cloud, or AWS Lambda Durable Functions.
1413
1515
 
1414
1516
  ### Other Tools
1415
1517
 
1416
- - **[Pydantic-AI](https://github.com/pydantic/pydantic-ai)** — Type-safe LLM integration that Tactus uses under the hood. Tactus adds orchestration, HITL, and durability on top.
1518
+ - **[Pydantic-AI](https://github.com/pydantic/pydantic-ai)** — Used for type-safe tool definitions and message structures.
1417
1519
 
1418
1520
  - **[Guidance](https://github.com/guidance-ai/guidance)** (Microsoft) — Interleaves constrained generation with control flow. Focuses on token-level control during generation rather than workflow orchestration.
1419
1521
 
1420
1522
  ## Complete Feature List
1421
1523
 
1422
1524
  - **Durable Execution**: Automatic position-based checkpointing for all operations (agent turns, model predictions, sub-procedure calls, HITL interactions) with replay-based recovery—resume from exactly where you left off after crashes, timeouts, or pauses
1525
+ - **DSPy Integration**: First-class support for DSPy Modules and Signatures, enabling declarative machine learning components and prompt optimization alongside agentic workflows
1423
1526
  - **Model Primitive**: First-class support for ML inference (PyTorch, HTTP, HuggingFace Transformers) with automatic checkpointing—distinct from conversational agents for classification, prediction, and transformation tasks
1424
1527
  - **Script Mode**: Write procedures without explicit `main` definitions—top-level `input`/`output` declarations and code automatically wrapped as the main procedure
1425
1528
  - **State Management**: Typed, schema-validated persistent state with automatic initialization from defaults and runtime validation
@@ -1434,7 +1537,7 @@ These frameworks are valuable if you're committed to a specific vendor's ecosyst
1434
1537
  - **Context Engineering**: Fine-grained control over conversation history per agent
1435
1538
  - **Typed Input/Output**: JSON Schema validation with UI generation support using `input`/`output`/`state` declarations
1436
1539
  - **Pluggable Backends**: Storage, HITL, and chat recording via Pydantic protocols
1437
- - **LLM Integration**: Works with OpenAI and Bedrock via [pydantic-ai](https://github.com/pydantic/pydantic-ai)
1540
+ - **LLM Integration**: Works with OpenAI and Bedrock via [DSPy](https://dspy.ai)
1438
1541
  - **Standalone CLI**: Run workflows without any infrastructure
1439
1542
  - **Type-Safe**: Pydantic models throughout for validation and type safety
1440
1543
 
@@ -1,6 +1,6 @@
1
- tactus/__init__.py,sha256=LUJ5Y8-SP4ux74ptueQkyZMMFke1LA8lJOuummuVh3E,1245
1
+ tactus/__init__.py,sha256=8Tz1eNKHHz9MXIcRw6cUoT1NdeOpUm4R4JjXnudVXZE,1245
2
2
  tactus/adapters/__init__.py,sha256=lU8uUxuryFRIpVrn_KeVK7aUhsvOT1tYsuE3FOOIFpI,289
3
- tactus/adapters/broker_log.py,sha256=Eis5yXdrAkPnYYc49PQzOQfIst98CAO_6gVxjgfq0tw,1789
3
+ tactus/adapters/broker_log.py,sha256=mIjARt1Q6ouWVbVri6zep1e8tzm9y28l4WOEdqiK39Q,2849
4
4
  tactus/adapters/cli_hitl.py,sha256=3dH58du0lN4k-OvQrAHrAqHFqBjolqNKFb94JaNHtn8,6964
5
5
  tactus/adapters/cli_log.py,sha256=uyTOLY9y26foAr-8COEYP6dejdO_Huur4i0DLaowfAY,8894
6
6
  tactus/adapters/cost_collector_log.py,sha256=Ha3pFMdC0HJ8eBnZpM1VRLm-94RKelu5PEPDgFgNKow,1701
@@ -16,15 +16,16 @@ tactus/backends/http_backend.py,sha256=D2N91I5bnjhHMLG84-U-BRS-mIuwoQq72Feffi7At
16
16
  tactus/backends/model_backend.py,sha256=P8dCUpDxJmA8_EO1snZuXyIyUZ_BlqReeC6zenO7Kv0,763
17
17
  tactus/backends/pytorch_backend.py,sha256=I7H7UTa_Scx9_FtmPWn-G4noadaNVEQj-9Kjtjpgl6E,3305
18
18
  tactus/broker/__init__.py,sha256=UTvqLofrgE3c4m6u2iNOg5R7BrS4dmfzMRO4Oq_0A9U,396
19
- tactus/broker/client.py,sha256=amN36-MHIjM7Sm-pImTGy9rJsf6rjB_BtxgHAIFxw7s,8983
20
- tactus/broker/server.py,sha256=x7DCf6DpeUSt9wECQTOlPxtNUoCCx9uZzml4RhX2DYo,16138
19
+ tactus/broker/client.py,sha256=sDi1Cimuv0zH5S4n597nnUy_qis7pLBZf5IkwF81oDc,8618
20
+ tactus/broker/protocol.py,sha256=fnVgMKU_R7oK2xBATnrYSH_r2R-yOmV2o_pJYw1JvVk,5238
21
+ tactus/broker/server.py,sha256=ciP6FkPBfenfzrTNzkr6If7kQFs4B7mLU77A0hh7y_8,17154
21
22
  tactus/broker/stdio.py,sha256=JXkEz-PCU3IQXNkt16YJtYmwkR43eS6CfjxAHc-YCfQ,439
22
23
  tactus/cli/__init__.py,sha256=kVhdCkwWEPdt3vn9si-iKvh6M9817aOH6rLSsNzRuyg,80
23
- tactus/cli/app.py,sha256=f7LYPLaplroowGvI3dUnc4xh_wUFwko6EEMpvdqKXFA,83495
24
+ tactus/cli/app.py,sha256=97lrjIQxDGM5PuvPZx9CeTZc0CyT1tBhLOl98oej3zE,83496
24
25
  tactus/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
26
  tactus/core/__init__.py,sha256=TK5rWr3HmOO_igFa5ESGp6teWwS58vnvQhIWqkcgqwk,880
26
27
  tactus/core/config_manager.py,sha256=u90XChTeb2reZ3I6c3o_zI2UlzlFCNtL9-NhE1Vm6L0,31577
27
- tactus/core/dsl_stubs.py,sha256=Q7ASuE3AjBgLNm6s3v6eDEJFWRy_eunl17kd-pcKV-A,67324
28
+ tactus/core/dsl_stubs.py,sha256=-gio8VFQ_8atH3SOPC2s2bimXu1vYZc-I3Z6yJqdhIU,76070
28
29
  tactus/core/exceptions.py,sha256=HruvJQ4yIi78hOvvHviNZolcraMwXrlGQzxHqYFQapA,1468
29
30
  tactus/core/execution_context.py,sha256=WNd55_JhmkDifA9Td3xIs8to5bwGDlCgPcbvkvLYAv0,16658
30
31
  tactus/core/lua_sandbox.py,sha256=WuXRuXSl9ylU0y3ZMvyDWjWiG6GdLVn2csMY-2Zmrbg,18262
@@ -32,15 +33,15 @@ tactus/core/message_history_manager.py,sha256=e3_seV6bWSJVicrZYf2LmaQBvroDXDRc5T
32
33
  tactus/core/mocking.py,sha256=1MKtg8FHCYj-Goihi5b8xNNYo-MDuzSpsHEX_e7bnfg,9217
33
34
  tactus/core/output_validator.py,sha256=a-a_L-8oondMA4dzJMekhlHUF0vA_G_prMdFaBu5vhU,7823
34
35
  tactus/core/registry.py,sha256=1FKjj9wcTbz3VhCBGO6ylSb5WAaN-liLCQFe06nPfU4,20128
35
- tactus/core/runtime.py,sha256=SwrPgg7WfZuhYja25WmTDG3Wmi9mVvkjUQS58WalDvE,121942
36
+ tactus/core/runtime.py,sha256=4iYe9ONVKTNc9QVf2Z2O99ofk_8shUYm0fn6oSwfzAg,122904
36
37
  tactus/core/template_resolver.py,sha256=6zRq4zT1lRHdLoa7M-yoLx4hFZ9RcjH9Y0EdaAtW9FU,4033
37
38
  tactus/core/yaml_parser.py,sha256=s7VB5Nijy6ReQE7ixlmvZArqupXs_sWP4EY4pCLv25k,13400
38
39
  tactus/core/dependencies/__init__.py,sha256=28-TM7_i-JqTD3hvkq1kMzr__A8VjfIKXymdW9mn5NM,362
39
40
  tactus/core/dependencies/registry.py,sha256=bgRdqJJTUrnQlu0wvjv2In1EPq7prZq-b9eBDhE3rmE,6114
40
41
  tactus/docker/Dockerfile,sha256=fnK5kZlgM-L7vboiwfTqcs70OsZsvh1ba4YzRxie138,1887
41
- tactus/docker/entrypoint.sh,sha256=-qYq5RQIGS6KirJ6NO0XiHZf_oAdfmk5HzHOBsiqxRM,1870
42
+ tactus/docker/entrypoint.sh,sha256=pL-1MwMdjD1fGgRZYkBeXmJZg57Knmub9ETLYAANvOg,1985
42
43
  tactus/dspy/__init__.py,sha256=beUkvMUFdPvZE9-bEOfRo2TH-FoCvPT_L9_dpJPW324,1226
43
- tactus/dspy/agent.py,sha256=nY3jATEPuSzYH1b2aSxGgbE1YQ4-YARw6hXs8vd9o0A,42254
44
+ tactus/dspy/agent.py,sha256=-GFvV6d-1ek-IMn-0ML_jFEL2a-2DsEhyKmgpeTdOmQ,43484
44
45
  tactus/dspy/broker_lm.py,sha256=EaXlJcUhfM0NV0fD1rASYKSO5gm846KRS5BoT0iO4zs,6239
45
46
  tactus/dspy/config.py,sha256=B22ON9Zp-dabI4NYeMbZ5lUL4kqihR7FQ8Z8xKT_eL8,6567
46
47
  tactus/dspy/history.py,sha256=0yGi3P5ruRUPoRyaCWsUDeuEYYsfproc_7pMVZuhmUo,5980
@@ -69,7 +70,7 @@ tactus/primitives/state.py,sha256=o3rsz-P8R2O66nsYmXOjn54342NIn6ldqTqp9XvgPLI,56
69
70
  tactus/primitives/step.py,sha256=2STt1M_9R0Ga5YHScA5i1eXqqIDI_S_q9E4GSyWhM2Y,7175
70
71
  tactus/primitives/system.py,sha256=jIzDLuL8a6owTPokAb7giwKYOxEtxmacntkNzzu8BWU,3350
71
72
  tactus/primitives/tool.py,sha256=KppWrbVxPwZ6aRk2Lw5ki1ACwV_65yK2wSFWaH3da88,12643
72
- tactus/primitives/tool_handle.py,sha256=Mxg5obWTeLvpGlKFPtVvUUJ0_AL8-KX2F3kqikhmsng,8987
73
+ tactus/primitives/tool_handle.py,sha256=x6D4Zi-x-werFVBgB-F3mTtIMRbkYjPq3IBjjs8VSTc,9085
73
74
  tactus/primitives/toolset.py,sha256=T9DtULPgDX7CGBnfOtEx6SsKEtJPWrKXMOnHJer_spY,7779
74
75
  tactus/protocols/__init__.py,sha256=w5PFgHq8ov7BbNKcgCmbPSQ_E9l6F8xwrtxEQ2YSWO4,783
75
76
  tactus/protocols/chat_recorder.py,sha256=dswAHpwlxq30GTGKT-ktCIKCaixn5izEMSb7sbiZARE,2074
@@ -86,8 +87,8 @@ tactus/providers/bedrock.py,sha256=cVNDV7uHhCnnL6BNl7DFF8OwkD9ZYqa9CP2wXMcCJGY,3
86
87
  tactus/providers/google.py,sha256=wgZ3eiQif1rq1T8BK5V2kL_QVCmqBQZuWLz37y9cxOQ,3123
87
88
  tactus/providers/openai.py,sha256=3qSXfdELTHdU7vuRSxQrtnfNctt0HhrePOLFj3YlViA,2692
88
89
  tactus/sandbox/__init__.py,sha256=UCBvPD63szvSdwSzpznLW-cnJOgGkVHiKcmJtsAmnuA,1424
89
- tactus/sandbox/config.py,sha256=m4YcvulVun2gVZHeXoOfl0VgpoFnvbmYPhnmavXVp7A,4919
90
- tactus/sandbox/container_runner.py,sha256=drM8FBl7pjfCCm0BE331vGPA_v7KdWEUj2MT8W7Dt6E,38339
90
+ tactus/sandbox/config.py,sha256=KuWtQwxHGVz3P_My5bOvMor3cxZMW8Y-wTLQszXP4Cg,5582
91
+ tactus/sandbox/container_runner.py,sha256=eefK37PoV7hclJdw5uodC32rzuFvNLNDavnob1Wymtk,39561
91
92
  tactus/sandbox/docker_manager.py,sha256=SGv0IEN9usgyQRvbonrgOLm6GICel8ifzBAopAwOyt0,13949
92
93
  tactus/sandbox/entrypoint.py,sha256=Jbw7ZIOhBygiZa-LHoQAbQg4VJBzK_XrN8wnf1xD5xg,6803
93
94
  tactus/sandbox/protocol.py,sha256=1h36423pOFAwwZBgzMkeAIIjan1asgmBiIjN234YlpQ,6060
@@ -102,12 +103,12 @@ tactus/stdlib/io/hdf5.py,sha256=7ELLaQZI1GOsycU1a60J6RTPNLH7EMdaPAYlNx0dQLA,3025
102
103
  tactus/stdlib/io/json.py,sha256=P6C6rIwAxY97MivCanxKF8TmRotIUxBlHcuv8etmLu8,2641
103
104
  tactus/stdlib/io/parquet.py,sha256=hycr0pjqysjhggHx7_UZJL_jkeP1wz8BCozL39EWk-0,2045
104
105
  tactus/stdlib/io/tsv.py,sha256=456V2g-dp0mOTxo0ojM-rQl-LlmeV6WAVh0HmEDd_kQ,2350
105
- tactus/stdlib/tac/tactus/tools/done.tac,sha256=Byl_G_JJafn7qfqvqOM6x17tkkjcl_XkzUjyOqtHPDI,777
106
- tactus/stdlib/tac/tactus/tools/log.tac,sha256=FngGUo9kqUzdVdP9cS1Qd4OqPX5yFtd5wSLp655fui4,1374
106
+ tactus/stdlib/tac/tactus/tools/done.tac,sha256=aCQzwL7SXq-rx18QGq3NLKoT_eweoVRObBkCSu4lkzo,732
107
+ tactus/stdlib/tac/tactus/tools/log.tac,sha256=oRwnKxQZsZPXmZcGABZ6zM4NASV54tGAMClfsX8QNGk,1392
107
108
  tactus/testing/README.md,sha256=8AI-N9Llw0cQPweVkeUctEPsAOUviHrTZb48mF82EDE,7042
108
109
  tactus/testing/__init__.py,sha256=M5b3r9E0vkltfhqfIOSASk-qp6fDnm3FBxc9dDBPUhU,1540
109
110
  tactus/testing/behave_integration.py,sha256=mtAM30Uhj57_raGbPxAyMvfT-vnGnTm01UyeUqyE0H8,14887
110
- tactus/testing/context.py,sha256=2q5iLspN_i2CM1Bsc11JmcayDDcxGFa3EskOZomNMBk,14265
111
+ tactus/testing/context.py,sha256=az7eQi9pZfjIYxIv2j02e9OGPNbr8Hww-UIRCEosvVY,14190
111
112
  tactus/testing/eval_models.py,sha256=UI3geZp4vilbn3Jt4Mjy95luRVON3T4sGnAwlpb7jLo,3540
112
113
  tactus/testing/evaluation_runner.py,sha256=_wemv2yf-N6wjIyhwxVJyoH4FABlKoBv-OKTcgwNm0Q,6908
113
114
  tactus/testing/evaluators.py,sha256=NW_LHhssdMRYCCoYmtJIsst-DEsk8iBVebsxRyHx7I0,20751
@@ -137,7 +138,7 @@ tactus/validation/LuaParserBase.py,sha256=o3klCIY0ANkVCU0VHml0IOYE4CdEledeoyoIAP
137
138
  tactus/validation/README.md,sha256=AS6vr4blY7IKWRsj4wuvWBHVMTc5fto7IgNmv-Rjkdo,5366
138
139
  tactus/validation/__init__.py,sha256=rnap-YvNievWigYYUewuXBcLtAdjZ8YpeJDYS1T7XZM,153
139
140
  tactus/validation/error_listener.py,sha256=ANaQHPzRSGQMgreYqZ4ZvIKGENj55FnrEQYUmqFvGaY,619
140
- tactus/validation/semantic_visitor.py,sha256=ERhrBDQ9kVCtC5QvjpYEHoCXjtiBE4-2gR8-eOUqwuo,36592
141
+ tactus/validation/semantic_visitor.py,sha256=pQ8WV_9kilY7orDbn7YGFTyX4DrcjWfoApxVL1vwqcU,36882
141
142
  tactus/validation/validator.py,sha256=Vut4nWoNVbm1n_RRbdLVLJyBb6S29KjnxXi-SrRQd3Y,4842
142
143
  tactus/validation/generated/LuaLexer.interp,sha256=B-Xb6HNXS7YYYQB_cvsWzf8OQLFnEhZHDN5vCOyP3yw,20444
143
144
  tactus/validation/generated/LuaLexer.py,sha256=6B-HNB_vAp3bA5iACLvMWw0R4KFENsuiG7bccysxbRQ,67252
@@ -151,8 +152,8 @@ tactus/validation/generated/LuaParserVisitor.py,sha256=ageKSmHPxnO3jBS2fBtkmYBOd
151
152
  tactus/validation/generated/__init__.py,sha256=5gWlwRI0UvmHw2fnBpj_IG6N8oZeabr5tbj1AODDvjc,196
152
153
  tactus/validation/grammar/LuaLexer.g4,sha256=t2MXiTCr127RWAyQGvamkcU_m4veqPzSuHUtAKwalw4,2771
153
154
  tactus/validation/grammar/LuaParser.g4,sha256=ceZenb90BdiZmVdOxMGj9qJk3QbbWVZe5HUqPgoePfY,3202
154
- tactus-0.27.0.dist-info/METADATA,sha256=aKGvCAKYFROL_2iq5UiWVLSGyoxbO6EWp5HROpUNsYI,55752
155
- tactus-0.27.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
156
- tactus-0.27.0.dist-info/entry_points.txt,sha256=vWseqty8m3z-Worje0IYxlioMjPDCoSsm0AtY4GghBY,47
157
- tactus-0.27.0.dist-info/licenses/LICENSE,sha256=ivohBcAIYnaLPQ-lKEeCXSMvQUVISpQfKyxHBHoa4GA,1066
158
- tactus-0.27.0.dist-info/RECORD,,
155
+ tactus-0.28.0.dist-info/METADATA,sha256=hvZRdVInGcwogSbsULPG4vXf4hNUCAQrT6ByzL6f0VM,58441
156
+ tactus-0.28.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
157
+ tactus-0.28.0.dist-info/entry_points.txt,sha256=vWseqty8m3z-Worje0IYxlioMjPDCoSsm0AtY4GghBY,47
158
+ tactus-0.28.0.dist-info/licenses/LICENSE,sha256=ivohBcAIYnaLPQ-lKEeCXSMvQUVISpQfKyxHBHoa4GA,1066
159
+ tactus-0.28.0.dist-info/RECORD,,