taifeng 0.0.1__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.
- taifeng-0.0.1/.github/workflows/publish.yml +41 -0
- taifeng-0.0.1/.gitignore +160 -0
- taifeng-0.0.1/AGENTS.md +110 -0
- taifeng-0.0.1/CLAUDE.md +192 -0
- taifeng-0.0.1/LICENSE +201 -0
- taifeng-0.0.1/NOTICE +28 -0
- taifeng-0.0.1/PKG-INFO +325 -0
- taifeng-0.0.1/README.md +286 -0
- taifeng-0.0.1/README_EN.md +287 -0
- taifeng-0.0.1/docs/README.md +57 -0
- taifeng-0.0.1/docs/architecture/agent-loop.md +412 -0
- taifeng-0.0.1/docs/architecture/capabilities/README.md +49 -0
- taifeng-0.0.1/docs/architecture/capabilities/hooks.md +138 -0
- taifeng-0.0.1/docs/architecture/capabilities/index-hook.md +86 -0
- taifeng-0.0.1/docs/architecture/capabilities/instructions-injection.md +139 -0
- taifeng-0.0.1/docs/architecture/capabilities/jsonl-transcript.md +152 -0
- taifeng-0.0.1/docs/architecture/capabilities/llm-provider-native.md +334 -0
- taifeng-0.0.1/docs/architecture/capabilities/llm-structured-output.md +106 -0
- taifeng-0.0.1/docs/architecture/capabilities/mcp-server.md +256 -0
- taifeng-0.0.1/docs/architecture/capabilities/permission-gate.md +316 -0
- taifeng-0.0.1/docs/architecture/capabilities/script-execution.md +152 -0
- taifeng-0.0.1/docs/architecture/capabilities/skill-dispatch.md +313 -0
- taifeng-0.0.1/docs/architecture/capabilities/skill-orchestration.md +63 -0
- taifeng-0.0.1/docs/architecture/capabilities/telemetry-otel.md +149 -0
- taifeng-0.0.1/docs/architecture/capabilities/test-layout.md +67 -0
- taifeng-0.0.1/docs/architecture/capabilities/thread-directory.md +156 -0
- taifeng-0.0.1/docs/architecture/capabilities/tool-builtins-extended.md +219 -0
- taifeng-0.0.1/docs/architecture/context-compression.md +331 -0
- taifeng-0.0.1/docs/architecture/conversation.md +145 -0
- taifeng-0.0.1/docs/architecture/hermes-gap-roadmap.md +135 -0
- taifeng-0.0.1/docs/architecture/kernel-gap-analysis.md +81 -0
- taifeng-0.0.1/docs/architecture/llm-client.md +208 -0
- taifeng-0.0.1/docs/architecture/overview.md +267 -0
- taifeng-0.0.1/docs/architecture/skill-system.md +504 -0
- taifeng-0.0.1/docs/configurable-knobs.md +737 -0
- taifeng-0.0.1/docs/decisions/0001-naming-taifeng.md +126 -0
- taifeng-0.0.1/docs/decisions/0002-python-language.md +95 -0
- taifeng-0.0.1/docs/decisions/0003-skill-as-context.md +86 -0
- taifeng-0.0.1/docs/decisions/0004-cache-aware-compression.md +131 -0
- taifeng-0.0.1/docs/decisions/0005-submission-event-bus.md +142 -0
- taifeng-0.0.1/docs/decisions/0006-unified-skill-model.md +186 -0
- taifeng-0.0.1/docs/decisions/0007-instructions-as-injection.md +137 -0
- taifeng-0.0.1/docs/decisions/0008-store-protocol-decoupling.md +118 -0
- taifeng-0.0.1/docs/decisions/0009-scripts-runtime.md +135 -0
- taifeng-0.0.1/docs/decisions/0010-permission-gate-completeness.md +200 -0
- taifeng-0.0.1/docs/decisions/0011-empty-api-key-omits-auth.md +70 -0
- taifeng-0.0.1/docs/real-llm-validation.md +83 -0
- taifeng-0.0.1/docs/usage.md +542 -0
- taifeng-0.0.1/examples/README.md +82 -0
- taifeng-0.0.1/examples/_provider_bootstrap.py +257 -0
- taifeng-0.0.1/examples/basic/composite_skill.py +112 -0
- taifeng-0.0.1/examples/basic/instructions_basic.py +217 -0
- taifeng-0.0.1/examples/basic/minimal_chat.py +124 -0
- taifeng-0.0.1/examples/basic/skill_with_script.py +182 -0
- taifeng-0.0.1/examples/code_review/demo.py +233 -0
- taifeng-0.0.1/examples/code_review/skills/code-review/SKILL.md +35 -0
- taifeng-0.0.1/examples/code_review/skills/code-review/scripts/lint_check.sh +43 -0
- taifeng-0.0.1/examples/code_review/skills/programmer/SKILL.md +45 -0
- taifeng-0.0.1/examples/code_review/skills/programmer/scripts/format_diff.py +42 -0
- taifeng-0.0.1/examples/compression_showcase/skills/chat-style-guide/SKILL.md +19 -0
- taifeng-0.0.1/examples/compression_showcase/skills/chatty-assistant/SKILL.md +38 -0
- taifeng-0.0.1/examples/concurrent_fanout/demo.py +100 -0
- taifeng-0.0.1/examples/concurrent_fanout/skills/research-fanout/SKILL.md +23 -0
- taifeng-0.0.1/examples/concurrent_fanout/skills/source-academic/SKILL.md +9 -0
- taifeng-0.0.1/examples/concurrent_fanout/skills/source-news/SKILL.md +9 -0
- taifeng-0.0.1/examples/concurrent_fanout/skills/source-web/SKILL.md +9 -0
- taifeng-0.0.1/examples/hooks_showcase/__init__.py +4 -0
- taifeng-0.0.1/examples/hooks_showcase/demo.py +109 -0
- taifeng-0.0.1/examples/hooks_showcase/hooks_lib.py +80 -0
- taifeng-0.0.1/examples/hooks_showcase/skills/data-export/SKILL.md +10 -0
- taifeng-0.0.1/examples/hooks_showcase/skills/task-runner/SKILL.md +20 -0
- taifeng-0.0.1/examples/kernel_knobs/demo.py +157 -0
- taifeng-0.0.1/examples/mcp_basic/demo.py +232 -0
- taifeng-0.0.1/examples/mcp_basic/skills/lung-anatomy/SKILL.md +47 -0
- taifeng-0.0.1/examples/mcp_basic/skills/lung-anatomy/scripts/lookup_segment.sh +26 -0
- taifeng-0.0.1/examples/mcp_basic/skills/lung-nodule-expert/SKILL.md +72 -0
- taifeng-0.0.1/examples/mcp_basic/skills/lung-nodule-expert/scripts/risk_score.py +106 -0
- taifeng-0.0.1/examples/mcp_hitl/demo.py +305 -0
- taifeng-0.0.1/examples/mcp_hitl/skills/code-review/SKILL.md +35 -0
- taifeng-0.0.1/examples/mcp_hitl/skills/code-review/scripts/lint_check.sh +43 -0
- taifeng-0.0.1/examples/mcp_hitl/skills/programmer/SKILL.md +45 -0
- taifeng-0.0.1/examples/mcp_hitl/skills/programmer/scripts/format_diff.py +42 -0
- taifeng-0.0.1/examples/mcp_showcase/__init__.py +4 -0
- taifeng-0.0.1/examples/mcp_showcase/demo.py +103 -0
- taifeng-0.0.1/examples/mcp_showcase/mcp_lib.py +32 -0
- taifeng-0.0.1/examples/mcp_showcase/mcp_server.py +135 -0
- taifeng-0.0.1/examples/mcp_showcase/skills/market-assistant/SKILL.md +22 -0
- taifeng-0.0.1/examples/mcp_showcase/skills/summary-writer/SKILL.md +9 -0
- taifeng-0.0.1/examples/memory/demo.py +249 -0
- taifeng-0.0.1/examples/numeric_loop/demo.py +242 -0
- taifeng-0.0.1/examples/numeric_loop/skills/numeric-tuner/SKILL.md +75 -0
- taifeng-0.0.1/examples/numeric_loop/skills/numeric-tuner/scripts/apply_delta.py +63 -0
- taifeng-0.0.1/examples/numeric_loop/skills/numeric-utils/SKILL.md +32 -0
- taifeng-0.0.1/examples/observability/audit_index_hook.py +174 -0
- taifeng-0.0.1/examples/orchestration/demo.py +98 -0
- taifeng-0.0.1/examples/orchestration/skills/itinerary-summarizer/SKILL.md +10 -0
- taifeng-0.0.1/examples/orchestration/skills/route-north/SKILL.md +10 -0
- taifeng-0.0.1/examples/orchestration/skills/route-south/SKILL.md +10 -0
- taifeng-0.0.1/examples/orchestration/skills/trip-planner/SKILL.md +26 -0
- taifeng-0.0.1/examples/orchestration/skills/weather-detail/SKILL.md +10 -0
- taifeng-0.0.1/examples/orchestration/skills/weather-probe/SKILL.md +18 -0
- taifeng-0.0.1/examples/permission/web_prompter.py +141 -0
- taifeng-0.0.1/examples/persistence/postgres_thread_directory.py +235 -0
- taifeng-0.0.1/examples/persistence/redis_thread_directory.py +209 -0
- taifeng-0.0.1/examples/product_review/demo.py +249 -0
- taifeng-0.0.1/examples/product_review/skills/design-critic/SKILL.md +50 -0
- taifeng-0.0.1/examples/product_review/skills/design-critic/scripts/ux_checklist.sh +51 -0
- taifeng-0.0.1/examples/product_review/skills/eng-feasibility/SKILL.md +51 -0
- taifeng-0.0.1/examples/product_review/skills/eng-feasibility/scripts/complexity_estimate.sh +54 -0
- taifeng-0.0.1/examples/product_review/skills/product-manager/SKILL.md +71 -0
- taifeng-0.0.1/examples/product_review/skills/qa-risk/SKILL.md +51 -0
- taifeng-0.0.1/examples/product_review/skills/qa-risk/scripts/test_surface.sh +55 -0
- taifeng-0.0.1/examples/read_skill_lazy/demo.py +93 -0
- taifeng-0.0.1/examples/read_skill_lazy/skills/knowledge-router/SKILL.md +18 -0
- taifeng-0.0.1/examples/read_skill_lazy/skills/regex-guide/SKILL.md +13 -0
- taifeng-0.0.1/examples/read_skill_lazy/skills/sql-injection-guide/SKILL.md +14 -0
- taifeng-0.0.1/examples/real_llm/capability_matrix.py +273 -0
- taifeng-0.0.1/examples/real_llm/composite.py +157 -0
- taifeng-0.0.1/examples/real_llm/e2e.py +181 -0
- taifeng-0.0.1/examples/real_llm/kernel_knobs.py +183 -0
- taifeng-0.0.1/examples/real_llm/with_hooks.py +130 -0
- taifeng-0.0.1/examples/research_assistant/demo.py +250 -0
- taifeng-0.0.1/examples/research_assistant/skills/fact-extractor/SKILL.md +56 -0
- taifeng-0.0.1/examples/research_assistant/skills/fact-extractor/scripts/extract_facts.sh +23 -0
- taifeng-0.0.1/examples/research_assistant/skills/report-writer/SKILL.md +62 -0
- taifeng-0.0.1/examples/research_assistant/skills/report-writer/scripts/draft_outline.sh +31 -0
- taifeng-0.0.1/examples/research_assistant/skills/research-lead/SKILL.md +62 -0
- taifeng-0.0.1/examples/research_assistant/skills/source-collector/SKILL.md +57 -0
- taifeng-0.0.1/examples/research_assistant/skills/source-collector/scripts/mock_search.sh +27 -0
- taifeng-0.0.1/examples/selective_approval/demo.py +350 -0
- taifeng-0.0.1/examples/selective_approval/skills/analysis-orchestrator/SKILL.md +67 -0
- taifeng-0.0.1/examples/selective_approval/skills/prd-evaluator/SKILL.md +52 -0
- taifeng-0.0.1/examples/selective_approval/skills/prd-evaluator/scripts/prd_check.sh +69 -0
- taifeng-0.0.1/examples/selective_approval/skills/swot-evaluator/SKILL.md +54 -0
- taifeng-0.0.1/examples/selective_approval/skills/swot-evaluator/scripts/swot_screen.sh +82 -0
- taifeng-0.0.1/examples/subagent_isolation/demo.py +156 -0
- taifeng-0.0.1/examples/subagent_isolation/skills/code-review/SKILL.md +35 -0
- taifeng-0.0.1/examples/subagent_isolation/skills/code-review/scripts/lint_check.sh +43 -0
- taifeng-0.0.1/examples/subagent_isolation/skills/programmer/SKILL.md +45 -0
- taifeng-0.0.1/examples/subagent_isolation/skills/programmer/scripts/format_diff.py +42 -0
- taifeng-0.0.1/examples/travel_planner/demo.py +252 -0
- taifeng-0.0.1/examples/travel_planner/skills/activities-finder/SKILL.md +58 -0
- taifeng-0.0.1/examples/travel_planner/skills/activities-finder/scripts/mock_activities.sh +33 -0
- taifeng-0.0.1/examples/travel_planner/skills/flights-finder/SKILL.md +57 -0
- taifeng-0.0.1/examples/travel_planner/skills/flights-finder/scripts/mock_flights.sh +28 -0
- taifeng-0.0.1/examples/travel_planner/skills/hotels-finder/SKILL.md +61 -0
- taifeng-0.0.1/examples/travel_planner/skills/hotels-finder/scripts/mock_hotels.sh +37 -0
- taifeng-0.0.1/examples/travel_planner/skills/trip-planner/SKILL.md +68 -0
- taifeng-0.0.1/examples/web_ui/README.md +218 -0
- taifeng-0.0.1/examples/web_ui/server.py +1133 -0
- taifeng-0.0.1/examples/web_ui/skills/code-review/SKILL.md +35 -0
- taifeng-0.0.1/examples/web_ui/skills/code-review/scripts/lint_check.sh +43 -0
- taifeng-0.0.1/examples/web_ui/skills/programmer/SKILL.md +45 -0
- taifeng-0.0.1/examples/web_ui/skills/programmer/scripts/format_diff.py +42 -0
- taifeng-0.0.1/examples/web_ui/static/index.html +1313 -0
- taifeng-0.0.1/pyproject.toml +72 -0
- taifeng-0.0.1/src/taifeng/__init__.py +248 -0
- taifeng-0.0.1/src/taifeng/__main__.py +346 -0
- taifeng-0.0.1/src/taifeng/context/__init__.py +45 -0
- taifeng-0.0.1/src/taifeng/context/budget.py +92 -0
- taifeng-0.0.1/src/taifeng/context/cache_stats.py +90 -0
- taifeng-0.0.1/src/taifeng/context/compressor.py +89 -0
- taifeng-0.0.1/src/taifeng/context/injection.py +50 -0
- taifeng-0.0.1/src/taifeng/context/memory.py +83 -0
- taifeng-0.0.1/src/taifeng/context/strategies/__init__.py +9 -0
- taifeng-0.0.1/src/taifeng/context/strategies/handoff.py +405 -0
- taifeng-0.0.1/src/taifeng/context/strategies/sliding.py +101 -0
- taifeng-0.0.1/src/taifeng/context/truncate.py +42 -0
- taifeng-0.0.1/src/taifeng/conversation/__init__.py +68 -0
- taifeng-0.0.1/src/taifeng/conversation/errors.py +25 -0
- taifeng-0.0.1/src/taifeng/conversation/hook_runner.py +138 -0
- taifeng-0.0.1/src/taifeng/conversation/models.py +212 -0
- taifeng-0.0.1/src/taifeng/conversation/protocols.py +169 -0
- taifeng-0.0.1/src/taifeng/conversation/rebuild.py +123 -0
- taifeng-0.0.1/src/taifeng/conversation/sqlite_directory.py +422 -0
- taifeng-0.0.1/src/taifeng/conversation/store.py +64 -0
- taifeng-0.0.1/src/taifeng/conversation/transcript.py +346 -0
- taifeng-0.0.1/src/taifeng/hooks/__init__.py +52 -0
- taifeng-0.0.1/src/taifeng/hooks/types.py +292 -0
- taifeng-0.0.1/src/taifeng/instructions/__init__.py +25 -0
- taifeng-0.0.1/src/taifeng/instructions/resolver.py +333 -0
- taifeng-0.0.1/src/taifeng/instructions/source.py +46 -0
- taifeng-0.0.1/src/taifeng/instructions/types.py +105 -0
- taifeng-0.0.1/src/taifeng/llm/__init__.py +65 -0
- taifeng-0.0.1/src/taifeng/llm/client.py +50 -0
- taifeng-0.0.1/src/taifeng/llm/errors.py +149 -0
- taifeng-0.0.1/src/taifeng/llm/events.py +139 -0
- taifeng-0.0.1/src/taifeng/llm/providers/__init__.py +39 -0
- taifeng-0.0.1/src/taifeng/llm/providers/_shared.py +349 -0
- taifeng-0.0.1/src/taifeng/llm/providers/anthropic_provider.py +469 -0
- taifeng-0.0.1/src/taifeng/llm/providers/deepseek_provider.py +56 -0
- taifeng-0.0.1/src/taifeng/llm/providers/gemini_provider.py +395 -0
- taifeng-0.0.1/src/taifeng/llm/providers/litellm_provider.py +378 -0
- taifeng-0.0.1/src/taifeng/llm/providers/mock.py +196 -0
- taifeng-0.0.1/src/taifeng/llm/providers/openai_compat.py +337 -0
- taifeng-0.0.1/src/taifeng/llm/recovery.py +105 -0
- taifeng-0.0.1/src/taifeng/llm/retry.py +90 -0
- taifeng-0.0.1/src/taifeng/llm/types.py +135 -0
- taifeng-0.0.1/src/taifeng/loop/__init__.py +109 -0
- taifeng-0.0.1/src/taifeng/loop/cancellation.py +92 -0
- taifeng-0.0.1/src/taifeng/loop/engine.py +907 -0
- taifeng-0.0.1/src/taifeng/loop/event.py +461 -0
- taifeng-0.0.1/src/taifeng/loop/orchestration_exec.py +209 -0
- taifeng-0.0.1/src/taifeng/loop/pool.py +498 -0
- taifeng-0.0.1/src/taifeng/loop/prompt.py +190 -0
- taifeng-0.0.1/src/taifeng/loop/spawn.py +68 -0
- taifeng-0.0.1/src/taifeng/loop/submission.py +136 -0
- taifeng-0.0.1/src/taifeng/loop/tool_batch.py +187 -0
- taifeng-0.0.1/src/taifeng/loop/turn.py +1018 -0
- taifeng-0.0.1/src/taifeng/mcp/__init__.py +43 -0
- taifeng-0.0.1/src/taifeng/mcp/prompter.py +182 -0
- taifeng-0.0.1/src/taifeng/mcp/server.py +619 -0
- taifeng-0.0.1/src/taifeng/mcp/stdio_client.py +351 -0
- taifeng-0.0.1/src/taifeng/permission/__init__.py +39 -0
- taifeng-0.0.1/src/taifeng/permission/types.py +723 -0
- taifeng-0.0.1/src/taifeng/skill/__init__.py +51 -0
- taifeng-0.0.1/src/taifeng/skill/definition.py +136 -0
- taifeng-0.0.1/src/taifeng/skill/dispatch.py +295 -0
- taifeng-0.0.1/src/taifeng/skill/eligibility.py +43 -0
- taifeng-0.0.1/src/taifeng/skill/loader.py +371 -0
- taifeng-0.0.1/src/taifeng/skill/orchestration.py +273 -0
- taifeng-0.0.1/src/taifeng/skill/registry.py +145 -0
- taifeng-0.0.1/src/taifeng/skill/scripts/__init__.py +39 -0
- taifeng-0.0.1/src/taifeng/skill/scripts/executor.py +54 -0
- taifeng-0.0.1/src/taifeng/skill/scripts/python.py +51 -0
- taifeng-0.0.1/src/taifeng/skill/scripts/shell.py +289 -0
- taifeng-0.0.1/src/taifeng/skill/scripts/types.py +110 -0
- taifeng-0.0.1/src/taifeng/skill/watcher.py +99 -0
- taifeng-0.0.1/src/taifeng/telemetry/__init__.py +38 -0
- taifeng-0.0.1/src/taifeng/telemetry/console.py +235 -0
- taifeng-0.0.1/src/taifeng/telemetry/jsonl_sink.py +32 -0
- taifeng-0.0.1/src/taifeng/telemetry/otel_sink.py +440 -0
- taifeng-0.0.1/src/taifeng/telemetry/sink.py +15 -0
- taifeng-0.0.1/src/taifeng/tool/__init__.py +20 -0
- taifeng-0.0.1/src/taifeng/tool/builtins/__init__.py +42 -0
- taifeng-0.0.1/src/taifeng/tool/builtins/apply_patch.py +291 -0
- taifeng-0.0.1/src/taifeng/tool/builtins/background.py +410 -0
- taifeng-0.0.1/src/taifeng/tool/builtins/call_skill.py +359 -0
- taifeng-0.0.1/src/taifeng/tool/builtins/file_io.py +169 -0
- taifeng-0.0.1/src/taifeng/tool/builtins/http_request.py +271 -0
- taifeng-0.0.1/src/taifeng/tool/builtins/read_skill.py +65 -0
- taifeng-0.0.1/src/taifeng/tool/builtins/run_script.py +417 -0
- taifeng-0.0.1/src/taifeng/tool/builtins/shell.py +173 -0
- taifeng-0.0.1/src/taifeng/tool/registry.py +59 -0
- taifeng-0.0.1/src/taifeng/tool/runtime.py +137 -0
- taifeng-0.0.1/src/taifeng/tool/spec.py +81 -0
- taifeng-0.0.1/tests/__init__.py +0 -0
- taifeng-0.0.1/tests/conftest.py +51 -0
- taifeng-0.0.1/tests/context/__init__.py +0 -0
- taifeng-0.0.1/tests/context/test_cache_stats.py +57 -0
- taifeng-0.0.1/tests/context/test_compaction.py +226 -0
- taifeng-0.0.1/tests/context/test_truncate.py +35 -0
- taifeng-0.0.1/tests/conversation/__init__.py +0 -0
- taifeng-0.0.1/tests/conversation/test_boundaries.py +248 -0
- taifeng-0.0.1/tests/conversation/test_index_hook.py +212 -0
- taifeng-0.0.1/tests/conversation/test_jsonl_writer.py +170 -0
- taifeng-0.0.1/tests/conversation/test_protocols.py +144 -0
- taifeng-0.0.1/tests/conversation/test_rebuild_index.py +166 -0
- taifeng-0.0.1/tests/conversation/test_sqlite_directory.py +274 -0
- taifeng-0.0.1/tests/conversation/test_store_compat.py +82 -0
- taifeng-0.0.1/tests/hooks/__init__.py +0 -0
- taifeng-0.0.1/tests/hooks/test_hooks.py +199 -0
- taifeng-0.0.1/tests/hooks/test_pre_turn_pre_compact.py +282 -0
- taifeng-0.0.1/tests/instructions/__init__.py +0 -0
- taifeng-0.0.1/tests/instructions/test_instructions.py +735 -0
- taifeng-0.0.1/tests/instructions/test_prompt_instructions.py +101 -0
- taifeng-0.0.1/tests/llm/__init__.py +0 -0
- taifeng-0.0.1/tests/llm/test_anthropic_provider.py +533 -0
- taifeng-0.0.1/tests/llm/test_deepseek_provider.py +242 -0
- taifeng-0.0.1/tests/llm/test_extract_usage_shared.py +138 -0
- taifeng-0.0.1/tests/llm/test_failure_class.py +136 -0
- taifeng-0.0.1/tests/llm/test_finish_reason_guard.py +110 -0
- taifeng-0.0.1/tests/llm/test_gemini_provider.py +460 -0
- taifeng-0.0.1/tests/llm/test_header_extractors.py +65 -0
- taifeng-0.0.1/tests/llm/test_litellm_error_classify.py +167 -0
- taifeng-0.0.1/tests/llm/test_openai_compat.py +110 -0
- taifeng-0.0.1/tests/llm/test_provider_error_classify_shared.py +149 -0
- taifeng-0.0.1/tests/llm/test_recovery.py +61 -0
- taifeng-0.0.1/tests/llm/test_routing_mock.py +43 -0
- taifeng-0.0.1/tests/llm/test_sse_parse_shared.py +88 -0
- taifeng-0.0.1/tests/llm/test_structured_output.py +336 -0
- taifeng-0.0.1/tests/loop/__init__.py +0 -0
- taifeng-0.0.1/tests/loop/test_bus_backpressure.py +82 -0
- taifeng-0.0.1/tests/loop/test_cache_break_reason.py +130 -0
- taifeng-0.0.1/tests/loop/test_cancellation.py +60 -0
- taifeng-0.0.1/tests/loop/test_compaction_hardening.py +231 -0
- taifeng-0.0.1/tests/loop/test_concurrent_dispatch.py +235 -0
- taifeng-0.0.1/tests/loop/test_empty_completion_tolerated.py +158 -0
- taifeng-0.0.1/tests/loop/test_engine_e2e.py +208 -0
- taifeng-0.0.1/tests/loop/test_engine_resume.py +225 -0
- taifeng-0.0.1/tests/loop/test_events.py +38 -0
- taifeng-0.0.1/tests/loop/test_introspect.py +105 -0
- taifeng-0.0.1/tests/loop/test_kernel_knobs_integration.py +138 -0
- taifeng-0.0.1/tests/loop/test_memory_swap.py +164 -0
- taifeng-0.0.1/tests/loop/test_orchestration_exec.py +356 -0
- taifeng-0.0.1/tests/loop/test_permission_policy_wiring.py +171 -0
- taifeng-0.0.1/tests/loop/test_resource_limit.py +123 -0
- taifeng-0.0.1/tests/loop/test_runtime_knobs.py +304 -0
- taifeng-0.0.1/tests/loop/test_spawn_lineage.py +75 -0
- taifeng-0.0.1/tests/loop/test_spawn_registry.py +123 -0
- taifeng-0.0.1/tests/loop/test_tool_batch.py +175 -0
- taifeng-0.0.1/tests/loop/test_turn_sample.py +98 -0
- taifeng-0.0.1/tests/mcp/__init__.py +0 -0
- taifeng-0.0.1/tests/mcp/test_hitl_e2e.py +202 -0
- taifeng-0.0.1/tests/mcp/test_mcp.py +151 -0
- taifeng-0.0.1/tests/mcp/test_prompter.py +181 -0
- taifeng-0.0.1/tests/mcp/test_request_timeout_config.py +96 -0
- taifeng-0.0.1/tests/mcp/test_server.py +306 -0
- taifeng-0.0.1/tests/mcp/test_server_initiated_request.py +266 -0
- taifeng-0.0.1/tests/mcp/test_server_initiated_telemetry.py +148 -0
- taifeng-0.0.1/tests/permission/__init__.py +0 -0
- taifeng-0.0.1/tests/permission/test_args_match.py +184 -0
- taifeng-0.0.1/tests/permission/test_call_skill_permission.py +673 -0
- taifeng-0.0.1/tests/permission/test_call_skill_reason.py +317 -0
- taifeng-0.0.1/tests/permission/test_capability_tier.py +64 -0
- taifeng-0.0.1/tests/permission/test_permission.py +380 -0
- taifeng-0.0.1/tests/permission/test_policy_from_dict.py +237 -0
- taifeng-0.0.1/tests/skill/__init__.py +0 -0
- taifeng-0.0.1/tests/skill/test_composite_e2e.py +432 -0
- taifeng-0.0.1/tests/skill/test_dispatch.py +76 -0
- taifeng-0.0.1/tests/skill/test_orchestration.py +158 -0
- taifeng-0.0.1/tests/skill/test_python_executor.py +111 -0
- taifeng-0.0.1/tests/skill/test_script_execution.py +400 -0
- taifeng-0.0.1/tests/skill/test_script_loader.py +287 -0
- taifeng-0.0.1/tests/skill/test_shell_executor.py +189 -0
- taifeng-0.0.1/tests/skill/test_skill.py +163 -0
- taifeng-0.0.1/tests/skill/test_skill_visibility.py +155 -0
- taifeng-0.0.1/tests/skill/test_subagent_isolation_integration.py +287 -0
- taifeng-0.0.1/tests/skill/test_subagent_policy.py +189 -0
- taifeng-0.0.1/tests/skill/test_watcher.py +85 -0
- taifeng-0.0.1/tests/telemetry/__init__.py +1 -0
- taifeng-0.0.1/tests/telemetry/test_otel_sink.py +476 -0
- taifeng-0.0.1/tests/tool/__init__.py +0 -0
- taifeng-0.0.1/tests/tool/test_apply_patch.py +157 -0
- taifeng-0.0.1/tests/tool/test_background_tasks.py +188 -0
- taifeng-0.0.1/tests/tool/test_builtin_tools.py +109 -0
- taifeng-0.0.1/tests/tool/test_cancel_terminal.py +85 -0
- taifeng-0.0.1/tests/tool/test_http_request.py +272 -0
- taifeng-0.0.1/tests/tool/test_run_script_tool.py +349 -0
- taifeng-0.0.1/uv.lock +2447 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# 发布到 PyPI —— 基于 GitHub Trusted Publishing(OIDC,无需在仓库存 token)
|
|
2
|
+
# 触发:推送形如 v* 的 tag(如 v0.0.2)即自动构建并发布。
|
|
3
|
+
# 一次性前置:在 https://pypi.org/manage/account/publishing/ 把本仓库 + 本文件名
|
|
4
|
+
# (publish.yml) + environment (pypi) 登记为 trusted publisher。
|
|
5
|
+
name: Publish to PyPI
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags:
|
|
10
|
+
- "v*"
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
# environment 名需与 PyPI trusted publisher 配置中的一致
|
|
16
|
+
environment: pypi
|
|
17
|
+
permissions:
|
|
18
|
+
# OIDC 令牌签发权限 —— Trusted Publishing 必需,缺它会鉴权失败
|
|
19
|
+
id-token: write
|
|
20
|
+
steps:
|
|
21
|
+
- name: 检出代码
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: 安装 uv
|
|
25
|
+
uses: astral-sh/setup-uv@v5
|
|
26
|
+
|
|
27
|
+
- name: 构建 wheel 与 sdist
|
|
28
|
+
run: uv build
|
|
29
|
+
|
|
30
|
+
- name: 校验 tag 版本与 pyproject 版本一致
|
|
31
|
+
# 防止打错 tag:tag 去掉前缀 v 后必须等于 pyproject.toml 的 version
|
|
32
|
+
run: |
|
|
33
|
+
tag_version="${GITHUB_REF_NAME#v}"
|
|
34
|
+
proj_version="$(uv version --short)"
|
|
35
|
+
if [ "$tag_version" != "$proj_version" ]; then
|
|
36
|
+
echo "::error::tag ($tag_version) 与 pyproject version ($proj_version) 不一致"
|
|
37
|
+
exit 1
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
- name: 发布到 PyPI(Trusted Publishing)
|
|
41
|
+
run: uv publish --trusted-publishing always
|
taifeng-0.0.1/.gitignore
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
.history/
|
|
2
|
+
.codex/
|
|
3
|
+
.claude/
|
|
4
|
+
.taifeng-*
|
|
5
|
+
.ruff_cache/
|
|
6
|
+
|
|
7
|
+
.playwright-mcp/*
|
|
8
|
+
|
|
9
|
+
# Byte-compiled / optimized / DLL files
|
|
10
|
+
__pycache__/
|
|
11
|
+
*.py[cod]
|
|
12
|
+
*$py.class
|
|
13
|
+
|
|
14
|
+
# C extensions
|
|
15
|
+
*.so
|
|
16
|
+
|
|
17
|
+
# Distribution / packaging
|
|
18
|
+
.Python
|
|
19
|
+
build/
|
|
20
|
+
develop-eggs/
|
|
21
|
+
dist/
|
|
22
|
+
downloads/
|
|
23
|
+
eggs/
|
|
24
|
+
.eggs/
|
|
25
|
+
lib/
|
|
26
|
+
lib64/
|
|
27
|
+
parts/
|
|
28
|
+
sdist/
|
|
29
|
+
var/
|
|
30
|
+
wheels/
|
|
31
|
+
share/python-wheels/
|
|
32
|
+
*.egg-info/
|
|
33
|
+
.installed.cfg
|
|
34
|
+
*.egg
|
|
35
|
+
MANIFEST
|
|
36
|
+
|
|
37
|
+
# PyInstaller
|
|
38
|
+
# Usually these files are written by a python script from a template
|
|
39
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
40
|
+
*.manifest
|
|
41
|
+
*.spec
|
|
42
|
+
|
|
43
|
+
# Installer logs
|
|
44
|
+
pip-log.txt
|
|
45
|
+
pip-delete-this-directory.txt
|
|
46
|
+
|
|
47
|
+
# Unit test / coverage reports
|
|
48
|
+
htmlcov/
|
|
49
|
+
.tox/
|
|
50
|
+
.nox/
|
|
51
|
+
.coverage
|
|
52
|
+
.coverage.*
|
|
53
|
+
.cache
|
|
54
|
+
nosetests.xml
|
|
55
|
+
coverage.xml
|
|
56
|
+
*.cover
|
|
57
|
+
*.py,cover
|
|
58
|
+
.hypothesis/
|
|
59
|
+
.pytest_cache/
|
|
60
|
+
cover/
|
|
61
|
+
|
|
62
|
+
# Translations
|
|
63
|
+
*.mo
|
|
64
|
+
*.pot
|
|
65
|
+
|
|
66
|
+
# Django stuff:
|
|
67
|
+
*.log
|
|
68
|
+
local_settings.py
|
|
69
|
+
db.sqlite3
|
|
70
|
+
db.sqlite3-journal
|
|
71
|
+
|
|
72
|
+
# Flask stuff:
|
|
73
|
+
instance/
|
|
74
|
+
.webassets-cache
|
|
75
|
+
|
|
76
|
+
# Scrapy stuff:
|
|
77
|
+
.scrapy
|
|
78
|
+
|
|
79
|
+
# Sphinx documentation
|
|
80
|
+
docs/_build/
|
|
81
|
+
|
|
82
|
+
# PyBuilder
|
|
83
|
+
.pybuilder/
|
|
84
|
+
target/
|
|
85
|
+
|
|
86
|
+
# Jupyter Notebook
|
|
87
|
+
.ipynb_checkpoints
|
|
88
|
+
|
|
89
|
+
# IPython
|
|
90
|
+
profile_default/
|
|
91
|
+
ipython_config.py
|
|
92
|
+
|
|
93
|
+
# pyenv
|
|
94
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
95
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
96
|
+
# .python-version
|
|
97
|
+
|
|
98
|
+
# pipenv
|
|
99
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
100
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
101
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
102
|
+
# install all needed dependencies.
|
|
103
|
+
#Pipfile.lock
|
|
104
|
+
|
|
105
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
106
|
+
__pypackages__/
|
|
107
|
+
|
|
108
|
+
# Celery stuff
|
|
109
|
+
celerybeat-schedule
|
|
110
|
+
celerybeat.pid
|
|
111
|
+
|
|
112
|
+
# SageMath parsed files
|
|
113
|
+
*.sage.py
|
|
114
|
+
|
|
115
|
+
# Environments
|
|
116
|
+
.env
|
|
117
|
+
.venv
|
|
118
|
+
env/
|
|
119
|
+
venv/
|
|
120
|
+
ENV/
|
|
121
|
+
env.bak/
|
|
122
|
+
venv.bak/
|
|
123
|
+
|
|
124
|
+
# Spyder project settings
|
|
125
|
+
.spyderproject
|
|
126
|
+
.spyproject
|
|
127
|
+
|
|
128
|
+
# Rope project settings
|
|
129
|
+
.ropeproject
|
|
130
|
+
|
|
131
|
+
# mkdocs documentation
|
|
132
|
+
/site
|
|
133
|
+
|
|
134
|
+
# mypy
|
|
135
|
+
.mypy_cache/
|
|
136
|
+
.dmypy.json
|
|
137
|
+
dmypy.json
|
|
138
|
+
|
|
139
|
+
# Pyre type checker
|
|
140
|
+
.pyre/
|
|
141
|
+
|
|
142
|
+
# pytype static type analyzer
|
|
143
|
+
.pytype/
|
|
144
|
+
|
|
145
|
+
# Cython debug symbols
|
|
146
|
+
cython_debug/
|
|
147
|
+
|
|
148
|
+
# Taifeng runtime artifacts
|
|
149
|
+
.taifeng/
|
|
150
|
+
threads/
|
|
151
|
+
*.jsonl
|
|
152
|
+
*.db
|
|
153
|
+
*.db-shm
|
|
154
|
+
*.db-wal
|
|
155
|
+
|
|
156
|
+
# Editor / OS
|
|
157
|
+
.vscode/
|
|
158
|
+
.idea/
|
|
159
|
+
.DS_Store
|
|
160
|
+
|
taifeng-0.0.1/AGENTS.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# AGENTS.md —— Taifeng 工程协作约定
|
|
2
|
+
|
|
3
|
+
> 本文件供 AI agent (Claude Code / codex / claw) 在本仓库工作时遵守。
|
|
4
|
+
|
|
5
|
+
## 项目身份
|
|
6
|
+
|
|
7
|
+
**Taifeng (泰逢)**:通用 LLM Agent 微内核 / OS 调度器。
|
|
8
|
+
独立 infra 包,不绑定任何业务系统。第一个生产用户是 宿主业务,但**绝不引入 宿主业务 概念**。
|
|
9
|
+
|
|
10
|
+
## 工作目录
|
|
11
|
+
|
|
12
|
+
- `src/taifeng/` —— 核心实现(6 个子包:skill / tool / conversation / context / llm / loop + telemetry)
|
|
13
|
+
- `tests/` —— pytest(asyncio_mode=auto)
|
|
14
|
+
- `examples/` —— 端到端示例(mock 客户端,无需 API key)
|
|
15
|
+
- `docs/` —— 架构 + ADR + 调研
|
|
16
|
+
- `docs/architecture/capabilities/` —— 能力契约(契约先行:数据结构 / 协议 / 事件 / 约束)
|
|
17
|
+
|
|
18
|
+
## 多 Session 并发协作(一 session 一 worktree)
|
|
19
|
+
|
|
20
|
+
> 多个 AI session 并发在本仓库工作时,**绝不共用主工作树**。
|
|
21
|
+
> 教训(真实事故):主工作树只有**一个共享的 HEAD / index / 工作目录**,谁 `git checkout` 切分支,就把 HEAD 从别人脚下抽走 —— 导致 commit 落错分支、别人的未提交改动被串走、被迫做 git 手术。**开分支 ≠ 隔离;独立的工作目录才隔离。** 因此"每个 session 各开分支但共用主树"恰恰是最乱的组合。
|
|
22
|
+
|
|
23
|
+
**三条硬规则:**
|
|
24
|
+
|
|
25
|
+
1. **主树只做集成**:任何 session **都不**在主树(`<repo-root>`)里做开发或 `git checkout` 切分支。主树仅用于最终 merge 或当干净参照。
|
|
26
|
+
2. **一 session = 一 worktree = 一分支**:session 启动即 `git worktree add .claude/worktrees/<task> -b feat/<task> <integration-point>`,全程钉死在自己的 worktree 里;**从不 `cd` 回主树、从不动别人的分支、从不切主树 HEAD**。
|
|
27
|
+
3. **任务范围作所有权单元**:一个 session 认领一个明确的任务范围;尽量按目录切分工(如 A 只碰 `loop/`、B 只碰 `context/`),减少重叠。
|
|
28
|
+
|
|
29
|
+
**降冲突:**
|
|
30
|
+
|
|
31
|
+
- `loop/event.py`(`MsgKind` / `Msg` Union 全局注册表)这类"全局枚举/注册表"是冲突高发区 —— 让单一 session 统一增改,或频繁从集成分支 rebase 早暴露冲突。
|
|
32
|
+
- 集成时**一次只合一条分支**,合完立即跑全量 `PYTHONPATH=src uv run pytest tests/` 再合下一条;不要同时合多条。
|
|
33
|
+
|
|
34
|
+
**操作前自检 + 收尾:**
|
|
35
|
+
|
|
36
|
+
- 动手提交前先 `git rev-parse --abbrev-ref HEAD` 确认在自己的 worktree 分支上。
|
|
37
|
+
- 合并完成后 `git worktree remove <path>` + `git branch -d <分支>`(`-d` 会校验已完全合并才删,安全)。
|
|
38
|
+
- 注:本仓库是 **git submodule**,worktree 建在 submodule 工作树下(`.claude/worktrees/`),不要建到父仓库去。
|
|
39
|
+
|
|
40
|
+
## 五条审 PR 红线(任何变更必须遵守)
|
|
41
|
+
|
|
42
|
+
1. **业务零侵入** —— 禁止 `tenant_id` / 业务术语 / 宿主业务 模块 import
|
|
43
|
+
2. **Cache 友好** —— 压缩必须返回 `cache_invalidated: bool` + `anchor_preserved_until: int`
|
|
44
|
+
3. **可观测** —— turn / tool / skill / compaction / cache_break 都必须有 EventMsg
|
|
45
|
+
4. **可取消** —— 长时操作接收 `CancellationToken`;不允许阻塞主 actor
|
|
46
|
+
5. **可 resume** —— 默认实现是 JSONL 追加写;其他 store 用 `MessageStore` 协议
|
|
47
|
+
|
|
48
|
+
## 实现约束
|
|
49
|
+
|
|
50
|
+
- Python 3.12+,类型注解全部 `from __future__ import annotations`
|
|
51
|
+
- 异步用 `anyio`(必要时回退 `asyncio`),不用同步阻塞调用
|
|
52
|
+
- 数据类用 `@dataclass(frozen=True)` 或 `pydantic.BaseModel`
|
|
53
|
+
- 文件 ≤ 800 行硬红线;函数 ≤ 80 行;圈复杂度 ≤ 10
|
|
54
|
+
- 注释中文(覆盖默认 no-comments 规则);module/class/function 必须有 docstring
|
|
55
|
+
- 配置走依赖注入;禁止 `os.getenv` 在 src/ 内
|
|
56
|
+
|
|
57
|
+
## 测试约束
|
|
58
|
+
|
|
59
|
+
- 新模块必须有 `tests/test_<module>.py`
|
|
60
|
+
- LLM 调用走 `MockClient` —— 不能在 CI 里调真实 API
|
|
61
|
+
- 文件 IO 走 `tmp_path` fixture
|
|
62
|
+
- 边界必测:cancel、空输入、超长 body、环检测、深度上限
|
|
63
|
+
|
|
64
|
+
## 命令速查
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# 安装
|
|
68
|
+
uv venv && uv pip install -e ".[dev,litellm]"
|
|
69
|
+
|
|
70
|
+
# 测试(全套)
|
|
71
|
+
PYTHONPATH=src uv run pytest tests/ -v
|
|
72
|
+
|
|
73
|
+
# 示例(basic/ 与各 pattern demo 走 MockClient,无需 API key;real_llm/ 需真实 key)
|
|
74
|
+
PYTHONPATH=src uv run python examples/basic/minimal_chat.py
|
|
75
|
+
PYTHONPATH=src uv run python examples/basic/composite_skill.py
|
|
76
|
+
PYTHONPATH=src uv run python examples/orchestration/demo.py # 声明式编排
|
|
77
|
+
PYTHONPATH=src uv run python examples/mcp_basic/demo.py # taifeng 作为 MCP server
|
|
78
|
+
# 完整清单见 examples/ 各子目录(instructions_basic / skill_with_script / research_assistant /
|
|
79
|
+
# travel_planner / code_review / mcp_hitl / permission / persistence / web_ui ...)
|
|
80
|
+
|
|
81
|
+
# CLI
|
|
82
|
+
PYTHONPATH=src uv run python -m taifeng skill list /path/to/skills
|
|
83
|
+
PYTHONPATH=src uv run python -m taifeng skill validate /path/to/skills
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 能力契约工作流(contract-first)
|
|
87
|
+
|
|
88
|
+
1. 定契约:在 `docs/architecture/capabilities/<capability>.md` 写清数据结构 / 协议 / 事件 / 约束
|
|
89
|
+
2. 实现:小步切片,每步完成立即 commit;红测试不可跳过
|
|
90
|
+
3. 同步:更新对应 `docs/architecture/<module>.md` 活文档
|
|
91
|
+
|
|
92
|
+
## 文档义务
|
|
93
|
+
|
|
94
|
+
`docs/README.md` 是文档索引 + 分类约定(权威)。两类文档处理方式不同,别混用:
|
|
95
|
+
|
|
96
|
+
- `docs/architecture/` = 当前架构**活文档**(含 `capabilities/` 契约层)→ 改了 `src/` 设计 / 数据流就**更新**对应篇(§编号对应:skill→skill-system、loop+tool→agent-loop、conversation、context→context-compression、llm→llm-client、切分→overview)。永远代表现状,**不归档、不堆废弃史**。
|
|
97
|
+
- `docs/decisions/` = ADR → **只增不改**,推翻写新 ADR 标 `Supersedes #NNNN`。
|
|
98
|
+
|
|
99
|
+
**判据**:写"现状"进 architecture(模块篇或 `capabilities/` 契约),写"决策 / 为什么"进 ADR。
|
|
100
|
+
**硬约束**:实现完成但 architecture 未同步 → 不得 archive,PR 不合并。
|
|
101
|
+
|
|
102
|
+
## 参照实现
|
|
103
|
+
|
|
104
|
+
代码参照三个开源项目(位于本机 `<opensource>/`):
|
|
105
|
+
|
|
106
|
+
- **codex** (Rust) —— 范式权威。`codex-rs/core/src/compact.rs` / `client.rs` 是 cache-aware + handoff 的源头
|
|
107
|
+
- **claw-code** (Rust) —— Claude Code 开源移植。`crates/runtime/src/compact.rs` 含 tool 配对边界保护
|
|
108
|
+
- **openclaw** (TS) —— `src/agents/*` 提供 actor + session 模式
|
|
109
|
+
|
|
110
|
+
移植到 Python 时**只学范式,不抄代码**(语言习惯不同)。
|
taifeng-0.0.1/CLAUDE.md
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
> 配套文件:`AGENTS.md` 是给所有 AI agent 看的工程协作约定;本文件聚焦 Claude Code 在本仓库执行任务时需要的快速上下文。两者冲突时以 `AGENTS.md` 为准(它是更早的工程契约)。
|
|
6
|
+
|
|
7
|
+
## 项目身份
|
|
8
|
+
|
|
9
|
+
**Taifeng (泰逢)** —— 通用 LLM Agent **微内核 / OS 调度器**(不是织造工具,不是业务框架)。Python 3.12+,对标 codex (Rust) / Claude Code (TS) / claw-code (Rust) 的 CLI agent 范式,为 Python 服务端提供可嵌入的 agent 引擎。
|
|
10
|
+
|
|
11
|
+
**关键定位**:
|
|
12
|
+
- 是独立 infra 包,**与业务完全解耦**。`src/` 内**禁止出现任何业务概念**(无 tenant / 无领域名词 / 无 LLM provider lock-in)。
|
|
13
|
+
- 不与 LangGraph / AutoGen / Letta 竞争(不同范式:codex 风格 vs 图/Actor/记忆)。
|
|
14
|
+
- 范式核心:**skill 是 markdown**(不是 function tool)、**LLM 是调度器**(不是被调度对象)、**压缩 cache-aware**、**Actor 风格 Submission/EventMsg 双总线**。
|
|
15
|
+
|
|
16
|
+
## 常用命令
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# 安装(uv 是必须,不用 pip)
|
|
20
|
+
uv venv && uv pip install -e ".[dev,litellm]"
|
|
21
|
+
|
|
22
|
+
# 跑全部测试(必须带 PYTHONPATH=src,因为是 src-layout)
|
|
23
|
+
PYTHONPATH=src uv run pytest tests/ -v
|
|
24
|
+
|
|
25
|
+
# 跑单个测试文件
|
|
26
|
+
PYTHONPATH=src uv run pytest tests/test_engine_e2e.py -v
|
|
27
|
+
|
|
28
|
+
# 跑单个测试
|
|
29
|
+
PYTHONPATH=src uv run pytest tests/test_dispatch.py::test_circular_reference_detection -v
|
|
30
|
+
|
|
31
|
+
# 端到端示例(examples/basic/ 与各 pattern demo 均走 MockClient,无需 API key)
|
|
32
|
+
PYTHONPATH=src uv run python examples/basic/minimal_chat.py
|
|
33
|
+
PYTHONPATH=src uv run python examples/basic/composite_skill.py
|
|
34
|
+
PYTHONPATH=src uv run python examples/basic/instructions_basic.py # 指令分层注入 + 热更
|
|
35
|
+
PYTHONPATH=src uv run python examples/basic/skill_with_script.py # SKILL.md scripts 运行时
|
|
36
|
+
PYTHONPATH=src uv run python examples/orchestration/demo.py # 声明式编排(parallel/serial/when)
|
|
37
|
+
PYTHONPATH=src uv run python examples/mcp_basic/demo.py # taifeng 作为 MCP server
|
|
38
|
+
# 其余 pattern demo:research_assistant / travel_planner / code_review / product_review /
|
|
39
|
+
# numeric_loop / mcp_hitl / selective_approval / subagent_isolation / observability /
|
|
40
|
+
# permission / persistence / web_ui —— 见 examples/<name>/demo.py(或 server.py)
|
|
41
|
+
PYTHONPATH=src uv run python examples/real_llm/e2e.py # 需要真实 LLM API key(real_llm/ 下均是)
|
|
42
|
+
|
|
43
|
+
# CLI(用于排查 SKILL.md 目录)
|
|
44
|
+
PYTHONPATH=src uv run python -m taifeng skill list <skills_dir>
|
|
45
|
+
PYTHONPATH=src uv run python -m taifeng skill show <skills_dir> <skill_id>
|
|
46
|
+
PYTHONPATH=src uv run python -m taifeng skill validate <skills_dir>
|
|
47
|
+
PYTHONPATH=src uv run python -m taifeng engine demo <skills_dir> <entry_id> -m "..."
|
|
48
|
+
|
|
49
|
+
# Lint / 类型检查(pyproject.toml 已配 ruff + mypy strict)
|
|
50
|
+
uv run ruff check src/ tests/
|
|
51
|
+
uv run mypy src/
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`pytest.ini_options.asyncio_mode = "auto"` —— 所有 async 测试函数无需 `@pytest.mark.asyncio` 装饰。
|
|
55
|
+
|
|
56
|
+
## 完成定义(DoD)
|
|
57
|
+
|
|
58
|
+
标记 task 完成、回报"已完成"、或提交 commit 前必须做到:
|
|
59
|
+
1. **跑通验证命令**:相关 `pytest tests/test_<x>.py` 全绿,或对应 example 端到端无异常。
|
|
60
|
+
2. **复述实际命令 + 关键输出**:不是"应该 OK",而是贴命令与输出。
|
|
61
|
+
3. 红测试**禁止**以 "pre-existing" 为借口跳过。先排查是否与本次改动相关。
|
|
62
|
+
|
|
63
|
+
## 多 Session 并发协作
|
|
64
|
+
|
|
65
|
+
多个 session 并发在本仓库工作时**绝不共用主工作树**——主树只有一个共享 HEAD,谁切分支就把 HEAD 从别人脚下抽走,会导致 commit 落错分支 / 别人未提交改动被串走(**开分支 ≠ 隔离,独立工作目录才隔离**)。规则:
|
|
66
|
+
|
|
67
|
+
1. **主树只做集成**,不在主树开发或 `git checkout` 切分支;
|
|
68
|
+
2. **一 session 一 worktree 一分支**:`git worktree add .claude/worktrees/<task> -b feat/<task> <integration-point>`,全程钉死其中,不 `cd` 回主树、不动别人分支;
|
|
69
|
+
3. **一个 session 认领一个明确的任务范围**,按目录切分工降冲突(`loop/event.py` 等全局注册表是冲突高发区);
|
|
70
|
+
4. 集成**一次合一条**分支 + 跑全量 `PYTHONPATH=src uv run pytest tests/`;收尾 `git worktree remove` + `git branch -d`。
|
|
71
|
+
|
|
72
|
+
> 完整约定(含真实事故教训、submodule 注意点)见 `AGENTS.md` 「多 Session 并发协作」节。
|
|
73
|
+
|
|
74
|
+
## 五条审 PR 红线(任何变更必须遵守)
|
|
75
|
+
|
|
76
|
+
| # | 红线 | 落实方式 |
|
|
77
|
+
| --- | --- | --- |
|
|
78
|
+
| **R1 业务零侵入** | `src/` 内禁止业务概念:`tenant_id`、`audience`、领域名词(无论中英文)、业务子模块路径 | 业务侧通过 `AgentPolicy` 钩子注入策略 |
|
|
79
|
+
| **R2 Cache 友好** | 压缩动作必须返回 `CompressionResult { cache_invalidated: bool, anchor_preserved_until: int }` | mid-turn 只改 tail;pre-turn 才允许动 head |
|
|
80
|
+
| **R3 可观测** | 关键路径必须打 `EventMsg`:`turn_started` / `tool_dispatched` / `compaction_attempted` / `cache_break_detected` / `provider_retry` | 通过 `TelemetrySink` 协议,不绑定后端 |
|
|
81
|
+
| **R4 可取消** | 长时操作必须接收 `CancellationToken`;子 agent 通过 `cancel.child()` 派生 | 不允许阻塞主 actor |
|
|
82
|
+
| **R5 可 resume** | 默认 store 是 JSONL 追加写;业务侧落 DB 自行实现 `MessageStore` 协议 | `MessageStore` 在 `conversation/store.py` |
|
|
83
|
+
|
|
84
|
+
## 实现约束(src/ 内强制)
|
|
85
|
+
|
|
86
|
+
- **Python 3.12+**,所有模块顶部 `from __future__ import annotations`
|
|
87
|
+
- **异步**用 `anyio`(必要时回退 `asyncio`),不写同步阻塞 IO
|
|
88
|
+
- **数据类**用 `@dataclass(frozen=True)` 或 `pydantic.BaseModel`
|
|
89
|
+
- **配置**通过依赖注入;**`src/` 内禁止 `os.getenv`**(业务侧读环境变量后传入构造函数)
|
|
90
|
+
- **文件 ≤ 800 行**硬红线,警戒线 500;**函数 ≤ 80 行**;圈复杂度 ≤ 10
|
|
91
|
+
- **中文注释**(覆盖默认 "no comments" 规则):所有 module / class / function 必须有 docstring;关键逻辑块行内中文注释
|
|
92
|
+
- **错误**:分类到既有 `LLMError` / `DispatchVerdict` 子类,禁止 silent fallback(`except: pass`、`data.get('x', 默认值)`)
|
|
93
|
+
|
|
94
|
+
## 测试约束
|
|
95
|
+
|
|
96
|
+
- 新模块必须有对应 `tests/test_<module>.py`
|
|
97
|
+
- LLM 调用走 `MockClient` —— **CI 内禁止调用真实 API**(`tests/` 全部用 mock;真实 LLM 验证只在 `examples/real_llm_*.py`)
|
|
98
|
+
- 文件 IO 走 `tmp_path` fixture,不写仓库内固定路径
|
|
99
|
+
- **边界必测**:cancel / 空输入 / 超长 body / 环检测 / 深度上限 / 并发
|
|
100
|
+
|
|
101
|
+
## 架构总览
|
|
102
|
+
|
|
103
|
+
详见 `docs/architecture/overview.md`。一张图速记:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
src/taifeng/
|
|
107
|
+
├── skill/ # §1.1 SkillDefinition (atomic/composite) / loader / registry / dispatch / 环检测 / FileWatcher
|
|
108
|
+
├── tool/ # §1.2 tool 部分:ToolSpec (parallel_safe) / Runtime(RwLock 并行调度)/ builtins
|
|
109
|
+
├── conversation/ # §1.3 ResponseItem / MessageStore 协议 / JsonlMessageStore + SQLite 旁路索引
|
|
110
|
+
├── context/ # §1.4 ContextBudget / CompressionStrategy 协议 / Handoff + Sliding 策略 / cache_stats
|
|
111
|
+
├── llm/ # §1.5 ModelClient 协议 / ResponseEvent / retry / providers (litellm / openai_compat / mock)
|
|
112
|
+
├── loop/ # §1.2 主循环:Submission/Op + EventMsg + Engine(主 actor)+ TurnRunner + Pool + Cancellation
|
|
113
|
+
├── hooks/ # PreToolUse / PostToolUse / PreCompact / PreTurn(claw-code 范式)
|
|
114
|
+
├── permission/ # HITL 审批:PermissionPolicy + Rule + Prompter(CLI / Callback)
|
|
115
|
+
├── mcp/ # MCP stdio client(连外部 MCP server 自动注册 tools)
|
|
116
|
+
└── telemetry/ # ConsoleSink + JsonlSink(其他后端业务侧自接)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
按 ADR 0006 **统一为 Skill 抽象** —— 没有独立的 `agent/` 包,skill-to-skill 派发归 `skill/dispatch.py`,composite skill 替代 agent 概念。
|
|
120
|
+
|
|
121
|
+
### 一次 turn 的数据流(速记)
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
Submission(UserMessage) → AgentEngine 入队 → TurnRunner.run_turn
|
|
125
|
+
├─ pre-sampling 压缩检查(动 head 允许)
|
|
126
|
+
├─ build_prompt(entry_skill body + child skills 列表[只 id+description, 不含 body])
|
|
127
|
+
├─ ModelClientSession.stream → ResponseEvent 流
|
|
128
|
+
│ ├─ TextDelta → EventMsg.AssistantText
|
|
129
|
+
│ ├─ ToolCallDone(read_skill) → 取子 skill body 回流
|
|
130
|
+
│ ├─ ToolCallDone(call_skill) → DispatchPolicy.check(深度/环/白名单)→ 派子 TurnRunner
|
|
131
|
+
│ ├─ ToolCallDone(其他) → ToolCallRuntime.dispatch(parallel_safe ? 读锁 : 写锁)
|
|
132
|
+
│ └─ Completed → break
|
|
133
|
+
├─ mid-turn 压缩检查(只动 tail,保 cache anchor)
|
|
134
|
+
└─ MessageStore.append → JSONL flush
|
|
135
|
+
→ AgentEngine emit EventMsg.TurnComplete
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## 关键抽象(找代码用)
|
|
139
|
+
|
|
140
|
+
| 你想做 / 改 | 看这里 |
|
|
141
|
+
| --- | --- |
|
|
142
|
+
| SKILL.md 字段、frontmatter 校验 | `src/taifeng/skill/definition.py` + `loader.py` |
|
|
143
|
+
| call_skill 派发 / 深度环检测 | `src/taifeng/skill/dispatch.py` |
|
|
144
|
+
| 内置工具 (read_skill / call_skill / file_read / file_write / shell_exec) | `src/taifeng/tool/builtins/` |
|
|
145
|
+
| 压缩策略 (handoff / sliding) | `src/taifeng/context/strategies/` |
|
|
146
|
+
| 多 provider 适配 | `src/taifeng/llm/providers/` |
|
|
147
|
+
| 主循环 / Engine / Pool | `src/taifeng/loop/engine.py` + `turn.py` + `pool.py` |
|
|
148
|
+
| 业务可配置参数全清单 | `docs/configurable-knobs.md`(构造时参数 + 运行时 Op + Engine 公开属性)|
|
|
149
|
+
| 公共 API 一览 | `src/taifeng/__init__.py` 的 `__all__` |
|
|
150
|
+
|
|
151
|
+
## 能力契约工作流(contract-first)
|
|
152
|
+
|
|
153
|
+
每个能力的**稳定契约**(数据结构 / 协议 / 事件 / 约束)落在 `docs/architecture/capabilities/<capability>.md`,索引见 [`docs/architecture/capabilities/README.md`](docs/architecture/capabilities/README.md)。
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
docs/architecture/capabilities/<capability>.md # 能力契约(数据契约 + 行为契约)
|
|
157
|
+
docs/architecture/<module>.md # 模块叙述活文档(如何协作)
|
|
158
|
+
docs/decisions/NNNN-*.md # ADR(为什么这么定)
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
工作流:先定/更新能力契约 → 小步实现(每步完成即 commit,≤ 3h)→ 同步对应 `architecture/<module>.md` 活文档。涉及压缩 / cache / dispatch 的改动 **必须显式声明对 R1–R5 的影响**。
|
|
162
|
+
|
|
163
|
+
## 文档体系与义务
|
|
164
|
+
|
|
165
|
+
> 文档索引与分类约定的**权威**在 `docs/README.md`。下表是速查——四类文档**寿命不同、处理方式不同,禁止混用**:
|
|
166
|
+
|
|
167
|
+
| 目录 | 是什么 | 设计 / 逻辑变更后怎么处理 |
|
|
168
|
+
| --- | --- | --- |
|
|
169
|
+
| `docs/architecture/` | **当前生效的架构设计**(活文档,含 `capabilities/` 契约层) | **更新**对应模块篇 / 契约,永远代表现状;**不归档、不堆废弃史** |
|
|
170
|
+
| `docs/decisions/` | ADR 决策记录(为什么这么定) | **只增不改**;要推翻写新 ADR 标 `Supersedes #NNNN` |
|
|
171
|
+
|
|
172
|
+
**判据**:这条信息是"系统现在的样子" → 改 architecture(模块篇或 `capabilities/` 契约);是"某次决策的经过 / 为什么" → 记 ADR,**不往 architecture 堆废弃史**(例:砍掉某 Op 的理由进 ADR,architecture 只写"现在有哪几种 Op")。
|
|
173
|
+
|
|
174
|
+
改了 `src/` 模块的设计 / 数据流,必须同步**对应** architecture 篇(§编号一一对应:`skill/`→skill-system、`loop/`+`tool/`→agent-loop、`conversation/`→conversation、`context/`→context-compression、`llm/`→llm-client、模块切分→overview)。
|
|
175
|
+
|
|
176
|
+
**硬约束**:实现完成但 architecture(模块篇 / 契约)未同步 → PR 不合并(同 `docs/README.md` 维护红线)。
|
|
177
|
+
|
|
178
|
+
## 参照实现
|
|
179
|
+
|
|
180
|
+
设计范式参照 `<opensource>/` 下三个开源项目(**只学范式,不抄代码**,语言习惯不同):
|
|
181
|
+
|
|
182
|
+
- **codex** (Rust) —— `codex-rs/core/src/{compact.rs, client.rs, session/*}`:cache-aware + handoff 源头
|
|
183
|
+
- **claw-code** (Rust) —— `crates/{runtime, api}/src/*`:tool 配对边界保护、hooks、permission
|
|
184
|
+
- **openclaw** (TS) —— `src/agents/* + src/context-engine/*`:actor + session 模式
|
|
185
|
+
|
|
186
|
+
不抄业务概念。所有移植后的 Python 文件必须有「参照 X,差异 Y」的注释或 ADR 说明。
|
|
187
|
+
|
|
188
|
+
## 语言要求
|
|
189
|
+
|
|
190
|
+
- 文档、注释、commit message、PR 描述:**中文**
|
|
191
|
+
- 变量 / 函数 / 类名:**英文**(遵循 PEP 8 与社区惯例)
|
|
192
|
+
- 与用户沟通:中英文均可,看用户偏好
|