roboshed 0.1.1.dev2__tar.gz → 0.1.1.dev3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/CHANGELOG.md +38 -0
  2. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/PKG-INFO +116 -28
  3. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/README.md +114 -26
  4. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/pyproject.toml +2 -2
  5. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/capabilities.py +14 -10
  6. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/dependency_health.py +35 -134
  7. roboshed-0.1.1.dev3/src/roboshed/deployments/robosprawl.py +77 -0
  8. roboshed-0.1.1.dev3/src/roboshed/tools/__init__.py +48 -0
  9. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/apply_patch.py +8 -20
  10. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/run_file_command/command.py +13 -6
  11. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/run_file_command/resolve.py +3 -19
  12. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/utilities/formatting.py +3 -3
  13. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/compactification/__init__.py +4 -0
  14. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/compactification/compactify_messages.py +5 -21
  15. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/compactification/summarize.py +1 -1
  16. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/consolidate_memory.py +5 -24
  17. roboshed-0.1.1.dev3/src/roboshed/tools/contexts.py +162 -0
  18. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/__init__.py +3 -0
  19. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/contracts.py +25 -5
  20. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/drafts.py +10 -21
  21. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/factory.py +13 -14
  22. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/messages.py +5 -10
  23. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/runtime.py +2 -11
  24. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/guard.py +5 -14
  25. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/guard_formatting.py +2 -2
  26. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/purge_files.py +8 -11
  27. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/runner.py +4 -11
  28. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/sleep_between_runs.py +5 -12
  29. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/snapshot_conversations.py +6 -25
  30. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/memory/test_consolidate_memory.py +3 -3
  31. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/memory/test_librarian.py +20 -5
  32. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/memory/test_purge_files.py +2 -2
  33. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/memory/test_snapshot_conversations.py +3 -3
  34. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/memory/test_summarize_conversation.py +17 -2
  35. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_build_guarded_tool_chain.py +3 -3
  36. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_capabilities.py +25 -40
  37. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_cli_command_utils.py +1 -1
  38. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_compactify_messages.py +4 -3
  39. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_compaction_runtime.py +23 -27
  40. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_dependency_health.py +128 -93
  41. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_email_factory.py +78 -0
  42. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_generic_guards.py +4 -3
  43. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_guard.py +3 -3
  44. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_robosprawl.py +105 -104
  45. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_sandbox.py +4 -10
  46. roboshed-0.1.1.dev3/tests/test_tool_contexts.py +120 -0
  47. roboshed-0.1.1.dev2/src/roboshed/deployments/robosprawl.py +0 -128
  48. roboshed-0.1.1.dev2/src/roboshed/tools/__init__.py +0 -21
  49. roboshed-0.1.1.dev2/tests/test_dependency_inspection.py +0 -123
  50. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/.gitignore +0 -0
  51. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/LICENSE +0 -0
  52. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/__init__.py +0 -0
  53. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/agents/__init__.py +0 -0
  54. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/agents/librarian.py +0 -0
  55. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/agents/orchestrator.py +0 -0
  56. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/deployments/__init__.py +0 -0
  57. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/identifiers.py +0 -0
  58. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/models.py +0 -0
  59. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/py.typed +0 -0
  60. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/sandbox.py +0 -0
  61. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/skills/__init__.py +0 -0
  62. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/skills/cli_tools/__init__.py +0 -0
  63. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/skills/cli_tools/prompts.py +0 -0
  64. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/skills/email_tools/__init__.py +0 -0
  65. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/skills/email_tools/prompts.py +0 -0
  66. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/skills/file_editing/__init__.py +0 -0
  67. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/skills/file_editing/prompts.py +0 -0
  68. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/skills/robosprawl.py +0 -0
  69. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/_snapshot_metadata.py +0 -0
  70. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/__init__.py +0 -0
  71. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/run_file_command/__init__.py +0 -0
  72. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/run_file_command/specs.py +0 -0
  73. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/utilities/__init__.py +0 -0
  74. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/utilities/cmd_spec.py +0 -0
  75. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/utilities/constants.py +0 -0
  76. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/utilities/path_extractors.py +0 -0
  77. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/compactification/prompts.py +0 -0
  78. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/compactification/summary_prompts.py +0 -0
  79. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/consolidate_memory_example.py +0 -0
  80. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/consolidate_memory_prompts.py +0 -0
  81. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/inputs.py +0 -0
  82. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/librarian_errors.py +0 -0
  83. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/memory_files.py +0 -0
  84. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/snapshot_conversation_example.py +0 -0
  85. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/snapshot_conversation_prompts.py +0 -0
  86. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/snapshot_normalize.py +0 -0
  87. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/truncation.py +0 -0
  88. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/types.py +0 -0
  89. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/src/roboshed/tools/utils.py +0 -0
  90. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/memory/test_memory_prompts.py +0 -0
  91. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_agent_deployment.py +0 -0
  92. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_agent_presets.py +0 -0
  93. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_apply_patch.py +0 -0
  94. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_cli_command_chaining.py +0 -0
  95. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_cli_tools_prompt_examples.py +0 -0
  96. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_deployment_graph.py +0 -0
  97. {roboshed-0.1.1.dev2 → roboshed-0.1.1.dev3}/tests/test_path_extractors.py +0 -0
