deepstrike 0.2.23__tar.gz → 0.2.24__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.
- {deepstrike-0.2.23 → deepstrike-0.2.24}/Cargo.lock +5 -5
- {deepstrike-0.2.23 → deepstrike-0.2.24}/Cargo.toml +2 -2
- {deepstrike-0.2.23 → deepstrike-0.2.24}/PKG-INFO +1 -1
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/__init__.py +6 -1
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/stream.py +13 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/execution_plane.py +78 -3
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/mcp_proxy_plane.py +2 -1
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/process_sandbox_plane.py +2 -1
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/remote_vpc_plane.py +2 -1
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/runner.py +4 -3
- deepstrike-0.2.24/deepstrike/tools/__init__.py +9 -0
- deepstrike-0.2.24/deepstrike/tools/errors.py +135 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/tools/execution.py +2 -1
- {deepstrike-0.2.23 → deepstrike-0.2.24}/pyproject.toml +1 -1
- deepstrike-0.2.23/deepstrike/tools/__init__.py +0 -5
- {deepstrike-0.2.23 → deepstrike-0.2.24}/README.md +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/Cargo.toml +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/compression.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/config.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/dashboard.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/manager.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/partitions.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/pressure.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/renderer.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/renewal.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/sections.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/skill_catalog.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/snapshot.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/summarizer.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/task_state.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/text.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/context/token_engine.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/governance/audit.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/governance/constraint.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/governance/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/governance/permission.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/governance/pipeline.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/governance/quota.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/governance/rate_limit.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/governance/sandbox.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/governance/tool_decision.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/governance/veto.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/harness/eval.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/harness/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/lib.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/memory/curator.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/memory/durable.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/memory/extractor.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/memory/idle_pipeline.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/memory/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/memory/runtime.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/memory/semantic.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/memory/session.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/memory/synthesis.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/memory/trace_analyzer.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/memory/working.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/mm/handle.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/mm/memory.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/mm/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/orchestration/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/orchestration/task_graph.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/orchestration/tournament.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/orchestration/workflow/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/orchestration/workflow/run.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/proc/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/runtime/event_log.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/runtime/kernel.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/runtime/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/runtime/repair.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/runtime/replay.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/runtime/session.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/runtime/snapshot.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/milestone.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/policy.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/rollback.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/state_machine/capability.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/state_machine/eviction.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/state_machine/gate.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/state_machine/milestone_exec.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/state_machine/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/state_machine/process.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/state_machine/signal.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/state_machine/tests.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/state_machine/workflow.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/tcb.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/signals/attention.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/signals/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/signals/queue.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/signals/router.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/syscall/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/types/agent.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/types/capability.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/types/contract.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/types/error.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/types/message.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/types/milestone.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/types/mod.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/types/model.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/types/policy.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/types/result.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/types/signal.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/types/skill.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/types/task.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-py/Cargo.toml +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-py/src/lib.rs +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/collaboration/__init__.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/collaboration/contract.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/collaboration/handoff.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/collaboration/harness.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/collaboration/modes.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/collaboration/pool.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/governance.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/harness/__init__.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/harness/harness.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/kernel/__init__.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/knowledge/__init__.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/knowledge/source.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/memory/__init__.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/memory/agent.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/memory/in_memory_store.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/memory/protocols.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/memory/working.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/__init__.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/anthropic.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/base.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/deepseek.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/gemini.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/glm.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/kimi.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/minimax.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/ollama.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/openai.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/openai_responses.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/qwen.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/replay.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/providers/replay_validator.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/__init__.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/archive.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/credential_vault.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/eval.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/filtered_plane.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/kernel_event_log.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/kernel_step.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/large_result_spool.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/os_profile.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/os_snapshot.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/output_schema.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/provider_replay.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/reducers.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/replay_fixture.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/replay_provider.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/replay_sanitize.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/session_log.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/session_repair.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/sub_agent_orchestrator.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/workflow_control_flow.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/workflow_store.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/runtime/worktree_plane.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/safety/__init__.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/safety/permissions.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/signals/__init__.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/signals/gateway.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/signals/scheduled.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/signals/types.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/skills/__init__.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/skills/registry.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/skills/watcher.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/tools/builtin/__init__.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/tools/builtin/read_file.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/tools/registry.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/types/__init__.py +0 -0
- {deepstrike-0.2.23 → deepstrike-0.2.24}/deepstrike/types/agent.py +0 -0
|
@@ -194,7 +194,7 @@ dependencies = [
|
|
|
194
194
|
|
|
195
195
|
[[package]]
|
|
196
196
|
name = "deepstrike-core"
|
|
197
|
-
version = "0.2.
|
|
197
|
+
version = "0.2.24"
|
|
198
198
|
dependencies = [
|
|
199
199
|
"compact_str",
|
|
200
200
|
"pretty_assertions",
|
|
@@ -206,7 +206,7 @@ dependencies = [
|
|
|
206
206
|
|
|
207
207
|
[[package]]
|
|
208
208
|
name = "deepstrike-node"
|
|
209
|
-
version = "0.2.
|
|
209
|
+
version = "0.2.24"
|
|
210
210
|
dependencies = [
|
|
211
211
|
"compact_str",
|
|
212
212
|
"deepstrike-core",
|
|
@@ -218,7 +218,7 @@ dependencies = [
|
|
|
218
218
|
|
|
219
219
|
[[package]]
|
|
220
220
|
name = "deepstrike-py"
|
|
221
|
-
version = "0.2.
|
|
221
|
+
version = "0.2.24"
|
|
222
222
|
dependencies = [
|
|
223
223
|
"compact_str",
|
|
224
224
|
"deepstrike-core",
|
|
@@ -229,7 +229,7 @@ dependencies = [
|
|
|
229
229
|
|
|
230
230
|
[[package]]
|
|
231
231
|
name = "deepstrike-sdk"
|
|
232
|
-
version = "0.2.
|
|
232
|
+
version = "0.2.24"
|
|
233
233
|
dependencies = [
|
|
234
234
|
"async-stream",
|
|
235
235
|
"async-trait",
|
|
@@ -263,7 +263,7 @@ dependencies = [
|
|
|
263
263
|
|
|
264
264
|
[[package]]
|
|
265
265
|
name = "deepstrike-wasm"
|
|
266
|
-
version = "0.2.
|
|
266
|
+
version = "0.2.24"
|
|
267
267
|
dependencies = [
|
|
268
268
|
"compact_str",
|
|
269
269
|
"deepstrike-core",
|
|
@@ -3,13 +3,13 @@ resolver = "2"
|
|
|
3
3
|
members = ["crates/deepstrike-core", "crates/deepstrike-py"]
|
|
4
4
|
|
|
5
5
|
[workspace.package]
|
|
6
|
-
version = "0.2.
|
|
6
|
+
version = "0.2.24"
|
|
7
7
|
edition = "2024"
|
|
8
8
|
license = "MIT"
|
|
9
9
|
repository = "https://github.com/kongusen/deepstrike"
|
|
10
10
|
|
|
11
11
|
[workspace.dependencies]
|
|
12
|
-
deepstrike-core = { path = "crates/deepstrike-core", version = "0.2.
|
|
12
|
+
deepstrike-core = { path = "crates/deepstrike-core", version = "0.2.24" }
|
|
13
13
|
notify = "6"
|
|
14
14
|
serde = { version = "1", features = ["derive"] }
|
|
15
15
|
serde_json = "1"
|
|
@@ -64,7 +64,11 @@ from deepstrike.providers import (
|
|
|
64
64
|
PermissionRequestEvent, PermissionResolvedEvent, PermissionResponse, ToolArgumentRepairedEvent,
|
|
65
65
|
RetryConfig, CircuitBreaker, TokenUsage, ProviderToolSpec,
|
|
66
66
|
)
|
|
67
|
-
from deepstrike.tools import
|
|
67
|
+
from deepstrike.tools import (
|
|
68
|
+
RegisteredTool, tool, streaming_tool, validate_tool_arguments, execute_tools, read_file,
|
|
69
|
+
ToolError, safe_tool, ok, fail, format_tool_error,
|
|
70
|
+
)
|
|
71
|
+
from deepstrike.providers.stream import ToolAuditFailedEvent
|
|
68
72
|
from deepstrike.memory import (
|
|
69
73
|
WorkingMemory,
|
|
70
74
|
DreamStore, DreamResult, SessionData, MemoryEntry, CurationResult, CurationStats,
|
|
@@ -139,6 +143,7 @@ __all__ = [
|
|
|
139
143
|
"PermissionRequestEvent", "PermissionResolvedEvent", "PermissionResponse", "ToolArgumentRepairedEvent",
|
|
140
144
|
"RetryConfig", "CircuitBreaker", "TokenUsage", "ProviderToolSpec",
|
|
141
145
|
"RegisteredTool", "tool", "streaming_tool", "validate_tool_arguments", "execute_tools", "read_file",
|
|
146
|
+
"ToolError", "safe_tool", "ok", "fail", "format_tool_error", "ToolAuditFailedEvent",
|
|
142
147
|
"WorkingMemory",
|
|
143
148
|
"DreamStore", "DreamResult", "SessionData", "MemoryEntry", "CurationResult", "CurationStats",
|
|
144
149
|
"PermissionManager", "PermissionMode", "Permission", "PermissionDecision",
|
|
@@ -126,6 +126,18 @@ class ToolDeniedEvent:
|
|
|
126
126
|
reason: str = ""
|
|
127
127
|
|
|
128
128
|
|
|
129
|
+
@dataclass
|
|
130
|
+
class ToolAuditFailedEvent:
|
|
131
|
+
"""A tool's ``ctx.audit(label, fn)`` best-effort side-effect threw. The tool itself completed
|
|
132
|
+
successfully (no ``is_error`` flip, no retry); this event lets the host log / monitor that an
|
|
133
|
+
audit-store / metrics-emit / non-essential persistence step failed."""
|
|
134
|
+
type: str = "tool_audit_failed"
|
|
135
|
+
call_id: str = ""
|
|
136
|
+
name: str = ""
|
|
137
|
+
label: str = ""
|
|
138
|
+
error: str = ""
|
|
139
|
+
|
|
140
|
+
|
|
129
141
|
@dataclass
|
|
130
142
|
class WorkflowNodesSubmittedEvent:
|
|
131
143
|
"""R3-1: a workflow node's agent called the ``submit_workflow_nodes`` tool. The runner surfaces
|
|
@@ -149,5 +161,6 @@ StreamEvent = Union[
|
|
|
149
161
|
PermissionResolvedEvent,
|
|
150
162
|
ToolArgumentRepairedEvent,
|
|
151
163
|
ToolDeniedEvent,
|
|
164
|
+
ToolAuditFailedEvent,
|
|
152
165
|
WorkflowNodesSubmittedEvent,
|
|
153
166
|
]
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
import inspect
|
|
4
5
|
import json
|
|
6
|
+
import warnings
|
|
5
7
|
from collections.abc import AsyncIterable, AsyncIterator
|
|
6
8
|
from dataclasses import dataclass
|
|
7
9
|
from pathlib import Path
|
|
@@ -13,12 +15,14 @@ from deepstrike.providers.stream import (
|
|
|
13
15
|
PermissionResolvedEvent,
|
|
14
16
|
PermissionResponse,
|
|
15
17
|
StreamEvent,
|
|
18
|
+
ToolAuditFailedEvent,
|
|
16
19
|
ToolDeltaEvent,
|
|
17
20
|
ToolDeniedEvent,
|
|
18
21
|
ToolResultEvent,
|
|
19
22
|
ToolSuspendEvent,
|
|
20
23
|
ToolArgumentRepairedEvent,
|
|
21
24
|
)
|
|
25
|
+
from deepstrike.tools.errors import format_tool_error
|
|
22
26
|
from deepstrike.tools.registry import RegisteredTool, normalize_tool_chunk, tool_chunk_text, validate_tool_arguments
|
|
23
27
|
|
|
24
28
|
if TYPE_CHECKING:
|
|
@@ -33,6 +37,39 @@ def _strip_frontmatter(content: str) -> str:
|
|
|
33
37
|
return re.sub(r"^---\n.*?\n---\n?", "", content, count=1, flags=re.DOTALL)
|
|
34
38
|
|
|
35
39
|
|
|
40
|
+
_WARNED_FAILURE_SHAPES: set[str] = set()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _maybe_warn_failure_shaped_chunk(tool_name: str, delta_text: str) -> None:
|
|
44
|
+
"""One-shot heuristic: detect when a streaming tool yielded text that *looks* like a failure
|
|
45
|
+
envelope. The runtime cannot block the tool from doing it, but we warn (once per tool) so
|
|
46
|
+
the author migrates to raising — the canonical "streaming tool fails" path. Aligns with the
|
|
47
|
+
non-streaming ``tool()`` / ``safe_tool`` contract: failures raise, successes return data."""
|
|
48
|
+
if not delta_text or tool_name in _WARNED_FAILURE_SHAPES:
|
|
49
|
+
return
|
|
50
|
+
trimmed = delta_text.strip()
|
|
51
|
+
if len(trimmed) < 2 or trimmed[0] != "{":
|
|
52
|
+
return
|
|
53
|
+
try:
|
|
54
|
+
parsed = json.loads(trimmed)
|
|
55
|
+
except Exception:
|
|
56
|
+
return
|
|
57
|
+
if not isinstance(parsed, dict):
|
|
58
|
+
return
|
|
59
|
+
looks_like_failure = parsed.get("success") is False or parsed.get("isError") is True or parsed.get("is_error") is True
|
|
60
|
+
if not looks_like_failure:
|
|
61
|
+
return
|
|
62
|
+
_WARNED_FAILURE_SHAPES.add(tool_name)
|
|
63
|
+
warnings.warn(
|
|
64
|
+
f'streaming tool "{tool_name}" yielded a failure-shaped chunk '
|
|
65
|
+
"(success:false / isError:true). Streaming tools should fail by raising; the runtime will "
|
|
66
|
+
"catch and surface the error consistently. Returning a failure-shaped chunk is a foot-gun: "
|
|
67
|
+
"the kernel still sees is_error=False.",
|
|
68
|
+
RuntimeWarning,
|
|
69
|
+
stacklevel=2,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
36
73
|
@dataclass
|
|
37
74
|
class RunContext:
|
|
38
75
|
agent_id: str | None = None
|
|
@@ -45,6 +82,12 @@ class RunContext:
|
|
|
45
82
|
# M3/G4: the working directory a sub-agent's tools should run in (the git worktree created for an
|
|
46
83
|
# ``isolation: "worktree"`` node). Injected by ``WorktreeExecutionPlane``; a cwd-aware tool reads it.
|
|
47
84
|
cwd: str | None = None
|
|
85
|
+
# Per-call best-effort side-effect helper (injected by the execution plane). Wrap audit-log
|
|
86
|
+
# writes, metrics emits, or any non-essential persistence in ``await ctx.audit(label, fn)``;
|
|
87
|
+
# if ``fn`` raises, the failure is surfaced as a ``ToolAuditFailedEvent`` and the tool still
|
|
88
|
+
# completes successfully — avoiding the foot-gun where a transient audit-store outage flips
|
|
89
|
+
# an already-committed write into ``is_error=True`` and triggers a duplicate retry.
|
|
90
|
+
audit: Callable[[str, Callable[[], Awaitable[None] | None]], Awaitable[None]] | None = None
|
|
48
91
|
|
|
49
92
|
|
|
50
93
|
class ExecutionPlane:
|
|
@@ -174,6 +217,29 @@ class LocalExecutionPlane:
|
|
|
174
217
|
error_kind="recoverable",
|
|
175
218
|
)
|
|
176
219
|
return
|
|
220
|
+
# Per-call ``audit`` helper: failures collected here are surfaced as
|
|
221
|
+
# ``ToolAuditFailedEvent`` rather than flipping the main tool result to ``is_error=True``.
|
|
222
|
+
audit_failures: list[tuple[str, str]] = []
|
|
223
|
+
|
|
224
|
+
async def _audit(label: str, fn: Callable[[], Awaitable[None] | None]) -> None:
|
|
225
|
+
try:
|
|
226
|
+
result = fn()
|
|
227
|
+
if inspect.isawaitable(result):
|
|
228
|
+
await result
|
|
229
|
+
except Exception as ae:
|
|
230
|
+
audit_failures.append((label, format_tool_error(ae)))
|
|
231
|
+
|
|
232
|
+
call_ctx = RunContext(
|
|
233
|
+
agent_id=ctx.agent_id,
|
|
234
|
+
skill_dir=ctx.skill_dir,
|
|
235
|
+
dream_store=ctx.dream_store,
|
|
236
|
+
knowledge_source=ctx.knowledge_source,
|
|
237
|
+
on_tool_suspend=ctx.on_tool_suspend,
|
|
238
|
+
on_permission_request=ctx.on_permission_request,
|
|
239
|
+
result_spool=ctx.result_spool,
|
|
240
|
+
cwd=ctx.cwd,
|
|
241
|
+
audit=_audit,
|
|
242
|
+
)
|
|
177
243
|
try:
|
|
178
244
|
kwargs = json.loads(call.arguments or "{}")
|
|
179
245
|
original_args_str = json.dumps(kwargs)
|
|
@@ -195,8 +261,9 @@ class LocalExecutionPlane:
|
|
|
195
261
|
original_arguments=original_args_str,
|
|
196
262
|
repaired_arguments=json.dumps(kwargs),
|
|
197
263
|
)
|
|
198
|
-
# M3/G4: pass the run context (incl. ``cwd``) so cwd-aware
|
|
199
|
-
|
|
264
|
+
# M3/G4: pass the run context (incl. ``cwd``, ``audit``) so cwd-aware / audit-aware tools
|
|
265
|
+
# scope work to the worktree and route best-effort side-effects through the plane.
|
|
266
|
+
output = await registered(_ctx=call_ctx, **kwargs)
|
|
200
267
|
if isinstance(output, AsyncIterable):
|
|
201
268
|
combined = ""
|
|
202
269
|
iterator = output.__aiter__()
|
|
@@ -234,22 +301,30 @@ class LocalExecutionPlane:
|
|
|
234
301
|
continue
|
|
235
302
|
delta = tool_chunk_text(raw)
|
|
236
303
|
combined += delta
|
|
304
|
+
if delta:
|
|
305
|
+
_maybe_warn_failure_shaped_chunk(call.name, delta)
|
|
237
306
|
yield ToolDeltaEvent(
|
|
238
307
|
call_id=call.id, name=call.name, delta=delta,
|
|
239
308
|
chunk=None if isinstance(raw, str) else chunk,
|
|
240
309
|
)
|
|
310
|
+
for label, error in audit_failures:
|
|
311
|
+
yield ToolAuditFailedEvent(call_id=call.id, name=call.name, label=label, error=error)
|
|
241
312
|
yield ToolResultEvent(call_id=call.id, name=call.name, content=combined, is_error=False)
|
|
242
313
|
return
|
|
314
|
+
for label, error in audit_failures:
|
|
315
|
+
yield ToolAuditFailedEvent(call_id=call.id, name=call.name, label=label, error=error)
|
|
243
316
|
yield ToolResultEvent(call_id=call.id, name=call.name, content=str(output), is_error=False)
|
|
244
317
|
except Exception as exc:
|
|
245
318
|
is_fatal = getattr(exc, "is_fatal", False)
|
|
246
319
|
error_kind = getattr(exc, "error_kind", None)
|
|
247
320
|
if error_kind is None:
|
|
248
321
|
error_kind = "fatal" if is_fatal else "recoverable"
|
|
322
|
+
for label, error in audit_failures:
|
|
323
|
+
yield ToolAuditFailedEvent(call_id=call.id, name=call.name, label=label, error=error)
|
|
249
324
|
yield ToolResultEvent(
|
|
250
325
|
call_id=call.id,
|
|
251
326
|
name=call.name,
|
|
252
|
-
content=
|
|
327
|
+
content=format_tool_error(exc),
|
|
253
328
|
is_error=True,
|
|
254
329
|
is_fatal=is_fatal,
|
|
255
330
|
error_kind=error_kind,
|
|
@@ -10,6 +10,7 @@ from typing import TYPE_CHECKING, Any
|
|
|
10
10
|
|
|
11
11
|
from deepstrike._kernel import ToolCall, ToolSchema
|
|
12
12
|
from deepstrike.providers.stream import StreamEvent, ToolResultEvent
|
|
13
|
+
from deepstrike.tools.errors import format_tool_error
|
|
13
14
|
from deepstrike.tools.registry import RegisteredTool
|
|
14
15
|
from deepstrike.runtime.execution_plane import ExecutionPlane, LocalExecutionPlane, RunContext
|
|
15
16
|
from deepstrike.runtime.credential_vault import CredentialVault
|
|
@@ -126,7 +127,7 @@ class _McpConnection:
|
|
|
126
127
|
)
|
|
127
128
|
return (text or json.dumps(result)), result.get("isError", False)
|
|
128
129
|
except Exception as exc:
|
|
129
|
-
return
|
|
130
|
+
return format_tool_error(exc), True
|
|
130
131
|
|
|
131
132
|
async def stop(self) -> None:
|
|
132
133
|
if self._reader_task:
|
|
@@ -6,6 +6,7 @@ import os
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
8
|
from deepstrike._kernel import ToolSchema
|
|
9
|
+
from deepstrike.tools.errors import format_tool_error
|
|
9
10
|
from deepstrike.tools.registry import RegisteredTool
|
|
10
11
|
from deepstrike.runtime.execution_plane import LocalExecutionPlane
|
|
11
12
|
|
|
@@ -72,7 +73,7 @@ class ProcessSandboxPlane(LocalExecutionPlane):
|
|
|
72
73
|
combined = combined[: self._max_output_bytes] + b"\n[output truncated]"
|
|
73
74
|
return combined.decode("utf-8", errors="replace"), proc.returncode != 0
|
|
74
75
|
except Exception as exc:
|
|
75
|
-
return
|
|
76
|
+
return format_tool_error(exc), True
|
|
76
77
|
|
|
77
78
|
def _make_bash_tool(self) -> RegisteredTool:
|
|
78
79
|
sandbox = self
|
|
@@ -9,6 +9,7 @@ import aiohttp
|
|
|
9
9
|
|
|
10
10
|
from deepstrike._kernel import ToolCall, ToolSchema
|
|
11
11
|
from deepstrike.providers.stream import StreamEvent, ToolResultEvent
|
|
12
|
+
from deepstrike.tools.errors import format_tool_error
|
|
12
13
|
from deepstrike.tools.registry import RegisteredTool
|
|
13
14
|
from deepstrike.runtime.execution_plane import LocalExecutionPlane, RunContext
|
|
14
15
|
from deepstrike.runtime.credential_vault import CredentialVault
|
|
@@ -97,4 +98,4 @@ class RemoteVpcPlane:
|
|
|
97
98
|
result: dict = await resp.json()
|
|
98
99
|
return result.get("output", ""), bool(result.get("isError", False))
|
|
99
100
|
except Exception as exc:
|
|
100
|
-
return
|
|
101
|
+
return format_tool_error(exc), True
|
|
@@ -37,6 +37,7 @@ from deepstrike.providers.stream import (
|
|
|
37
37
|
WorkflowNodesSubmittedEvent,
|
|
38
38
|
)
|
|
39
39
|
from deepstrike.runtime.execution_plane import ExecutionPlane, LocalExecutionPlane, RunContext
|
|
40
|
+
from deepstrike.tools.errors import format_tool_error
|
|
40
41
|
from deepstrike.governance import governance_policy_to_kernel_event
|
|
41
42
|
from deepstrike.runtime.kernel_event_log import kernel_observation_to_session_event, with_category
|
|
42
43
|
from deepstrike.runtime.kernel_step import (
|
|
@@ -1449,7 +1450,7 @@ class RuntimeRunner:
|
|
|
1449
1450
|
id=evt.id, name=evt.name, arguments=json.dumps(evt.arguments),
|
|
1450
1451
|
))
|
|
1451
1452
|
except Exception as exc:
|
|
1452
|
-
err_msg =
|
|
1453
|
+
err_msg = format_tool_error(exc).lower()
|
|
1453
1454
|
if (
|
|
1454
1455
|
("413" in err_msg or "too long" in err_msg or "context length exceeded" in err_msg or "context_length_exceeded" in err_msg)
|
|
1455
1456
|
and not has_attempted_reactive_compact
|
|
@@ -1462,7 +1463,7 @@ class RuntimeRunner:
|
|
|
1462
1463
|
should_retry = True
|
|
1463
1464
|
|
|
1464
1465
|
if not should_retry:
|
|
1465
|
-
yield ErrorEvent(message=
|
|
1466
|
+
yield ErrorEvent(message=format_tool_error(exc))
|
|
1466
1467
|
action = kernel_action(runtime, self._pending_observations, {"kind": "timeout"})
|
|
1467
1468
|
break
|
|
1468
1469
|
|
|
@@ -1716,7 +1717,7 @@ class RuntimeRunner:
|
|
|
1716
1717
|
except Exception as err:
|
|
1717
1718
|
# I0b: kernel rejection (or any other thrown error inside the loop) is observable here — emit
|
|
1718
1719
|
# run_terminal so downstream code sees a clean end rather than mid-loop EOF.
|
|
1719
|
-
err_msg =
|
|
1720
|
+
err_msg = format_tool_error(err)
|
|
1720
1721
|
is_invalid_arg = "invalidarg" in err_msg.lower() or "invalid argument" in err_msg.lower()
|
|
1721
1722
|
reason = "invalid_arg" if is_invalid_arg else "error"
|
|
1722
1723
|
yield ErrorEvent(message=err_msg)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from .registry import RegisteredTool, tool, streaming_tool, validate_tool_arguments
|
|
2
|
+
from .execution import execute_tools
|
|
3
|
+
from .builtin import read_file
|
|
4
|
+
from .errors import ToolError, safe_tool, ok, fail, format_tool_error
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"RegisteredTool", "tool", "streaming_tool", "validate_tool_arguments", "execute_tools", "read_file",
|
|
8
|
+
"ToolError", "safe_tool", "ok", "fail", "format_tool_error",
|
|
9
|
+
]
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Tool error envelope + ``safe_tool`` decorator (Python parity for the Node ``tools/errors.ts``).
|
|
2
|
+
|
|
3
|
+
Three pieces:
|
|
4
|
+
|
|
5
|
+
- ``format_tool_error`` replaces the old ``str(exc)`` at SDK error sites: an ``Exception`` with
|
|
6
|
+
no extra fields gives ``str(exc)`` (the message); an exception carrying ``code`` / ``hint`` /
|
|
7
|
+
``__cause__`` gives JSON; a non-exception value falls back to ``str(...)``.
|
|
8
|
+
- ``ToolError`` is the canonical "the tool wants to fail with a code+hint" exception. Throwing it
|
|
9
|
+
from a ``safe_tool``-wrapped body produces ``{success:false, code, error, hint?}``.
|
|
10
|
+
- ``safe_tool`` wraps a function so plain-data returns become ``{success:true, data}`` and any
|
|
11
|
+
raise becomes a fail envelope — opt-in equivalent of ``tool()`` for tools that want the
|
|
12
|
+
stable structured shape on the wire instead of free-form strings.
|
|
13
|
+
|
|
14
|
+
The classic ``tool()`` factory is untouched; ``safe_tool`` is the migration path."""
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import inspect
|
|
18
|
+
import json
|
|
19
|
+
from collections.abc import AsyncIterable
|
|
20
|
+
from typing import Any, Callable
|
|
21
|
+
|
|
22
|
+
from .registry import RegisteredTool, _schema_for
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ToolError(Exception):
|
|
26
|
+
"""Carries machine-readable ``code`` + optional ``hint`` alongside the message. ``safe_tool``
|
|
27
|
+
converts a raised ``ToolError`` into ``{success:false, code, error, hint?}``. Code defaults
|
|
28
|
+
to ``"internal"`` so a bare ``raise ToolError("...")`` still produces a usable envelope."""
|
|
29
|
+
|
|
30
|
+
def __init__(self, message: str, *, code: str = "internal", hint: str | None = None,
|
|
31
|
+
cause: BaseException | None = None) -> None:
|
|
32
|
+
super().__init__(message)
|
|
33
|
+
self.code = code
|
|
34
|
+
self.hint = hint
|
|
35
|
+
if cause is not None:
|
|
36
|
+
self.__cause__ = cause
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def ok(data: Any = None) -> dict[str, Any]:
|
|
40
|
+
return {"success": True} if data is None else {"success": True, "data": data}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def fail(code: str, error: str, hint: str | None = None) -> dict[str, Any]:
|
|
44
|
+
env: dict[str, Any] = {"success": False, "code": code, "error": error}
|
|
45
|
+
if hint is not None:
|
|
46
|
+
env["hint"] = hint
|
|
47
|
+
return env
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _is_envelope(v: Any) -> bool:
|
|
51
|
+
return isinstance(v, dict) and isinstance(v.get("success"), bool)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def format_tool_error(err: Any) -> str:
|
|
55
|
+
"""Error-aware replacement for ``str(exc)`` / ``String(err)``.
|
|
56
|
+
|
|
57
|
+
- ``Exception`` with no extra fields → ``str(exc)`` (the message).
|
|
58
|
+
- ``Exception`` carrying ``code`` / ``hint`` / ``__cause__`` → JSON ``{message, name?, code?,
|
|
59
|
+
hint?, cause?}`` — agents can branch on ``code``.
|
|
60
|
+
- ``None`` / primitives / strings → ``str(...)`` unchanged.
|
|
61
|
+
- Other objects → ``json.dumps(...)`` if possible (replaces the old ``"<X object at 0x...>"``)."""
|
|
62
|
+
if err is None:
|
|
63
|
+
return "None"
|
|
64
|
+
if isinstance(err, str):
|
|
65
|
+
return err
|
|
66
|
+
if isinstance(err, BaseException):
|
|
67
|
+
code = getattr(err, "code", None)
|
|
68
|
+
hint = getattr(err, "hint", None)
|
|
69
|
+
cause = getattr(err, "__cause__", None)
|
|
70
|
+
if code is None and hint is None and cause is None:
|
|
71
|
+
return str(err) or type(err).__name__
|
|
72
|
+
payload: dict[str, Any] = {"message": str(err)}
|
|
73
|
+
name = type(err).__name__
|
|
74
|
+
if name not in ("Exception", "ToolError"):
|
|
75
|
+
payload["name"] = name
|
|
76
|
+
if code is not None:
|
|
77
|
+
payload["code"] = code
|
|
78
|
+
if hint is not None:
|
|
79
|
+
payload["hint"] = hint
|
|
80
|
+
if cause is not None:
|
|
81
|
+
payload["cause"] = str(cause) if isinstance(cause, BaseException) else cause
|
|
82
|
+
try:
|
|
83
|
+
return json.dumps(payload, default=str)
|
|
84
|
+
except Exception:
|
|
85
|
+
return str(err) or type(err).__name__
|
|
86
|
+
try:
|
|
87
|
+
return json.dumps(err, default=str)
|
|
88
|
+
except Exception:
|
|
89
|
+
return str(err)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class _SafeRegisteredTool(RegisteredTool):
|
|
93
|
+
"""``RegisteredTool`` subclass with the safe-envelope try/except baked into ``__call__``.
|
|
94
|
+
|
|
95
|
+
We can't reuse ``RegisteredTool``'s wrapper because that one stringifies the result; here we
|
|
96
|
+
serialize via ``json.dumps`` so the model receives a proper envelope, not ``str({...})``."""
|
|
97
|
+
|
|
98
|
+
async def __call__(self, _ctx: Any = None, **kwargs: Any) -> str:
|
|
99
|
+
if self._wants_ctx:
|
|
100
|
+
kwargs["ctx"] = _ctx
|
|
101
|
+
try:
|
|
102
|
+
result = self.fn(**kwargs)
|
|
103
|
+
if inspect.isawaitable(result):
|
|
104
|
+
result = await result
|
|
105
|
+
if isinstance(result, AsyncIterable):
|
|
106
|
+
# Streaming safe_tool: collect chunks, then envelope. Authors who want streaming
|
|
107
|
+
# output should use the classic ``streaming_tool`` + raise convention; ``safe_tool``
|
|
108
|
+
# is for the structured envelope path.
|
|
109
|
+
chunks: list[str] = []
|
|
110
|
+
async for chunk in result:
|
|
111
|
+
chunks.append(chunk if isinstance(chunk, str) else str(chunk))
|
|
112
|
+
result = "".join(chunks)
|
|
113
|
+
if _is_envelope(result):
|
|
114
|
+
return json.dumps(result)
|
|
115
|
+
return json.dumps(ok(result))
|
|
116
|
+
except ToolError as e:
|
|
117
|
+
return json.dumps(fail(e.code, str(e) or type(e).__name__, e.hint))
|
|
118
|
+
except Exception as e:
|
|
119
|
+
code = getattr(e, "code", None)
|
|
120
|
+
hint = getattr(e, "hint", None)
|
|
121
|
+
code_str = code if isinstance(code, str) else "internal"
|
|
122
|
+
hint_str = hint if isinstance(hint, str) else None
|
|
123
|
+
return json.dumps(fail(code_str, str(e) or type(e).__name__, hint_str))
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def safe_tool(fn: Callable) -> RegisteredTool:
|
|
127
|
+
"""``tool()`` equivalent that wraps the body in a try/except and returns a stable
|
|
128
|
+
``{success, code, error, hint?}`` JSON envelope to the model. Drop-in: ``@safe_tool``
|
|
129
|
+
instead of ``@tool``.
|
|
130
|
+
|
|
131
|
+
The body may return plain data (auto-wrapped as ``ok(data)``), an envelope produced by
|
|
132
|
+
``ok()`` / ``fail()`` (passed through), or raise — ``ToolError`` becomes a fail envelope
|
|
133
|
+
with the ``code`` and ``hint``; any other ``Exception`` becomes ``{success:false, code:
|
|
134
|
+
err.code if str else "internal", error: str(err)}``."""
|
|
135
|
+
return _SafeRegisteredTool(fn, _schema_for(fn))
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
import json
|
|
3
3
|
from deepstrike._kernel import ToolCall, ToolResult
|
|
4
4
|
from collections.abc import AsyncIterable
|
|
5
|
+
from .errors import format_tool_error
|
|
5
6
|
from .registry import RegisteredTool, tool_chunk_text, validate_tool_arguments
|
|
6
7
|
|
|
7
8
|
|
|
@@ -29,5 +30,5 @@ async def execute_tools(
|
|
|
29
30
|
output = "".join(chunks)
|
|
30
31
|
results.append(ToolResult(call_id=call.id, output=str(output)))
|
|
31
32
|
except Exception as exc:
|
|
32
|
-
results.append(ToolResult(call_id=call.id, output=
|
|
33
|
+
results.append(ToolResult(call_id=call.id, output=format_tool_error(exc), is_error=True))
|
|
33
34
|
return results
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/governance/tool_decision.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/orchestration/task_graph.rs
RENAMED
|
File without changes
|
{deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/orchestration/tournament.rs
RENAMED
|
File without changes
|
{deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/orchestration/workflow/mod.rs
RENAMED
|
File without changes
|
{deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/orchestration/workflow/run.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/state_machine/gate.rs
RENAMED
|
File without changes
|
|
File without changes
|
{deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/state_machine/mod.rs
RENAMED
|
File without changes
|
|
File without changes
|
{deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/state_machine/signal.rs
RENAMED
|
File without changes
|
{deepstrike-0.2.23 → deepstrike-0.2.24}/crates/deepstrike-core/src/scheduler/state_machine/tests.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|