devsper 2.1.7__tar.gz → 2.1.8__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.
- {devsper-2.1.7 → devsper-2.1.8}/CHANGELOG.md +6 -0
- {devsper-2.1.7 → devsper-2.1.8}/PKG-INFO +2 -2
- {devsper-2.1.7 → devsper-2.1.8}/README.md +1 -1
- devsper-2.1.8/branding/logo.svg +3 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/agents/agent.py +11 -1
- devsper-2.1.8/devsper/memory/context.py +36 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/memory/memory_index.py +6 -1
- {devsper-2.1.7 → devsper-2.1.8}/devsper/memory/memory_router.py +6 -1
- {devsper-2.1.7 → devsper-2.1.8}/devsper/memory/memory_store.py +77 -22
- {devsper-2.1.7 → devsper-2.1.8}/devsper/memory/redis_memory.py +59 -23
- devsper-2.1.8/devsper/memory/store.py +10 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/nodes/worker.py +16 -1
- devsper-2.1.8/devsper/runtime/executor.py +5 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/swarm/executor.py +12 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/memory/delete_memory.py +4 -3
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/memory/list_memory.py +4 -3
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/memory/search_memory.py +4 -3
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/memory/store_memory.py +5 -3
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/memory/summarize_memory.py +4 -3
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/memory/tag_memory.py +6 -13
- {devsper-2.1.7 → devsper-2.1.8}/devsper/types/task.py +6 -1
- {devsper-2.1.7 → devsper-2.1.8}/pyproject.toml +1 -1
- devsper-2.1.8/tests/test_memory_isolation.py +129 -0
- {devsper-2.1.7 → devsper-2.1.8}/uv.lock +1 -1
- {devsper-2.1.7 → devsper-2.1.8}/.env.example +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/.github/FUNDING.yml +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/.github/workflows/publish-plugin.yml +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/.github/workflows/pypi-publish.yml +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/.github/workflows/release-on-tag.yml +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/.github/workflows/worker-release.yml +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/.gitignore +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/.python-version +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/CODE_OF_CONDUCT.md +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/CONTRIBUTING.md +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/Cargo.lock +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/Cargo.toml +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/LICENSE +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/SECURITY.md +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/benchmarks/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/benchmarks/bench_dataset_analysis.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/benchmarks/bench_repository_analysis.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/benchmarks/bench_research_pipeline.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/agents/a2a/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/agents/a2a/client.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/agents/a2a/discovery.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/agents/a2a/server.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/agents/a2a/tool_adapter.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/agents/a2a/types.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/agents/critic.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/agents/message_bus.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/agents/roles.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/agents/run_agent.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/analytics/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/analytics/tool_analytics.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/audit/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/audit/logger.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/bus/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/bus/backends/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/bus/backends/base.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/bus/backends/memory.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/bus/backends/redis.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/bus/message.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/bus/schema_version.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/bus/topics.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cache/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cache/embedding_index.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cache/hashing.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cache/store.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cache/task_cache.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/commands/reg.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/github_oauth.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/init.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/main.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/run_progress.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/ui/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/ui/components.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/ui/controller_run_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/ui/errors.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/ui/logging.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/ui/onboarding.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/ui/progress.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/ui/run_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cli/ui/theme.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cluster/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cluster/election.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cluster/local.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cluster/node_info.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cluster/registry.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cluster/router.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/cluster/state_backend.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/compliance/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/compliance/pii.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/config/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/config/config_loader.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/config/defaults.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/config/resolver.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/config/schema.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/credentials/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/credentials/cli.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/credentials/migration.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/credentials/store.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/dashboard/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/dashboard/dashboard.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/dev/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/dev/builder.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/dev/debugger.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/dev/repo_index.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/dev/sandbox.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/dev/scaffold.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/docs/architecture/execution-model.md +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/embeddings/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/embeddings/service.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/events.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/explainability/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/explainability/decision_tree.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/explainability/rationale.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/explainability/simulation.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/export/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/export/branding.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/export/collector.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/export/model.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/export/pdf.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/export/service.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/export/writers.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/hitl/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/hitl/approval.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/hitl/escalation.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/adaptation.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/analysis/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/analysis/analyzer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/analysis/cost_estimator.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/analysis/formatter.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/analysis/run_report.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/learning_engine.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/strategies/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/strategies/base.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/strategies/code_analysis_strategy.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/strategies/data_science_strategy.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/strategies/document_pipeline_strategy.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/strategies/experiment_strategy.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/strategies/research_strategy.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/strategy_selector.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/synthesis.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/intelligence/task_optimizer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/knowledge/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/knowledge/extractor.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/knowledge/knowledge_graph.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/knowledge/query.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/memory/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/memory/consolidation.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/memory/embeddings.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/memory/memory_types.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/memory/namespaces.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/memory/scoring.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/memory/summarizer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/nodes/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/nodes/controller.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/nodes/rpc.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/nodes/single.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/orchestration/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/orchestration/meta_planner.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/orchestration/priority_queue.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/plugins/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/plugins/marketplace/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/plugins/plugin_loader.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/plugins/plugin_registry.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/plugins/registry.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/protocols/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/anthropic.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/base.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/complexity_router.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/gemini.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/github.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/model_router.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/openai.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/router/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/router/backends/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/router/backends/anthropic_backend.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/router/backends/custom_backend.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/router/backends/gemini_backend.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/router/backends/github_backend.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/router/backends/ollama_backend.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/router/backends/openai_backend.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/router/backends/vllm_backend.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/router/base.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/router/factory.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/router/legacy.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/providers/router/router.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/reasoning/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/reasoning/graph.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/reasoning/nodes.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/reasoning/store.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/runtime/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/runtime/clarification_manager.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/runtime/health.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/runtime/replay.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/runtime/replay_engine.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/runtime/run_history.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/runtime/task_state.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/runtime/telemetry.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/runtime/visualize.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/sandbox/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/sandbox/sandbox.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/swarm/checkpointer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/swarm/map_reduce.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/swarm/planner.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/swarm/prefetcher.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/swarm/scheduler.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/swarm/speculation.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/swarm/swarm.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/base.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/code_intelligence/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/code_intelligence/api_surface_extractor.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/code_intelligence/architecture_analyzer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/code_intelligence/codebase_indexer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/code_intelligence/dependency_graph_builder.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/code_intelligence/design_pattern_detector.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/code_intelligence/large_function_detector.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/code_intelligence/module_responsibility_mapper.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/code_intelligence/parallel_codebase_analysis.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/code_intelligence/refactor_candidate_detector.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/code_intelligence/repository_semantic_index.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/code_intelligence/test_coverage_estimator.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/coding/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/coding/analyze_code_complexity.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/coding/dependency_analyzer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/coding/extract_functions.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/coding/format_python.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/coding/generate_docstrings.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/coding/generate_unit_tests.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/coding/lint_python.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/coding/refactor_function.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/coding/repo_structure_map.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/coding/run_python.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data/column_type_detection.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data/csv_summary.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data/dataframe_filter.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data/dataframe_groupby.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data/dataframe_stats.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data/dataset_sampling.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data/dataset_schema.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data/json_pretty_print.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data/json_query.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data/missing_value_report.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data_science/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data_science/correlation_heatmap.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data_science/dataset_bias_detector.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data_science/dataset_distribution_report.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data_science/dataset_drift_detector.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data_science/dataset_outlier_detector.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data_science/dataset_profile.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data_science/distributed_dataset_processor.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data_science/feature_engineering_suggestions.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data_science/feature_importance_estimator.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data_science/model_input_validator.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/data_science/time_series_analyzer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/documents/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/documents/_docproc.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/documents/document_to_markdown.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/documents/extract_document_images.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/documents/extract_document_text.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/documents/extract_equations.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/documents/extract_tables.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/documents/summarize_document.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/documents/write_latex_document.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/documents/write_markdown_document.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/documents/write_word_document.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/experiments/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/experiments/bootstrap_estimator.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/experiments/experiment_report_generator.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/experiments/experiment_tracker.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/experiments/grid_search_runner.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/experiments/model_benchmark_runner.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/experiments/monte_carlo_experiment.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/experiments/parameter_sweep_runner.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/experiments/result_comparator.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/experiments/simulation_runner.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/experiments/statistical_significance_test.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/experiments/swarm_map_reduce.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/filesystem/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/filesystem/append_file.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/filesystem/file_hash.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/filesystem/file_line_count.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/filesystem/file_metadata.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/filesystem/file_preview.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/filesystem/find_large_files.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/filesystem/list_directory.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/filesystem/read_file.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/filesystem/search_files.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/filesystem/write_file.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/flagship/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/flagship/distributed_document_analysis.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/flagship/docproc_corpus_pipeline.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/flagship/repository_semantic_map.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/flagship/research_graph_builder.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/flagship/swarm_experiment_runner.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/knowledge/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/knowledge/citation_graph_builder.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/knowledge/concept_frequency_analyzer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/knowledge/corpus_builder.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/knowledge/cross_document_entity_linker.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/knowledge/document_corpus_summary.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/knowledge/document_topic_extractor.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/knowledge/knowledge_graph_extractor.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/knowledge/timeline_extractor.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/math/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/math/calculate_expression.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/math/correlation.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/math/distribution_summary.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/math/histogram.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/math/linear_regression.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/math/matrix_multiply.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/math/mean_std.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/math/monte_carlo_simulation.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/math/polynomial_fit.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/math/random_sample.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/mcp/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/mcp/adapter.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/mcp/client.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/mcp/discovery.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/memory/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/pipelines.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/registry.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research/arxiv_download.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research/arxiv_search.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research/citation_extractor.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research/duckduckgo_search.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research/paper_metadata_extractor.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research/paper_summarizer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research/research_question_generator.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research/topic_cluster.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research/web_search.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research/wikipedia_lookup.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research_advanced/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research_advanced/citation_context_extractor.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research_advanced/literature_review_generator.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research_advanced/methodology_extractor.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research_advanced/paper_contribution_extractor.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research_advanced/paper_dataset_identifier.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research_advanced/paper_method_comparator.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research_advanced/paper_similarity_search.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research_advanced/paper_trend_analyzer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research_advanced/parallel_document_analyzer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research_advanced/research_gap_finder.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research_advanced/research_topic_mapper.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/research_advanced/swarm_literature_review.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/scoring/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/scoring/report.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/scoring/scorer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/scoring/selector.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/scoring/store.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/selector.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/system/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/system/cpu_usage.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/system/disk_usage.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/system/environment_variables.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/system/memory_usage.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/system/pip_install.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/system/pip_search.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/system/process_list.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/system/python_package_list.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/system/run_shell_command.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/system/system_info.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tools/tool_runner.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/activity_feed_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/adaptive_tasks_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/agent_role_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/app.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/dashboard_screen.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/dev_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/inject_screen.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/knowledge_graph_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/layout.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/logs_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/memory_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/performance_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/reasoning_graph_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/results_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/swarm_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/task_detail_screen.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/tui/task_view.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/types/event.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/types/exceptions.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/types/swarm.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/upgrade/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/upgrade/changelog.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/upgrade/cli.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/upgrade/installer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/upgrade/notifier.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/upgrade/version_check.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/utils/event_logger.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/utils/http.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/utils/models.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/visualization/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/visualization/dag_export.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/workflow/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/workflow/conditions.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/workflow/context.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/workflow/loader.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/workflow/resolver.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/workflow/runner.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/workflow/schema.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper/workflow/validator.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/devsper.toml +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/docker-compose.yml +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/_common.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/_config.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/coding/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/coding/analyze_repository.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/coding/generate_docs.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/coding/refactor_candidates.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/data_science/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/data_science/dataset_analysis.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/data_science/run_experiments.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/demo_swarm.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/distributed/README.md +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/distributed/controller.toml +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/distributed/parallel_survey.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/distributed/run_controller.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/distributed/run_demo.sh +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/distributed/run_worker.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/distributed/worker.toml +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/documents/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/documents/analyze_documents.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/experiments/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/experiments/monte_carlo_demo.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/experiments/parameter_sweep.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/research/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/research/literature_review.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/research/research_gap_analysis.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/examples/research/research_graph.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/requirements-docs.txt +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/scripts/README.md +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/scripts/seed_tool_scores.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/scripts/test_tool_scoring_cli.sh +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/scripts/test_tool_scoring_full.sh +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/scripts/test_tool_scoring_smoke.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/scripts/test_v2_router.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/agents/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/agents/test_roles.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/benchmarks/test_v16_perf.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/intelligence/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/intelligence/test_adaptation.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/intelligence/test_learning_engine.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/intelligence/test_strategy_selector.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/intelligence/test_task_optimizer.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/memory/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/memory/test_agent_memory_integration.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/memory/test_memory_index.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/memory/test_memory_router.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/memory/test_memory_store.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/reasoning/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/reasoning/test_reasoning_graph.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/runtime/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/runtime/test_replay.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/runtime/test_replay_engine.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/runtime/test_telemetry.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/runtime/test_visualize.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_agent.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_analysis.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_analytics.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_auto_model.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_clarification.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_clarification_multinode.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_config_loader.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_credentials.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_cross_boundary_serialization.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_dag_export.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_dev_agents.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_dev_build_cmd.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_dev_debugger.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_dev_repo_index.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_dev_sandbox.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_dev_scaffold.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_distributed_bugs.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_embeddings_service.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_event_logger.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_executor.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_export_runs.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_github_provider.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_init.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_knowledge_graph.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_knowledge_query.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_map_reduce.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_memory_evolution.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_model_router.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_planner.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_plugins.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_protocols.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_reg.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_router.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_scheduler.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_speculation.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_strategies.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_swarm.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_task_cache.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_tool_scoring.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_tool_selector.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_upgrade.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_v110.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_v16.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_v17.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_v18.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_v19.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/test_workflow.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/__init__.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_code_intelligence_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_coding_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_data_science_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_data_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_document_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_experiments_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_filesystem_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_flagship_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_knowledge_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_math_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_memory_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_pipelines.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_registry.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_research_advanced_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_research_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_system_tools.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/tests/tools/test_tool_runner.py +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/.dockerignore +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/Cargo.lock +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/Cargo.toml +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/Dockerfile +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/README.md +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/bus.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/claim.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/clarification.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/config.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/controller.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/election.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/error.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/executor.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/health.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/heartbeat.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/lib.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/main.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/metrics.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/reconnect.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/registry.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/router.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/rpc.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/scheduler.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/snapshot.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/types/agent.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/types/event.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/types/mod.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/types/node.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/types/task.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/src/worker_node.rs +0 -0
- {devsper-2.1.7 → devsper-2.1.8}/worker/tests/integration.rs +0 -0
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.1.8] — 2026-03-24
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- **Memory management** — Runtime lifecycle and retention tuned for lower steady-state memory use (agent/worker paths, caches, and long-run cleanup).
|
|
15
|
+
|
|
10
16
|
## [2.1.7] — 2026-03-18
|
|
11
17
|
|
|
12
18
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devsper
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.8
|
|
4
4
|
Summary: Orchestrate distributed swarms of AI agents that collaboratively solve complex tasks.
|
|
5
5
|
Project-URL: Homepage, https://github.com/devsper-com/runtime
|
|
6
6
|
Project-URL: Documentation, https://docs.devsper.com
|
|
@@ -68,7 +68,7 @@ Provides-Extra: worker
|
|
|
68
68
|
Description-Content-Type: text/markdown
|
|
69
69
|
|
|
70
70
|
<p align="center">
|
|
71
|
-
<img src="https://raw.githubusercontent.com/
|
|
71
|
+
<img src="https://raw.githubusercontent.com/devsper-com/runtime/refs/heads/main/branding/logo.svg" alt="devsper" width="120" height="140" style="background:#fff; padding:12px; border-radius:10px; filter:invert(1);" />
|
|
72
72
|
</p>
|
|
73
73
|
|
|
74
74
|
<h1 align="center">devsper</h1>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/
|
|
2
|
+
<img src="https://raw.githubusercontent.com/devsper-com/runtime/refs/heads/main/branding/logo.svg" alt="devsper" width="120" height="140" style="background:#fff; padding:12px; border-radius:10px; filter:invert(1);" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">devsper</h1>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg width="796" height="583" viewBox="0 0 796 583" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M109.999 149.049C213.579 53.4691 359.089 14.2192 498.169 37.6292C660.529 64.9592 805.309 196.569 794.479 370.739C777.819 638.639 360.969 598.919 185.739 538.289C147.749 525.149 58.8887 459.529 29.8687 430.079C-11.9913 387.589 -8.84095 271.889 32.979 229.329C47.099 214.949 74.6887 209.779 77.6387 189.029C81.8087 159.639 71.5488 123.319 75.5088 92.8392C74.2888 86.6392 62.4288 80.8592 57.2388 74.3592C28.5488 38.4192 64.5488 -12.2908 108.239 2.69915C136.239 12.3092 146.359 49.4892 129.359 73.1192C125.319 78.7392 109.989 87.8091 109.989 92.7891V149.049H109.999ZM91.0088 34.6392C77.4188 36.5892 79.219 59.4391 94.919 57.2691C107.559 55.5191 106.439 32.4292 91.0088 34.6392ZM619.819 211.029C614.309 175.759 579.229 98.4692 546.379 83.5692C509.949 67.0392 431.269 61.7293 391.219 63.9793C378.359 64.6993 299.969 75.6292 296.039 83.6392L333.839 110.079C351.789 126.299 367.599 144.409 379.079 165.879C383.579 174.299 395.509 208.969 400.949 210.599C413.689 214.419 447.149 206.879 462.419 206.349C515.169 204.519 567.349 209.439 619.819 211.019V211.029ZM376.219 215.439C369.819 175.289 339.429 134.849 305.019 113.639C296.649 108.479 270.829 95.1192 262.169 94.4092C246.879 93.1592 178.579 135.229 164.029 146.809C157.269 152.199 116.869 188.409 121.479 194.939C159.499 198.249 181.829 231.399 192.749 264.919C209.559 316.579 207.659 419.479 160.579 455.629C151.539 462.569 139.999 464.549 132.969 472.769C155.319 484.189 175.289 495.459 198.999 504.359C217.709 511.379 256.219 525.129 274.819 527.339C279.329 527.879 282.219 528.829 286.789 526.719C295.239 522.829 327.199 477.729 323.579 472.829C283.529 460.149 249.339 422.139 245.529 379.769C240.769 326.759 248.699 275.109 295.299 243.609C320.669 226.459 347.149 222.529 376.219 215.429V215.439ZM649.679 514.109C685.779 509.179 717.399 477.099 735.079 446.819C792.989 347.639 761.959 248.689 686.489 170.799C662.499 146.039 631.189 120.889 599.169 107.729C607.749 125.499 618.289 142.059 625.529 160.569C630.439 173.099 637.119 205.239 643.999 213.279C649.259 219.429 666.519 222.709 675.649 227.559C751.649 267.899 749.069 394.439 701.159 454.249C686.909 472.029 684.069 467.459 667.419 475.629C654.679 481.879 656.599 502.809 649.679 514.119V514.109ZM87.0391 429.149C127.029 437.859 141.059 441.249 157.029 401.579C171.909 364.619 172.469 325.329 164.039 286.729C156.619 252.759 134.849 216.799 94.3687 233.309C74.8187 241.279 90.049 242.929 97.149 252.579C125.339 287.599 126.559 362.739 106.289 401.359L87.0391 429.149ZM54.2789 268.809C31.8589 272.789 32.749 334.979 34.129 352.339C35.479 369.449 44.2189 413.119 68.7789 393.689C84.6789 381.109 88.2687 341.359 87.1187 322.319C86.0987 305.429 78.3589 264.539 54.2789 268.819V268.809ZM619.289 294.139C572.689 299.459 577.849 405.859 620.929 406.299C671.199 406.809 672.469 288.059 619.289 294.139ZM377.169 303.669C352.459 328.529 358.179 412.999 402.219 405.719C437.079 399.959 439.229 336.489 422.759 310.489C412.359 294.069 391.329 289.419 377.159 303.669H377.169ZM638.189 481.999C575.279 490.409 512.219 492.709 448.639 491.259L347.719 479.619C345.669 479.589 344.539 480.829 343.109 482.019C334.899 488.809 320.389 525.109 309.799 534.779C411.509 553.719 520.819 559.009 620.559 528.079L638.189 482.009V481.999Z" fill="white"/>
|
|
3
|
+
</svg>
|
|
@@ -379,12 +379,14 @@ class Agent:
|
|
|
379
379
|
message_bus=None,
|
|
380
380
|
audit_logger=None,
|
|
381
381
|
audit_run_id: str = "",
|
|
382
|
+
memory_namespace: str | None = None,
|
|
382
383
|
):
|
|
383
384
|
self.model_name = model_name
|
|
384
385
|
self.event_log = event_log or EventLog()
|
|
385
386
|
self.use_tools = use_tools
|
|
386
387
|
self.max_tool_iterations = max_tool_iterations
|
|
387
388
|
self.memory_router = memory_router
|
|
389
|
+
self.memory_namespace = memory_namespace
|
|
388
390
|
self.store_result_to_memory = store_result_to_memory
|
|
389
391
|
self.reasoning_store = reasoning_store
|
|
390
392
|
self.user_task = user_task
|
|
@@ -397,8 +399,14 @@ class Agent:
|
|
|
397
399
|
def run(self, request: AgentRequest) -> AgentResponse:
|
|
398
400
|
"""Stateless run: all context in AgentRequest, all output in AgentResponse."""
|
|
399
401
|
import time
|
|
402
|
+
from devsper.memory.context import attach_memory_context, detach_memory_context
|
|
403
|
+
|
|
400
404
|
t0 = time.perf_counter()
|
|
401
405
|
task_id = request.task.id
|
|
406
|
+
ctx = attach_memory_context(
|
|
407
|
+
getattr(self.memory_router, "store", None) if self.memory_router else None,
|
|
408
|
+
self.memory_namespace,
|
|
409
|
+
)
|
|
402
410
|
try:
|
|
403
411
|
self._emit(events.AGENT_STARTED, {"task_id": task_id})
|
|
404
412
|
self._emit(events.TASK_STARTED, {"task_id": task_id})
|
|
@@ -503,6 +511,8 @@ class Agent:
|
|
|
503
511
|
error=str(e),
|
|
504
512
|
success=False,
|
|
505
513
|
)
|
|
514
|
+
finally:
|
|
515
|
+
detach_memory_context(ctx)
|
|
506
516
|
|
|
507
517
|
def build_request(
|
|
508
518
|
self,
|
|
@@ -690,7 +700,7 @@ class Agent:
|
|
|
690
700
|
index = getattr(self.memory_router, "index", None)
|
|
691
701
|
if isinstance(index, MemoryIndex):
|
|
692
702
|
record = index.ensure_embedding(record)
|
|
693
|
-
store.store(record)
|
|
703
|
+
store.store(record, namespace=self.memory_namespace)
|
|
694
704
|
|
|
695
705
|
def _run_with_tools_for_request(
|
|
696
706
|
self,
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Process/async context for memory store + namespace (tools + agent execution)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from contextvars import ContextVar, Token
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
_current_store: ContextVar[object | None] = ContextVar("devsper_memory_store", default=None)
|
|
12
|
+
_current_namespace: ContextVar[str | None] = ContextVar("devsper_memory_namespace", default=None)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def attach_memory_context(store: object | None, namespace: str | None) -> tuple[Token[object | None], Token[str | None]]:
|
|
16
|
+
return (_current_store.set(store), _current_namespace.set(namespace))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def detach_memory_context(tokens: tuple[Token[object | None], Token[str | None]]) -> None:
|
|
20
|
+
_current_store.reset(tokens[0])
|
|
21
|
+
_current_namespace.reset(tokens[1])
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_effective_memory_store():
|
|
25
|
+
"""Prefer agent/router store when set; else process default SQLite store."""
|
|
26
|
+
s = _current_store.get()
|
|
27
|
+
if s is not None:
|
|
28
|
+
return s
|
|
29
|
+
from devsper.memory.memory_store import get_default_store
|
|
30
|
+
|
|
31
|
+
return get_default_store()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def get_effective_memory_namespace() -> str | None:
|
|
35
|
+
"""Active namespace for tool memory ops (None = legacy global/run default)."""
|
|
36
|
+
return _current_namespace.get()
|
|
@@ -33,6 +33,7 @@ class MemoryIndex:
|
|
|
33
33
|
top_k: int = 5,
|
|
34
34
|
min_similarity: float = 0.0,
|
|
35
35
|
include_archived: bool = False,
|
|
36
|
+
namespace: str | None = None,
|
|
36
37
|
) -> list[MemoryRecord]:
|
|
37
38
|
"""
|
|
38
39
|
Semantic search: embed query, score against stored records with embeddings,
|
|
@@ -41,7 +42,9 @@ class MemoryIndex:
|
|
|
41
42
|
Use min_similarity > 0 (e.g. 0.45) to avoid injecting barely-related memory.
|
|
42
43
|
By default excludes archived records (consolidation).
|
|
43
44
|
"""
|
|
44
|
-
records = self.store.list_memory(
|
|
45
|
+
records = self.store.list_memory(
|
|
46
|
+
limit=500, include_archived=include_archived, namespace=namespace
|
|
47
|
+
)
|
|
45
48
|
if not records:
|
|
46
49
|
return []
|
|
47
50
|
query_emb = embed_text(text)
|
|
@@ -64,6 +67,7 @@ class MemoryIndex:
|
|
|
64
67
|
min_similarity: float = 0.0,
|
|
65
68
|
run_id_filter: str | None = None,
|
|
66
69
|
include_archived: bool = False,
|
|
70
|
+
namespace: str | None = None,
|
|
67
71
|
) -> list[MemoryRecord]:
|
|
68
72
|
"""
|
|
69
73
|
v1.8: Same as query_memory but over more records (all runs), optional run_id filter.
|
|
@@ -73,6 +77,7 @@ class MemoryIndex:
|
|
|
73
77
|
limit=2000,
|
|
74
78
|
include_archived=include_archived,
|
|
75
79
|
run_id_filter=run_id_filter,
|
|
80
|
+
namespace=namespace,
|
|
76
81
|
)
|
|
77
82
|
if not records:
|
|
78
83
|
return []
|
|
@@ -20,11 +20,13 @@ class MemoryRouter:
|
|
|
20
20
|
index: MemoryIndex | None = None,
|
|
21
21
|
top_k: int = 10,
|
|
22
22
|
min_similarity: float = 0.55,
|
|
23
|
+
default_namespace: str | None = None,
|
|
23
24
|
) -> None:
|
|
24
25
|
self.store = store or MemoryStore()
|
|
25
26
|
self.index = index or MemoryIndex(self.store)
|
|
26
27
|
self.top_k = top_k
|
|
27
28
|
self.min_similarity = min_similarity
|
|
29
|
+
self.default_namespace = default_namespace
|
|
28
30
|
|
|
29
31
|
def get_relevant_memory(self, task: str) -> list[MemoryRecord]:
|
|
30
32
|
"""
|
|
@@ -35,6 +37,7 @@ class MemoryRouter:
|
|
|
35
37
|
task,
|
|
36
38
|
top_k=self.top_k,
|
|
37
39
|
min_similarity=self.min_similarity,
|
|
40
|
+
namespace=self.default_namespace,
|
|
38
41
|
)
|
|
39
42
|
|
|
40
43
|
def get_memory_context(self, task: str) -> str:
|
|
@@ -44,7 +47,9 @@ class MemoryRouter:
|
|
|
44
47
|
Empty if no memories meet the relevance threshold.
|
|
45
48
|
"""
|
|
46
49
|
lines = []
|
|
47
|
-
inject_records = self.store.list_memory(
|
|
50
|
+
inject_records = self.store.list_memory(
|
|
51
|
+
tag_contains="user_injection", limit=10, namespace=self.default_namespace
|
|
52
|
+
)
|
|
48
53
|
if inject_records:
|
|
49
54
|
lines.append("USER INJECTIONS (high priority):")
|
|
50
55
|
for r in inject_records:
|
|
@@ -20,6 +20,13 @@ def _default_db_path() -> str:
|
|
|
20
20
|
return os.path.join(base, "memory.db")
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
def _norm_namespace(namespace: str | None) -> str:
|
|
24
|
+
"""SQLite partition key; empty string means legacy default (same as namespace=None)."""
|
|
25
|
+
if namespace is None or namespace == "":
|
|
26
|
+
return ""
|
|
27
|
+
return namespace
|
|
28
|
+
|
|
29
|
+
|
|
23
30
|
class MemoryStore:
|
|
24
31
|
"""Local persistent store for memory records. Uses SQLite."""
|
|
25
32
|
|
|
@@ -60,8 +67,17 @@ class MemoryStore:
|
|
|
60
67
|
conn.execute("ALTER TABLE memory ADD COLUMN archived INTEGER DEFAULT 0")
|
|
61
68
|
except sqlite3.OperationalError:
|
|
62
69
|
pass
|
|
70
|
+
try:
|
|
71
|
+
conn.execute(
|
|
72
|
+
"ALTER TABLE memory ADD COLUMN namespace TEXT NOT NULL DEFAULT ''"
|
|
73
|
+
)
|
|
74
|
+
except sqlite3.OperationalError:
|
|
75
|
+
pass
|
|
76
|
+
conn.execute(
|
|
77
|
+
"CREATE INDEX IF NOT EXISTS ix_memory_namespace ON memory(namespace)"
|
|
78
|
+
)
|
|
63
79
|
|
|
64
|
-
def store(self, record: MemoryRecord) -> str:
|
|
80
|
+
def store(self, record: MemoryRecord, namespace: str | None = None) -> str:
|
|
65
81
|
"""Store a memory record. Returns record id. Redacts PII if compliance.pii_redaction enabled."""
|
|
66
82
|
content = record.content
|
|
67
83
|
try:
|
|
@@ -84,12 +100,13 @@ class MemoryStore:
|
|
|
84
100
|
embedding_json = json.dumps(emb) if emb is not None else None
|
|
85
101
|
archived = row.get("archived", 0)
|
|
86
102
|
run_id = row.get("run_id", "") or ""
|
|
103
|
+
ns = _norm_namespace(namespace)
|
|
87
104
|
with self._conn() as conn:
|
|
88
105
|
conn.execute(
|
|
89
106
|
"""
|
|
90
107
|
INSERT OR REPLACE INTO memory
|
|
91
|
-
(memory_id, memory_type, content, tags, timestamp, source_task, embedding, run_id, archived)
|
|
92
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
108
|
+
(memory_id, memory_type, content, tags, timestamp, source_task, embedding, run_id, archived, namespace)
|
|
109
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
93
110
|
""",
|
|
94
111
|
(
|
|
95
112
|
row["memory_id"],
|
|
@@ -101,27 +118,39 @@ class MemoryStore:
|
|
|
101
118
|
embedding_json,
|
|
102
119
|
run_id,
|
|
103
120
|
archived,
|
|
121
|
+
ns,
|
|
104
122
|
),
|
|
105
123
|
)
|
|
106
124
|
return row["memory_id"]
|
|
107
125
|
|
|
108
|
-
def retrieve(self, memory_id: str) -> MemoryRecord | None:
|
|
126
|
+
def retrieve(self, memory_id: str, namespace: str | None = None) -> MemoryRecord | None:
|
|
109
127
|
"""Retrieve a single record by id."""
|
|
128
|
+
ns = _norm_namespace(namespace)
|
|
110
129
|
with self._conn() as conn:
|
|
111
130
|
conn.row_factory = sqlite3.Row
|
|
112
131
|
cur = conn.execute(
|
|
113
|
-
"
|
|
114
|
-
|
|
132
|
+
"""
|
|
133
|
+
SELECT memory_id, memory_type, content, tags, timestamp, source_task, embedding, run_id, archived,
|
|
134
|
+
COALESCE(namespace, '') AS namespace
|
|
135
|
+
FROM memory WHERE memory_id = ? AND COALESCE(namespace, '') = ?
|
|
136
|
+
""",
|
|
137
|
+
(memory_id, ns),
|
|
115
138
|
)
|
|
116
139
|
row = cur.fetchone()
|
|
117
140
|
if row is None:
|
|
118
141
|
return None
|
|
119
|
-
|
|
142
|
+
d = dict(row)
|
|
143
|
+
d.pop("namespace", None)
|
|
144
|
+
return _row_to_record(d)
|
|
120
145
|
|
|
121
|
-
def delete(self, memory_id: str) -> bool:
|
|
146
|
+
def delete(self, memory_id: str, namespace: str | None = None) -> bool:
|
|
122
147
|
"""Delete a record. Returns True if something was deleted."""
|
|
148
|
+
ns = _norm_namespace(namespace)
|
|
123
149
|
with self._conn() as conn:
|
|
124
|
-
cur = conn.execute(
|
|
150
|
+
cur = conn.execute(
|
|
151
|
+
"DELETE FROM memory WHERE memory_id = ? AND COALESCE(namespace, '') = ?",
|
|
152
|
+
(memory_id, ns),
|
|
153
|
+
)
|
|
125
154
|
return cur.rowcount > 0
|
|
126
155
|
|
|
127
156
|
def list_memory(
|
|
@@ -132,12 +161,14 @@ class MemoryStore:
|
|
|
132
161
|
tag_contains: str | None = None,
|
|
133
162
|
include_archived: bool = False,
|
|
134
163
|
run_id_filter: str | None = None,
|
|
164
|
+
namespace: str | None = None,
|
|
135
165
|
) -> list[MemoryRecord]:
|
|
136
|
-
"""List records, optionally filtered by type, tag, archived, run_id, with limit/offset."""
|
|
166
|
+
"""List records, optionally filtered by type, tag, archived, run_id, namespace, with limit/offset."""
|
|
167
|
+
ns = _norm_namespace(namespace)
|
|
137
168
|
with self._conn() as conn:
|
|
138
169
|
conn.row_factory = sqlite3.Row
|
|
139
|
-
conditions = []
|
|
140
|
-
params = []
|
|
170
|
+
conditions = ["COALESCE(namespace, '') = ?"]
|
|
171
|
+
params: list = [ns]
|
|
141
172
|
if memory_type is not None:
|
|
142
173
|
conditions.append("memory_type = ?")
|
|
143
174
|
params.append(memory_type.value)
|
|
@@ -149,40 +180,64 @@ class MemoryStore:
|
|
|
149
180
|
if run_id_filter is not None:
|
|
150
181
|
conditions.append("run_id = ?")
|
|
151
182
|
params.append(run_id_filter)
|
|
152
|
-
where =
|
|
183
|
+
where = " WHERE " + " AND ".join(conditions)
|
|
153
184
|
params.extend([limit, offset])
|
|
154
185
|
cur = conn.execute(
|
|
155
186
|
f"""
|
|
156
187
|
SELECT memory_id, memory_type, content, tags, timestamp, source_task, embedding,
|
|
157
|
-
COALESCE(run_id, '') as run_id, COALESCE(archived, 0) as archived
|
|
188
|
+
COALESCE(run_id, '') as run_id, COALESCE(archived, 0) as archived,
|
|
189
|
+
COALESCE(namespace, '') as namespace
|
|
158
190
|
FROM memory{where} ORDER BY timestamp DESC LIMIT ? OFFSET ?
|
|
159
191
|
""",
|
|
160
192
|
params,
|
|
161
193
|
)
|
|
162
194
|
rows = cur.fetchall()
|
|
163
|
-
|
|
195
|
+
out = []
|
|
196
|
+
for r in rows:
|
|
197
|
+
d = dict(r)
|
|
198
|
+
d.pop("namespace", None)
|
|
199
|
+
out.append(_row_to_record(d))
|
|
200
|
+
return out
|
|
164
201
|
|
|
165
|
-
def list_all_ids(self, memory_type: MemoryType | None = None) -> list[str]:
|
|
202
|
+
def list_all_ids(self, memory_type: MemoryType | None = None, namespace: str | None = None) -> list[str]:
|
|
166
203
|
"""List all memory ids (for index sync)."""
|
|
204
|
+
ns = _norm_namespace(namespace)
|
|
167
205
|
with self._conn() as conn:
|
|
168
206
|
if memory_type is not None:
|
|
169
207
|
cur = conn.execute(
|
|
170
|
-
"
|
|
171
|
-
|
|
208
|
+
"""
|
|
209
|
+
SELECT memory_id FROM memory
|
|
210
|
+
WHERE memory_type = ? AND COALESCE(namespace, '') = ?
|
|
211
|
+
""",
|
|
212
|
+
(memory_type.value, ns),
|
|
172
213
|
)
|
|
173
214
|
else:
|
|
174
|
-
cur = conn.execute(
|
|
215
|
+
cur = conn.execute(
|
|
216
|
+
"SELECT memory_id FROM memory WHERE COALESCE(namespace, '') = ?",
|
|
217
|
+
(ns,),
|
|
218
|
+
)
|
|
175
219
|
return [r[0] for r in cur.fetchall()]
|
|
176
220
|
|
|
177
|
-
def set_archived(self, memory_id: str, archived: bool = True) -> bool:
|
|
221
|
+
def set_archived(self, memory_id: str, archived: bool = True, namespace: str | None = None) -> bool:
|
|
178
222
|
"""v1.8: Mark a record as archived (e.g. after consolidation)."""
|
|
223
|
+
ns = _norm_namespace(namespace)
|
|
179
224
|
with self._conn() as conn:
|
|
180
225
|
cur = conn.execute(
|
|
181
|
-
"
|
|
182
|
-
|
|
226
|
+
"""
|
|
227
|
+
UPDATE memory SET archived = ?
|
|
228
|
+
WHERE memory_id = ? AND COALESCE(namespace, '') = ?
|
|
229
|
+
""",
|
|
230
|
+
(1 if archived else 0, memory_id, ns),
|
|
183
231
|
)
|
|
184
232
|
return cur.rowcount > 0
|
|
185
233
|
|
|
234
|
+
def purge_namespace(self, namespace: str) -> None:
|
|
235
|
+
"""Remove all memory rows for a logical namespace (e.g. when a project is deleted)."""
|
|
236
|
+
if not namespace or not str(namespace).strip():
|
|
237
|
+
return
|
|
238
|
+
with self._conn() as conn:
|
|
239
|
+
conn.execute("DELETE FROM memory WHERE namespace = ?", (namespace,))
|
|
240
|
+
|
|
186
241
|
|
|
187
242
|
def _row_to_record(row: dict) -> MemoryRecord:
|
|
188
243
|
tags_str = row.get("tags") or ""
|
|
@@ -20,12 +20,15 @@ class RedisMemoryStore(MemoryStore):
|
|
|
20
20
|
"""
|
|
21
21
|
Shared memory store backed by Redis hashes + sorted set.
|
|
22
22
|
|
|
23
|
-
Keys:
|
|
23
|
+
Keys (namespace None → same as legacy run-scoped layout):
|
|
24
24
|
devsper:memory:{run_id}:records (HASH) memory_id -> json row
|
|
25
25
|
devsper:memory:{run_id}:index (ZSET) memory_id -> timestamp score
|
|
26
|
+
|
|
27
|
+
With explicit namespace (e.g. project:uuid):
|
|
28
|
+
devsper:memory:{namespace}:records / :index
|
|
26
29
|
"""
|
|
27
30
|
|
|
28
|
-
def __init__(self, redis_url: str, run_id: str):
|
|
31
|
+
def __init__(self, redis_url: str, run_id: str, default_namespace: str | None = None):
|
|
29
32
|
# Don't init sqlite schema; this store isn't sqlite-backed.
|
|
30
33
|
self.db_path = ""
|
|
31
34
|
try:
|
|
@@ -34,27 +37,39 @@ class RedisMemoryStore(MemoryStore):
|
|
|
34
37
|
raise ImportError("RedisMemoryStore requires 'redis' package.") from e
|
|
35
38
|
self._redis = redis.Redis.from_url(redis_url, decode_responses=True)
|
|
36
39
|
self._run_id = run_id
|
|
37
|
-
self.
|
|
38
|
-
|
|
40
|
+
self._default_namespace = default_namespace
|
|
41
|
+
|
|
42
|
+
def set_default_namespace(self, namespace: str | None) -> None:
|
|
43
|
+
"""Switch logical partition for subsequent ops with namespace=None."""
|
|
44
|
+
self._default_namespace = namespace
|
|
39
45
|
|
|
40
|
-
def
|
|
46
|
+
def _keys(self, namespace: str | None) -> tuple[str, str]:
|
|
47
|
+
ns = namespace if namespace is not None else self._default_namespace
|
|
48
|
+
if ns is None or ns == "":
|
|
49
|
+
base = f"devsper:memory:{self._run_id}"
|
|
50
|
+
else:
|
|
51
|
+
base = f"devsper:memory:{ns}"
|
|
52
|
+
return f"{base}:records", f"{base}:index"
|
|
53
|
+
|
|
54
|
+
def store(self, record: MemoryRecord, namespace: str | None = None) -> str:
|
|
55
|
+
records_key, index_key = self._keys(namespace)
|
|
41
56
|
row = record.to_store_row()
|
|
42
57
|
row["run_id"] = record.run_id or self._run_id
|
|
43
58
|
# embedding can be list[float] or None
|
|
44
59
|
data = json.dumps(row)
|
|
45
60
|
memory_id = row["memory_id"]
|
|
46
|
-
ts = row.get("timestamp") or datetime.now(timezone.utc).isoformat()
|
|
47
61
|
score = time.time()
|
|
48
62
|
pipe = self._redis.pipeline()
|
|
49
|
-
pipe.hset(
|
|
50
|
-
pipe.zadd(
|
|
51
|
-
pipe.expire(
|
|
52
|
-
pipe.expire(
|
|
63
|
+
pipe.hset(records_key, memory_id, data)
|
|
64
|
+
pipe.zadd(index_key, {memory_id: score})
|
|
65
|
+
pipe.expire(records_key, 86400 * 7)
|
|
66
|
+
pipe.expire(index_key, 86400 * 7)
|
|
53
67
|
pipe.execute()
|
|
54
68
|
return memory_id
|
|
55
69
|
|
|
56
|
-
def retrieve(self, memory_id: str) -> MemoryRecord | None:
|
|
57
|
-
|
|
70
|
+
def retrieve(self, memory_id: str, namespace: str | None = None) -> MemoryRecord | None:
|
|
71
|
+
records_key, _ = self._keys(namespace)
|
|
72
|
+
raw = self._redis.hget(records_key, memory_id)
|
|
58
73
|
if not raw:
|
|
59
74
|
return None
|
|
60
75
|
try:
|
|
@@ -63,10 +78,11 @@ class RedisMemoryStore(MemoryStore):
|
|
|
63
78
|
except Exception:
|
|
64
79
|
return None
|
|
65
80
|
|
|
66
|
-
def delete(self, memory_id: str) -> bool:
|
|
81
|
+
def delete(self, memory_id: str, namespace: str | None = None) -> bool:
|
|
82
|
+
records_key, index_key = self._keys(namespace)
|
|
67
83
|
pipe = self._redis.pipeline()
|
|
68
|
-
pipe.hdel(
|
|
69
|
-
pipe.zrem(
|
|
84
|
+
pipe.hdel(records_key, memory_id)
|
|
85
|
+
pipe.zrem(index_key, memory_id)
|
|
70
86
|
res = pipe.execute()
|
|
71
87
|
try:
|
|
72
88
|
return bool(res and res[0] > 0)
|
|
@@ -81,14 +97,16 @@ class RedisMemoryStore(MemoryStore):
|
|
|
81
97
|
tag_contains: str | None = None,
|
|
82
98
|
include_archived: bool = False,
|
|
83
99
|
run_id_filter: str | None = None,
|
|
100
|
+
namespace: str | None = None,
|
|
84
101
|
) -> list[MemoryRecord]:
|
|
85
|
-
|
|
102
|
+
_, index_key = self._keys(namespace)
|
|
103
|
+
records_key, _ = self._keys(namespace)
|
|
104
|
+
ids = self._redis.zrevrange(index_key, 0, -1)
|
|
86
105
|
if not ids:
|
|
87
106
|
return []
|
|
88
|
-
# Apply offset/limit after filtering
|
|
89
107
|
out: list[MemoryRecord] = []
|
|
90
108
|
for mid in ids:
|
|
91
|
-
raw = self._redis.hget(
|
|
109
|
+
raw = self._redis.hget(records_key, mid)
|
|
92
110
|
if not raw:
|
|
93
111
|
continue
|
|
94
112
|
try:
|
|
@@ -106,18 +124,19 @@ class RedisMemoryStore(MemoryStore):
|
|
|
106
124
|
if not any(tag_contains in t for t in (rec.tags or [])):
|
|
107
125
|
continue
|
|
108
126
|
out.append(rec)
|
|
109
|
-
|
|
110
|
-
return sliced
|
|
127
|
+
return out[offset : offset + limit]
|
|
111
128
|
|
|
112
|
-
def list_all_ids(self, memory_type: MemoryType | None = None) -> list[str]:
|
|
113
|
-
|
|
129
|
+
def list_all_ids(self, memory_type: MemoryType | None = None, namespace: str | None = None) -> list[str]:
|
|
130
|
+
_, index_key = self._keys(namespace)
|
|
131
|
+
records_key, _ = self._keys(namespace)
|
|
132
|
+
ids = self._redis.zrevrange(index_key, 0, -1)
|
|
114
133
|
if not ids:
|
|
115
134
|
return []
|
|
116
135
|
if memory_type is None:
|
|
117
136
|
return [str(i) for i in ids]
|
|
118
137
|
out: list[str] = []
|
|
119
138
|
for mid in ids:
|
|
120
|
-
raw = self._redis.hget(
|
|
139
|
+
raw = self._redis.hget(records_key, mid)
|
|
121
140
|
if not raw:
|
|
122
141
|
continue
|
|
123
142
|
try:
|
|
@@ -129,3 +148,20 @@ class RedisMemoryStore(MemoryStore):
|
|
|
129
148
|
continue
|
|
130
149
|
return out
|
|
131
150
|
|
|
151
|
+
def set_archived(self, memory_id: str, archived: bool = True, namespace: str | None = None) -> bool:
|
|
152
|
+
rec = self.retrieve(memory_id, namespace=namespace)
|
|
153
|
+
if rec is None:
|
|
154
|
+
return False
|
|
155
|
+
rec = rec.model_copy(update={"archived": archived})
|
|
156
|
+
self.store(rec, namespace=namespace)
|
|
157
|
+
return True
|
|
158
|
+
|
|
159
|
+
def purge_namespace(self, namespace: str) -> None:
|
|
160
|
+
if not namespace or not str(namespace).strip():
|
|
161
|
+
return
|
|
162
|
+
records_key, index_key = self._keys(namespace)
|
|
163
|
+
pipe = self._redis.pipeline()
|
|
164
|
+
pipe.delete(records_key)
|
|
165
|
+
pipe.delete(index_key)
|
|
166
|
+
pipe.execute()
|
|
167
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Platform-facing memory storage API (namespaced MemoryStore).
|
|
3
|
+
|
|
4
|
+
Implementation lives in ``memory_store``; this module is the stable import path
|
|
5
|
+
for project/org/run-scoped isolation.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from devsper.memory.memory_store import MemoryStore, generate_memory_id, get_default_store
|
|
9
|
+
|
|
10
|
+
__all__ = ["MemoryStore", "generate_memory_id", "get_default_store"]
|
|
@@ -29,6 +29,7 @@ from devsper.cluster.registry import ClusterRegistry
|
|
|
29
29
|
from devsper.swarm.prefetcher import PrefetchResult
|
|
30
30
|
from devsper.tools.registry import ToolRegistry
|
|
31
31
|
from devsper.memory.redis_memory import RedisMemoryStore
|
|
32
|
+
from devsper.memory.memory_index import MemoryIndex
|
|
32
33
|
|
|
33
34
|
log = logging.getLogger(__name__)
|
|
34
35
|
|
|
@@ -207,6 +208,7 @@ class WorkerNode:
|
|
|
207
208
|
self._draining = False
|
|
208
209
|
self._snapshot: dict | None = None
|
|
209
210
|
self._tool_registry: ToolRegistry | None = None
|
|
211
|
+
self._redis_url: str | None = None
|
|
210
212
|
|
|
211
213
|
async def start(self) -> None:
|
|
212
214
|
await self.registry.register(self.node_info)
|
|
@@ -246,11 +248,11 @@ class WorkerNode:
|
|
|
246
248
|
# Shared memory via Redis: point MemoryRouter.store to RedisMemoryStore for this run.
|
|
247
249
|
redis_url = payload.get("redis_url")
|
|
248
250
|
if redis_url:
|
|
251
|
+
self._redis_url = redis_url
|
|
249
252
|
try:
|
|
250
253
|
# Replace store with shared redis-backed store, keep same MemoryRouter interface.
|
|
251
254
|
self.memory_router.store = RedisMemoryStore(redis_url=redis_url, run_id=run_id)
|
|
252
255
|
# MemoryIndex holds reference to store; rebuild index to point at shared store.
|
|
253
|
-
from devsper.memory.memory_index import MemoryIndex
|
|
254
256
|
self.memory_router.index = MemoryIndex(self.memory_router.store)
|
|
255
257
|
log.info("shared memory initialized run_id=%s backend=redis", run_id)
|
|
256
258
|
except Exception as e:
|
|
@@ -317,6 +319,14 @@ class WorkerNode:
|
|
|
317
319
|
self._current_tasks[task.id] = task
|
|
318
320
|
start = time.monotonic()
|
|
319
321
|
task_id_short = (task.id or "?")[:12]
|
|
322
|
+
mem_ns = f"project:{task.project_id}" if getattr(task, "project_id", None) else None
|
|
323
|
+
try:
|
|
324
|
+
st = self.memory_router.store
|
|
325
|
+
if isinstance(st, RedisMemoryStore):
|
|
326
|
+
st.set_default_namespace(mem_ns)
|
|
327
|
+
except Exception:
|
|
328
|
+
pass
|
|
329
|
+
self.memory_router.default_namespace = mem_ns
|
|
320
330
|
try:
|
|
321
331
|
prefetch = self.prefetcher.consume(task.id) if self.prefetcher else None
|
|
322
332
|
request = _build_agent_request(
|
|
@@ -329,6 +339,11 @@ class WorkerNode:
|
|
|
329
339
|
score_store=self.score_store,
|
|
330
340
|
)
|
|
331
341
|
agent = self.agent_factory(self.config)
|
|
342
|
+
agent.memory_namespace = mem_ns
|
|
343
|
+
if getattr(agent, "memory_router", None) is None:
|
|
344
|
+
agent.memory_router = self.memory_router
|
|
345
|
+
elif agent.memory_router is not self.memory_router:
|
|
346
|
+
agent.memory_router = self.memory_router
|
|
332
347
|
# Wire clarification requester for distributed mode.
|
|
333
348
|
try:
|
|
334
349
|
loop = asyncio.get_running_loop()
|
|
@@ -80,9 +80,11 @@ class Executor:
|
|
|
80
80
|
hitl_notifier: object = None,
|
|
81
81
|
hitl_resolver: object = None,
|
|
82
82
|
clarification_bus: queue.Queue | None = None,
|
|
83
|
+
project_id: str | None = None,
|
|
83
84
|
) -> None:
|
|
84
85
|
self.scheduler = scheduler
|
|
85
86
|
self.agent = agent
|
|
87
|
+
self._project_id = project_id
|
|
86
88
|
self.worker_count = worker_count
|
|
87
89
|
self.event_log = event_log or EventLog()
|
|
88
90
|
self.planner = planner
|
|
@@ -112,6 +114,15 @@ class Executor:
|
|
|
112
114
|
self._pending_clarification_queues: dict[str, tuple[queue.Queue, str]] = {} # request_id -> (response_queue, task_id)
|
|
113
115
|
self._pending_clarification_lock = threading.Lock()
|
|
114
116
|
|
|
117
|
+
def _apply_project_memory_namespace(self) -> None:
|
|
118
|
+
ns = f"project:{self._project_id}" if getattr(self, "_project_id", None) else None
|
|
119
|
+
if self.agent is None:
|
|
120
|
+
return
|
|
121
|
+
self.agent.memory_namespace = ns
|
|
122
|
+
mr = getattr(self.agent, "memory_router", None)
|
|
123
|
+
if mr is not None:
|
|
124
|
+
mr.default_namespace = ns
|
|
125
|
+
|
|
115
126
|
def request_clarification(self, req: ClarificationRequest) -> ClarificationResponse:
|
|
116
127
|
"""
|
|
117
128
|
Called from agent thread. Puts request on clarification_bus, blocks until
|
|
@@ -252,6 +263,7 @@ class Executor:
|
|
|
252
263
|
)
|
|
253
264
|
return task.id
|
|
254
265
|
|
|
266
|
+
self._apply_project_memory_namespace()
|
|
255
267
|
self._publish_bus("task.started", task.to_dict())
|
|
256
268
|
if self.audit_logger is not None and self.scheduler is not None:
|
|
257
269
|
try:
|