@@ -2,6 +2,44 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.1.1.dev3 - 2026-09-13
6
+
7
+ - Migrate capability bindings to the central typed contexts. Existing capability
8
+ arguments, owner configuration, endpoint overrides, defaults, and maintenance
9
+ order are preserved. Each build creates fresh tool state and reports actual
10
+ resources without initializing model clients. The RoboSprawl recipe now uses
11
+ `LLMEndpointRoute` for the selectable orchestrator while its Librarian endpoint
12
+ remains fixed.
13
+
14
+ - Breaking: email factories now use the central `EmailContext`; attachment
15
+ resolvers bind a `Path` directly. `get_work_with_email` keeps its arguments and
16
+ requires a complete `EmailService`, which now inherits `ExternalDependency`
17
+ and implements `check()` using its read-only probe. Email dependencies are
18
+ inspectable without mailbox access and can be monitored without an agent.
19
+ Mailbox operations, permission checks, defaults, and error messages are preserved.
20
+ See the [context migration guide](../../docs/shed-tool-contexts.md#email-services-and-contexts).
21
+
22
+ - Breaking: bind built-in file and maintenance factories to concrete typed contexts
23
+ instead of `Ctx`; direct patch stages accept a `Path` or `TruncationSpec`.
24
+ Existing `get_*` helper arguments remain supported. Command and summary contexts
25
+ report their actual resources through `tool.external_dependencies()`. Compaction
26
+ counters belong to the context: rebinding/copying shares them; constructing a new
27
+ context creates fresh state. See the [tool-context migration](../../docs/shed-tool-contexts.md).
28
+
29
+ - Breaking: remove callback-based `inspect_dependencies`; inspect the configured
30
+ `DeployableAgent.external_dependencies()` instead; it constructs unstarted
31
+ agents using normal capability builders, without temporary sandbox isolation.
32
+ The health monitor accepts the resulting resources together with standalone
33
+ dependencies such as selectable models, deduplicating the combined sequence. Each resource owns its
34
+ synchronous `check() -> bool`; remove checker registrations and replace the
35
+ three category-specific probe helpers with `check_dependency(resource)` when
36
+ a sanitized observation is needed. Timeout, concurrency, metadata filtering,
37
+ and cached health-record behavior remain unchanged. See the README health guide.
38
+
39
+ - Breaking: replace the setter-based `RoboSprawl` class with `robosprawl(sandbox, ...)`.
40
+ Supply deployment choices directly and unpack the returned root/background
41
+ agents. See [the recipe guide](../../docs/agent-factories.md).
42
+
5
43
  ## 0.1.1.dev2 - 2026-09-12
6
44
 
7
45
  - Breaking: move permission, sandbox, watched-agent, and default model inputs
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: roboshed
3
- Version: 0.1.1.dev2
3
+ Version: 0.1.1.dev3
4
4
  Import-Name: roboshed
5
5
  Summary: roboshed: optional building blocks for Roboz
6
6
  Project-URL: Repository, https://github.com/Tachion-Oy/roboz
@@ -11,7 +11,7 @@ Classifier: Development Status :: 2 - Pre-Alpha
11
11
  Classifier: Typing :: Typed
12
12
  Requires-Python: >=3.13
13
13
  Requires-Dist: pydantic>=2.12.4
14
- Requires-Dist: roboz<0.2.0,>=0.1.2.dev4
14
+ Requires-Dist: roboz<0.2.0,>=0.1.2.dev5
15
15
  Description-Content-Type: text/markdown
16
16
 
17
17
  # roboshed
@@ -65,29 +65,30 @@ role definitions.
65
65
  Each capability declares the typed attributes it reads from its owning
66
66
  `DeployableAgent`. Runtime controls remain separate. Use `set_attributes()` to
67
67
  supply standalone permission policies and sandbox inputs before building.
68
+ Capability builders construct the central typed tool contexts; each build gets
69
+ fresh runtime state while retaining the selected endpoint objects. Build-based
70
+ resource inspection uses those tools without initializing model clients.
68
71
 
69
72
  See the [factory and migration guide](../../docs/agent-factories.md).
70
73
 
71
74
  ## RoboSprawl deployment recipe
72
75
 
73
- `roboshed.deployments.robosprawl.RoboSprawl` is the concrete lazy persistent
74
- orchestrator and Librarian recipe. Construct `RoboSprawl()` without inputs;
75
- supply the required scoped sandbox, endpoint getter, and memory endpoint with
76
- `set_sandbox()`, `set_endpoint_getter()`, and `set_memory_endpoint()`.
77
- `set_additional_capabilities()`, `set_specialists()`, `set_interaction_mode()`,
78
- and `set_event_sinks()` supply optional inputs (empty sequences and
79
- `interaction_mode=None` by default). A `None` mode inherits core's current output
80
- setting, falling back to CLI when none is bound. Argument-free `build()` returns
81
- a fresh root/background-agent tuple
82
- or reports missing required inputs. `robosprawl` is an alias for this class.
76
+ The recipe still requires migration to the concrete endpoint contract in this
77
+ branch; importing it currently fails on the removed lazy-reference API. The
78
+ standalone `orchestrator` and `librarian` constructors and their capabilities are
79
+ migrated. The description below records the recipe behavior to preserve.
80
+
81
+ `roboshed.deployments.robosprawl.robosprawl` is the concrete lazy persistent
82
+ orchestrator and Librarian recipe. Call it with an already-scoped sandbox,
83
+ `endpoint_getter`, `memory_endpoint`, `additional_capabilities`, `specialists`,
84
+ `interaction_mode`, and optional `event_sinks`. It returns a fresh root and
85
+ background-agent tuple.
83
86
 
84
87
  The recipe loads project memory and supplies project locations through initial
85
88
  messages. Its root follows the selected model getter; the Librarian uses its
86
- separate memory endpoint. Configuration and building start no agents or provider
87
- clients and create no project directories. Use a fresh recipe per new run;
88
- setters snapshot the sandbox and sequence containers, while supplied endpoints
89
- and capability/child objects remain caller-owned. The application owns scope
90
- selection and runtime lifecycle. See the [migration example](../../docs/agent-factories.md#fixed-robosprawl-recipe).
89
+ separate memory endpoint. Construction starts no agents and creates no
90
+ directories before the build requires its persistence sinks. The application
91
+ owns scope selection and runtime lifecycle.
91
92
 
92
93
  ## Conversation compaction
93
94
 
@@ -108,8 +109,9 @@ Include this tool in an agent's `default_tools` and pass that agent's owning
108
109
  `system_prompt` and `skill_message` override the full continuation instructions.
109
110
  The tool preserves the contiguous bootstrap prefix and folds the remaining
110
111
  history, including previous summaries, into a new continuation message. Its
111
- status also carries the summary for event persistence. Each constructed tool
112
- owns its compaction count; constructing one per agent keeps counters independent.
112
+ status also carries the summary for event persistence. Each capability build
113
+ creates a fresh compaction context; tools copied or rebound to that context share
114
+ its count, while separate builds keep counters independent.
113
115
 
114
116
  Successful status reports describe the compacted history's current usage and
115
117
  headroom. Summaries are budgeted below the configured threshold and endpoint
@@ -132,12 +134,12 @@ memory pipeline; core provides the mechanisms they use.
132
134
 
133
135
  ## Context API migration
134
136
 
135
- Low-level tool factories now use `roboz.Ctx(**values)` directly, with service,
136
- endpoint, and executable objects supplied without wrappers. The specialized
137
- context classes have been removed. Existing tool builders retain their keyword
138
- arguments, defaults, permission checks, cancellation, and timeout behavior.
139
- See the [migration guide](https://github.com/Tachion-Oy/roboz/blob/main/docs/context-migration.md)
140
- for low-level context fields and state ownership.
137
+ Low-level tool factories use concrete context classes from `roboshed.tools`.
138
+ Their typed constructors own required fields, defaults, validation, and fresh
139
+ state. Direct resources such as endpoints may also be factory contexts. Existing
140
+ tool builders retain their keyword arguments, permission checks, cancellation,
141
+ and timeout behavior. See the
142
+ [context guide](../../docs/shed-tool-contexts.md) for the complete mapping.
141
143
 
142
144
 
143
145
  ## Deployable agent graphs
@@ -177,9 +179,10 @@ capabilities, and sinks remain caller-owned. No execution state is retained on
177
179
  the definition. The old deployment wrapper, factories, host protocols, and
178
180
  result bundles are removed.
179
181
  Use core's `roboz.llm.ModelSelector` for lazy model selection.
180
- `roboz.dependencies` supplies exact dependency registration and binding;
181
- `roboshed.dependency_health` supplies isolated `inspect_dependencies`, probes,
182
- and monitoring without a web framework or provider SDK.
182
+ `roboz.dependencies` supplies the resource contract and ordered deduplication.
183
+ `DeployableAgent.external_dependencies()` builds an unstarted graph and inspects
184
+ its resources. `roboshed.dependency_health` monitors resource-owned checks without a
185
+ web framework or provider SDK.
183
186
  Permission policies treat configured folder names literally. Health scheduling
184
187
  retries observation failures; timed-out workers retain their concurrency slots
185
188
  until completion.
@@ -190,3 +193,88 @@ HUD file-link/markdown contract. The external RoboSprawl application may select
190
193
  it through `Capability(auto_loaded_skills=(robosprawl,))`. Concrete paths,
191
194
  endpoints, extra capabilities, and specialist definitions remain application
192
195
  choices. The `robosprawl` recipe assembles and builds a fresh agent graph.
196
+
197
+
198
+ ## Dependency health
199
+
200
+ Call `definition.external_dependencies()` on the configured `DeployableAgent`.
201
+ It constructs fresh agents without event sinks and delegates to their existing
202
+ tool dependency inspection, including foreground and background descendants and
203
+ unloaded skills. It returns a deduplicated `tuple[ExternalDependency, ...]` and
204
+ does not invoke agents or request endpoint initialization or availability checks.
205
+ Capability builders run normally, including any construction effects they own.
206
+
207
+ The former `inspect_dependencies` callback helper and its temporary sandbox are
208
+ removed. The optional definition method requires configuration sufficient for
209
+ normal construction; the monitor never calls it automatically. Agents do not need
210
+ to be running. Existing runtime agents can still be inspected directly. If inputs
211
+ are substituted for discovery, they must produce the resource declarations used
212
+ by the actual deployment.
213
+
214
+ The monitor accepts resources independently of agents. Combine agent resources
215
+ with other resources explicitly, for example:
216
+
217
+ ```python
218
+ monitor = DependencyHealthMonitor((
219
+ *definition.external_dependencies(),
220
+ *selectable_models,
221
+ transcription_endpoint,
222
+ ))
223
+ ```
224
+
225
+ Here `selectable_models` is a sequence of concrete `LLMEndpoint` objects; they need
226
+ not be attached to an agent or selected yet. The monitor keeps the first resource
227
+ for each dependency ID across the combined sequence. Resources are captured when
228
+ the monitor is constructed; create a new monitor if the resource set changes.
229
+
230
+ Pass those resources directly to `DependencyHealthMonitor(resources)`. Its
231
+ constructor creates pending records without performing checks. Explicit
232
+ `run_once()` or scheduled observation calls each resource's synchronous
233
+ `check() -> bool` in a worker thread. Checks own their service-specific behavior
234
+ and any required client initialization; the monitor supplies bounded concurrency,
235
+ timeouts, scheduling, and cached observations.
236
+
237
+ ```python
238
+ import asyncio
239
+ import sys
240
+
241
+ from roboz.dependencies import ExecutableDependency
242
+ from roboshed.dependency_health import DependencyHealthMonitor, DependencyStatus
243
+
244
+ program = ExecutableDependency(sys.executable)
245
+ monitor = DependencyHealthMonitor((program,))
246
+ assert monitor.records()[0].status is DependencyStatus.PENDING
247
+ asyncio.run(monitor.run_once())
248
+ assert monitor.records()[0].status is DependencyStatus.AVAILABLE
249
+ ```
250
+
251
+ `check_dependency(resource)` performs one synchronous check and returns a
252
+ `DependencyCheckResult`: `True` means available, `False` becomes `model_unavailable`
253
+ for models or `not_found` for other resources, and exceptions become sanitized
254
+ reason codes. Other return values produce `protocol_error`. Provider exception
255
+ payloads are not exposed through records. Record schemas and metadata filtering
256
+ are unchanged. Async checker callbacks and registration records are removed;
257
+ implement the synchronous method on the resource instead.
258
+
259
+ Replace `check_executable`, `check_openai_compatible_endpoint`, and
260
+ `check_network_service` with `check_dependency` when a sanitized health result
261
+ is needed, or use `resource.check()` for the primitive boolean/exception contract.
262
+ The old helper names have no compatibility aliases. Capability bindings and the
263
+ RoboSprawl deployment recipe now use the concrete context and endpoint contracts.
264
+
265
+ ## Concrete tool contexts
266
+
267
+ File-command, guard, editing, maintenance, and email factories now use concrete context
268
+ classes exported from `roboshed.tools`. Existing `get_run_file_command`,
269
+ `get_apply_patch`, and `get_compactify_messages_when_needed_tool` keyword arguments
270
+ are retained. Direct factory users should follow the
271
+ [context migration guide](../../docs/shed-tool-contexts.md), including the context
272
+ ownership rules for compaction counters. Command and summary resources are
273
+ reported through `tool.external_dependencies()` without running external work.
274
+
275
+
276
+ Email contexts live in the same module. `get_work_with_email` keeps its existing
277
+ arguments; direct email execution uses `EmailContext`, and attachment resolvers
278
+ accept `Path`. `EmailService` defines every provider operation and the resource
279
+ identity/metadata contract. Its availability check calls the existing read-only
280
+ probe. See the [email context contract](../../docs/shed-tool-contexts.md#email-services-and-contexts).
@@ -49,29 +49,30 @@ role definitions.
49
49
  Each capability declares the typed attributes it reads from its owning
50
50
  `DeployableAgent`. Runtime controls remain separate. Use `set_attributes()` to
51
51
  supply standalone permission policies and sandbox inputs before building.
52
+ Capability builders construct the central typed tool contexts; each build gets
53
+ fresh runtime state while retaining the selected endpoint objects. Build-based
54
+ resource inspection uses those tools without initializing model clients.
52
55
 
53
56
  See the [factory and migration guide](../../docs/agent-factories.md).
54
57
 
55
58
  ## RoboSprawl deployment recipe
56
59
 
57
- `roboshed.deployments.robosprawl.RoboSprawl` is the concrete lazy persistent
58
- orchestrator and Librarian recipe. Construct `RoboSprawl()` without inputs;
59
- supply the required scoped sandbox, endpoint getter, and memory endpoint with
60
- `set_sandbox()`, `set_endpoint_getter()`, and `set_memory_endpoint()`.
61
- `set_additional_capabilities()`, `set_specialists()`, `set_interaction_mode()`,
62
- and `set_event_sinks()` supply optional inputs (empty sequences and
63
- `interaction_mode=None` by default). A `None` mode inherits core's current output
64
- setting, falling back to CLI when none is bound. Argument-free `build()` returns
65
- a fresh root/background-agent tuple
66
- or reports missing required inputs. `robosprawl` is an alias for this class.
60
+ The recipe still requires migration to the concrete endpoint contract in this
61
+ branch; importing it currently fails on the removed lazy-reference API. The
62
+ standalone `orchestrator` and `librarian` constructors and their capabilities are
63
+ migrated. The description below records the recipe behavior to preserve.
64
+
65
+ `roboshed.deployments.robosprawl.robosprawl` is the concrete lazy persistent
66
+ orchestrator and Librarian recipe. Call it with an already-scoped sandbox,
67
+ `endpoint_getter`, `memory_endpoint`, `additional_capabilities`, `specialists`,
68
+ `interaction_mode`, and optional `event_sinks`. It returns a fresh root and
69
+ background-agent tuple.
67
70
 
68
71
  The recipe loads project memory and supplies project locations through initial
69
72
  messages. Its root follows the selected model getter; the Librarian uses its
70
- separate memory endpoint. Configuration and building start no agents or provider
71
- clients and create no project directories. Use a fresh recipe per new run;
72
- setters snapshot the sandbox and sequence containers, while supplied endpoints
73
- and capability/child objects remain caller-owned. The application owns scope
74
- selection and runtime lifecycle. See the [migration example](../../docs/agent-factories.md#fixed-robosprawl-recipe).
73
+ separate memory endpoint. Construction starts no agents and creates no
74
+ directories before the build requires its persistence sinks. The application
75
+ owns scope selection and runtime lifecycle.
75
76
 
76
77
  ## Conversation compaction
77
78
 
@@ -92,8 +93,9 @@ Include this tool in an agent's `default_tools` and pass that agent's owning
92
93
  `system_prompt` and `skill_message` override the full continuation instructions.
93
94
  The tool preserves the contiguous bootstrap prefix and folds the remaining
94
95
  history, including previous summaries, into a new continuation message. Its
95
- status also carries the summary for event persistence. Each constructed tool
96
- owns its compaction count; constructing one per agent keeps counters independent.
96
+ status also carries the summary for event persistence. Each capability build
97
+ creates a fresh compaction context; tools copied or rebound to that context share
98
+ its count, while separate builds keep counters independent.
97
99
 
98
100
  Successful status reports describe the compacted history's current usage and
99
101
  headroom. Summaries are budgeted below the configured threshold and endpoint
@@ -116,12 +118,12 @@ memory pipeline; core provides the mechanisms they use.
116
118
 
117
119
  ## Context API migration
118
120
 
119
- Low-level tool factories now use `roboz.Ctx(**values)` directly, with service,
120
- endpoint, and executable objects supplied without wrappers. The specialized
121
- context classes have been removed. Existing tool builders retain their keyword
122
- arguments, defaults, permission checks, cancellation, and timeout behavior.
123
- See the [migration guide](https://github.com/Tachion-Oy/roboz/blob/main/docs/context-migration.md)
124
- for low-level context fields and state ownership.
121
+ Low-level tool factories use concrete context classes from `roboshed.tools`.
122
+ Their typed constructors own required fields, defaults, validation, and fresh
123
+ state. Direct resources such as endpoints may also be factory contexts. Existing
124
+ tool builders retain their keyword arguments, permission checks, cancellation,
125
+ and timeout behavior. See the
126
+ [context guide](../../docs/shed-tool-contexts.md) for the complete mapping.
125
127
 
126
128
 
127
129
  ## Deployable agent graphs
@@ -161,9 +163,10 @@ capabilities, and sinks remain caller-owned. No execution state is retained on
161
163
  the definition. The old deployment wrapper, factories, host protocols, and
162
164
  result bundles are removed.
163
165
  Use core's `roboz.llm.ModelSelector` for lazy model selection.
164
- `roboz.dependencies` supplies exact dependency registration and binding;
165
- `roboshed.dependency_health` supplies isolated `inspect_dependencies`, probes,
166
- and monitoring without a web framework or provider SDK.
166
+ `roboz.dependencies` supplies the resource contract and ordered deduplication.
167
+ `DeployableAgent.external_dependencies()` builds an unstarted graph and inspects
168
+ its resources. `roboshed.dependency_health` monitors resource-owned checks without a
169
+ web framework or provider SDK.
167
170
  Permission policies treat configured folder names literally. Health scheduling
168
171
  retries observation failures; timed-out workers retain their concurrency slots
169
172
  until completion.
@@ -174,3 +177,88 @@ HUD file-link/markdown contract. The external RoboSprawl application may select
174
177
  it through `Capability(auto_loaded_skills=(robosprawl,))`. Concrete paths,
175
178
  endpoints, extra capabilities, and specialist definitions remain application
176
179
  choices. The `robosprawl` recipe assembles and builds a fresh agent graph.
180
+
181
+
182
+ ## Dependency health
183
+
184
+ Call `definition.external_dependencies()` on the configured `DeployableAgent`.
185
+ It constructs fresh agents without event sinks and delegates to their existing
186
+ tool dependency inspection, including foreground and background descendants and
187
+ unloaded skills. It returns a deduplicated `tuple[ExternalDependency, ...]` and
188
+ does not invoke agents or request endpoint initialization or availability checks.
189
+ Capability builders run normally, including any construction effects they own.
190
+
191
+ The former `inspect_dependencies` callback helper and its temporary sandbox are
192
+ removed. The optional definition method requires configuration sufficient for
193
+ normal construction; the monitor never calls it automatically. Agents do not need
194
+ to be running. Existing runtime agents can still be inspected directly. If inputs
195
+ are substituted for discovery, they must produce the resource declarations used
196
+ by the actual deployment.
197
+
198
+ The monitor accepts resources independently of agents. Combine agent resources
199
+ with other resources explicitly, for example:
200
+
201
+ ```python
202
+ monitor = DependencyHealthMonitor((
203
+ *definition.external_dependencies(),
204
+ *selectable_models,
205
+ transcription_endpoint,
206
+ ))
207
+ ```
208
+
209
+ Here `selectable_models` is a sequence of concrete `LLMEndpoint` objects; they need
210
+ not be attached to an agent or selected yet. The monitor keeps the first resource
211
+ for each dependency ID across the combined sequence. Resources are captured when
212
+ the monitor is constructed; create a new monitor if the resource set changes.
213
+
214
+ Pass those resources directly to `DependencyHealthMonitor(resources)`. Its
215
+ constructor creates pending records without performing checks. Explicit
216
+ `run_once()` or scheduled observation calls each resource's synchronous
217
+ `check() -> bool` in a worker thread. Checks own their service-specific behavior
218
+ and any required client initialization; the monitor supplies bounded concurrency,
219
+ timeouts, scheduling, and cached observations.
220
+
221
+ ```python
222
+ import asyncio
223
+ import sys
224
+
225
+ from roboz.dependencies import ExecutableDependency
226
+ from roboshed.dependency_health import DependencyHealthMonitor, DependencyStatus
227
+
228
+ program = ExecutableDependency(sys.executable)
229
+ monitor = DependencyHealthMonitor((program,))
230
+ assert monitor.records()[0].status is DependencyStatus.PENDING
231
+ asyncio.run(monitor.run_once())
232
+ assert monitor.records()[0].status is DependencyStatus.AVAILABLE
233
+ ```
234
+
235
+ `check_dependency(resource)` performs one synchronous check and returns a
236
+ `DependencyCheckResult`: `True` means available, `False` becomes `model_unavailable`
237
+ for models or `not_found` for other resources, and exceptions become sanitized
238
+ reason codes. Other return values produce `protocol_error`. Provider exception
239
+ payloads are not exposed through records. Record schemas and metadata filtering
240
+ are unchanged. Async checker callbacks and registration records are removed;
241
+ implement the synchronous method on the resource instead.
242
+
243
+ Replace `check_executable`, `check_openai_compatible_endpoint`, and
244
+ `check_network_service` with `check_dependency` when a sanitized health result
245
+ is needed, or use `resource.check()` for the primitive boolean/exception contract.
246
+ The old helper names have no compatibility aliases. Capability bindings and the
247
+ RoboSprawl deployment recipe now use the concrete context and endpoint contracts.
248
+
249
+ ## Concrete tool contexts
250
+
251
+ File-command, guard, editing, maintenance, and email factories now use concrete context
252
+ classes exported from `roboshed.tools`. Existing `get_run_file_command`,
253
+ `get_apply_patch`, and `get_compactify_messages_when_needed_tool` keyword arguments
254
+ are retained. Direct factory users should follow the
255
+ [context migration guide](../../docs/shed-tool-contexts.md), including the context
256
+ ownership rules for compaction counters. Command and summary resources are
257
+ reported through `tool.external_dependencies()` without running external work.
258
+
259
+
260
+ Email contexts live in the same module. `get_work_with_email` keeps its existing
261
+ arguments; direct email execution uses `EmailContext`, and attachment resolvers
262
+ accept `Path`. `EmailService` defines every provider operation and the resource
263
+ identity/metadata contract. Its availability check calls the existing read-only
264
+ probe. See the [email context contract](../../docs/shed-tool-contexts.md#email-services-and-contexts).
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "roboshed"
3
- version = "0.1.1.dev2"
3
+ version = "0.1.1.dev3"
4
4
  description = "roboshed: optional building blocks for Roboz"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -9,7 +9,7 @@ license = "Apache-2.0"
9
9
  license-files = ["LICENSE"]
10
10
  import-names = ["roboshed"]
11
11
  classifiers = ["Development Status :: 2 - Pre-Alpha", "Typing :: Typed"]
12
- dependencies = ["roboz>=0.1.2.dev4,<0.2.0","pydantic>=2.12.4"]
12
+ dependencies = ["roboz>=0.1.2.dev5,<0.2.0","pydantic>=2.12.4"]
13
13
 
14
14
  [build-system]
15
15
  requires = ["hatchling>=1.32"]
@@ -25,11 +25,16 @@ from roboshed.tools.compactification import (
25
25
  DEFAULT_THRESHOLD_PERCENT,
26
26
  )
27
27
  from roboshed.tools.consolidate_memory import consolidate_memory
28
+ from roboshed.tools.contexts import (
29
+ ConsolidateMemoryContext,
30
+ PurgeFilesContext,
31
+ SleepBetweenRunsContext,
32
+ SnapshotConversationsContext,
33
+ )
28
34
  from roboshed.tools.purge_files import purge_files
29
35
  from roboshed.tools.sleep_between_runs import sleep_between_runs
30
36
  from roboshed.tools.snapshot_conversations import snapshot_conversations
31
37
  from roboshed.sandbox import PermissionPolicy, Sandbox
32
- from roboz.dependencies import ExternalDependencyReference
33
38
  from roboz.deployment import (
34
39
  AgentCapability,
35
40
  Capability,
@@ -37,12 +42,11 @@ from roboz.deployment import (
37
42
  RequiredAttributeType,
38
43
  RequiredAttributes,
39
44
  )
40
- from roboz.llm import EndpointLike, LLMEndpoint, MockLLMEndpoint
45
+ from roboz.llm import EndpointLike, LLMEndpoint, LLMEndpointRoute, MockLLMEndpoint
41
46
  from roboz.runtime import EventPipe
42
- from roboz.tooling.context import Ctx
43
47
 
44
48
 
45
- _ENDPOINT_TYPES = (LLMEndpoint, MockLLMEndpoint, ExternalDependencyReference)
49
+ _ENDPOINT_TYPES = (LLMEndpoint, MockLLMEndpoint, LLMEndpointRoute)
46
50
  _AGENT_ENDPOINT_REQUIRED: RequiredAttributes = {
47
51
  "agent_endpoint": _ENDPOINT_TYPES,
48
52
  }
@@ -174,7 +178,7 @@ class ConversationSnapshots(AgentCapability):
174
178
  return Capability(
175
179
  default_tools=(
176
180
  snapshot_conversations(
177
- Ctx(
181
+ SnapshotConversationsContext(
178
182
  endpoint=endpoint,
179
183
  conversation_root=sandbox.project_logs_dir(),
180
184
  snapshot_root=sandbox.project_snapshots_dir(),
@@ -241,7 +245,7 @@ class MemoryConsolidation(AgentCapability):
241
245
  return Capability(
242
246
  default_tools=(
243
247
  consolidate_memory(
244
- Ctx(
248
+ ConsolidateMemoryContext(
245
249
  endpoint=endpoint,
246
250
  snapshot_root=sandbox.project_snapshots_dir(),
247
251
  memory_root=sandbox.project_memory_dir(),
@@ -278,14 +282,14 @@ class ArtifactRetention(AgentCapability):
278
282
  return Capability(
279
283
  default_tools=(
280
284
  purge_files(
281
- Ctx(
285
+ PurgeFilesContext(
282
286
  folders=[sandbox.project_logs_dir()],
283
287
  pattern="*.json",
284
288
  max_files=self.max_log_files,
285
289
  )
286
290
  ).copy(name=PURGE_LOGS_TOOL_NAME),
287
291
  purge_files(
288
- Ctx(
292
+ PurgeFilesContext(
289
293
  folders=[sandbox.project_snapshots_dir()],
290
294
  pattern="*.md",
291
295
  max_files=self.max_snapshot_files,
@@ -293,7 +297,7 @@ class ArtifactRetention(AgentCapability):
293
297
  )
294
298
  ).copy(name=PURGE_SNAPSHOTS_TOOL_NAME),
295
299
  purge_files(
296
- Ctx(
300
+ PurgeFilesContext(
297
301
  folders=[sandbox.project_memory_dir()],
298
302
  pattern="*.md",
299
303
  max_files=self.max_memory_files,
@@ -328,7 +332,7 @@ class MaintenanceCadence(AgentCapability):
328
332
  return Capability(
329
333
  default_tools=(
330
334
  sleep_between_runs(
331
- Ctx(
335
+ SleepBetweenRunsContext(
332
336
  seconds=self.seconds,
333
337
  is_cancelled=lambda: pipe.cancelled,
334
338
  conversation_root=sandbox.project_logs_dir(),