roboshed 0.1.1.dev1__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 (101) hide show
  1. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/CHANGELOG.md +52 -0
  2. roboshed-0.1.1.dev3/PKG-INFO +280 -0
  3. roboshed-0.1.1.dev3/README.md +264 -0
  4. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/pyproject.toml +2 -2
  5. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/agents/librarian.py +14 -9
  6. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/agents/orchestrator.py +9 -7
  7. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/capabilities.py +123 -63
  8. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/dependency_health.py +35 -135
  9. roboshed-0.1.1.dev3/src/roboshed/deployments/__init__.py +5 -0
  10. roboshed-0.1.1.dev3/src/roboshed/deployments/robosprawl.py +77 -0
  11. roboshed-0.1.1.dev3/src/roboshed/tools/__init__.py +48 -0
  12. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/apply_patch.py +8 -20
  13. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/run_file_command/command.py +13 -6
  14. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/run_file_command/resolve.py +3 -19
  15. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/utilities/formatting.py +3 -3
  16. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/compactification/__init__.py +4 -0
  17. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/compactification/compactify_messages.py +5 -21
  18. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/compactification/summarize.py +1 -1
  19. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/consolidate_memory.py +5 -24
  20. roboshed-0.1.1.dev3/src/roboshed/tools/contexts.py +162 -0
  21. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/__init__.py +3 -0
  22. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/contracts.py +25 -5
  23. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/drafts.py +10 -21
  24. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/factory.py +13 -14
  25. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/messages.py +5 -10
  26. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/runtime.py +2 -11
  27. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/guard.py +5 -14
  28. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/guard_formatting.py +2 -2
  29. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/purge_files.py +8 -11
  30. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/runner.py +4 -11
  31. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/sleep_between_runs.py +5 -12
  32. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/snapshot_conversations.py +6 -25
  33. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/memory/test_consolidate_memory.py +3 -3
  34. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/memory/test_librarian.py +86 -77
  35. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/memory/test_purge_files.py +2 -2
  36. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/memory/test_snapshot_conversations.py +3 -3
  37. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/memory/test_summarize_conversation.py +17 -2
  38. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_agent_deployment.py +83 -76
  39. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_agent_presets.py +16 -12
  40. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_build_guarded_tool_chain.py +3 -3
  41. roboshed-0.1.1.dev3/tests/test_capabilities.py +89 -0
  42. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_cli_command_utils.py +1 -1
  43. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_compactify_messages.py +4 -3
  44. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_compaction_runtime.py +23 -27
  45. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_dependency_health.py +128 -93
  46. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_deployment_graph.py +50 -39
  47. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_email_factory.py +78 -0
  48. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_generic_guards.py +4 -3
  49. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_guard.py +3 -3
  50. roboshed-0.1.1.dev3/tests/test_robosprawl.py +234 -0
  51. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_sandbox.py +4 -10
  52. roboshed-0.1.1.dev3/tests/test_tool_contexts.py +120 -0
  53. roboshed-0.1.1.dev1/PKG-INFO +0 -182
  54. roboshed-0.1.1.dev1/README.md +0 -166
  55. roboshed-0.1.1.dev1/src/roboshed/deployments/__init__.py +0 -60
  56. roboshed-0.1.1.dev1/src/roboshed/deployments/robosprawl.py +0 -84
  57. roboshed-0.1.1.dev1/src/roboshed/tools/__init__.py +0 -21
  58. roboshed-0.1.1.dev1/tests/test_capabilities.py +0 -101
  59. roboshed-0.1.1.dev1/tests/test_dependency_inspection.py +0 -123
  60. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/.gitignore +0 -0
  61. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/LICENSE +0 -0
  62. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/__init__.py +0 -0
  63. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/agents/__init__.py +0 -0
  64. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/identifiers.py +0 -0
  65. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/models.py +0 -0
  66. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/py.typed +0 -0
  67. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/sandbox.py +0 -0
  68. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/skills/__init__.py +0 -0
  69. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/skills/cli_tools/__init__.py +0 -0
  70. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/skills/cli_tools/prompts.py +0 -0
  71. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/skills/email_tools/__init__.py +0 -0
  72. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/skills/email_tools/prompts.py +0 -0
  73. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/skills/file_editing/__init__.py +0 -0
  74. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/skills/file_editing/prompts.py +0 -0
  75. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/skills/robosprawl.py +0 -0
  76. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/_snapshot_metadata.py +0 -0
  77. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/__init__.py +0 -0
  78. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/run_file_command/__init__.py +0 -0
  79. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/run_file_command/specs.py +0 -0
  80. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/utilities/__init__.py +0 -0
  81. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/utilities/cmd_spec.py +0 -0
  82. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/utilities/constants.py +0 -0
  83. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/cli_commands/utilities/path_extractors.py +0 -0
  84. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/compactification/prompts.py +0 -0
  85. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/compactification/summary_prompts.py +0 -0
  86. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/consolidate_memory_example.py +0 -0
  87. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/consolidate_memory_prompts.py +0 -0
  88. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/email/inputs.py +0 -0
  89. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/librarian_errors.py +0 -0
  90. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/memory_files.py +0 -0
  91. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/snapshot_conversation_example.py +0 -0
  92. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/snapshot_conversation_prompts.py +0 -0
  93. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/snapshot_normalize.py +0 -0
  94. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/truncation.py +0 -0
  95. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/types.py +0 -0
  96. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/src/roboshed/tools/utils.py +0 -0
  97. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/memory/test_memory_prompts.py +0 -0
  98. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_apply_patch.py +0 -0
  99. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_cli_command_chaining.py +0 -0
  100. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_cli_tools_prompt_examples.py +0 -0
  101. {roboshed-0.1.1.dev1 → roboshed-0.1.1.dev3}/tests/test_path_extractors.py +0 -0
