tagword-codeagent 1.2.6__tar.gz → 1.2.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tagword_codeagent-1.2.6/tagword_codeagent.egg-info → tagword_codeagent-1.2.8}/PKG-INFO +2 -2
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/a2a/agent_card.py +17 -7
- tagword_codeagent-1.2.8/codeagent/server/a2a/auth.py +59 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/a2a/handlers.py +7 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/pyproject.toml +2 -2
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8/tagword_codeagent.egg-info}/PKG-INFO +2 -2
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tagword_codeagent.egg-info/SOURCES.txt +2 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tagword_codeagent.egg-info/requires.txt +1 -1
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_a2a.py +15 -1
- tagword_codeagent-1.2.8/tests/test_a2a_auth.py +147 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/LICENSE +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/README.md +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/__init__.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/__main__.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/cli/__init__.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/cli/entrypoint.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/cli/main.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/__init__.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/attachments.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/audio_models.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/bootstrap.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/default_presets.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/env.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/folder_picker.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/image_understanding.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/models.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/paths.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/pricing.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/process_ports.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/seed_bridge.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/settings.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/speech_synth.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/team_config.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/team_manager.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/token_counter.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/tts_voices.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/usage_billing.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/core/vision_models.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/memory/diary.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/persona_defaults/README.md +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/persona_defaults/agent.md +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/persona_defaults/identity.md +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/persona_defaults/memory.md +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/persona_defaults/skills.md +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/persona_defaults/soul.md +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/persona_defaults/tools.md +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/persona_defaults/user.md +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/__init__.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/agent_bootstrap.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/agent_context.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/agent_handle.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/agent_runtime.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/compact_prompt.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/compact_state.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/llm_worker.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/orchestrator.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/prompt_enrichment.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/session_manager.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/task_split.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/turn_loop.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/runtime/worker.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/__init__.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/a2a/__init__.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/a2a/client.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/a2a/client_card.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/a2a/context.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/a2a/models.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/a2a/streaming.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/app_factory.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/attachment_api.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/auto_continue.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/chat_turn.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/evidence.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/hub.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/icon.png +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/self_healing.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/team_engine.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/team_worker.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/tts_api.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_api_app.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_agentmeta.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_agents.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_auth.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_cronallow.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_envllm.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_files.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_git.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_health.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_mcp.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_projects.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_sessions.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_skills.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_teams.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/skills/__init__.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/skills/select.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/tools/__init__.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/tools/agent_tools.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/__init__.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/__pycache__/__init__.cpython-311.pyc +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/__pycache__/__init__.cpython-313.pyc +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/__pycache__/app.cpython-313.pyc +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/__pycache__/auth_impl.cpython-311.pyc +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/__pycache__/auth_impl.cpython-313.pyc +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/auth_impl.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/00-marked.min.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/00-mermaid.min.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/00-purify.min.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/00-storage.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/00-utils.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01-theme.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01a-scroll.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01b-think.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01c-session-identity.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01c-session-thinking.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01c-session-tree-menus.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01c-session-tree.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01c-session-utilities.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01c-vision-model.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01d-image-gen-model.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01e-audio-model.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01f-compose-ui.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01g-tts-settings.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01h-music-model.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01i-model-stack.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01j-video-gen-model.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01k-model-stack-bootstrap.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01k-model-stack-state.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/01q-inflight.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/02-reset.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/02-session-ui.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/03-layout-p1.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/03-layout-p2.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/03a-links-stream.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/03b-stream-text.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/03c-render-bubble.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/03d-agent-bubble.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/03e-tool-trace.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/03f-timeline.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/03g-bubble-tts.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/04-components-p1.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/04-components-p2b.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/04-components-p3.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/04-components-p4.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/04-components-p5.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/04-components-p6.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/04-components-p7.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/04-components-p8.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/04-components-p9.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/04-ws-connect.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/04-ws-helpers.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/05-chat-p1.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/05-chat-p2.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/05-chat-p3.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/05a-session-history.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/05b-session-list.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/05c-dialog.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/05d-project-create.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/05e-project-remote.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/06-chat.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/06-utilities.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/06b-attachments.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/06c-camera.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/07-activity-bar.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/09-git-p1.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/09-git-p2.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/09a-init-bind.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/09b-panel-toggle.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/09c-api-refresh.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/09d-status-log.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/09e-commit.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/09f-remote.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/11a-cron-parse.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/11b-cron-panel.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/11c-cron-card.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/11d-cron-form.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/11e-env-config.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/11f-env-llm-a-state.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/11f-env-llm-b-form.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/11f-env-llm-c-board.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/11g-env-paths-git.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/11h-env-mcp-a-state.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/11h-env-mcp-b-form.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/11h-env-mcp-c-board.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/12-plugins.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/13a-skills.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/13a-todo-utils.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/13b-todo-fetch.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/13b-tools.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/13c-skills-panel.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/13c-todo-crud.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/13d-file-browser.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/14-activity-bar.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/15-plans.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/15-plans.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/16-mobile.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/16-mobile.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/17-agents-list.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/17-agents-list.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/17-preset-ux.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/18-agent-mgr.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/18-agent-mgr.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/24-health-dashboard.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/25-teams-panel.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/25-teams-panel.js +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/99-brand-polish.css +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/body.html +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/setup/setup_form.html +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/setup/setup_head.html +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/setup/setup_tail.html +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/static/setup/setup_test.html +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/web_login.html +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/webui.html +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/setup.cfg +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tagword_codeagent.egg-info/dependency_links.txt +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tagword_codeagent.egg-info/entry_points.txt +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tagword_codeagent.egg-info/top_level.txt +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_a2a_context.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_a2a_streaming.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_a2a_tool.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_agent_discovery_hollow.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_agent_file_safety.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_agent_registry_bridge.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_agent_root_consistency.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_archive_probe.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_attachment_safety.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_attachments.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_auth_pure_fns.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_auth_routes.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_auto_continue.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_auto_continue_wiring.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_cli_chat_project_id.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_compact_state.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_default_presets.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_env.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_env_chat.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_evidence.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_git_provider.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_git_ssh_helpers.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_history_json_safe.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_history_rows.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_hub.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_image_understanding.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_list_agents_tool.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_listen_port.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_metas.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_nudge_edge.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_orchestrator.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_paths_files.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_paths_safety.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_persist_summarize.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_persona_fallback.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_persona_hash.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_persona_init.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_preset_support.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_pricing.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_project_dirs.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_prompt_enrichment.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_reply_summary.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_self_healing.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_selfheal_heal.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_selfheal_health.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_server_init.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_server_pure.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_session_history.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_settings.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_skills_select.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_speech_synth_pure.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_task_split.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_team_concurrency.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_team_config.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_team_engine.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_token_counter.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_tts_voices.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_usage_billing.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_webui_auth_cookie.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_webui_pure_fns.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_webui_pure_fns2.py +0 -0
- {tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/tests/test_write_env.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tagword-codeagent
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.8
|
|
4
4
|
Summary: Autonomous AI coding agent driven by Markdown config — DeepSeek-ready, CLI + Web UI, 45+ tools, self-hosted
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/tagword/codeagent
|
|
@@ -27,7 +27,7 @@ Description-Content-Type: text/markdown
|
|
|
27
27
|
License-File: LICENSE
|
|
28
28
|
Requires-Dist: seed-kernel
|
|
29
29
|
Requires-Dist: seed-model-providers>=1.0.3
|
|
30
|
-
Requires-Dist: seed-toolbox[code]>=1.0.
|
|
30
|
+
Requires-Dist: seed-toolbox[code]>=1.0.9
|
|
31
31
|
Requires-Dist: uvicorn[standard]>=0.30.0
|
|
32
32
|
Requires-Dist: starlette>=0.37.0
|
|
33
33
|
Provides-Extra: dev
|
|
@@ -10,6 +10,8 @@ from __future__ import annotations
|
|
|
10
10
|
import os
|
|
11
11
|
from typing import Any
|
|
12
12
|
|
|
13
|
+
from .auth import auth_enabled
|
|
14
|
+
|
|
13
15
|
PROTOCOL_VERSION = "0.2.5"
|
|
14
16
|
|
|
15
17
|
|
|
@@ -74,12 +76,20 @@ def build_agent_card() -> dict[str, Any]:
|
|
|
74
76
|
"outputModes": ["text"],
|
|
75
77
|
}
|
|
76
78
|
],
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
"
|
|
79
|
+
# 认证声明与真实行为一致:未配置 token 时不声明 security,
|
|
80
|
+
# 否则客户端会带 token 而服务端根本不校验(声明与实现脱节)。
|
|
81
|
+
**(
|
|
82
|
+
{
|
|
83
|
+
"securitySchemes": {
|
|
84
|
+
"bearer": {
|
|
85
|
+
"type": "http",
|
|
86
|
+
"scheme": "bearer",
|
|
87
|
+
"description": "Bearer token(复用 WebUI token,见 config/webui.token)",
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"security": [{"bearer": []}],
|
|
82
91
|
}
|
|
83
|
-
|
|
84
|
-
|
|
92
|
+
if auth_enabled()
|
|
93
|
+
else {}
|
|
94
|
+
),
|
|
85
95
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""A2A Bearer 认证 — 复用 WebUI token。
|
|
2
|
+
|
|
3
|
+
设计要点:
|
|
4
|
+
- **单一 token 源**:复用 `codeagent.web.auth_impl.get_webui_token()`,
|
|
5
|
+
即 `CODEAGENT_WEBUI_TOKEN` 环境变量或 `config/webui.token` 文件。
|
|
6
|
+
不引入第二套密钥,避免运维分裂。
|
|
7
|
+
- **未配置 token 时放行**:与 WebUI 行为一致(未设 token = 本机开发模式,
|
|
8
|
+
WebUI 本身也不鉴权)。此时 Agent Card 不声明 security,客户端不会带 token。
|
|
9
|
+
- **常量时间比较**:`hmac.compare_digest` 防时序侧信道。
|
|
10
|
+
- **认证在 JSON-RPC 入口统一做**:所有方法(含 `message/stream` SSE)
|
|
11
|
+
都经过 `a2a_jsonrpc`,故一处拦截即全覆盖。
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import hmac
|
|
17
|
+
import logging
|
|
18
|
+
|
|
19
|
+
from starlette.requests import Request
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
# JSON-RPC 错误码:-32001 = 未授权(A2A/实现自定义区间 -32000..-32099)
|
|
24
|
+
ERR_UNAUTHORIZED = -32001
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_a2a_token() -> str:
|
|
28
|
+
"""返回期望的 Bearer token;空字符串表示未启用认证。"""
|
|
29
|
+
try:
|
|
30
|
+
from codeagent.web.auth_impl import get_webui_token
|
|
31
|
+
|
|
32
|
+
return get_webui_token()
|
|
33
|
+
except Exception: # noqa: BLE001 - 认证不可用时不阻断服务
|
|
34
|
+
logger.warning("a2a: 无法读取 webui token,A2A 认证降级为关闭", exc_info=True)
|
|
35
|
+
return ""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def auth_enabled() -> bool:
|
|
39
|
+
"""是否启用 A2A 认证(配置了 token 才启用)。"""
|
|
40
|
+
return bool(get_a2a_token())
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _extract_bearer(request: Request) -> str:
|
|
44
|
+
raw = request.headers.get("authorization") or ""
|
|
45
|
+
parts = raw.split(None, 1)
|
|
46
|
+
if len(parts) == 2 and parts[0].lower() == "bearer":
|
|
47
|
+
return parts[1].strip()
|
|
48
|
+
return ""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def check_request(request: Request) -> bool:
|
|
52
|
+
"""校验请求是否通过认证。未配置 token 时恒为 True。"""
|
|
53
|
+
expected = get_a2a_token()
|
|
54
|
+
if not expected:
|
|
55
|
+
return True
|
|
56
|
+
got = _extract_bearer(request)
|
|
57
|
+
if not got:
|
|
58
|
+
return False
|
|
59
|
+
return hmac.compare_digest(got.encode("utf-8"), expected.encode("utf-8"))
|
|
@@ -18,6 +18,7 @@ from starlette.requests import Request
|
|
|
18
18
|
from starlette.responses import JSONResponse
|
|
19
19
|
|
|
20
20
|
from .agent_card import build_agent_card
|
|
21
|
+
from .auth import ERR_UNAUTHORIZED, check_request
|
|
21
22
|
from .context import ContextError, context_id_for_task, record_task
|
|
22
23
|
from .context import resolve as resolve_context
|
|
23
24
|
from .models import (
|
|
@@ -52,7 +53,13 @@ async def a2a_jsonrpc(request: Request):
|
|
|
52
53
|
"""POST /a2a — A2A JSON-RPC 2.0 入口。
|
|
53
54
|
|
|
54
55
|
``message/stream`` 返回 SSE 流(StreamingResponse),其余返回 JSON。
|
|
56
|
+
|
|
57
|
+
认证在此统一校验:所有方法(含 SSE)都经过本入口。
|
|
55
58
|
"""
|
|
59
|
+
# ── Bearer 认证(未配置 token 时放行,见 auth.py)──
|
|
60
|
+
if not check_request(request):
|
|
61
|
+
return _rpc_error(None, ERR_UNAUTHORIZED, "Unauthorized: invalid or missing Bearer token")
|
|
62
|
+
|
|
56
63
|
try:
|
|
57
64
|
body = await request.json()
|
|
58
65
|
except Exception:
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tagword-codeagent"
|
|
7
|
-
version = "1.2.
|
|
7
|
+
version = "1.2.8"
|
|
8
8
|
description = "Autonomous AI coding agent driven by Markdown config — DeepSeek-ready, CLI + Web UI, 45+ tools, self-hosted"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -29,7 +29,7 @@ classifiers = [
|
|
|
29
29
|
dependencies = [
|
|
30
30
|
"seed-kernel",
|
|
31
31
|
"seed-model-providers>=1.0.3",
|
|
32
|
-
"seed-toolbox[code]>=1.0.
|
|
32
|
+
"seed-toolbox[code]>=1.0.9",
|
|
33
33
|
"uvicorn[standard]>=0.30.0",
|
|
34
34
|
"starlette>=0.37.0"
|
|
35
35
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tagword-codeagent
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.8
|
|
4
4
|
Summary: Autonomous AI coding agent driven by Markdown config — DeepSeek-ready, CLI + Web UI, 45+ tools, self-hosted
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/tagword/codeagent
|
|
@@ -27,7 +27,7 @@ Description-Content-Type: text/markdown
|
|
|
27
27
|
License-File: LICENSE
|
|
28
28
|
Requires-Dist: seed-kernel
|
|
29
29
|
Requires-Dist: seed-model-providers>=1.0.3
|
|
30
|
-
Requires-Dist: seed-toolbox[code]>=1.0.
|
|
30
|
+
Requires-Dist: seed-toolbox[code]>=1.0.9
|
|
31
31
|
Requires-Dist: uvicorn[standard]>=0.30.0
|
|
32
32
|
Requires-Dist: starlette>=0.37.0
|
|
33
33
|
Provides-Extra: dev
|
|
@@ -78,6 +78,7 @@ codeagent/server/webui_handlers_skills.py
|
|
|
78
78
|
codeagent/server/webui_handlers_teams.py
|
|
79
79
|
codeagent/server/a2a/__init__.py
|
|
80
80
|
codeagent/server/a2a/agent_card.py
|
|
81
|
+
codeagent/server/a2a/auth.py
|
|
81
82
|
codeagent/server/a2a/client.py
|
|
82
83
|
codeagent/server/a2a/client_card.py
|
|
83
84
|
codeagent/server/a2a/context.py
|
|
@@ -210,6 +211,7 @@ tagword_codeagent.egg-info/entry_points.txt
|
|
|
210
211
|
tagword_codeagent.egg-info/requires.txt
|
|
211
212
|
tagword_codeagent.egg-info/top_level.txt
|
|
212
213
|
tests/test_a2a.py
|
|
214
|
+
tests/test_a2a_auth.py
|
|
213
215
|
tests/test_a2a_context.py
|
|
214
216
|
tests/test_a2a_streaming.py
|
|
215
217
|
tests/test_a2a_tool.py
|
|
@@ -40,7 +40,11 @@ def test_agent_card_structure():
|
|
|
40
40
|
skill = card["skills"][0]
|
|
41
41
|
for key in ("id", "name", "description", "inputModes", "outputModes"):
|
|
42
42
|
assert key in skill
|
|
43
|
-
|
|
43
|
+
# security 声明与 auth_enabled() 一致(未配置 token 时不声明),
|
|
44
|
+
# 两种状态各自的行为由 test_a2a_auth.py 覆盖。
|
|
45
|
+
from codeagent.server.a2a.auth import auth_enabled
|
|
46
|
+
|
|
47
|
+
assert ("securitySchemes" in card) is auth_enabled()
|
|
44
48
|
|
|
45
49
|
|
|
46
50
|
def test_agent_card_endpoint(client):
|
|
@@ -79,6 +83,16 @@ def test_empty_text(client):
|
|
|
79
83
|
|
|
80
84
|
|
|
81
85
|
# ---------- 项目校验默认放行 ----------
|
|
86
|
+
@pytest.fixture(autouse=True)
|
|
87
|
+
def _no_a2a_auth(monkeypatch):
|
|
88
|
+
"""禁用 A2A 认证,隔离本机 config/webui.token 的影响。
|
|
89
|
+
|
|
90
|
+
认证行为由 tests/test_a2a_auth.py 专门覆盖;本文件测的是协议逻辑,
|
|
91
|
+
若读取真实 token 文件,所有用例都会因缺 Bearer 头而 401。
|
|
92
|
+
"""
|
|
93
|
+
monkeypatch.setattr(ai, "get_webui_token", lambda *a, **k: "")
|
|
94
|
+
|
|
95
|
+
|
|
82
96
|
@pytest.fixture(autouse=True)
|
|
83
97
|
def _allow_any_project(monkeypatch):
|
|
84
98
|
"""默认认为任意 projectId 都存在,避免每个测试都要 mock。
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"""A2A Bearer 认证测试。
|
|
2
|
+
|
|
3
|
+
覆盖 4 种情形 + 声明一致性:
|
|
4
|
+
1. 未配置 token → 放行(本机开发模式),且 Agent Card 不声明 security
|
|
5
|
+
2. 配置 token + 无 Authorization → 401 语义(JSON-RPC -32001)
|
|
6
|
+
3. 配置 token + 错误 token → 拒绝
|
|
7
|
+
4. 配置 token + 正确 token → 通过
|
|
8
|
+
5. Agent Card 的 security 声明与 auth_enabled() 一致(声明不脱节)
|
|
9
|
+
|
|
10
|
+
认证在 JSON-RPC 入口统一做,故 message/send 与 message/stream 均覆盖。
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import pytest
|
|
14
|
+
from starlette.applications import Starlette
|
|
15
|
+
from starlette.routing import Route
|
|
16
|
+
from starlette.testclient import TestClient
|
|
17
|
+
|
|
18
|
+
from codeagent.server.a2a import a2a_agent_card, a2a_jsonrpc
|
|
19
|
+
from codeagent.server.a2a.agent_card import build_agent_card
|
|
20
|
+
from codeagent.server.a2a.auth import ERR_UNAUTHORIZED, auth_enabled, check_request
|
|
21
|
+
from codeagent.web import auth_impl as ai
|
|
22
|
+
|
|
23
|
+
TOKEN = "test-a2a-secret-token"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@pytest.fixture()
|
|
27
|
+
def client():
|
|
28
|
+
app = Starlette(routes=[
|
|
29
|
+
Route("/.well-known/agent-card.json", a2a_agent_card, methods=["GET"]),
|
|
30
|
+
Route("/a2a", a2a_jsonrpc, methods=["POST"]),
|
|
31
|
+
])
|
|
32
|
+
return TestClient(app)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@pytest.fixture()
|
|
36
|
+
def no_token(monkeypatch):
|
|
37
|
+
monkeypatch.setattr(ai, "get_webui_token", lambda *a, **k: "")
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@pytest.fixture()
|
|
42
|
+
def with_token(monkeypatch):
|
|
43
|
+
monkeypatch.setattr(ai, "get_webui_token", lambda *a, **k: TOKEN)
|
|
44
|
+
return TOKEN
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _rpc_body():
|
|
48
|
+
return {
|
|
49
|
+
"jsonrpc": "2.0",
|
|
50
|
+
"id": 1,
|
|
51
|
+
"method": "message/send",
|
|
52
|
+
"params": {
|
|
53
|
+
"message": {
|
|
54
|
+
"role": "user",
|
|
55
|
+
"parts": [{"kind": "text", "text": "hi"}],
|
|
56
|
+
"messageId": "m-1",
|
|
57
|
+
"contextId": "ctx-auth",
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# ---------- 1. 未配置 token:放行 ----------
|
|
64
|
+
def test_no_token_configured_allows_request(client, no_token):
|
|
65
|
+
r = client.post("/a2a", json=_rpc_body())
|
|
66
|
+
assert r.status_code == 200
|
|
67
|
+
assert r.json().get("error", {}).get("code") != ERR_UNAUTHORIZED
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_auth_disabled_when_no_token(no_token):
|
|
71
|
+
assert auth_enabled() is False
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
# ---------- 2. 配置 token + 无 header:拒绝 ----------
|
|
75
|
+
def test_missing_header_rejected(client, with_token, monkeypatch):
|
|
76
|
+
# 避免真的跑 chat turn:认证失败应在进入业务逻辑前返回
|
|
77
|
+
r = client.post("/a2a", json=_rpc_body())
|
|
78
|
+
assert r.status_code == 200 # JSON-RPC 错误走 200 + error 字段
|
|
79
|
+
err = r.json().get("error") or {}
|
|
80
|
+
assert err.get("code") == ERR_UNAUTHORIZED
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
# ---------- 3. 配置 token + 错误 token:拒绝 ----------
|
|
84
|
+
def test_wrong_token_rejected(client, with_token):
|
|
85
|
+
r = client.post("/a2a", json=_rpc_body(), headers={"Authorization": "Bearer wrong"})
|
|
86
|
+
err = r.json().get("error") or {}
|
|
87
|
+
assert err.get("code") == ERR_UNAUTHORIZED
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def test_non_bearer_scheme_rejected(client, with_token):
|
|
91
|
+
r = client.post("/a2a", json=_rpc_body(), headers={"Authorization": f"Basic {TOKEN}"})
|
|
92
|
+
err = r.json().get("error") or {}
|
|
93
|
+
assert err.get("code") == ERR_UNAUTHORIZED
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# ---------- 4. 配置 token + 正确 token:通过 ----------
|
|
97
|
+
def test_correct_token_accepted(client, with_token, monkeypatch):
|
|
98
|
+
"""认证通过后应进入业务逻辑(此处用假 run_chat_turn 隔离)。"""
|
|
99
|
+
import codeagent.server.a2a.handlers as h
|
|
100
|
+
|
|
101
|
+
async def fake_turn(**kwargs):
|
|
102
|
+
return {"text": "pong", "tools_used": [], "token_usage": {}}
|
|
103
|
+
|
|
104
|
+
monkeypatch.setattr(h, "run_chat_turn", fake_turn, raising=False)
|
|
105
|
+
r = client.post("/a2a", json=_rpc_body(), headers={"Authorization": f"Bearer {TOKEN}"})
|
|
106
|
+
assert r.status_code == 200
|
|
107
|
+
assert "error" not in r.json()
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def test_token_case_insensitive_scheme(client, with_token, monkeypatch):
|
|
111
|
+
"""`bearer` 小写也应被接受(HTTP 认证方案大小写不敏感)。"""
|
|
112
|
+
import codeagent.server.a2a.handlers as h
|
|
113
|
+
|
|
114
|
+
async def fake_turn(**kwargs):
|
|
115
|
+
return {"text": "pong", "tools_used": [], "token_usage": {}}
|
|
116
|
+
|
|
117
|
+
monkeypatch.setattr(h, "run_chat_turn", fake_turn, raising=False)
|
|
118
|
+
r = client.post("/a2a", json=_rpc_body(), headers={"Authorization": f"bearer {TOKEN}"})
|
|
119
|
+
assert "error" not in r.json()
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
# ---------- 5. Agent Card 声明与实现一致 ----------
|
|
123
|
+
def test_card_declares_security_when_token_configured(with_token):
|
|
124
|
+
card = build_agent_card()
|
|
125
|
+
assert "security" in card
|
|
126
|
+
assert "bearer" in card.get("securitySchemes", {})
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def test_card_omits_security_when_no_token(no_token):
|
|
130
|
+
card = build_agent_card()
|
|
131
|
+
assert "security" not in card
|
|
132
|
+
assert "securitySchemes" not in card
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
# ---------- check_request 单元级 ----------
|
|
136
|
+
def test_check_request_uses_constant_time_compare(with_token):
|
|
137
|
+
class _Req:
|
|
138
|
+
headers = {"authorization": f"Bearer {TOKEN}"}
|
|
139
|
+
|
|
140
|
+
assert check_request(_Req()) is True
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def test_check_request_empty_header(with_token):
|
|
144
|
+
class _Req:
|
|
145
|
+
headers = {}
|
|
146
|
+
|
|
147
|
+
assert check_request(_Req()) is False
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_agentmeta.py
RENAMED
|
File without changes
|
{tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_agents.py
RENAMED
|
File without changes
|
|
File without changes
|
{tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_cronallow.py
RENAMED
|
File without changes
|
{tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_envllm.py
RENAMED
|
File without changes
|
{tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_files.py
RENAMED
|
File without changes
|
|
File without changes
|
{tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_health.py
RENAMED
|
File without changes
|
|
File without changes
|
{tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_projects.py
RENAMED
|
File without changes
|
{tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_sessions.py
RENAMED
|
File without changes
|
{tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_skills.py
RENAMED
|
File without changes
|
{tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/server/webui_handlers_teams.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tagword_codeagent-1.2.6 → tagword_codeagent-1.2.8}/codeagent/web/__pycache__/app.cpython-313.pyc
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|