nodetool-core 0.7.0__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.
- nodetool_core-0.7.0/.cursorignore +4 -0
- nodetool_core-0.7.0/.dockerignore +9 -0
- nodetool_core-0.7.0/.env.example +134 -0
- nodetool_core-0.7.0/.github/ISSUE_TEMPLATE/bug_report.md +2 -0
- nodetool_core-0.7.0/.github/dependabot.yml +11 -0
- nodetool_core-0.7.0/.github/opencode-memory/README.md +103 -0
- nodetool_core-0.7.0/.github/opencode-memory/USAGE-GUIDE.md +153 -0
- nodetool_core-0.7.0/.github/opencode-memory/build-test-lint.md +14 -0
- nodetool_core-0.7.0/.github/opencode-memory/features.md +24 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/accessibility/logging-with-context.md +32 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/accessibility/user-friendly-error-messages.md +32 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/api/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/architecture/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/async/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/async/async-concurrency-utilities.md +41 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/async/async-flat-map-utility.md +43 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/async/async-iterator-utilities.md +35 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/async/async-partition-chunked.md +55 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/async/async-priority-queue.md +36 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/async/async-reader-writer-lock.md +50 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/async/async-reduce-utility.md +41 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/async/async-retry-utilities.md +45 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/async/async-task-group.md +43 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/async/async-timeout-utilities.md +32 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/code-quality/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/code-quality/bulk-linting-fixes-pattern.md +18 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/code-quality/documentation-command-validation.md +21 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/code-quality/exception-handling-in-security-code.md +35 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/code-quality/keeping-makefile-and-docs-in-sync.md +19 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/code-quality/pr-merge-rate-analysis.md +40 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/code-quality/resource-cleanup-pattern-external-resources.md +29 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/code-quality/time.sleep-in-sync-vs-async-code.md +33 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/code-quality/typing-cast-quotes.md +20 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/code-quality/validate-method-return-statements.md +34 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/concurrency/async-condition-variable.md +43 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/concurrency/async-event.md +39 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/concurrency/async-lock.md +35 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/concurrency/async-rate-limiting.md +25 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/concurrency/async-resource-pool.md +71 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/concurrency/circuit-breaker-pattern.md +38 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/concurrency/debounce-throttle-patterns.md +43 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/concurrency/export-async-byte-stream.md +22 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/concurrency/fan-out-channel-closing-pattern.md +33 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/deployment/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/performance/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/performance/agent-skill-regex-caching.md +39 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/performance/edge-query-optimization.md +29 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/performance/file-metadata-batching.md +48 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/performance/single-pass-aggregation.md +32 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/performance/topological-sort-optimization.md +28 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/storage/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/testing/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/testing/async-fixture-cleanup.md +9 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/testing/debug-api-test-coverage.md +28 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/testing/storage-abstraction-test-patterns.md +30 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/testing/unit-tests-for-core-workflow-modules.md +43 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/typing/type-guard-with-cast.md +29 -0
- nodetool_core-0.7.0/.github/opencode-memory/insights/workflows/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/accessibility/api-validation-errors-hidden-in-production.md +31 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/accessibility/cli-error-messages-lack-context.md +28 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/accessibility/generic-500-errors-expose-internal-details.md +26 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/api/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/ci/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/agents-md-outdated-commands.md +15 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/asyncchannel-nowait-methods-incorrectly-async.md +11 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/basetype-from_dict-missing-return.md +19 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/blocking-http-calls-async-code.md +19 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/broad-exception-handling-security-code.md +13 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/code-quality-issues-20260112.md +67 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/contributing-md-outdated-commands.md +17 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/gradio-app-workflow-runner-usage.md +13 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/insecure-deserialization-model-cache.md +12 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/makedirs-empty-dirname-bug.md +21 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/pydantic-config-deprecation-unused-imports.md +37 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/pymupdf-document-resource-leaks.md +17 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/retry-type-annotations.md +22 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/shell-injection-docker-commands.md +12 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/silent-exception-handlers-chat-cli.md +15 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/test-crash-xdist.md +14 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/type-safety-durable-inbox-recovery.md +16 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/unused-imports-cleanup.md +21 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/unused-imports-examples.md +15 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/unused-parameter-task-executor.md +10 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/code-quality/workspace-dir-none-check.md +10 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/common-patterns.md +16 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/config/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/dependencies/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/error-type-attribute-bug.md +13 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/import-errors-dependencies.md +11 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/issue-template.md +12 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/linting/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/linting/classvar-missing-annotations-feb-2026.md +12 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/linting/import-sorting-workflows-io.md +9 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/linting/minimax-provider-typecheck-warnings.md +19 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/linting/ruff-fixes-jan-2026.md +25 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/linting/simplified-conditional-returns-feb-2026.md +21 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/linting/unused-imports-agents.md +16 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/linting/unused-unpacked-variables-feb-2026.md +15 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/makefile-outdated-commands.md +13 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/parallel-test-race-conditions.md +11 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/performance/blocking-io-async.md +14 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/python-environment-confusion.md +14 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/qa/2026-01-12-check-summary.md +52 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/span-auto-started-events.md +11 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/storage/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/test-mock-target-error.md +11 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/test-status-timing-issues.md +15 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/testing/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/testing/autosave-max-versions-test.md +9 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/testing/flaky-parallel-test-execution.md +11 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/testing/minimax-test-mock-params-argument.md +17 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/testing/pytest-xdist-async-timeout.md +19 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/testing/workflow-node-test-api-update.md +16 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/testing/zip-all-early-stop.md +9 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/typing/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/typing/chatcli-missing-attributes-feb-2026.md +23 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/typing/deployment-state-type-errors.md +19 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/typing/missing-dict-type-argument.md +10 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/typing/type-annotation-improvements.md +22 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/typing/typecheck-147-errors-jan-2026.md +26 -0
- nodetool_core-0.7.0/.github/opencode-memory/issues/workflows/README.md +3 -0
- nodetool_core-0.7.0/.github/opencode-memory/project-context.md +17 -0
- nodetool_core-0.7.0/.github/opencode-memory/repository-context.md +163 -0
- nodetool_core-0.7.0/.github/opencode-memory/tech-stack.md +10 -0
- nodetool_core-0.7.0/.github/workflows/codeql.yml +41 -0
- nodetool_core-0.7.0/.github/workflows/copilot-setup-steps.yml +42 -0
- nodetool_core-0.7.0/.github/workflows/publish-wheel.yml +236 -0
- nodetool_core-0.7.0/.github/workflows/test.yml +114 -0
- nodetool_core-0.7.0/.github/workflows/typecheck.yml +55 -0
- nodetool_core-0.7.0/.gitignore +156 -0
- nodetool_core-0.7.0/.jules/bolt.md +35 -0
- nodetool_core-0.7.0/.jules/sentinel.md +59 -0
- nodetool_core-0.7.0/.pre-commit-config.yaml +66 -0
- nodetool_core-0.7.0/.pylintrc +28 -0
- nodetool_core-0.7.0/AGENTS.md +210 -0
- nodetool_core-0.7.0/CHANGELOG.md +377 -0
- nodetool_core-0.7.0/CLAUDE.md +149 -0
- nodetool_core-0.7.0/CONTRIBUTING.md +140 -0
- nodetool_core-0.7.0/Dockerfile +155 -0
- nodetool_core-0.7.0/Dockerfile.proxy +32 -0
- nodetool_core-0.7.0/LICENSE +661 -0
- nodetool_core-0.7.0/Makefile +45 -0
- nodetool_core-0.7.0/PKG-INFO +175 -0
- nodetool_core-0.7.0/README.md +103 -0
- nodetool_core-0.7.0/SECURITY.md +243 -0
- nodetool_core-0.7.0/build.py +325 -0
- nodetool_core-0.7.0/docker/nginx/conf.d/default.conf +51 -0
- nodetool_core-0.7.0/docker-compose.yaml +73 -0
- nodetool_core-0.7.0/docs/adr/MODEL3D_TYPE_STRUCTURE.md +197 -0
- nodetool_core-0.7.0/docs/asset-tracking.md +229 -0
- nodetool_core-0.7.0/docs/audio-stream.md +329 -0
- nodetool_core-0.7.0/environment.yml +26 -0
- nodetool_core-0.7.0/examples/README.md +18 -0
- nodetool_core-0.7.0/examples/asset_tracking_example.py +105 -0
- nodetool_core-0.7.0/examples/audio_stream_example.py +157 -0
- nodetool_core-0.7.0/examples/minimax_example.py +209 -0
- nodetool_core-0.7.0/examples/model3d_example.py +212 -0
- nodetool_core-0.7.0/examples/papers/1706.03762v7.pdf +0 -0
- nodetool_core-0.7.0/examples/simple_node_execution.py +68 -0
- nodetool_core-0.7.0/lock.sh +19 -0
- nodetool_core-0.7.0/patch_file.py +45 -0
- nodetool_core-0.7.0/patch_tests.py +47 -0
- nodetool_core-0.7.0/pip-audit.json +0 -0
- nodetool_core-0.7.0/pyproject.toml +229 -0
- nodetool_core-0.7.0/pyrightconfig.json +17 -0
- nodetool_core-0.7.0/pytest.ini +37 -0
- nodetool_core-0.7.0/requirements-dev.txt +19 -0
- nodetool_core-0.7.0/scripts/export_parity_snapshot.py +389 -0
- nodetool_core-0.7.0/scripts/inspect_hf_cache.py +52 -0
- nodetool_core-0.7.0/scripts/server-otel.sh +103 -0
- nodetool_core-0.7.0/scripts/server.ps1 +3 -0
- nodetool_core-0.7.0/scripts/server.sh +4 -0
- nodetool_core-0.7.0/scripts/test_default_nodes.py +192 -0
- nodetool_core-0.7.0/scripts/test_pool_concurrency.py +255 -0
- nodetool_core-0.7.0/setup.cfg +23 -0
- nodetool_core-0.7.0/src/nodetool/config/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/config/configuration.py +82 -0
- nodetool_core-0.7.0/src/nodetool/config/env_guard.py +34 -0
- nodetool_core-0.7.0/src/nodetool/config/environment.py +818 -0
- nodetool_core-0.7.0/src/nodetool/config/logging_config.py +149 -0
- nodetool_core-0.7.0/src/nodetool/config/settings.py +556 -0
- nodetool_core-0.7.0/src/nodetool/integrations/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/artifact_inspector.py +319 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/async_downloader.py +498 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/gguf_models.json +312951 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/hf_auth.py +28 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/hf_cache.py +127 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/hf_fast_cache.py +721 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/hf_utils.py +23 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/huggingface_file.py +76 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/huggingface_models.py +2154 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/llama_cpp_download.py +202 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/mlx_models.json +34946 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/progress_download.py +579 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/safetensor_layout.py +124 -0
- nodetool_core-0.7.0/src/nodetool/integrations/huggingface/safetensors_inspector.py +572 -0
- nodetool_core-0.7.0/src/nodetool/integrations/vectorstores/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/integrations/vectorstores/chroma/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/integrations/vectorstores/chroma/async_chroma_client.py +225 -0
- nodetool_core-0.7.0/src/nodetool/integrations/vectorstores/chroma/chroma_client.py +229 -0
- nodetool_core-0.7.0/src/nodetool/integrations/vectorstores/chroma/provider_embedding_function.py +196 -0
- nodetool_core-0.7.0/src/nodetool/io/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/io/asset_utils.py +30 -0
- nodetool_core-0.7.0/src/nodetool/io/get_files.py +59 -0
- nodetool_core-0.7.0/src/nodetool/io/media_fetch.py +264 -0
- nodetool_core-0.7.0/src/nodetool/io/path_utils.py +86 -0
- nodetool_core-0.7.0/src/nodetool/io/uri_utils.py +29 -0
- nodetool_core-0.7.0/src/nodetool/media/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/media/audio/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/media/audio/audio_helpers.py +318 -0
- nodetool_core-0.7.0/src/nodetool/media/common/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/media/common/media_constants.py +9 -0
- nodetool_core-0.7.0/src/nodetool/media/common/media_utils.py +230 -0
- nodetool_core-0.7.0/src/nodetool/media/image/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/media/image/font_utils.py +97 -0
- nodetool_core-0.7.0/src/nodetool/media/image/image_utils.py +166 -0
- nodetool_core-0.7.0/src/nodetool/media/image/web_font_utils.py +417 -0
- nodetool_core-0.7.0/src/nodetool/media/video/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/media/video/video_utils.py +447 -0
- nodetool_core-0.7.0/src/nodetool/metadata/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/metadata/node_metadata.py +206 -0
- nodetool_core-0.7.0/src/nodetool/metadata/tool_types.py +61 -0
- nodetool_core-0.7.0/src/nodetool/metadata/type_metadata.py +306 -0
- nodetool_core-0.7.0/src/nodetool/metadata/typecheck.py +249 -0
- nodetool_core-0.7.0/src/nodetool/metadata/types.py +2752 -0
- nodetool_core-0.7.0/src/nodetool/metadata/utils.py +136 -0
- nodetool_core-0.7.0/src/nodetool/ml/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/ml/core/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/ml/core/model_manager.py +904 -0
- nodetool_core-0.7.0/src/nodetool/ml/models/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/ml/models/asr_models.py +42 -0
- nodetool_core-0.7.0/src/nodetool/ml/models/image_models.py +47 -0
- nodetool_core-0.7.0/src/nodetool/ml/models/language_models.py +61 -0
- nodetool_core-0.7.0/src/nodetool/ml/models/model_cache.py +193 -0
- nodetool_core-0.7.0/src/nodetool/ml/models/tts_models.py +61 -0
- nodetool_core-0.7.0/src/nodetool/ml/models/video_models.py +40 -0
- nodetool_core-0.7.0/src/nodetool/package_metadata/nodetool-core.json +9 -0
- nodetool_core-0.7.0/src/nodetool/package_tools/__init__.py +9 -0
- nodetool_core-0.7.0/src/nodetool/package_tools/__main__.py +101 -0
- nodetool_core-0.7.0/src/nodetool/package_tools/enrich.py +135 -0
- nodetool_core-0.7.0/src/nodetool/package_tools/scanner.py +294 -0
- nodetool_core-0.7.0/src/nodetool/providers/README.md +14 -0
- nodetool_core-0.7.0/src/nodetool/providers/__init__.py +187 -0
- nodetool_core-0.7.0/src/nodetool/providers/base.py +1008 -0
- nodetool_core-0.7.0/src/nodetool/providers/types.py +129 -0
- nodetool_core-0.7.0/src/nodetool/py.typed +0 -0
- nodetool_core-0.7.0/src/nodetool/runtime/__init__.py +6 -0
- nodetool_core-0.7.0/src/nodetool/runtime/resources.py +138 -0
- nodetool_core-0.7.0/src/nodetool/security/README.md +25 -0
- nodetool_core-0.7.0/src/nodetool/security/__init__.py +16 -0
- nodetool_core-0.7.0/src/nodetool/security/crypto.py +119 -0
- nodetool_core-0.7.0/src/nodetool/security/master_key.py +245 -0
- nodetool_core-0.7.0/src/nodetool/security/secret_helper.py +60 -0
- nodetool_core-0.7.0/src/nodetool/storage/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/storage/abstract_storage.py +15 -0
- nodetool_core-0.7.0/src/nodetool/storage/file_storage.py +47 -0
- nodetool_core-0.7.0/src/nodetool/storage/memory_storage.py +27 -0
- nodetool_core-0.7.0/src/nodetool/types/api_graph.py +148 -0
- nodetool_core-0.7.0/src/nodetool/types/content_types.py +181 -0
- nodetool_core-0.7.0/src/nodetool/types/message_types.py +21 -0
- nodetool_core-0.7.0/src/nodetool/types/model.py +67 -0
- nodetool_core-0.7.0/src/nodetool/types/prediction.py +74 -0
- nodetool_core-0.7.0/src/nodetool/types/wrap_primitive_types.py +23 -0
- nodetool_core-0.7.0/src/nodetool/utils/__init__.py +0 -0
- nodetool_core-0.7.0/src/nodetool/utils/message_parsing.py +118 -0
- nodetool_core-0.7.0/src/nodetool/utils/network.py +47 -0
- nodetool_core-0.7.0/src/nodetool/worker/__init__.py +15 -0
- nodetool_core-0.7.0/src/nodetool/worker/__main__.py +75 -0
- nodetool_core-0.7.0/src/nodetool/worker/context_stub.py +137 -0
- nodetool_core-0.7.0/src/nodetool/worker/executor.py +439 -0
- nodetool_core-0.7.0/src/nodetool/worker/node_loader.py +265 -0
- nodetool_core-0.7.0/src/nodetool/worker/protocol.py +186 -0
- nodetool_core-0.7.0/src/nodetool/worker/provider_handler.py +548 -0
- nodetool_core-0.7.0/src/nodetool/worker/server.py +120 -0
- nodetool_core-0.7.0/src/nodetool/worker/stdio_server.py +191 -0
- nodetool_core-0.7.0/src/nodetool/worker/stdio_stdout_guard.py +68 -0
- nodetool_core-0.7.0/src/nodetool/workflows/README.md +18 -0
- nodetool_core-0.7.0/src/nodetool/workflows/__init__.py +1 -0
- nodetool_core-0.7.0/src/nodetool/workflows/asset_storage.py +515 -0
- nodetool_core-0.7.0/src/nodetool/workflows/base_node.py +2461 -0
- nodetool_core-0.7.0/src/nodetool/workflows/channel.py +472 -0
- nodetool_core-0.7.0/src/nodetool/workflows/graph.py +581 -0
- nodetool_core-0.7.0/src/nodetool/workflows/inbox.py +472 -0
- nodetool_core-0.7.0/src/nodetool/workflows/io.py +331 -0
- nodetool_core-0.7.0/src/nodetool/workflows/memory_utils.py +933 -0
- nodetool_core-0.7.0/src/nodetool/workflows/processing_context.py +2491 -0
- nodetool_core-0.7.0/src/nodetool/workflows/processing_offload.py +279 -0
- nodetool_core-0.7.0/src/nodetool/workflows/property.py +155 -0
- nodetool_core-0.7.0/src/nodetool/workflows/torch_support.py +298 -0
- nodetool_core-0.7.0/src/nodetool/workflows/types.py +382 -0
- nodetool_core-0.7.0/test_list_files.py +11 -0
- nodetool_core-0.7.0/test_tmp_dl.py +11 -0
- nodetool_core-0.7.0/tests/__init__.py +1 -0
- nodetool_core-0.7.0/tests/common/test_asset_utils.py +82 -0
- nodetool_core-0.7.0/tests/common/test_async_chroma_client.py +665 -0
- nodetool_core-0.7.0/tests/common/test_configuration.py +11 -0
- nodetool_core-0.7.0/tests/common/test_dynamic_language_models.py +137 -0
- nodetool_core-0.7.0/tests/common/test_font_utils.py +107 -0
- nodetool_core-0.7.0/tests/common/test_hf_utils.py +38 -0
- nodetool_core-0.7.0/tests/common/test_image_utils_jpeg.py +143 -0
- nodetool_core-0.7.0/tests/common/test_media_utils.py +75 -0
- nodetool_core-0.7.0/tests/common/test_path_utils.py +97 -0
- nodetool_core-0.7.0/tests/common/test_video_export_optimization.py +124 -0
- nodetool_core-0.7.0/tests/common/test_video_utils.py +74 -0
- nodetool_core-0.7.0/tests/common/test_video_utils_fallback.py +90 -0
- nodetool_core-0.7.0/tests/common/test_web_font_utils.py +182 -0
- nodetool_core-0.7.0/tests/config/__init__.py +0 -0
- nodetool_core-0.7.0/tests/config/test_environment.py +70 -0
- nodetool_core-0.7.0/tests/conftest.py +249 -0
- nodetool_core-0.7.0/tests/integrations/test_hf_fast_cache.py +102 -0
- nodetool_core-0.7.0/tests/integrations/test_hf_model_discovery_comprehensive.py +270 -0
- nodetool_core-0.7.0/tests/integrations/test_huggingface_model_detection.py +188 -0
- nodetool_core-0.7.0/tests/integrations/test_huggingface_models.py +269 -0
- nodetool_core-0.7.0/tests/integrations/test_huggingface_repo_packaging.py +66 -0
- nodetool_core-0.7.0/tests/integrations/test_progress_download.py +142 -0
- nodetool_core-0.7.0/tests/integrations/test_safetensor_layout.py +71 -0
- nodetool_core-0.7.0/tests/integrations/test_safetensors_inspector.py +83 -0
- nodetool_core-0.7.0/tests/integrations/vectorstores/test_async_chroma_client.py +45 -0
- nodetool_core-0.7.0/tests/integrations/vectorstores/test_chroma_client.py +363 -0
- nodetool_core-0.7.0/tests/io/__init__.py +0 -0
- nodetool_core-0.7.0/tests/io/test_get_files.py +66 -0
- nodetool_core-0.7.0/tests/io/test_media_fetch.py +388 -0
- nodetool_core-0.7.0/tests/metadata/__init__.py +1 -0
- nodetool_core-0.7.0/tests/metadata/test_audio_stream.py +152 -0
- nodetool_core-0.7.0/tests/metadata/test_message_type.py +77 -0
- nodetool_core-0.7.0/tests/metadata/test_metadata_utils.py +42 -0
- nodetool_core-0.7.0/tests/metadata/test_typecheck.py +447 -0
- nodetool_core-0.7.0/tests/metadata/test_utils.py +42 -0
- nodetool_core-0.7.0/tests/ml/__init__.py +1 -0
- nodetool_core-0.7.0/tests/ml/test_model_discovery.py +217 -0
- nodetool_core-0.7.0/tests/ml/test_model_manager.py +85 -0
- nodetool_core-0.7.0/tests/ml/test_tts_models.py +73 -0
- nodetool_core-0.7.0/tests/package_tools/__init__.py +0 -0
- nodetool_core-0.7.0/tests/package_tools/fixtures/sample_pkg/pyproject.toml +16 -0
- nodetool_core-0.7.0/tests/package_tools/fixtures/sample_pkg/src/nodetool/examples/nodetool-sample/echo.json +6 -0
- nodetool_core-0.7.0/tests/package_tools/fixtures/sample_pkg/src/nodetool/nodes/demo.py +16 -0
- nodetool_core-0.7.0/tests/package_tools/test_enrich.py +83 -0
- nodetool_core-0.7.0/tests/package_tools/test_scanner.py +74 -0
- nodetool_core-0.7.0/tests/security/__init__.py +1 -0
- nodetool_core-0.7.0/tests/security/test_crypto.py +138 -0
- nodetool_core-0.7.0/tests/security/test_master_key.py +184 -0
- nodetool_core-0.7.0/tests/storage/test_file_storage.py +11 -0
- nodetool_core-0.7.0/tests/test.jpg +0 -0
- nodetool_core-0.7.0/tests/test.mp3 +0 -0
- nodetool_core-0.7.0/tests/test.mp4 +0 -0
- nodetool_core-0.7.0/tests/test_joblib_security.py +67 -0
- nodetool_core-0.7.0/tests/test_stdio_worker.py +155 -0
- nodetool_core-0.7.0/tests/types/test_graph.py +46 -0
- nodetool_core-0.7.0/tests/types/test_wrap_primitive_types.py +66 -0
- nodetool_core-0.7.0/tests/utils/__init__.py +1 -0
- nodetool_core-0.7.0/tests/utils/test_message_parsing.py +214 -0
- nodetool_core-0.7.0/tests/worker/__init__.py +0 -0
- nodetool_core-0.7.0/tests/worker/test_context_stub.py +50 -0
- nodetool_core-0.7.0/tests/worker/test_executor.py +416 -0
- nodetool_core-0.7.0/tests/worker/test_node_loader.py +161 -0
- nodetool_core-0.7.0/tests/worker/test_provider_handler.py +71 -0
- nodetool_core-0.7.0/tests/worker/test_server.py +163 -0
- nodetool_core-0.7.0/tests/worker/test_stdio_stdout_guard.py +27 -0
- nodetool_core-0.7.0/tests/workflows/Controlnet.json +445 -0
- nodetool_core-0.7.0/tests/workflows/E2E_TEST_SCENARIOS.md +483 -0
- nodetool_core-0.7.0/tests/workflows/Image Enhance.json +218 -0
- nodetool_core-0.7.0/tests/workflows/Summarize RSS.json +171 -0
- nodetool_core-0.7.0/tests/workflows/Test Control Workflow.json +143 -0
- nodetool_core-0.7.0/tests/workflows/Test Workflow.json +109 -0
- nodetool_core-0.7.0/tests/workflows/test_asset_storage.py +464 -0
- nodetool_core-0.7.0/tests/workflows/test_base_node.py +977 -0
- nodetool_core-0.7.0/tests/workflows/test_channels.py +799 -0
- nodetool_core-0.7.0/tests/workflows/test_download_file_cache.py +24 -0
- nodetool_core-0.7.0/tests/workflows/test_e2e_inbox_scenarios.py +490 -0
- nodetool_core-0.7.0/tests/workflows/test_graph.py +427 -0
- nodetool_core-0.7.0/tests/workflows/test_graph_from_dict_errors.py +140 -0
- nodetool_core-0.7.0/tests/workflows/test_graph_module.py +342 -0
- nodetool_core-0.7.0/tests/workflows/test_graph_validation.py +199 -0
- nodetool_core-0.7.0/tests/workflows/test_inbox.py +860 -0
- nodetool_core-0.7.0/tests/workflows/test_memory_uri_assets.py +38 -0
- nodetool_core-0.7.0/tests/workflows/test_memory_uri_sanitization.py +257 -0
- nodetool_core-0.7.0/tests/workflows/test_memory_utils.py +200 -0
- nodetool_core-0.7.0/tests/workflows/test_message_envelope.py +380 -0
- nodetool_core-0.7.0/tests/workflows/test_nodetool_nodes.py +358 -0
- nodetool_core-0.7.0/tests/workflows/test_processing_context.py +165 -0
- nodetool_core-0.7.0/tests/workflows/test_processing_context_audio_stream.py +241 -0
- nodetool_core-0.7.0/tests/workflows/test_processing_context_dataframe.py +76 -0
- nodetool_core-0.7.0/tests/workflows/test_processing_context_security.py +73 -0
- nodetool_core-0.7.0/tests/workflows/test_processing_offload_module.py +73 -0
- nodetool_core-0.7.0/tests/workflows/test_property.py +221 -0
- nodetool_core-0.7.0/tests/workflows/test_property_module.py +126 -0
- nodetool_core-0.7.0/tests/workflows/test_result_for_client_assetref.py +258 -0
- nodetool_core-0.7.0/tools/generate_docs.py +34 -0
- nodetool_core-0.7.0/tools/traceviewer.html +581 -0
- nodetool_core-0.7.0/ty.toml +22 -0
- nodetool_core-0.7.0/uv.lock +5497 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Example Environment Configuration
|
|
2
|
+
# Copy this file to .env.development, .env.test, or .env.production and fill in your values
|
|
3
|
+
# You can also copy to .env for quick local development
|
|
4
|
+
|
|
5
|
+
# Basic Configuration
|
|
6
|
+
PYTHONPATH=src
|
|
7
|
+
ENV=development
|
|
8
|
+
|
|
9
|
+
# API Keys (replace with your actual keys)
|
|
10
|
+
ANTHROPIC_API_KEY=your_anthropic_api_key_here
|
|
11
|
+
MINIMAX_API_KEY=your_minimax_api_key_here
|
|
12
|
+
OPENAI_API_KEY=your_openai_api_key_here
|
|
13
|
+
OPENROUTER_API_KEY=your_openrouter_api_key_here
|
|
14
|
+
TOGETHER_API_KEY=your_together_api_key_here
|
|
15
|
+
GEMINI_API_KEY=your_gemini_api_key_here
|
|
16
|
+
HF_TOKEN=your_huggingface_token_here
|
|
17
|
+
REPLICATE_API_TOKEN=your_replicate_token_here
|
|
18
|
+
ELEVENLABS_API_KEY=your_elevenlabs_api_key_here
|
|
19
|
+
FAL_API_KEY=your_fal_api_key_here
|
|
20
|
+
SERPAPI_API_KEY=your_serpapi_key_here
|
|
21
|
+
APIFY_API_KEY=your_apify_api_key_here
|
|
22
|
+
KIE_API_KEY=your_kie_api_key_here
|
|
23
|
+
AIME_API_KEY=your_aime_api_key
|
|
24
|
+
|
|
25
|
+
# RunPod (for cloud deployment)
|
|
26
|
+
RUNPOD_API_KEY=your_runpod_api_key_here
|
|
27
|
+
|
|
28
|
+
# Google Services
|
|
29
|
+
GOOGLE_MAIL_USER=your_gmail_address
|
|
30
|
+
GOOGLE_APP_PASSWORD=your_google_app_password
|
|
31
|
+
|
|
32
|
+
# DataForSEO
|
|
33
|
+
DATA_FOR_SEO_LOGIN=your_dataforseo_login
|
|
34
|
+
DATA_FOR_SEO_PASSWORD=your_dataforseo_password
|
|
35
|
+
|
|
36
|
+
# SERP Provider Selection
|
|
37
|
+
# Choose which SERP provider to use: serpapi, apify, or dataforseo
|
|
38
|
+
# If not set, auto-selects based on available API keys (SerpApi > Apify > DataForSEO)
|
|
39
|
+
# SERP_PROVIDER=serpapi
|
|
40
|
+
|
|
41
|
+
# Browser automation
|
|
42
|
+
BROWSER_URL=your_browser_instance_url
|
|
43
|
+
|
|
44
|
+
# Database Configuration
|
|
45
|
+
# For development: use SQLite (now stored in data directory for persistence across updates)
|
|
46
|
+
# Windows: %LOCALAPPDATA%/nodetool/nodetool.sqlite3
|
|
47
|
+
# Linux/macOS: ~/.local/share/nodetool/nodetool.sqlite3
|
|
48
|
+
DB_PATH=~/.local/share/nodetool/nodetool.sqlite3
|
|
49
|
+
|
|
50
|
+
# For production: use PostgreSQL
|
|
51
|
+
# POSTGRES_DB=nodetool
|
|
52
|
+
# POSTGRES_USER=nodetool_user
|
|
53
|
+
# POSTGRES_PASSWORD=your_postgres_password
|
|
54
|
+
# POSTGRES_HOST=localhost
|
|
55
|
+
# POSTGRES_PORT=5432
|
|
56
|
+
|
|
57
|
+
# Or use Supabase
|
|
58
|
+
# SUPABASE_URL=https://your-project.supabase.co
|
|
59
|
+
# SUPABASE_KEY=your_supabase_service_role_key # Service role key for project API access
|
|
60
|
+
# SUPABASE_POSTGRES_URL=postgresql://postgres... # PostgreSQL connection URL for migrations (from Supabase Dashboard > Settings > Database > Connection String)
|
|
61
|
+
# NODE_SUPABASE_URL=https://user-nodes.supabase.co # Optional: user-provided Supabase for nodes
|
|
62
|
+
# NODE_SUPABASE_KEY=your_user_node_service_key # Kept separate from core SUPABASE_KEY
|
|
63
|
+
# NODE_SUPABASE_SCHEMA=public
|
|
64
|
+
# NODE_SUPABASE_TABLE_PREFIX=node_
|
|
65
|
+
|
|
66
|
+
# Storage Configuration
|
|
67
|
+
ASSET_BUCKET=images
|
|
68
|
+
ASSET_TEMP_BUCKET=temp-images
|
|
69
|
+
|
|
70
|
+
# S3 Configuration (for production)
|
|
71
|
+
# S3_ACCESS_KEY_ID=your_s3_access_key
|
|
72
|
+
# S3_SECRET_ACCESS_KEY=your_s3_secret_key
|
|
73
|
+
# S3_ENDPOINT_URL=https://s3.amazonaws.com
|
|
74
|
+
# S3_REGION=us-east-1
|
|
75
|
+
|
|
76
|
+
# Asset domains (for production)
|
|
77
|
+
# ASSET_DOMAIN=https://your-cdn-domain.com
|
|
78
|
+
# ASSET_TEMP_DOMAIN=https://your-temp-cdn-domain.com
|
|
79
|
+
|
|
80
|
+
# Vector Database
|
|
81
|
+
CHROMA_PATH=~/.local/share/nodetool/chroma
|
|
82
|
+
# CHROMA_URL=http://localhost:7777 # For remote ChromaDB
|
|
83
|
+
# CHROMA_TOKEN=your_chroma_token
|
|
84
|
+
|
|
85
|
+
# External Services
|
|
86
|
+
OLLAMA_API_URL=http://127.0.0.1:11434
|
|
87
|
+
LMSTUDIO_API_URL=http://127.0.0.1:1234
|
|
88
|
+
NODETOOL_API_URL=http://localhost:7777
|
|
89
|
+
|
|
90
|
+
# Llama.cpp Server
|
|
91
|
+
# Set this to enable the LlamaCpp provider for local GGUF models
|
|
92
|
+
# Example: LLAMA_CPP_URL=http://127.0.0.1:8080
|
|
93
|
+
# LLAMA_CPP_URL=
|
|
94
|
+
# LLAMA_CPP_CONTEXT_LENGTH=128000 # Optional: context window size in tokens
|
|
95
|
+
|
|
96
|
+
# Folders
|
|
97
|
+
# FONT_PATH=/path/to/fonts
|
|
98
|
+
# COMFY_FOLDER=/path/to/ComfyUI
|
|
99
|
+
|
|
100
|
+
# Caching
|
|
101
|
+
# MEMCACHE_HOST=localhost
|
|
102
|
+
# MEMCACHE_PORT=11211
|
|
103
|
+
|
|
104
|
+
# Logging and Monitoring
|
|
105
|
+
LOG_LEVEL=INFO
|
|
106
|
+
DEBUG=false
|
|
107
|
+
# SENTRY_DSN=your_sentry_dsn_for_error_tracking
|
|
108
|
+
# TRACELOOP_ENABLED=true
|
|
109
|
+
# TRACELOOP_API_KEY=your_traceloop_api_key
|
|
110
|
+
# TRACELOOP_BASE_URL=https://api.traceloop.com
|
|
111
|
+
# TRACELOOP_DISABLE_BATCH=true
|
|
112
|
+
# TRACELOOP_APP_NAME=nodetool
|
|
113
|
+
|
|
114
|
+
# OpenTelemetry Auto-Instrumentation (for server environments)
|
|
115
|
+
# Run with: opentelemetry-instrument uvicorn nodetool.api.app:app --host 0.0.0.0 --port 8000
|
|
116
|
+
# Or use the provided script: ./scripts/server-otel.sh
|
|
117
|
+
OTEL_SERVICE_NAME=nodetool-api # Service name for traces
|
|
118
|
+
OTEL_TRACES_EXPORTER=console,otlp # Exporters: console,otlp (comma-separated)
|
|
119
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 # OTLP collector endpoint (gRPC)
|
|
120
|
+
OTEL_EXPORTER_OTLP_PROTOCOL=grpc # Protocol: grpc, http/protobuf, http/json
|
|
121
|
+
OTEL_METRICS_EXPORTER=otlp # Metrics exporter: console,otlp,none
|
|
122
|
+
OTEL_LOGS_EXPORTER=none # Logs exporter: console,otlp,none
|
|
123
|
+
OTEL_SAMPLING_RATIO=1.0 # Sampling ratio 0.0-1.0
|
|
124
|
+
OTEL_RESOURCE_ATTRIBUTES=deployment.environment=development # Resource attributes
|
|
125
|
+
|
|
126
|
+
# Authentication
|
|
127
|
+
# Select provider: none | local | static | supabase
|
|
128
|
+
AUTH_PROVIDER=local
|
|
129
|
+
|
|
130
|
+
# OAuth Configuration
|
|
131
|
+
# GitHub OAuth App credentials (for OAuth PKCE flow)
|
|
132
|
+
# Get these from https://github.com/settings/developers
|
|
133
|
+
GITHUB_CLIENT_ID=your_github_client_id_here
|
|
134
|
+
GITHUB_CLIENT_SECRET=your_github_client_secret_here
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# To get started with Dependabot version updates, you'll need to specify which
|
|
2
|
+
# package ecosystems to update and where the package manifests are located.
|
|
3
|
+
# Please see the documentation for all configuration options:
|
|
4
|
+
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
|
5
|
+
|
|
6
|
+
version: 2
|
|
7
|
+
updates:
|
|
8
|
+
- package-ecosystem: "pip"
|
|
9
|
+
directory: "/"
|
|
10
|
+
schedule:
|
|
11
|
+
interval: "weekly"
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# OpenCode Long-Term Memory
|
|
2
|
+
|
|
3
|
+
This directory contains persistent knowledge for OpenCode workflows in **nodetool-core**. Content is organized into folders by topic, with individual files per issue/insight to keep context focused and reduce merge conflicts.
|
|
4
|
+
|
|
5
|
+
## Directory Structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
opencode-memory/
|
|
9
|
+
├── README.md # This file - overview and usage
|
|
10
|
+
├── features.md # List of user-facing features
|
|
11
|
+
├── build-test-lint.md # Quality requirements and commands
|
|
12
|
+
├── tech-stack.md # Key technologies and versions
|
|
13
|
+
├── repository-context.md # Project structure and conventions
|
|
14
|
+
│
|
|
15
|
+
├── issues/ # Known issues organized by topic
|
|
16
|
+
│ ├── README.md # How to add new issues
|
|
17
|
+
│ ├── testing/
|
|
18
|
+
│ ├── linting/
|
|
19
|
+
│ ├── typing/
|
|
20
|
+
│ ├── workflows/
|
|
21
|
+
│ ├── api/
|
|
22
|
+
│ ├── storage/
|
|
23
|
+
│ ├── dependencies/
|
|
24
|
+
│ ├── config/
|
|
25
|
+
│ └── ci/
|
|
26
|
+
│
|
|
27
|
+
└── insights/ # Best practices organized by topic
|
|
28
|
+
├── README.md # How to add new insights
|
|
29
|
+
├── architecture/
|
|
30
|
+
├── performance/
|
|
31
|
+
├── testing/
|
|
32
|
+
├── code-quality/
|
|
33
|
+
├── async/
|
|
34
|
+
├── workflows/
|
|
35
|
+
├── api/
|
|
36
|
+
├── storage/
|
|
37
|
+
└── deployment/
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## How to Use
|
|
41
|
+
|
|
42
|
+
### Before Making Changes
|
|
43
|
+
|
|
44
|
+
1. Check `features.md` to avoid duplicate feature work
|
|
45
|
+
2. List `issues/` to discover relevant topics, then read descriptive files
|
|
46
|
+
3. List `insights/` to discover best practices, then read descriptive files
|
|
47
|
+
4. Read `repository-context.md`
|
|
48
|
+
|
|
49
|
+
### After Completing Work
|
|
50
|
+
|
|
51
|
+
1. New feature? → Add ONE line to `features.md`
|
|
52
|
+
2. Solved a tricky issue? → Create a file in `issues/<topic>/`
|
|
53
|
+
3. Discovered a best practice? → Create a file in `insights/<topic>/`
|
|
54
|
+
|
|
55
|
+
## File Naming Convention
|
|
56
|
+
|
|
57
|
+
Use descriptive, kebab-case names that make the topic obvious at a glance:
|
|
58
|
+
- `issues/testing/pytest-async-timeouts.md`
|
|
59
|
+
- `issues/workflows/workflow-runner-state-leaks.md`
|
|
60
|
+
- `insights/async/non-blocking-db-queries.md`
|
|
61
|
+
|
|
62
|
+
## File Format
|
|
63
|
+
|
|
64
|
+
### Issue Files (`issues/<topic>/*.md`)
|
|
65
|
+
|
|
66
|
+
```markdown
|
|
67
|
+
# Issue Title
|
|
68
|
+
|
|
69
|
+
**Problem**: One sentence describing the issue
|
|
70
|
+
|
|
71
|
+
**Solution**: One sentence or brief code snippet
|
|
72
|
+
|
|
73
|
+
**Why**: Brief explanation (optional)
|
|
74
|
+
|
|
75
|
+
**Files**: Related files (optional)
|
|
76
|
+
|
|
77
|
+
**Date**: YYYY-MM-DD
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Insight Files (`insights/<topic>/*.md`)
|
|
81
|
+
|
|
82
|
+
```markdown
|
|
83
|
+
# Insight Title
|
|
84
|
+
|
|
85
|
+
**Insight**: What was learned or discovered
|
|
86
|
+
|
|
87
|
+
**Rationale**: Why it matters
|
|
88
|
+
|
|
89
|
+
**Example**: Code example (if applicable)
|
|
90
|
+
|
|
91
|
+
**Impact**: Measurable benefit (if known)
|
|
92
|
+
|
|
93
|
+
**Files**: Related files (optional)
|
|
94
|
+
|
|
95
|
+
**Date**: YYYY-MM-DD
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Benefits
|
|
99
|
+
|
|
100
|
+
✅ Fewer merge conflicts with file-based entries
|
|
101
|
+
✅ Focused context per issue or insight
|
|
102
|
+
✅ Easier discovery by listing topic folders
|
|
103
|
+
✅ Cleaner diffs for updates and removals
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# Memory System Usage Guide for AI Agents
|
|
2
|
+
|
|
3
|
+
This guide explains how AI agents working on nodetool-core should use the OpenCode memory system.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### Before Every Task
|
|
8
|
+
|
|
9
|
+
1. **Read repository-context.md** (Required)
|
|
10
|
+
- Contains essential project information
|
|
11
|
+
- Explains structure, conventions, and commands
|
|
12
|
+
- Provides environment setup details
|
|
13
|
+
|
|
14
|
+
2. **Check issues/ folder** (If encountering issues)
|
|
15
|
+
- See if your problem has been solved before
|
|
16
|
+
- Avoid redundant debugging
|
|
17
|
+
- Learn from past solutions
|
|
18
|
+
|
|
19
|
+
3. **Review insights.md** (For architectural work)
|
|
20
|
+
- Understand key design patterns
|
|
21
|
+
- Learn important architectural decisions
|
|
22
|
+
- Follow established conventions
|
|
23
|
+
|
|
24
|
+
## When to Update Memory Files
|
|
25
|
+
|
|
26
|
+
### Update repository-context.md When:
|
|
27
|
+
- Adding new major project conventions
|
|
28
|
+
- Changing build/test/lint commands
|
|
29
|
+
- Updating development environment setup
|
|
30
|
+
- Adding new core dependencies or system requirements
|
|
31
|
+
- Documenting new architectural components
|
|
32
|
+
|
|
33
|
+
### Add files to issues/ When:
|
|
34
|
+
- You solve a non-trivial problem that took >10 minutes
|
|
35
|
+
- You encounter a confusing error with a clear solution
|
|
36
|
+
- You fix an issue that's likely to recur
|
|
37
|
+
- You discover an environment-specific quirk
|
|
38
|
+
- You find a workaround for a known limitation
|
|
39
|
+
|
|
40
|
+
### Update insights.md When:
|
|
41
|
+
- You discover an important architectural pattern
|
|
42
|
+
- You learn why something is designed a certain way
|
|
43
|
+
- You identify a performance consideration
|
|
44
|
+
- You find a security best practice specific to this codebase
|
|
45
|
+
- You document a design decision that should be followed
|
|
46
|
+
|
|
47
|
+
## What NOT to Document
|
|
48
|
+
|
|
49
|
+
Avoid documenting:
|
|
50
|
+
- Temporary workarounds that should be fixed properly
|
|
51
|
+
- Personal preferences without justification
|
|
52
|
+
- Information already in official docs (README, CONTRIBUTING)
|
|
53
|
+
- Overly specific details that change frequently
|
|
54
|
+
- One-off issues unlikely to recur
|
|
55
|
+
- Secrets or sensitive information
|
|
56
|
+
|
|
57
|
+
## Examples of Good Memory Entries
|
|
58
|
+
|
|
59
|
+
### Good Common Issue Entry
|
|
60
|
+
```markdown
|
|
61
|
+
### Import Errors After Adding Dependencies
|
|
62
|
+
**Date Discovered**: 2024-01-10
|
|
63
|
+
**Context**: New dependencies not found after adding to pyproject.toml
|
|
64
|
+
**Solution**: Run `uv sync --all-extras --dev` or `pip install -e .`
|
|
65
|
+
**Related Files**: `pyproject.toml`
|
|
66
|
+
**Prevention**: Document dependency installation in PR description
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Good Insight Entry
|
|
70
|
+
```markdown
|
|
71
|
+
### Async-First Design
|
|
72
|
+
**Date**: 2024-01-10
|
|
73
|
+
**Category**: Architecture
|
|
74
|
+
**Insight**: The codebase is heavily async-oriented. Most subsystems use asyncio.
|
|
75
|
+
**Impact**: New code should prefer async/await patterns. Avoid blocking calls.
|
|
76
|
+
**Examples**: `src/nodetool/workflows/`, `src/nodetool/agents/`
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Bad Entry (Too Specific)
|
|
80
|
+
```markdown
|
|
81
|
+
### Fixed typo on line 42 of utils.py
|
|
82
|
+
**Date**: 2024-01-10
|
|
83
|
+
**Solution**: Changed "teh" to "the"
|
|
84
|
+
```
|
|
85
|
+
This is too specific and not worth documenting.
|
|
86
|
+
|
|
87
|
+
### Bad Entry (Temporary Workaround)
|
|
88
|
+
```markdown
|
|
89
|
+
### Temporarily disable failing test
|
|
90
|
+
**Solution**: Comment out test_complicated_function() until we fix it
|
|
91
|
+
```
|
|
92
|
+
This is a workaround, not a proper solution.
|
|
93
|
+
|
|
94
|
+
## Memory File Maintenance
|
|
95
|
+
|
|
96
|
+
### Monthly Review (Suggested)
|
|
97
|
+
- Remove outdated information
|
|
98
|
+
- Consolidate duplicate entries
|
|
99
|
+
- Update dates and examples
|
|
100
|
+
- Archive old entries that are no longer relevant
|
|
101
|
+
- Verify all file paths and examples still exist
|
|
102
|
+
|
|
103
|
+
### Keep It Lean
|
|
104
|
+
- Each file should be readable in 2-3 minutes
|
|
105
|
+
- Focus on actionable information
|
|
106
|
+
- Use clear, concise language
|
|
107
|
+
- Link to detailed docs when appropriate
|
|
108
|
+
|
|
109
|
+
## Integration with Workflows
|
|
110
|
+
|
|
111
|
+
### opencode-hourly-test.yaml
|
|
112
|
+
- Reads memory before running tests
|
|
113
|
+
- Adds files to issues/ if fixing recurring problems
|
|
114
|
+
- Records test-specific patterns in insights/
|
|
115
|
+
|
|
116
|
+
### opencode-hourly-improve.yaml
|
|
117
|
+
- Consults memory before scanning for issues
|
|
118
|
+
- Documents discovered patterns in insights/
|
|
119
|
+
- Adds files to issues/
|
|
120
|
+
|
|
121
|
+
### opencode.yml (Comment-triggered)
|
|
122
|
+
- System prompt directs agent to memory files
|
|
123
|
+
- Agent should read relevant memory before starting
|
|
124
|
+
- Updates memory after completing significant work
|
|
125
|
+
|
|
126
|
+
## Benefits of Proper Memory Usage
|
|
127
|
+
|
|
128
|
+
✅ **Faster problem solving** - Check if issue is already solved
|
|
129
|
+
✅ **Consistent code quality** - Follow documented patterns
|
|
130
|
+
✅ **Institutional knowledge** - Build understanding over time
|
|
131
|
+
✅ **Reduced redundancy** - Don't solve the same problem twice
|
|
132
|
+
✅ **Better onboarding** - New agents learn from past work
|
|
133
|
+
✅ **Pattern recognition** - Identify recurring issues
|
|
134
|
+
|
|
135
|
+
## Measuring Success
|
|
136
|
+
|
|
137
|
+
Good memory usage leads to:
|
|
138
|
+
- Fewer repeated issues in PRs
|
|
139
|
+
- More consistent code patterns
|
|
140
|
+
- Faster resolution times
|
|
141
|
+
- Better PR descriptions (referencing past solutions)
|
|
142
|
+
- Proactive prevention of known issues
|
|
143
|
+
|
|
144
|
+
## Questions?
|
|
145
|
+
|
|
146
|
+
If the memory system isn't working well:
|
|
147
|
+
1. Are entries too vague or too specific?
|
|
148
|
+
2. Is information duplicated across files?
|
|
149
|
+
3. Are entries kept up-to-date?
|
|
150
|
+
4. Are agents actually reading the files?
|
|
151
|
+
5. Is the format easy to scan quickly?
|
|
152
|
+
|
|
153
|
+
Adjust the system based on what actually helps with coding work.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Build, Test, Lint
|
|
2
|
+
|
|
3
|
+
## Required Commands
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
make typecheck
|
|
7
|
+
make lint
|
|
8
|
+
make test
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Notes
|
|
12
|
+
|
|
13
|
+
- Use Python 3.11+ with dependencies installed via `uv sync --all-extras --dev`.
|
|
14
|
+
- Keep async code non-blocking; prefer `async`/`await` patterns.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Feature Inventory
|
|
2
|
+
|
|
3
|
+
- **Workflow Engine**: Executes async workflows in Python
|
|
4
|
+
- **Node System**: Typed nodes with media refs and processing context
|
|
5
|
+
- **Agent Framework**: LLM-backed planning and tool execution
|
|
6
|
+
- **API Server**: FastAPI HTTP/WebSocket services
|
|
7
|
+
- **Storage Layer**: Pluggable persistence backends
|
|
8
|
+
- **Async Utilities**: `AsyncSemaphore` and `gather_with_concurrency` for async concurrency control
|
|
9
|
+
- **Async Iterators**: `AsyncByteStream` for async byte sequence iteration in chunks, plus `async_take`, `async_slice`, `async_first`, `async_list`, `async_map`, `async_merge`, `async_filter`, `async_flat_map`, `async_reduce`, `async_partition`, and `async_chunked` utilities for async iterable manipulation
|
|
10
|
+
- **Retry Utilities**: `retry_with_exponential_backoff` and `RetryPolicy` for handling transient failures
|
|
11
|
+
- **Timeout Utilities**: `timeout`, `with_timeout`, `TimeoutPolicy`, and `TimeoutContext` for async timeout control
|
|
12
|
+
- **Batching Utilities**: `batched_async_iterable` and `process_in_batches` for async batch processing
|
|
13
|
+
- **Rate Limiting**: `AsyncTokenBucket` and `AsyncRateLimiter` for controlling operation rates (token bucket algorithm)
|
|
14
|
+
- **Circuit Breaker**: `CircuitBreaker`, `MultiCircuitBreaker`, and `CircuitBreakerConfig` for preventing cascading failures in distributed systems
|
|
15
|
+
- **Async Lock**: `AsyncLock` for exclusive resource access with timeout support, complementing `AsyncSemaphore`
|
|
16
|
+
- **Task Group Management**: `AsyncTaskGroup` for managing groups of related async tasks with spawn, run, cancel, and result collection
|
|
17
|
+
- **Priority Queue**: `AsyncPriorityQueue` for priority-based async task scheduling with configurable max size and timeout support
|
|
18
|
+
- **Async Event**: `AsyncEvent` for inter-task signaling with one-shot and auto-reset modes, supports value passing and predicate-based waiting
|
|
19
|
+
- **Async Barrier**: `AsyncBarrier` for synchronizing multiple coroutines at a synchronization point, useful for phased concurrent operations
|
|
20
|
+
- **Async Condition**: `AsyncCondition` for condition variables allowing tasks to wait until notified by another task, with lock-based coordination to prevent race conditions
|
|
21
|
+
- **Async Reader-Writer Lock**: `AsyncReaderWriterLock` for multiple concurrent readers with exclusive writer access, using writer-preference semantics to prevent starvation
|
|
22
|
+
- **Async Channel**: `AsyncChannel` for producer-consumer patterns with send/receive/close operations, async iteration, and fan-in/fan-out utilities for channel composition
|
|
23
|
+
- **Debounce & Throttle**: `AsyncDebounce`, `AsyncThrottle`, and `AdaptiveThrottle` for controlling async function execution frequency, useful for rate limiting and preventing excessive API calls
|
|
24
|
+
- **Resource Pool**: `AsyncResourcePool` for managing reusable async resources like HTTP clients, database connections, or other expensive-to-create objects with lazy creation, size limits, expiration, and graceful shutdown
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Logging with Context
|
|
2
|
+
|
|
3
|
+
**Insight**: Error logs should include sufficient context for debugging (user IDs, request details, timestamps) to enable effective troubleshooting.
|
|
4
|
+
|
|
5
|
+
**Rationale**: Logs without context make it difficult to trace issues back to specific requests or users. Adding structured context improves observability and debugging.
|
|
6
|
+
|
|
7
|
+
**Best Practices**:
|
|
8
|
+
1. **Include user context**: Add user IDs, workflow IDs, or other identifiers
|
|
9
|
+
2. **Request context**: Include method, path, and client information
|
|
10
|
+
3. **Use structured logging**: Use proper log levels and format parameters
|
|
11
|
+
4. **Avoid string concatenation**: Use %s formatting or f-strings for lazy evaluation
|
|
12
|
+
|
|
13
|
+
**Example Pattern**:
|
|
14
|
+
```python
|
|
15
|
+
# Before:
|
|
16
|
+
log.error(f"Request validation error: {exc}")
|
|
17
|
+
|
|
18
|
+
# After:
|
|
19
|
+
log.error(
|
|
20
|
+
"Request validation error: %s | Method: %s | Path: %s | Client: %s",
|
|
21
|
+
exc.errors(),
|
|
22
|
+
request.method,
|
|
23
|
+
request.url.path,
|
|
24
|
+
request.client.host if request.client else "unknown",
|
|
25
|
+
)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Impact**: Better traceability of issues, easier debugging, improved incident response.
|
|
29
|
+
|
|
30
|
+
**Files**: `src/nodetool/api/server.py`, `src/nodetool/api/workspace.py`
|
|
31
|
+
|
|
32
|
+
**Date**: 2026-02-24
|
nodetool_core-0.7.0/.github/opencode-memory/insights/accessibility/user-friendly-error-messages.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# User-Friendly Error Messages
|
|
2
|
+
|
|
3
|
+
**Insight**: Error messages should be actionable and user-facing, while detailed technical information should be logged server-side for debugging.
|
|
4
|
+
|
|
5
|
+
**Rationale**: Raw exception strings expose internal implementation details and are not helpful to end users. Users need clear, actionable error messages that explain what went wrong and what they can do about it.
|
|
6
|
+
|
|
7
|
+
**Best Practices**:
|
|
8
|
+
1. **User-facing messages**: Explain what went wrong and suggest next steps
|
|
9
|
+
2. **Server-side logs**: Include full context (user IDs, request details, full stack traces)
|
|
10
|
+
3. **Consistent format**: Use similar structure across all error responses
|
|
11
|
+
4. **Appropriate detail**: More detail in development, sanitized in production
|
|
12
|
+
|
|
13
|
+
**Example Pattern**:
|
|
14
|
+
```python
|
|
15
|
+
try:
|
|
16
|
+
# operation
|
|
17
|
+
except SpecificException as e:
|
|
18
|
+
log.error("Context about what failed: %s", e, extra={"user_id": user, "request_id": id})
|
|
19
|
+
raise HTTPException(
|
|
20
|
+
status_code=appropriate_code,
|
|
21
|
+
detail="User-friendly message explaining what to do",
|
|
22
|
+
) from e
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Impact**: Improved user experience, better debugging capability, enhanced security by not exposing internals.
|
|
26
|
+
|
|
27
|
+
**Files**:
|
|
28
|
+
- `src/nodetool/api/server.py` - Validation error handling
|
|
29
|
+
- `src/nodetool/api/workspace.py` - Consistent error messages
|
|
30
|
+
- `src/nodetool/cli.py` - Enhanced CLI error messages
|
|
31
|
+
|
|
32
|
+
**Date**: 2026-02-24
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Async Concurrency Utilities
|
|
2
|
+
|
|
3
|
+
**Insight**: Added `AsyncSemaphore` and `gather_with_concurrency` utilities in `src/nodetool/concurrency/async_utils.py` for managing async concurrency control.
|
|
4
|
+
|
|
5
|
+
**Rationale**: The codebase heavily uses async patterns, and these utilities provide common patterns for:
|
|
6
|
+
- Rate limiting concurrent operations with timeout support
|
|
7
|
+
- Batched execution of async tasks with configurable concurrency limits
|
|
8
|
+
- Clean context manager support for resource management
|
|
9
|
+
|
|
10
|
+
**Example**:
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
from nodetool.concurrency.async_utils import AsyncSemaphore, gather_with_concurrency
|
|
14
|
+
|
|
15
|
+
# Rate limiting with timeout
|
|
16
|
+
sem = AsyncSemaphore(max_tasks=5)
|
|
17
|
+
if await sem.acquire(timeout=10.0):
|
|
18
|
+
try:
|
|
19
|
+
await do_concurrent_work()
|
|
20
|
+
finally:
|
|
21
|
+
sem.release()
|
|
22
|
+
|
|
23
|
+
# Context manager pattern
|
|
24
|
+
async with AsyncSemaphore(max_tasks=3):
|
|
25
|
+
await do_work()
|
|
26
|
+
|
|
27
|
+
# Batched execution with concurrency limit
|
|
28
|
+
results = await gather_with_concurrency(
|
|
29
|
+
[fetch_url(url) for url in urls],
|
|
30
|
+
max_concurrent=10
|
|
31
|
+
)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**Impact**: Provides reusable async utilities that follow the codebase's async-first patterns and DI conventions.
|
|
35
|
+
|
|
36
|
+
**Files**:
|
|
37
|
+
- `src/nodetool/concurrency/async_utils.py`
|
|
38
|
+
- `src/nodetool/concurrency/__init__.py`
|
|
39
|
+
- `tests/concurrency/test_async_utils.py`
|
|
40
|
+
|
|
41
|
+
**Date**: 2026-01-12
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# async_flat_map Utility
|
|
2
|
+
|
|
3
|
+
**Insight**: Flat mapping is a common pattern for one-to-many transformations on async iterables, combining mapping and flattening into a single operation.
|
|
4
|
+
|
|
5
|
+
**Rationale**: When working with async iterables, it's common to need to transform each element into multiple elements (e.g., splitting a string into characters, expanding a range, or processing nested data structures). The `async_flat_map` utility provides a composable way to handle this pattern without intermediate list allocations.
|
|
6
|
+
|
|
7
|
+
**Example**:
|
|
8
|
+
```python
|
|
9
|
+
from nodetool.concurrency import async_flat_map, async_list
|
|
10
|
+
|
|
11
|
+
# Split each number into a range
|
|
12
|
+
async def split(x):
|
|
13
|
+
for j in range(x):
|
|
14
|
+
yield j
|
|
15
|
+
|
|
16
|
+
async def gen():
|
|
17
|
+
for i in range(3):
|
|
18
|
+
yield i
|
|
19
|
+
|
|
20
|
+
result = await async_list(async_flat_map(split, gen()))
|
|
21
|
+
# Result: [0, 0, 1] (split(0)=[], split(1)=[0], split(2)=[0, 1])
|
|
22
|
+
|
|
23
|
+
# Flatten nested lists
|
|
24
|
+
async def flatten(lst):
|
|
25
|
+
for item in lst:
|
|
26
|
+
yield item
|
|
27
|
+
|
|
28
|
+
async def nested_gen():
|
|
29
|
+
for lst in [[1, 2], [3, 4, 5], [6]]:
|
|
30
|
+
yield lst
|
|
31
|
+
|
|
32
|
+
result = await async_list(async_flat_map(flatten, nested_gen()))
|
|
33
|
+
# Result: [1, 2, 3, 4, 5, 6]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Impact**: Reduces code complexity for common async iterable transformations and provides a consistent API with other async iterator utilities like `async_map` and `async_filter`.
|
|
37
|
+
|
|
38
|
+
**Files**:
|
|
39
|
+
- `src/nodetool/concurrency/async_iterators.py`: Implementation
|
|
40
|
+
- `src/nodetool/concurrency/__init__.py`: Export
|
|
41
|
+
- `tests/concurrency/test_async_iterators.py`: Test coverage (13 tests)
|
|
42
|
+
|
|
43
|
+
**Date**: 2026-02-09
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Async Iterator Utilities
|
|
2
|
+
|
|
3
|
+
**Insight**: Added utility functions for working with async iterables in `src/nodetool/concurrency/async_iterators.py`: `async_take`, `async_slice`, `async_first`, `async_list`, and `async_merge`.
|
|
4
|
+
|
|
5
|
+
**Rationale**: While Python 3.11+ has excellent async iterator support, common operations like taking the first N items, slicing, or consuming to a list require boilerplate code. These utilities provide familiar functional programming patterns for async iterables, making async code more readable and maintainable.
|
|
6
|
+
|
|
7
|
+
**Example**:
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
from nodetool.concurrency import async_take, async_first, async_list, async_merge
|
|
11
|
+
|
|
12
|
+
# Take first N items from an async generator
|
|
13
|
+
first_5 = await async_take(async_generator(), 5)
|
|
14
|
+
|
|
15
|
+
# Get just the first item (with optional default)
|
|
16
|
+
first = await async_first(async_generator(), default=None)
|
|
17
|
+
|
|
18
|
+
# Slice async iterables like lists
|
|
19
|
+
items_5_to_10 = await async_slice(async_generator(), 5, 10)
|
|
20
|
+
|
|
21
|
+
# Consume to list
|
|
22
|
+
all_items = await async_list(async_generator())
|
|
23
|
+
|
|
24
|
+
# Merge multiple async iterables sequentially
|
|
25
|
+
combined = await async_list(async_merge(gen1(), gen2(), gen3()))
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**Impact**: Provides reusable async iterator utilities that follow the codebase's async-first patterns. Reduces boilerplate code when working with async generators and iterables. All utilities are fully type-hinted with Generic TypeVar support for better IDE autocomplete and type checking.
|
|
29
|
+
|
|
30
|
+
**Files**:
|
|
31
|
+
- `src/nodetool/concurrency/async_iterators.py` - Added utility functions
|
|
32
|
+
- `src/nodetool/concurrency/__init__.py` - Updated exports
|
|
33
|
+
- `tests/concurrency/test_async_iterators.py` - 29 new tests covering all utilities
|
|
34
|
+
|
|
35
|
+
**Date**: 2026-02-08
|