@@ -2,6 +2,58 @@
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
+
43
+ ## 0.1.1.dev2 - 2026-09-12
44
+
45
+ - Breaking: move permission, sandbox, watched-agent, and default model inputs
46
+ from Shed capability objects to their owning `DeployableAgent` configuration.
47
+ Capability-specific thresholds, limits, timeouts, and endpoint overrides stay
48
+ on the capability objects.
49
+ - Breaking: remove `Deployment` and replace the callable `RoboSprawl` dataclass
50
+ with a standalone configuration class. Construct `RoboSprawl()` without
51
+ inputs, supply runtime inputs through its setters, then call argument-free
52
+ `build()` to obtain fresh root/background agents. `robosprawl` aliases the
53
+ class, not the former function signature. The existing orchestrator defaults,
54
+ Librarian pipeline, project context, and persistence remain in the recipe.
55
+ Use one configuration instance per new run; see `docs/agent-factories.md`.
56
+
5
57
  ## 0.1.1.dev1 - 2026-09-12
6
58
 
7
59
  - Add `roboshed.deployments.robosprawl.RoboSprawl`, a callable configuration
@@ -0,0 +1,280 @@
1
+ Metadata-Version: 2.5
2
+ Name: roboshed
3
+ Version: 0.1.1.dev3
4
+ Import-Name: roboshed
5
+ Summary: roboshed: optional building blocks for Roboz
6
+ Project-URL: Repository, https://github.com/Tachion-Oy/roboz
7
+ Author: Tachion Oy
8
+ License-Expression: Apache-2.0
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 2 - Pre-Alpha
11
+ Classifier: Typing :: Typed
12
+ Requires-Python: >=3.13
13
+ Requires-Dist: pydantic>=2.12.4
14
+ Requires-Dist: roboz<0.2.0,>=0.1.2.dev5
15
+ Description-Content-Type: text/markdown
16
+
17
+ # roboshed
18
+
19
+ Reusable agent factories, capabilities, sandbox policies, tools, and skills built on Roboz. Version `0.1.1.dev1`
20
+ is a development snapshot; APIs are unstable. Dependencies are Roboz and Pydantic only.
21
+
22
+ Includes guarded Unix file commands, Python patch editing, CLI/file/email
23
+ instructions, and provider-neutral email contracts and tools. It does not
24
+ install any model SDK, Proton, document SDK, web service, or backend framework.
25
+
26
+ ```python
27
+ from pathlib import Path
28
+ from roboz import stop
29
+ from roboz.deployment import DeployableAgent, Capability
30
+ from roboz.llm import MockLLMEndpoint
31
+ from roboshed.capabilities import FileCommands, FileEditing
32
+ from roboshed.sandbox import PermissionPolicy, Sandbox
33
+
34
+ permissions = PermissionPolicy.local(Path("./sandbox"))
35
+ agent = DeployableAgent(
36
+ name="file_worker",
37
+ system_prompt="Complete the user's task, then call stop.",
38
+ default_capabilities=(
39
+ Capability(tools=(stop,)),
40
+ FileCommands(),
41
+ FileEditing(),
42
+ ),
43
+ )
44
+ agent.set_agent_endpoint(MockLLMEndpoint([
45
+ {"action": "stop", "rationale": "done", "value": "Ready."}
46
+ ]))
47
+ agent.set_attributes(permissions=permissions)
48
+ agent, background_agents = agent.build()
49
+ result, messages = agent.invoke()
50
+ ```
51
+
52
+ `roboshed.capabilities` provides `FileCommands`, `FileEditing`, `Compactification`,
53
+ `ConversationSnapshots`, `MemoryConsolidation`, `ArtifactRetention`, and
54
+ `MaintenanceCadence`, alongside the `tools` and `skills` modules. Applications
55
+ choose fixed capabilities through `default_capabilities` and append application
56
+ extensions with `add_capabilities()`.
57
+ A capability owns its tools and skills. Generic `DeployableAgent` definitions
58
+ live in `roboz.deployment`.
59
+ Reusable `orchestrator` and `librarian` constructors live in `roboshed.agents`.
60
+ The orchestrator owns stop and guarded file work, and the Librarian owns
61
+ snapshots, consolidation, retention, and cadence. Root-only application
62
+ capabilities append after the agent's protected defaults, without unpacking the
63
+ role definitions.
64
+
65
+ Each capability declares the typed attributes it reads from its owning
66
+ `DeployableAgent`. Runtime controls remain separate. Use `set_attributes()` to
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.
71
+
72
+ See the [factory and migration guide](../../docs/agent-factories.md).
73
+
74
+ ## RoboSprawl deployment recipe
75
+
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.
86
+
87
+ The recipe loads project memory and supplies project locations through initial
88
+ messages. Its root follows the selected model getter; the Librarian uses its
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.
92
+
93
+ ## Conversation compaction
94
+
95
+ The following fragment belongs inside an agent or tool builder. `endpoint` is
96
+ the selected compaction model, and `agent_pipe` is the owning agent's event
97
+ pipe. These are independent inputs to the tool.
98
+
99
+ ```python
100
+ from roboshed.tools import get_compactify_messages_when_needed_tool
101
+
102
+ compact = get_compactify_messages_when_needed_tool(
103
+ endpoint=endpoint, threshold_percent=60, pipe=agent_pipe, timeout_s=60,
104
+ )
105
+ ```
106
+
107
+ Include this tool in an agent's `default_tools` and pass that agent's owning
108
+ `EventPipe`. The standalone factory defaults to an 80% threshold and no timeout;
109
+ `system_prompt` and `skill_message` override the full continuation instructions.
110
+ The tool preserves the contiguous bootstrap prefix and folds the remaining
111
+ history, including previous summaries, into a new continuation message. Its
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.
115
+
116
+ Successful status reports describe the compacted history's current usage and
117
+ headroom. Summaries are budgeted below the configured threshold and endpoint
118
+ capacity, including the preserved prefix and continuation payload. If there is
119
+ no room for a summary, or the returned replacement still exceeds the budget
120
+ after summarization retries, the tool returns `blocked` without changing history
121
+ or the counter. The continuation payload retains `percent_used_before`.
122
+
123
+ Cancellation and interruption propagate through the existing Roboz summarizer.
124
+ An optional positive, finite `timeout_s` bounds each provider attempt, not the
125
+ whole compaction. Failed attempts leave history and the counter unchanged;
126
+ late provider results are ignored without forcibly killing worker threads.
127
+ Summarization messages and model-call events use the supplied pipe.
128
+
129
+ The public tool name and persisted caller are `compactify_messages_when_needed`.
130
+ This tool owns the shared continuation prompts and retains RoboSprawl's caller
131
+ name. The old `robosprawl.compaction` import is
132
+ replaced by `roboshed.tools`. Shed also owns the shared summarizer and Librarian
133
+ memory pipeline; core provides the mechanisms they use.
134
+
135
+ ## Context API migration
136
+
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.
143
+
144
+
145
+ ## Deployable agent graphs
146
+
147
+ The root `DeployableAgent` owns recursive `subagents` and `background_agents`;
148
+ both slots contain the same definition type. Configure each object explicitly
149
+ before building:
150
+
151
+ ```python
152
+ sandbox.configure_scope(folder)
153
+ definition.set_attributes(permissions=sandbox.permissions())
154
+ agent, background_agents = definition.build(event_sinks=(dispatch,))
155
+ ```
156
+
157
+ Construct each application sandbox directly:
158
+
159
+ ```python
160
+ sandbox = Sandbox(root=application_root, shared="workspace")
161
+ sandbox.configure_scope(folder)
162
+ ```
163
+
164
+ The host supplies `folder` at runtime. For now it is a direct child of the
165
+ sandbox's existing `projects_dir`, with unchanged tiered permission behavior.
166
+ Default persistence paths follow that scope. Startup memory and endpoints are
167
+ agent configuration. Each build creates fresh runtime state; applications can
168
+ supply an agent-specific sink factory for persistence.
169
+
170
+ The Librarian constructor declares its standard maintenance sequence:
171
+ snapshots, consolidation, retention, then cadence. Pass its sandbox and the
172
+ recursive foreground names directly to the constructor before attaching it as
173
+ a background agent. The orchestrator also takes the configured sandbox and
174
+ captures its permission policy when constructed.
175
+
176
+ Invoke the returned agent directly and retain the background agents for control.
177
+ Repeated builds create fresh runtimes and bindings, but supplied endpoints,
178
+ capabilities, and sinks remain caller-owned. No execution state is retained on
179
+ the definition. The old deployment wrapper, factories, host protocols, and
180
+ result bundles are removed.
181
+ Use core's `roboz.llm.ModelSelector` for lazy model selection.
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.
186
+ Permission policies treat configured folder names literally. Health scheduling
187
+ retries observation failures; timed-out workers retain their concurrency slots
188
+ until completion.
189
+ See [agent factories](../../docs/agent-factories.md) for the contracts and examples.
190
+
191
+ The `robosprawl` skill from `roboshed.skills` covers sandbox orientation and the
192
+ HUD file-link/markdown contract. The external RoboSprawl application may select
193
+ it through `Capability(auto_loaded_skills=(robosprawl,))`. Concrete paths,
194
+ endpoints, extra capabilities, and specialist definitions remain application
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).
@@ -0,0 +1,264 @@
1
+ # roboshed
2
+
3
+ Reusable agent factories, capabilities, sandbox policies, tools, and skills built on Roboz. Version `0.1.1.dev1`
4
+ is a development snapshot; APIs are unstable. Dependencies are Roboz and Pydantic only.
5
+
6
+ Includes guarded Unix file commands, Python patch editing, CLI/file/email
7
+ instructions, and provider-neutral email contracts and tools. It does not
8
+ install any model SDK, Proton, document SDK, web service, or backend framework.
9
+
10
+ ```python
11
+ from pathlib import Path
12
+ from roboz import stop
13
+ from roboz.deployment import DeployableAgent, Capability
14
+ from roboz.llm import MockLLMEndpoint
15
+ from roboshed.capabilities import FileCommands, FileEditing
16
+ from roboshed.sandbox import PermissionPolicy, Sandbox
17
+
18
+ permissions = PermissionPolicy.local(Path("./sandbox"))
19
+ agent = DeployableAgent(
20
+ name="file_worker",
21
+ system_prompt="Complete the user's task, then call stop.",
22
+ default_capabilities=(
23
+ Capability(tools=(stop,)),
24
+ FileCommands(),
25
+ FileEditing(),
26
+ ),
27
+ )
28
+ agent.set_agent_endpoint(MockLLMEndpoint([
29
+ {"action": "stop", "rationale": "done", "value": "Ready."}
30
+ ]))
31
+ agent.set_attributes(permissions=permissions)
32
+ agent, background_agents = agent.build()
33
+ result, messages = agent.invoke()
34
+ ```
35
+
36
+ `roboshed.capabilities` provides `FileCommands`, `FileEditing`, `Compactification`,
37
+ `ConversationSnapshots`, `MemoryConsolidation`, `ArtifactRetention`, and
38
+ `MaintenanceCadence`, alongside the `tools` and `skills` modules. Applications
39
+ choose fixed capabilities through `default_capabilities` and append application
40
+ extensions with `add_capabilities()`.
41
+ A capability owns its tools and skills. Generic `DeployableAgent` definitions
42
+ live in `roboz.deployment`.
43
+ Reusable `orchestrator` and `librarian` constructors live in `roboshed.agents`.
44
+ The orchestrator owns stop and guarded file work, and the Librarian owns
45
+ snapshots, consolidation, retention, and cadence. Root-only application
46
+ capabilities append after the agent's protected defaults, without unpacking the
47
+ role definitions.
48
+
49
+ Each capability declares the typed attributes it reads from its owning
50
+ `DeployableAgent`. Runtime controls remain separate. Use `set_attributes()` to
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.
55
+
56
+ See the [factory and migration guide](../../docs/agent-factories.md).
57
+
58
+ ## RoboSprawl deployment recipe
59
+
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.
70
+
71
+ The recipe loads project memory and supplies project locations through initial
72
+ messages. Its root follows the selected model getter; the Librarian uses its
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.
76
+
77
+ ## Conversation compaction
78
+
79
+ The following fragment belongs inside an agent or tool builder. `endpoint` is
80
+ the selected compaction model, and `agent_pipe` is the owning agent's event
81
+ pipe. These are independent inputs to the tool.
82
+
83
+ ```python
84
+ from roboshed.tools import get_compactify_messages_when_needed_tool
85
+
86
+ compact = get_compactify_messages_when_needed_tool(
87
+ endpoint=endpoint, threshold_percent=60, pipe=agent_pipe, timeout_s=60,
88
+ )
89
+ ```
90
+
91
+ Include this tool in an agent's `default_tools` and pass that agent's owning
92
+ `EventPipe`. The standalone factory defaults to an 80% threshold and no timeout;
93
+ `system_prompt` and `skill_message` override the full continuation instructions.
94
+ The tool preserves the contiguous bootstrap prefix and folds the remaining
95
+ history, including previous summaries, into a new continuation message. Its
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.
99
+
100
+ Successful status reports describe the compacted history's current usage and
101
+ headroom. Summaries are budgeted below the configured threshold and endpoint
102
+ capacity, including the preserved prefix and continuation payload. If there is
103
+ no room for a summary, or the returned replacement still exceeds the budget
104
+ after summarization retries, the tool returns `blocked` without changing history
105
+ or the counter. The continuation payload retains `percent_used_before`.
106
+
107
+ Cancellation and interruption propagate through the existing Roboz summarizer.
108
+ An optional positive, finite `timeout_s` bounds each provider attempt, not the
109
+ whole compaction. Failed attempts leave history and the counter unchanged;
110
+ late provider results are ignored without forcibly killing worker threads.
111
+ Summarization messages and model-call events use the supplied pipe.
112
+
113
+ The public tool name and persisted caller are `compactify_messages_when_needed`.
114
+ This tool owns the shared continuation prompts and retains RoboSprawl's caller
115
+ name. The old `robosprawl.compaction` import is
116
+ replaced by `roboshed.tools`. Shed also owns the shared summarizer and Librarian
117
+ memory pipeline; core provides the mechanisms they use.
118
+
119
+ ## Context API migration
120
+
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.
127
+
128
+
129
+ ## Deployable agent graphs
130
+
131
+ The root `DeployableAgent` owns recursive `subagents` and `background_agents`;
132
+ both slots contain the same definition type. Configure each object explicitly
133
+ before building:
134
+
135
+ ```python
136
+ sandbox.configure_scope(folder)
137
+ definition.set_attributes(permissions=sandbox.permissions())
138
+ agent, background_agents = definition.build(event_sinks=(dispatch,))
139
+ ```
140
+
141
+ Construct each application sandbox directly:
142
+
143
+ ```python
144
+ sandbox = Sandbox(root=application_root, shared="workspace")
145
+ sandbox.configure_scope(folder)
146
+ ```
147
+
148
+ The host supplies `folder` at runtime. For now it is a direct child of the
149
+ sandbox's existing `projects_dir`, with unchanged tiered permission behavior.
150
+ Default persistence paths follow that scope. Startup memory and endpoints are
151
+ agent configuration. Each build creates fresh runtime state; applications can
152
+ supply an agent-specific sink factory for persistence.
153
+
154
+ The Librarian constructor declares its standard maintenance sequence:
155
+ snapshots, consolidation, retention, then cadence. Pass its sandbox and the
156
+ recursive foreground names directly to the constructor before attaching it as
157
+ a background agent. The orchestrator also takes the configured sandbox and
158
+ captures its permission policy when constructed.
159
+
160
+ Invoke the returned agent directly and retain the background agents for control.
161
+ Repeated builds create fresh runtimes and bindings, but supplied endpoints,
162
+ capabilities, and sinks remain caller-owned. No execution state is retained on
163
+ the definition. The old deployment wrapper, factories, host protocols, and
164
+ result bundles are removed.
165
+ Use core's `roboz.llm.ModelSelector` for lazy model selection.
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.
170
+ Permission policies treat configured folder names literally. Health scheduling
171
+ retries observation failures; timed-out workers retain their concurrency slots
172
+ until completion.
173
+ See [agent factories](../../docs/agent-factories.md) for the contracts and examples.
174
+
175
+ The `robosprawl` skill from `roboshed.skills` covers sandbox orientation and the
176
+ HUD file-link/markdown contract. The external RoboSprawl application may select
177
+ it through `Capability(auto_loaded_skills=(robosprawl,))`. Concrete paths,
178
+ endpoints, extra capabilities, and specialist definitions remain application
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.dev1"
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.dev3,<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"]
@@ -21,25 +21,30 @@ LIBRARIAN_AGENT_DESCRIPTION: Final[str] = (
21
21
 
22
22
  def librarian(
23
23
  sandbox: Sandbox,
24
- agent_names: Collection[str],
24
+ watched_agent_names: Collection[str],
25
25
  *,
26
26
  agent_endpoint: EndpointLike | None,
27
27
  ) -> DeployableAgent:
28
28
  """Configure maintenance for the sandbox and foreground agent names."""
29
- return DeployableAgent(
29
+ agent = DeployableAgent(
30
30
  name=LIBRARIAN_AGENT_NAME,
31
31
  description=LIBRARIAN_AGENT_DESCRIPTION,
32
- interaction_mode=None,
33
32
  is_agentic=False,
34
33
  automatic_tool_prompt=False,
35
- agent_endpoint=agent_endpoint,
36
- capabilities=(
37
- ConversationSnapshots(sandbox=sandbox, agent_names=agent_names),
38
- MemoryConsolidation(sandbox=sandbox, agent_names=agent_names),
39
- ArtifactRetention(sandbox=sandbox),
40
- MaintenanceCadence(sandbox=sandbox, agent_names=agent_names),
34
+ default_capabilities=(
35
+ ConversationSnapshots(),
36
+ MemoryConsolidation(),
37
+ ArtifactRetention(),
38
+ MaintenanceCadence(),
41
39
  ),
42
40
  )
41
+ agent.set_agent_endpoint(agent_endpoint)
42
+ agent.set_interaction_mode(None)
43
+ agent.set_attributes(
44
+ sandbox=sandbox,
45
+ watched_agent_names=frozenset(watched_agent_names),
46
+ )
47
+ return agent
43
48
 
44
49
 
45
50
  __all__ = ["LIBRARIAN_AGENT_DESCRIPTION", "librarian"]