deepstrike 0.2.35__tar.gz → 0.2.37__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.35 → deepstrike-0.2.37}/Cargo.lock +5 -5
- {deepstrike-0.2.35 → deepstrike-0.2.37}/Cargo.toml +2 -2
- {deepstrike-0.2.35 → deepstrike-0.2.37}/PKG-INFO +4 -4
- {deepstrike-0.2.35 → deepstrike-0.2.37}/README.md +3 -3
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/context/compression.rs +29 -126
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/context/config.rs +9 -16
- deepstrike-0.2.37/crates/deepstrike-core/src/context/fault.rs +23 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/context/manager.rs +264 -206
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/context/mod.rs +1 -3
- deepstrike-0.2.37/crates/deepstrike-core/src/context/partitions.rs +331 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/context/renderer.rs +16 -9
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/context/renewal.rs +10 -51
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/context/summarizer.rs +5 -8
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/governance/constraint.rs +1 -5
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/governance/mod.rs +1 -3
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/governance/permission.rs +5 -17
- deepstrike-0.2.37/crates/deepstrike-core/src/governance/pipeline.rs +236 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/governance/quota.rs +0 -27
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/governance/rate_limit.rs +0 -4
- deepstrike-0.2.37/crates/deepstrike-core/src/governance/repeat_fuse.rs +48 -0
- deepstrike-0.2.37/crates/deepstrike-core/src/governance/veto.rs +71 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/lib.rs +5 -14
- deepstrike-0.2.37/crates/deepstrike-core/src/memory/durable.rs +15 -0
- deepstrike-0.2.37/crates/deepstrike-core/src/memory/mod.rs +13 -0
- deepstrike-0.2.37/crates/deepstrike-core/src/memory/semantic.rs +10 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/mm/memory.rs +12 -100
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/mm/mod.rs +6 -57
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/orchestration/task_graph.rs +53 -7
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/orchestration/tournament.rs +0 -4
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/orchestration/workflow/mod.rs +43 -73
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/orchestration/workflow/run.rs +491 -56
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/proc/mod.rs +11 -21
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/runtime/event_log.rs +2 -39
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/runtime/kernel.rs +478 -154
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/runtime/mod.rs +2 -4
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/runtime/repair.rs +2 -6
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/runtime/replay.rs +4 -46
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/runtime/session.rs +1 -124
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/scheduler/milestone.rs +33 -24
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/scheduler/mod.rs +1 -1
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/scheduler/policy.rs +0 -4
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/scheduler/state_machine/eviction.rs +37 -27
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/scheduler/state_machine/gate.rs +136 -61
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/scheduler/state_machine/milestone_exec.rs +30 -44
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/scheduler/state_machine/mod.rs +317 -163
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/scheduler/state_machine/process.rs +4 -4
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/scheduler/state_machine/signal.rs +17 -27
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/scheduler/state_machine/tests.rs +507 -189
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/scheduler/state_machine/workflow.rs +96 -38
- deepstrike-0.2.37/crates/deepstrike-core/src/scheduler/tcb.rs +311 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/signals/attention.rs +5 -5
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/signals/queue.rs +0 -33
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/signals/router.rs +4 -57
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/syscall/mod.rs +1 -42
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/types/agent.rs +25 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/types/mod.rs +0 -1
- deepstrike-0.2.37/crates/deepstrike-core/src/types/policy.rs +45 -0
- deepstrike-0.2.37/crates/deepstrike-core/src/types/result.rs +145 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/types/task.rs +5 -11
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-py/src/lib.rs +2 -20
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/__init__.py +15 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/stream.py +3 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/__init__.py +17 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/facade.py +8 -5
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/kernel_event_log.py +34 -60
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/kernel_step.py +13 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/large_result_spool.py +20 -0
- deepstrike-0.2.37/deepstrike/runtime/loop_driver.py +292 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/os_snapshot.py +0 -16
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/reactive_session.py +12 -3
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/run_group.py +30 -12
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/runner.py +662 -151
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/session_log.py +8 -56
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/session_repair.py +75 -22
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/sub_agent_orchestrator.py +73 -32
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/workflow_control_flow.py +30 -6
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/signals/gateway.py +14 -1
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/types/agent.py +62 -2
- {deepstrike-0.2.35 → deepstrike-0.2.37}/pyproject.toml +1 -1
- deepstrike-0.2.35/crates/deepstrike-core/src/context/dashboard.rs +0 -149
- deepstrike-0.2.35/crates/deepstrike-core/src/context/partitions.rs +0 -127
- deepstrike-0.2.35/crates/deepstrike-core/src/context/sections.rs +0 -366
- deepstrike-0.2.35/crates/deepstrike-core/src/context/snapshot.rs +0 -166
- deepstrike-0.2.35/crates/deepstrike-core/src/governance/audit.rs +0 -87
- deepstrike-0.2.35/crates/deepstrike-core/src/governance/pipeline.rs +0 -357
- deepstrike-0.2.35/crates/deepstrike-core/src/governance/sandbox.rs +0 -137
- deepstrike-0.2.35/crates/deepstrike-core/src/governance/tool_decision.rs +0 -145
- deepstrike-0.2.35/crates/deepstrike-core/src/governance/veto.rs +0 -151
- deepstrike-0.2.35/crates/deepstrike-core/src/memory/durable.rs +0 -95
- deepstrike-0.2.35/crates/deepstrike-core/src/memory/extractor.rs +0 -103
- deepstrike-0.2.35/crates/deepstrike-core/src/memory/mod.rs +0 -10
- deepstrike-0.2.35/crates/deepstrike-core/src/memory/runtime.rs +0 -123
- deepstrike-0.2.35/crates/deepstrike-core/src/memory/semantic.rs +0 -102
- deepstrike-0.2.35/crates/deepstrike-core/src/memory/session.rs +0 -152
- deepstrike-0.2.35/crates/deepstrike-core/src/memory/working.rs +0 -44
- deepstrike-0.2.35/crates/deepstrike-core/src/runtime/snapshot.rs +0 -507
- deepstrike-0.2.35/crates/deepstrike-core/src/scheduler/tcb.rs +0 -1018
- deepstrike-0.2.35/crates/deepstrike-core/src/types/model.rs +0 -34
- deepstrike-0.2.35/crates/deepstrike-core/src/types/policy.rs +0 -60
- deepstrike-0.2.35/crates/deepstrike-core/src/types/result.rs +0 -58
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/Cargo.toml +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/context/pressure.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/context/skill_catalog.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/context/task_state.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/context/text.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/context/token_engine.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/harness/eval.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/harness/mod.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/memory/curator.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/memory/idle_pipeline.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/memory/synthesis.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/memory/trace_analyzer.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/mm/handle.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/orchestration/mod.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/scheduler/rollback.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/scheduler/state_machine/capability.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/signals/mod.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/types/capability.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/types/contract.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/types/error.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/types/message.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/types/milestone.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/types/signal.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-core/src/types/skill.rs +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/crates/deepstrike-py/Cargo.toml +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/collaboration/__init__.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/collaboration/contract.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/collaboration/handoff.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/collaboration/harness.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/collaboration/modes.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/collaboration/pool.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/governance.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/harness/__init__.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/harness/harness.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/harness/judge.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/kernel/__init__.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/knowledge/__init__.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/knowledge/source.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/memory/__init__.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/memory/agent.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/memory/in_memory_store.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/memory/protocols.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/memory/working.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/__init__.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/anthropic.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/anthropic_compatible.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/base.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/deepseek.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/factories.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/gemini.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/glm.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/kimi.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/minimax.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/ollama.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/openai.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/openai_responses.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/qwen.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/replay.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/replay_validator.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/providers/vendor_profiles.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/archive.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/credential_vault.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/eval.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/event_stream.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/execution_plane.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/filtered_plane.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/mcp_proxy_plane.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/os_profile.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/output_schema.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/process_sandbox_plane.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/provider_replay.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/reducers.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/remote_vpc_plane.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/replay_fixture.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/replay_provider.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/replay_sanitize.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/turn_policy.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/workflow_store.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/runtime/worktree_plane.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/safety/__init__.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/safety/permissions.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/signals/__init__.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/signals/scheduled.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/signals/types.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/skills/__init__.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/skills/registry.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/skills/watcher.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/tools/__init__.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/tools/builtin/__init__.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/tools/builtin/read_file.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/tools/errors.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/tools/execution.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/tools/registry.py +0 -0
- {deepstrike-0.2.35 → deepstrike-0.2.37}/deepstrike/types/__init__.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.37"
|
|
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.37"
|
|
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.37"
|
|
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.37"
|
|
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.37"
|
|
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.37"
|
|
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.37" }
|
|
13
13
|
notify = "6"
|
|
14
14
|
serde = { version = "1", features = ["derive"] }
|
|
15
15
|
serde_json = "1"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepstrike
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.37
|
|
4
4
|
Requires-Dist: httpx>=0.27
|
|
5
5
|
Requires-Dist: pyyaml>=6.0
|
|
6
6
|
Requires-Dist: anyio>=4.0
|
|
@@ -149,7 +149,7 @@ The mechanisms above are not internal refactors — they change what you can bui
|
|
|
149
149
|
Tool calls, spawns, compression, and signals pass through one kernel gate with an explicit lifecycle (Ready / Running / Blocked / Suspended). You implement I/O; the kernel decides *when* and *whether*. Node, Python, and Rust share the same decision path, so `wake(session_id)` and cross-language tooling see consistent behavior.
|
|
150
150
|
|
|
151
151
|
**Longer, sturdier sessions (Layer-1 spool + semantic page-out)**
|
|
152
|
-
Oversized tool results (> 50 KB) stay in context as a preview plus a `.spool/` reference — the model reads the full payload on demand via ordinary file tools. When pressure triggers semantic eviction, the SDK summarizes archived content into `DreamStore
|
|
152
|
+
Oversized tool results (> 50 KB) stay in context as a preview plus a `.spool/` reference — the model reads the full payload on demand via ordinary file tools. When pressure triggers semantic eviction, the SDK summarizes archived content into `DreamStore`. Long tasks survive token pressure instead of failing mid-run.
|
|
153
153
|
|
|
154
154
|
**Safety and governance by default (OS native profile)**
|
|
155
155
|
Every run loads declarative `governance_policy` (deny / ask_user / rate-limit / param rules) and in-kernel signal routing (`attention_policy`, default queue 64). Dangerous tools, external interrupts, and approval flows are policy — not ad-hoc checks in your handlers.
|
|
@@ -443,9 +443,9 @@ effort: 1
|
|
|
443
443
|
|
|
444
444
|
## Knowledge
|
|
445
445
|
|
|
446
|
-
Implement `KnowledgeSource` — the kernel injects a `knowledge` meta-tool. Runtime retrieval results land in **history** as tool results. Use `initial_memory` for durable preload into Slot 2.
|
|
446
|
+
Implement `KnowledgeSource` — the kernel injects a `knowledge` meta-tool. Runtime retrieval results land in **history** as tool results (single-use fact content that decays with compaction), not in the durable `knowledge` partition. Use `initial_memory` for durable preload into Slot 2.
|
|
447
447
|
|
|
448
|
-
|
|
448
|
+
For durable content at runtime use `runner.push_knowledge(content, key=..., pinned=...)` — a **keyed** entry upserts on a repeated key and `runner.remove_knowledge(key)` removes it, both applied at the next compaction/renewal boundary. `knowledge_budget_ratio` (default 0.25, 0 disables) caps the partition: over budget, the oldest unpinned, non-skill entries are evicted at boundaries while `pinned=True` entries survive. A loaded skill's body is pinned here as `skill:<name>` and unpinned by `runner.deactivate_skill(name)` or a `skill_lease_turns` expiry.
|
|
449
449
|
|
|
450
450
|
```python
|
|
451
451
|
from deepstrike import KnowledgeSource
|
|
@@ -136,7 +136,7 @@ The mechanisms above are not internal refactors — they change what you can bui
|
|
|
136
136
|
Tool calls, spawns, compression, and signals pass through one kernel gate with an explicit lifecycle (Ready / Running / Blocked / Suspended). You implement I/O; the kernel decides *when* and *whether*. Node, Python, and Rust share the same decision path, so `wake(session_id)` and cross-language tooling see consistent behavior.
|
|
137
137
|
|
|
138
138
|
**Longer, sturdier sessions (Layer-1 spool + semantic page-out)**
|
|
139
|
-
Oversized tool results (> 50 KB) stay in context as a preview plus a `.spool/` reference — the model reads the full payload on demand via ordinary file tools. When pressure triggers semantic eviction, the SDK summarizes archived content into `DreamStore
|
|
139
|
+
Oversized tool results (> 50 KB) stay in context as a preview plus a `.spool/` reference — the model reads the full payload on demand via ordinary file tools. When pressure triggers semantic eviction, the SDK summarizes archived content into `DreamStore`. Long tasks survive token pressure instead of failing mid-run.
|
|
140
140
|
|
|
141
141
|
**Safety and governance by default (OS native profile)**
|
|
142
142
|
Every run loads declarative `governance_policy` (deny / ask_user / rate-limit / param rules) and in-kernel signal routing (`attention_policy`, default queue 64). Dangerous tools, external interrupts, and approval flows are policy — not ad-hoc checks in your handlers.
|
|
@@ -430,9 +430,9 @@ effort: 1
|
|
|
430
430
|
|
|
431
431
|
## Knowledge
|
|
432
432
|
|
|
433
|
-
Implement `KnowledgeSource` — the kernel injects a `knowledge` meta-tool. Runtime retrieval results land in **history** as tool results. Use `initial_memory` for durable preload into Slot 2.
|
|
433
|
+
Implement `KnowledgeSource` — the kernel injects a `knowledge` meta-tool. Runtime retrieval results land in **history** as tool results (single-use fact content that decays with compaction), not in the durable `knowledge` partition. Use `initial_memory` for durable preload into Slot 2.
|
|
434
434
|
|
|
435
|
-
|
|
435
|
+
For durable content at runtime use `runner.push_knowledge(content, key=..., pinned=...)` — a **keyed** entry upserts on a repeated key and `runner.remove_knowledge(key)` removes it, both applied at the next compaction/renewal boundary. `knowledge_budget_ratio` (default 0.25, 0 disables) caps the partition: over budget, the oldest unpinned, non-skill entries are evicted at boundaries while `pinned=True` entries survive. A loaded skill's body is pinned here as `skill:<name>` and unpinned by `runner.deactivate_skill(name)` or a `skill_lease_turns` expiry.
|
|
436
436
|
|
|
437
437
|
```python
|
|
438
438
|
from deepstrike import KnowledgeSource
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
use super::config::ContextConfig;
|
|
2
2
|
use super::partitions::ContextPartitions;
|
|
3
3
|
use super::pressure::PressureAction;
|
|
4
|
-
use super::summarizer::Summarizer;
|
|
5
4
|
use super::token_engine::ContextTokenEngine;
|
|
6
5
|
use crate::types::message::{Content, ContentPart, Message};
|
|
7
6
|
|
|
@@ -28,7 +27,6 @@ pub trait Compressor: Send + Sync {
|
|
|
28
27
|
target_tokens: u32,
|
|
29
28
|
max_tokens: u32,
|
|
30
29
|
preserve_k: usize,
|
|
31
|
-
summarizer: &dyn Summarizer,
|
|
32
30
|
engine: &ContextTokenEngine,
|
|
33
31
|
) -> CompressResult;
|
|
34
32
|
}
|
|
@@ -45,7 +43,6 @@ impl Compressor for SnipCompactor {
|
|
|
45
43
|
_target_tokens: u32,
|
|
46
44
|
max_tokens: u32,
|
|
47
45
|
preserve_k: usize,
|
|
48
|
-
_summarizer: &dyn Summarizer,
|
|
49
46
|
engine: &ContextTokenEngine,
|
|
50
47
|
) -> CompressResult {
|
|
51
48
|
let per_msg_limit = ((max_tokens as f64 * self.per_msg_ratio) as u32).max(50);
|
|
@@ -63,40 +60,17 @@ impl Compressor for SnipCompactor {
|
|
|
63
60
|
for &i in &indices {
|
|
64
61
|
let msg = &mut partition.messages[i];
|
|
65
62
|
let original_tokens = msg.token_count.unwrap_or_else(|| engine.count_message(msg));
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if mid >= chars.len() {
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
80
|
-
let candidate: String = chars[mid..].iter().collect();
|
|
81
|
-
let tokens = engine.count(&candidate);
|
|
82
|
-
if tokens <= tail_limit {
|
|
83
|
-
suffix_start = mid;
|
|
84
|
-
if mid == 0 {
|
|
85
|
-
break;
|
|
86
|
-
}
|
|
87
|
-
high = mid - 1;
|
|
88
|
-
} else {
|
|
89
|
-
low = mid + 1;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
let tail_text: String = chars[suffix_start..].iter().collect();
|
|
93
|
-
let omitted = original_tokens
|
|
94
|
-
.saturating_sub(head_limit)
|
|
95
|
-
.saturating_sub(tail_limit);
|
|
96
|
-
msg.content = Content::Text(format!(
|
|
97
|
-
"{}… [… {} tokens omitted …] …{}",
|
|
98
|
-
head_text, omitted, tail_text
|
|
99
|
-
));
|
|
63
|
+
let head_limit = per_msg_limit / 2;
|
|
64
|
+
let tail_limit = per_msg_limit.saturating_sub(head_limit);
|
|
65
|
+
// Same head/tail elision as excerpt_text; the omitted count comes from the recorded
|
|
66
|
+
// token metadata (not a recount) so the elision marker matches the saved accounting.
|
|
67
|
+
let snipped = if let Content::Text(ref t) = msg.content {
|
|
68
|
+
Some(excerpt_text_with_total(t, head_limit, tail_limit, engine, original_tokens))
|
|
69
|
+
} else {
|
|
70
|
+
None
|
|
71
|
+
};
|
|
72
|
+
if let Some(text) = snipped {
|
|
73
|
+
msg.content = Content::Text(text);
|
|
100
74
|
msg.token_count = Some(per_msg_limit);
|
|
101
75
|
saved += original_tokens.saturating_sub(per_msg_limit);
|
|
102
76
|
}
|
|
@@ -157,13 +131,6 @@ fn oversized_text_message_indices(
|
|
|
157
131
|
.collect()
|
|
158
132
|
}
|
|
159
133
|
|
|
160
|
-
/// 获取当前UTC时间戳
|
|
161
|
-
fn utc_now() -> String {
|
|
162
|
-
// 在实际使用中,这应该从ProviderResult.now_ms获取
|
|
163
|
-
// 这里简化为占位符
|
|
164
|
-
format!("{:?}", std::time::SystemTime::now())
|
|
165
|
-
}
|
|
166
|
-
|
|
167
134
|
/// Helper to extract key fields and info from JSON strings.
|
|
168
135
|
fn extract_json_excerpt(output: &str) -> Option<String> {
|
|
169
136
|
let val: serde_json::Value = serde_json::from_str(output).ok()?;
|
|
@@ -215,7 +182,18 @@ fn excerpt_text(
|
|
|
215
182
|
tail_tokens: u32,
|
|
216
183
|
engine: &ContextTokenEngine,
|
|
217
184
|
) -> String {
|
|
218
|
-
|
|
185
|
+
excerpt_text_with_total(text, head_tokens, tail_tokens, engine, engine.count(text))
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/// [`excerpt_text`] with the total token count supplied by the caller (e.g. from recorded
|
|
189
|
+
/// message metadata) instead of recounted — the count only feeds the elision marker.
|
|
190
|
+
fn excerpt_text_with_total(
|
|
191
|
+
text: &str,
|
|
192
|
+
head_tokens: u32,
|
|
193
|
+
tail_tokens: u32,
|
|
194
|
+
engine: &ContextTokenEngine,
|
|
195
|
+
total_tokens: u32,
|
|
196
|
+
) -> String {
|
|
219
197
|
if total_tokens <= head_tokens + tail_tokens {
|
|
220
198
|
return text.to_string();
|
|
221
199
|
}
|
|
@@ -295,7 +273,6 @@ impl Compressor for MicroCompactor {
|
|
|
295
273
|
_target_tokens: u32,
|
|
296
274
|
_max_tokens: u32,
|
|
297
275
|
preserve_k: usize,
|
|
298
|
-
_summarizer: &dyn Summarizer,
|
|
299
276
|
engine: &ContextTokenEngine,
|
|
300
277
|
) -> CompressResult {
|
|
301
278
|
let find_tool_name = |call_id: &str, msgs: &[Message]| -> Option<String> {
|
|
@@ -416,7 +393,6 @@ impl Compressor for CollapseCompactor {
|
|
|
416
393
|
target_tokens: u32,
|
|
417
394
|
_max_tokens: u32,
|
|
418
395
|
preserve_k: usize,
|
|
419
|
-
_summarizer: &dyn Summarizer,
|
|
420
396
|
engine: &ContextTokenEngine,
|
|
421
397
|
) -> CompressResult {
|
|
422
398
|
let partition = &mut partitions.history;
|
|
@@ -452,7 +428,6 @@ impl Compressor for AutoCompactor {
|
|
|
452
428
|
_target_tokens: u32,
|
|
453
429
|
_max_tokens: u32,
|
|
454
430
|
preserve_k: usize,
|
|
455
|
-
_summarizer: &dyn Summarizer,
|
|
456
431
|
engine: &ContextTokenEngine,
|
|
457
432
|
) -> CompressResult {
|
|
458
433
|
let partition = &mut partitions.history;
|
|
@@ -496,47 +471,6 @@ impl Compressor for AutoCompactor {
|
|
|
496
471
|
}
|
|
497
472
|
}
|
|
498
473
|
|
|
499
|
-
// ─── Cache-aware compaction (W1-1 step 2) ───────────────────────────────────────────────────────
|
|
500
|
-
// Additive cost model: introduced + tested before it drives the cascade, so the behavior-changing
|
|
501
|
-
// wiring (prefix-safe-first selection + batching, with golden updates) is a separate, reviewable step.
|
|
502
|
-
|
|
503
|
-
/// A fully-specified compaction step the cache-aware planner emits; the executor applies it
|
|
504
|
-
/// mechanically (all *selection* already done by the planner via the pure helpers above).
|
|
505
|
-
#[derive(Debug, Clone, PartialEq)]
|
|
506
|
-
pub enum CompactionStep {
|
|
507
|
-
/// Excerpt the tool results at these history-message indices. Prefix-safe in practice: tool
|
|
508
|
-
/// results are interleaved mid/late, so the earliest touched index is rarely the cache prefix.
|
|
509
|
-
Excerpt { msg_idx: Vec<usize> },
|
|
510
|
-
/// Cap the oversized text messages at these indices to `per_msg_limit`.
|
|
511
|
-
Snip { msg_idx: Vec<usize>, per_msg_limit: u32 },
|
|
512
|
-
/// Drop the `count` oldest messages (the pipeline summarizes them). Prefix-breaking at index 0.
|
|
513
|
-
DropOldest { count: usize },
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
impl CompactionStep {
|
|
517
|
-
/// The earliest history-message index this step rewrites or removes — i.e. where it invalidates
|
|
518
|
-
/// the prompt-cache prefix. `None` = prefix-safe (touches nothing). A lower index is a higher
|
|
519
|
-
/// cache cost (Anthropic keys the cache off the first N messages), so the planner prefers `None`
|
|
520
|
-
/// or a later index, and escalates to a prefix-breaking drop only when the safe steps can't free
|
|
521
|
-
/// enough.
|
|
522
|
-
pub fn invalidates_prefix_at(&self) -> Option<usize> {
|
|
523
|
-
match self {
|
|
524
|
-
CompactionStep::Excerpt { msg_idx } | CompactionStep::Snip { msg_idx, .. } => {
|
|
525
|
-
msg_idx.iter().min().copied()
|
|
526
|
-
}
|
|
527
|
-
CompactionStep::DropOldest { count } => (*count > 0).then_some(0),
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
/// The prompt-cache-invalidation index of a whole plan = the earliest break across its steps (an
|
|
533
|
-
/// earlier break invalidates everything after it, so the minimum dominates the cost). `None` means
|
|
534
|
-
/// the plan is entirely prefix-safe and preserves the prompt cache — the cache-aware planner's goal
|
|
535
|
-
/// whenever the safe steps can free enough.
|
|
536
|
-
pub fn plan_cache_cost(steps: &[CompactionStep]) -> Option<usize> {
|
|
537
|
-
steps.iter().filter_map(|s| s.invalidates_prefix_at()).min()
|
|
538
|
-
}
|
|
539
|
-
|
|
540
474
|
/// Compression pipeline — operates on history partition but can reference full partitions.
|
|
541
475
|
pub struct CompressionPipeline {
|
|
542
476
|
stages: Vec<(PressureAction, Box<dyn Compressor>)>,
|
|
@@ -590,7 +524,6 @@ impl CompressionPipeline {
|
|
|
590
524
|
target_tokens,
|
|
591
525
|
max_tokens,
|
|
592
526
|
self.preserve_recent_turns,
|
|
593
|
-
&summarizer,
|
|
594
527
|
engine,
|
|
595
528
|
);
|
|
596
529
|
total_saved += res.tokens_saved;
|
|
@@ -647,7 +580,7 @@ mod tests {
|
|
|
647
580
|
let mut ctx = ContextPartitions::new(&cfg);
|
|
648
581
|
ctx.history.push(Message::user("a".repeat(800)), 200);
|
|
649
582
|
// preserve_k=0: exercise the truncation transform directly (no cache-prefix protection).
|
|
650
|
-
let result = compactor.compress(&mut ctx, 0, MAX, 0, &
|
|
583
|
+
let result = compactor.compress(&mut ctx, 0, MAX, 0, &engine());
|
|
651
584
|
assert!(result.tokens_saved > 0);
|
|
652
585
|
if let Content::Text(ref t) = ctx.history.messages[0].content {
|
|
653
586
|
assert!(t.contains("… [… 100 tokens omitted …] …"), "got: {t}");
|
|
@@ -665,7 +598,7 @@ mod tests {
|
|
|
665
598
|
};
|
|
666
599
|
let mut ctx = ContextPartitions::new(&cfg);
|
|
667
600
|
ctx.history.push(Message::user("short"), 5);
|
|
668
|
-
let result = compactor.compress(&mut ctx, 0, MAX, 2, &
|
|
601
|
+
let result = compactor.compress(&mut ctx, 0, MAX, 2, &engine());
|
|
669
602
|
assert_eq!(result.tokens_saved, 0);
|
|
670
603
|
}
|
|
671
604
|
|
|
@@ -691,7 +624,7 @@ mod tests {
|
|
|
691
624
|
ctx.history.token_count = 300;
|
|
692
625
|
|
|
693
626
|
// preserve_k=0: exercise the excerpt transform directly (no cache-prefix protection).
|
|
694
|
-
let result = compactor.compress(&mut ctx, 0, MAX, 0, &
|
|
627
|
+
let result = compactor.compress(&mut ctx, 0, MAX, 0, &engine());
|
|
695
628
|
assert!(result.tokens_saved > 0);
|
|
696
629
|
let text = ctx.history.messages[0].content.as_text().unwrap();
|
|
697
630
|
assert!(
|
|
@@ -707,7 +640,7 @@ mod tests {
|
|
|
707
640
|
for _ in 0..8 {
|
|
708
641
|
ctx.history.push(Message::user("msg"), 50);
|
|
709
642
|
}
|
|
710
|
-
let result = compactor.compress(&mut ctx, 250, MAX, 2, &
|
|
643
|
+
let result = compactor.compress(&mut ctx, 250, MAX, 2, &engine());
|
|
711
644
|
assert!(result.tokens_saved > 0);
|
|
712
645
|
assert!(ctx.history.messages.len() < 8);
|
|
713
646
|
// Pure executor: returns the drained messages; summary + log attribution is the pipeline's
|
|
@@ -764,7 +697,7 @@ mod tests {
|
|
|
764
697
|
ctx.history.messages.push(msg);
|
|
765
698
|
ctx.history.token_count = 300;
|
|
766
699
|
|
|
767
|
-
let result = compactor.compress(&mut ctx, 0, MAX, 2, &
|
|
700
|
+
let result = compactor.compress(&mut ctx, 0, MAX, 2, &engine());
|
|
768
701
|
// Since call_id "keep_me" is in preserved_refs, it should not be replaced!
|
|
769
702
|
assert_eq!(result.tokens_saved, 0);
|
|
770
703
|
let text_opt = ctx.history.messages[0].content.as_text();
|
|
@@ -781,7 +714,7 @@ mod tests {
|
|
|
781
714
|
for i in 0..10 {
|
|
782
715
|
ctx.history.push(Message::user(format!("msg {i}")), 10);
|
|
783
716
|
}
|
|
784
|
-
let result = compactor.compress(&mut ctx, 0, MAX, 2, &
|
|
717
|
+
let result = compactor.compress(&mut ctx, 0, MAX, 2, &engine());
|
|
785
718
|
assert!(result.tokens_saved > 0);
|
|
786
719
|
assert_eq!(ctx.history.messages.len(), 4); // kept last 2 turns = 4 messages
|
|
787
720
|
// Pure executor: returns the drained messages; the pipeline summarizes + logs under the
|
|
@@ -820,36 +753,6 @@ mod tests {
|
|
|
820
753
|
assert_eq!(prefix_keep_for(0, 2), 0);
|
|
821
754
|
}
|
|
822
755
|
|
|
823
|
-
#[test]
|
|
824
|
-
fn compaction_step_prefix_cost() {
|
|
825
|
-
// Excerpt/Snip cost = the earliest touched message index; DropOldest breaks the prefix at 0.
|
|
826
|
-
assert_eq!(CompactionStep::Excerpt { msg_idx: vec![5, 8] }.invalidates_prefix_at(), Some(5));
|
|
827
|
-
assert_eq!(
|
|
828
|
-
CompactionStep::Snip { msg_idx: vec![3, 9], per_msg_limit: 50 }.invalidates_prefix_at(),
|
|
829
|
-
Some(3)
|
|
830
|
-
);
|
|
831
|
-
assert_eq!(CompactionStep::DropOldest { count: 4 }.invalidates_prefix_at(), Some(0));
|
|
832
|
-
assert_eq!(CompactionStep::DropOldest { count: 0 }.invalidates_prefix_at(), None);
|
|
833
|
-
// An empty selection touches nothing → prefix-safe.
|
|
834
|
-
assert_eq!(CompactionStep::Excerpt { msg_idx: vec![] }.invalidates_prefix_at(), None);
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
#[test]
|
|
838
|
-
fn plan_cache_cost_is_the_earliest_break() {
|
|
839
|
-
// Cost of a plan = the earliest message any step touches (an earlier break dominates).
|
|
840
|
-
let late = vec![
|
|
841
|
-
CompactionStep::Excerpt { msg_idx: vec![6] },
|
|
842
|
-
CompactionStep::Snip { msg_idx: vec![7], per_msg_limit: 50 },
|
|
843
|
-
];
|
|
844
|
-
assert_eq!(plan_cache_cost(&late), Some(6));
|
|
845
|
-
// Escalating to a DropOldest breaks the prefix at 0 — the whole plan's cost collapses to 0.
|
|
846
|
-
let mut with_drop = late.clone();
|
|
847
|
-
with_drop.push(CompactionStep::DropOldest { count: 3 });
|
|
848
|
-
assert_eq!(plan_cache_cost(&with_drop), Some(0));
|
|
849
|
-
// An empty plan preserves the cache entirely.
|
|
850
|
-
assert_eq!(plan_cache_cost(&[]), None);
|
|
851
|
-
}
|
|
852
|
-
|
|
853
756
|
#[test]
|
|
854
757
|
fn pipeline_reports_accurate_prefix_invalidation() {
|
|
855
758
|
// (a) DoD #4: the pipeline surfaces the earliest message any stage actually touched. On the
|
|
@@ -41,10 +41,6 @@ pub struct ContextConfig {
|
|
|
41
41
|
pub preserve_recent_turns: usize,
|
|
42
42
|
|
|
43
43
|
// ── Noise reduction ──────────────────────────────────────────────────────
|
|
44
|
-
/// Include the dashboard block in the rendered system context.
|
|
45
|
-
/// Defaults to false; enable only in explicit agent-os mode.
|
|
46
|
-
pub render_dashboard: bool,
|
|
47
|
-
|
|
48
44
|
/// Use verbose internal control notes (e.g. "[SYSTEM] Transaction rollback: …").
|
|
49
45
|
/// Defaults to false; uses concise natural-language notes instead.
|
|
50
46
|
pub verbose_control_notes: bool,
|
|
@@ -83,18 +79,16 @@ pub struct ContextConfig {
|
|
|
83
79
|
|
|
84
80
|
/// Preview byte budget kept in context when a tool result is spooled. Default: 2 KiB.
|
|
85
81
|
pub spool_preview_bytes: u32,
|
|
86
|
-
}
|
|
87
82
|
|
|
88
|
-
|
|
89
|
-
60
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
fn default_preserved_tool_results() -> usize {
|
|
93
|
-
5
|
|
94
|
-
}
|
|
83
|
+
// ── K2: knowledge budget ─────────────────────────────────────────────
|
|
95
84
|
|
|
96
|
-
|
|
97
|
-
|
|
85
|
+
/// Max share of `max_tokens` the knowledge partition may occupy. Exceeding it emits a
|
|
86
|
+
/// `KnowledgeBudgetExceeded` observation (once per cache generation) and marks the OLDEST
|
|
87
|
+
/// unpinned, non-skill entries for eviction at the next compaction/renewal boundary until the
|
|
88
|
+
/// projected usage fits. Pinned entries and `skill:`-keyed pins are never budget-evicted
|
|
89
|
+
/// (skills are governed by deactivation/lease, not the budget). `0.0` disables (no cap).
|
|
90
|
+
/// Default: 0.25.
|
|
91
|
+
pub knowledge_budget_ratio: f64,
|
|
98
92
|
}
|
|
99
93
|
|
|
100
94
|
impl Default for ContextConfig {
|
|
@@ -111,7 +105,6 @@ impl Default for ContextConfig {
|
|
|
111
105
|
recovery_content_ratio: 0.25,
|
|
112
106
|
preserve_recent_msgs: 4,
|
|
113
107
|
preserve_recent_turns: 2,
|
|
114
|
-
render_dashboard: false,
|
|
115
108
|
verbose_control_notes: false,
|
|
116
109
|
collapse_assistant_narration: true,
|
|
117
110
|
micro_compact_idle_minutes: 60,
|
|
@@ -119,6 +112,7 @@ impl Default for ContextConfig {
|
|
|
119
112
|
autocompact_buffer: 13_000,
|
|
120
113
|
spool_threshold_bytes: 50 * 1024,
|
|
121
114
|
spool_preview_bytes: 2 * 1024,
|
|
115
|
+
knowledge_budget_ratio: 0.25,
|
|
122
116
|
}
|
|
123
117
|
}
|
|
124
118
|
}
|
|
@@ -159,7 +153,6 @@ mod tests {
|
|
|
159
153
|
#[test]
|
|
160
154
|
fn noise_reduction_defaults_to_quiet() {
|
|
161
155
|
let c = ContextConfig::default();
|
|
162
|
-
assert!(!c.render_dashboard, "dashboard should be off by default");
|
|
163
156
|
assert!(!c.verbose_control_notes, "verbose notes should be off by default");
|
|
164
157
|
}
|
|
165
158
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
use serde::{Deserialize, Serialize};
|
|
2
|
+
|
|
3
|
+
/// Errors/Faults that can occur during Context VM execution or replay.
|
|
4
|
+
#[derive(Debug, Clone, thiserror::Error, Serialize, Deserialize)]
|
|
5
|
+
pub enum ContextFault {
|
|
6
|
+
#[error("Prompt exceeds maximum token limit: budget={budget}, actual={actual}")]
|
|
7
|
+
PromptTooLong { budget: u32, actual: u32 },
|
|
8
|
+
#[error("Missing archive chunk {seq} for session {session_id}")]
|
|
9
|
+
MissingArchive { session_id: String, seq: u64 },
|
|
10
|
+
#[error("Invalid replay at turn {turn}: {reason}")]
|
|
11
|
+
InvalidReplay { turn: u32, reason: String },
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/// FNV-1a 64-bit — the render layer's cache-stability test fingerprint dialect.
|
|
15
|
+
#[cfg(test)]
|
|
16
|
+
pub(crate) fn stable_hash(bytes: &[u8]) -> u64 {
|
|
17
|
+
let mut hash = 0xcbf29ce484222325u64;
|
|
18
|
+
for byte in bytes {
|
|
19
|
+
hash ^= u64::from(*byte);
|
|
20
|
+
hash = hash.wrapping_mul(0x100000001b3);
|
|
21
|
+
}
|
|
22
|
+
hash
|
|
23
|
+
}
|