tagword-codeagent 1.1.36__tar.gz → 1.2.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.
- {tagword_codeagent-1.1.36/tagword_codeagent.egg-info → tagword_codeagent-1.2.1}/PKG-INFO +2 -2
- tagword_codeagent-1.2.1/codeagent/__init__.py +25 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/cli/entrypoint.py +2 -1
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/cli/main.py +85 -34
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/attachments.py +12 -16
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/audio_models.py +2 -2
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/bootstrap.py +1 -2
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/default_presets.py +6 -7
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/folder_picker.py +5 -6
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/image_understanding.py +7 -7
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/paths.py +79 -15
- tagword_codeagent-1.2.1/codeagent/core/pricing.py +67 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/process_ports.py +14 -14
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/speech_synth.py +18 -21
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/team_config.py +9 -9
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/team_manager.py +10 -10
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/usage_billing.py +14 -9
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/vision_models.py +7 -12
- tagword_codeagent-1.2.1/codeagent/runtime/agent_bootstrap.py +121 -0
- tagword_codeagent-1.2.1/codeagent/runtime/agent_handle.py +110 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/runtime/llm_worker.py +2 -3
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/runtime/orchestrator.py +163 -161
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/runtime/prompt_enrichment.py +10 -9
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/server/__init__.py +5 -4
- tagword_codeagent-1.2.1/codeagent/server/a2a/__init__.py +28 -0
- tagword_codeagent-1.2.1/codeagent/server/a2a/agent_card.py +77 -0
- tagword_codeagent-1.2.1/codeagent/server/a2a/handlers.py +217 -0
- tagword_codeagent-1.2.1/codeagent/server/a2a/models.py +144 -0
- tagword_codeagent-1.2.1/codeagent/server/a2a/streaming.py +260 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/server/app_factory.py +37 -25
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/server/attachment_api.py +8 -8
- tagword_codeagent-1.2.1/codeagent/server/auto_continue.py +308 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/server/chat_turn.py +63 -17
- tagword_codeagent-1.2.1/codeagent/server/evidence.py +335 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/server/hub.py +3 -5
- tagword_codeagent-1.2.1/codeagent/server/team_engine.py +771 -0
- tagword_codeagent-1.2.1/codeagent/server/team_worker.py +168 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_api_app.py +375 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_handlers_agentmeta.py +152 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_handlers_agents.py +292 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_handlers_auth.py +104 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_handlers_cronallow.py +104 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_handlers_envllm.py +252 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_handlers_files.py +285 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_handlers_git.py +695 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_handlers_health.py +86 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_handlers_mcp.py +390 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_handlers_projects.py +481 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_handlers_sessions.py +197 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_handlers_skills.py +255 -0
- tagword_codeagent-1.2.1/codeagent/server/webui_handlers_teams.py +224 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/skills/select.py +0 -1
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/__pycache__/auth_impl.cpython-313.pyc +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/auth_impl.py +8 -4
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01c-session-thinking.js +9 -5
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/04-ws-connect.js +1 -1
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/06-chat.js +6 -1
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/11c-cron-card.js +5 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/12-plugins.js +12 -1
- tagword_codeagent-1.2.1/codeagent/web/static/17-agents-list.css +396 -0
- tagword_codeagent-1.2.1/codeagent/web/static/17-agents-list.js +221 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/18-agent-mgr.js +13 -3
- tagword_codeagent-1.2.1/codeagent/web/static/25-teams-panel.css +121 -0
- tagword_codeagent-1.2.1/codeagent/web/static/25-teams-panel.js +537 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/body.html +87 -34
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/pyproject.toml +2 -2
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1/tagword_codeagent.egg-info}/PKG-INFO +2 -2
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/tagword_codeagent.egg-info/SOURCES.txt +88 -1
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/tagword_codeagent.egg-info/requires.txt +1 -1
- tagword_codeagent-1.2.1/tests/test_a2a.py +213 -0
- tagword_codeagent-1.2.1/tests/test_a2a_streaming.py +154 -0
- tagword_codeagent-1.2.1/tests/test_agent_discovery_hollow.py +101 -0
- tagword_codeagent-1.2.1/tests/test_agent_file_safety.py +72 -0
- tagword_codeagent-1.2.1/tests/test_agent_registry_bridge.py +151 -0
- tagword_codeagent-1.2.1/tests/test_agent_root_consistency.py +117 -0
- tagword_codeagent-1.2.1/tests/test_archive_probe.py +97 -0
- tagword_codeagent-1.2.1/tests/test_attachment_safety.py +60 -0
- tagword_codeagent-1.2.1/tests/test_attachments.py +112 -0
- tagword_codeagent-1.2.1/tests/test_auth_pure_fns.py +95 -0
- tagword_codeagent-1.2.1/tests/test_auth_routes.py +87 -0
- tagword_codeagent-1.2.1/tests/test_auto_continue.py +422 -0
- tagword_codeagent-1.2.1/tests/test_auto_continue_wiring.py +127 -0
- tagword_codeagent-1.2.1/tests/test_cli_chat_project_id.py +83 -0
- tagword_codeagent-1.2.1/tests/test_compact_state.py +71 -0
- tagword_codeagent-1.2.1/tests/test_default_presets.py +110 -0
- tagword_codeagent-1.2.1/tests/test_env.py +111 -0
- tagword_codeagent-1.2.1/tests/test_env_chat.py +99 -0
- tagword_codeagent-1.2.1/tests/test_evidence.py +338 -0
- tagword_codeagent-1.2.1/tests/test_git_provider.py +91 -0
- tagword_codeagent-1.2.1/tests/test_git_ssh_helpers.py +257 -0
- tagword_codeagent-1.2.1/tests/test_history_json_safe.py +62 -0
- tagword_codeagent-1.2.1/tests/test_history_rows.py +91 -0
- tagword_codeagent-1.2.1/tests/test_hub.py +92 -0
- tagword_codeagent-1.2.1/tests/test_image_understanding.py +102 -0
- tagword_codeagent-1.2.1/tests/test_list_agents_tool.py +81 -0
- tagword_codeagent-1.2.1/tests/test_listen_port.py +74 -0
- tagword_codeagent-1.2.1/tests/test_metas.py +111 -0
- tagword_codeagent-1.2.1/tests/test_nudge_edge.py +73 -0
- tagword_codeagent-1.2.1/tests/test_orchestrator.py +93 -0
- tagword_codeagent-1.2.1/tests/test_paths_files.py +83 -0
- tagword_codeagent-1.2.1/tests/test_paths_safety.py +88 -0
- tagword_codeagent-1.2.1/tests/test_persist_summarize.py +92 -0
- tagword_codeagent-1.2.1/tests/test_persona_fallback.py +80 -0
- tagword_codeagent-1.2.1/tests/test_persona_hash.py +65 -0
- tagword_codeagent-1.2.1/tests/test_persona_init.py +64 -0
- tagword_codeagent-1.2.1/tests/test_preset_support.py +75 -0
- tagword_codeagent-1.2.1/tests/test_pricing.py +172 -0
- tagword_codeagent-1.2.1/tests/test_project_dirs.py +54 -0
- tagword_codeagent-1.2.1/tests/test_prompt_enrichment.py +42 -0
- tagword_codeagent-1.2.1/tests/test_reply_summary.py +85 -0
- tagword_codeagent-1.2.1/tests/test_self_healing.py +88 -0
- tagword_codeagent-1.2.1/tests/test_selfheal_heal.py +55 -0
- tagword_codeagent-1.2.1/tests/test_selfheal_health.py +102 -0
- tagword_codeagent-1.2.1/tests/test_server_init.py +149 -0
- tagword_codeagent-1.2.1/tests/test_server_pure.py +64 -0
- tagword_codeagent-1.2.1/tests/test_session_history.py +114 -0
- tagword_codeagent-1.2.1/tests/test_settings.py +100 -0
- tagword_codeagent-1.2.1/tests/test_skills_select.py +83 -0
- tagword_codeagent-1.2.1/tests/test_speech_synth_pure.py +115 -0
- tagword_codeagent-1.2.1/tests/test_task_split.py +83 -0
- tagword_codeagent-1.2.1/tests/test_team_concurrency.py +150 -0
- tagword_codeagent-1.2.1/tests/test_team_config.py +124 -0
- tagword_codeagent-1.2.1/tests/test_team_engine.py +398 -0
- tagword_codeagent-1.2.1/tests/test_token_counter.py +86 -0
- tagword_codeagent-1.2.1/tests/test_tts_voices.py +95 -0
- tagword_codeagent-1.2.1/tests/test_usage_billing.py +105 -0
- tagword_codeagent-1.2.1/tests/test_webui_pure_fns.py +133 -0
- tagword_codeagent-1.2.1/tests/test_webui_pure_fns2.py +79 -0
- tagword_codeagent-1.2.1/tests/test_write_env.py +44 -0
- tagword_codeagent-1.1.36/codeagent/__init__.py +0 -16
- tagword_codeagent-1.1.36/codeagent/core/pricing.py +0 -107
- tagword_codeagent-1.1.36/codeagent/server/team_engine.py +0 -243
- tagword_codeagent-1.1.36/codeagent/server/webui_api_app.py +0 -3350
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/LICENSE +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/README.md +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/__main__.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/cli/__init__.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/__init__.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/env.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/models.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/seed_bridge.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/settings.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/token_counter.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/core/tts_voices.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/memory/diary.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/persona_defaults/README.md +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/persona_defaults/agent.md +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/persona_defaults/identity.md +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/persona_defaults/memory.md +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/persona_defaults/skills.md +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/persona_defaults/soul.md +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/persona_defaults/tools.md +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/persona_defaults/user.md +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/runtime/__init__.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/runtime/agent_context.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/runtime/agent_runtime.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/runtime/compact_prompt.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/runtime/compact_state.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/runtime/session_manager.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/runtime/task_split.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/runtime/turn_loop.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/runtime/worker.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/server/icon.png +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/server/self_healing.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/server/tts_api.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/skills/__init__.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/tools/__init__.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/tools/agent_tools.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/__init__.py +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/__pycache__/__init__.cpython-311.pyc +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/__pycache__/__init__.cpython-313.pyc +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/__pycache__/app.cpython-313.pyc +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/__pycache__/auth_impl.cpython-311.pyc +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/00-marked.min.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/00-mermaid.min.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/00-purify.min.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/00-storage.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/00-utils.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01-theme.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01a-scroll.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01b-think.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01c-session-identity.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01c-session-tree-menus.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01c-session-tree.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01c-session-utilities.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01c-vision-model.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01d-image-gen-model.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01e-audio-model.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01f-compose-ui.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01g-tts-settings.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01h-music-model.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01i-model-stack.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01j-video-gen-model.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01k-model-stack-bootstrap.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01k-model-stack-state.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/01q-inflight.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/02-reset.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/02-session-ui.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/03-layout-p1.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/03-layout-p2.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/03a-links-stream.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/03b-stream-text.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/03c-render-bubble.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/03d-agent-bubble.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/03e-tool-trace.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/03f-timeline.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/03g-bubble-tts.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/04-components-p1.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/04-components-p2b.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/04-components-p3.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/04-components-p4.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/04-components-p5.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/04-components-p6.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/04-components-p7.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/04-components-p8.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/04-components-p9.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/04-ws-helpers.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/05-chat-p1.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/05-chat-p2.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/05-chat-p3.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/05a-session-history.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/05b-session-list.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/05c-dialog.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/05d-project-create.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/05e-project-remote.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/06-utilities.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/06b-attachments.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/06c-camera.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/07-activity-bar.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/09-git-p1.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/09-git-p2.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/09a-init-bind.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/09b-panel-toggle.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/09c-api-refresh.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/09d-status-log.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/09e-commit.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/09f-remote.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/11a-cron-parse.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/11b-cron-panel.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/11d-cron-form.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/11e-env-config.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/11f-env-llm-a-state.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/11f-env-llm-b-form.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/11f-env-llm-c-board.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/11g-env-paths-git.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/11h-env-mcp-a-state.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/11h-env-mcp-b-form.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/11h-env-mcp-c-board.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/13a-skills.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/13a-todo-utils.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/13b-todo-fetch.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/13b-tools.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/13c-skills-panel.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/13c-todo-crud.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/13d-file-browser.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/14-activity-bar.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/15-plans.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/15-plans.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/16-mobile.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/16-mobile.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/17-preset-ux.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/18-agent-mgr.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/24-health-dashboard.js +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/99-brand-polish.css +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/setup/setup_form.html +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/setup/setup_head.html +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/setup/setup_tail.html +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/static/setup/setup_test.html +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/web_login.html +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/codeagent/web/webui.html +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/setup.cfg +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/tagword_codeagent.egg-info/dependency_links.txt +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/tagword_codeagent.egg-info/entry_points.txt +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/tagword_codeagent.egg-info/top_level.txt +0 -0
- {tagword_codeagent-1.1.36 → tagword_codeagent-1.2.1}/tests/test_webui_auth_cookie.py +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tagword-codeagent
|
|
3
|
-
Version: 1.1
|
|
3
|
+
Version: 1.2.1
|
|
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
|
|
@@ -26,7 +26,7 @@ Requires-Python: >=3.9
|
|
|
26
26
|
Description-Content-Type: text/markdown
|
|
27
27
|
License-File: LICENSE
|
|
28
28
|
Requires-Dist: seed-kernel
|
|
29
|
-
Requires-Dist: seed-model-providers
|
|
29
|
+
Requires-Dist: seed-model-providers>=1.0.3
|
|
30
30
|
Requires-Dist: seed-toolbox[code]
|
|
31
31
|
Requires-Dist: uvicorn[standard]>=0.30.0
|
|
32
32
|
Requires-Dist: starlette>=0.37.0
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CodeAgent — Personality layer
|
|
3
|
+
|
|
4
|
+
Architecture:
|
|
5
|
+
- seed/ : Core engine (LLM execution, tool system, session management)
|
|
6
|
+
- codeagent/ : Personality layer (CLI, server, web UI, skills, per-agent config)
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# 版本号从包元数据动态读取,避免 pyproject.toml 与 __init__ 写死值不同步
|
|
10
|
+
# 注意:发行名(tagword-codeagent)与历史 editable 安装的 dist-info 名(codeagent)
|
|
11
|
+
# 可能不一致,两者都尝试,避免静默回落到 0.0.0。
|
|
12
|
+
def _resolve_version() -> str:
|
|
13
|
+
from importlib.metadata import PackageNotFoundError
|
|
14
|
+
from importlib.metadata import version as _pkg_version
|
|
15
|
+
|
|
16
|
+
for dist_name in ("tagword-codeagent", "codeagent"):
|
|
17
|
+
try:
|
|
18
|
+
return _pkg_version(dist_name)
|
|
19
|
+
except PackageNotFoundError:
|
|
20
|
+
continue
|
|
21
|
+
return "0.0.0"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
__version__ = _resolve_version()
|
|
25
|
+
|
|
@@ -3,9 +3,10 @@ import argparse
|
|
|
3
3
|
import sys
|
|
4
4
|
from datetime import datetime
|
|
5
5
|
|
|
6
|
+
from seed_tools import setup_builtin_tools
|
|
7
|
+
|
|
6
8
|
from seed.core.persistence import ensure_session_dir, list_sessions, save_session
|
|
7
9
|
from seed.core.routing import find_commands, get_all_commands
|
|
8
|
-
from seed_tools import setup_builtin_tools
|
|
9
10
|
|
|
10
11
|
# Prefer ``python -m codeagent`` / ``codeagent.cli.main`` — kept for compatibility.
|
|
11
12
|
|
|
@@ -184,7 +184,11 @@ def main():
|
|
|
184
184
|
formatter_class=argparse.RawDescriptionHelpFormatter
|
|
185
185
|
)
|
|
186
186
|
|
|
187
|
-
|
|
187
|
+
from codeagent import __version__ as _codeagent_version
|
|
188
|
+
|
|
189
|
+
parser.add_argument(
|
|
190
|
+
'--version', action='version', version=f'CodeAgent v{_codeagent_version}'
|
|
191
|
+
)
|
|
188
192
|
subparsers = parser.add_subparsers(dest='command', help='Available commands')
|
|
189
193
|
|
|
190
194
|
# Run command
|
|
@@ -307,6 +311,15 @@ def main():
|
|
|
307
311
|
metavar='PRESET_ID',
|
|
308
312
|
help='Video generation preset for video_generate (or CODEAGENT_VIDEO_GEN_PRESET_ID)',
|
|
309
313
|
)
|
|
314
|
+
chat_parser.add_argument(
|
|
315
|
+
'--project-id',
|
|
316
|
+
default=None,
|
|
317
|
+
help=(
|
|
318
|
+
'Project id this chat belongs to. When set, the session is registered '
|
|
319
|
+
'under that project in the Web UI (instead of 未分类), so dispatched '
|
|
320
|
+
'tasks stay grouped with their project.'
|
|
321
|
+
),
|
|
322
|
+
)
|
|
310
323
|
|
|
311
324
|
serve_parser = subparsers.add_parser(
|
|
312
325
|
'serve',
|
|
@@ -471,9 +484,8 @@ def _cli_vision_preset_id(args) -> str:
|
|
|
471
484
|
|
|
472
485
|
|
|
473
486
|
def _cli_stage_path_attachment(path: str, *, agent_id: str, session_id: str):
|
|
474
|
-
from pathlib import Path
|
|
475
|
-
|
|
476
487
|
import mimetypes
|
|
488
|
+
from pathlib import Path
|
|
477
489
|
|
|
478
490
|
from codeagent.core.attachments import save_attachment
|
|
479
491
|
|
|
@@ -541,10 +553,8 @@ def _cli_startup_attachments(args, *, agent_id: str, session_id: str, project_ro
|
|
|
541
553
|
|
|
542
554
|
def _cli_handle_slash_attach(line: str, *, agent_id: str, session_id: str, project_root):
|
|
543
555
|
"""Return (handled, attachments, image_dir_tag, message_text)."""
|
|
544
|
-
from pathlib import Path
|
|
545
556
|
|
|
546
557
|
from codeagent.core import env as ca_env
|
|
547
|
-
from codeagent.core.attachments import scan_image_directory
|
|
548
558
|
|
|
549
559
|
low = line.strip().lower()
|
|
550
560
|
if low in ('/clear-vision', '/clear_vision'):
|
|
@@ -575,14 +585,19 @@ def _cmd_chat_llm(args):
|
|
|
575
585
|
|
|
576
586
|
from seed_tools import setup_builtin_tools
|
|
577
587
|
|
|
588
|
+
from codeagent.runtime.prompt_enrichment import (
|
|
589
|
+
build_skills_suffix,
|
|
590
|
+
get_cached_system_prompt,
|
|
591
|
+
record_chat_turn_diary,
|
|
592
|
+
)
|
|
578
593
|
from seed.core.agent_context import (
|
|
579
594
|
set_active_agent_id,
|
|
580
595
|
set_active_audio_preset,
|
|
581
596
|
set_active_image_gen_preset,
|
|
582
597
|
set_active_llm_session,
|
|
583
|
-
set_active_vision_preset,
|
|
584
598
|
set_active_music_preset,
|
|
585
599
|
set_active_video_gen_preset,
|
|
600
|
+
set_active_vision_preset,
|
|
586
601
|
)
|
|
587
602
|
from seed.core.agent_runtime import (
|
|
588
603
|
build_api_projection_messages,
|
|
@@ -592,12 +607,6 @@ def _cmd_chat_llm(args):
|
|
|
592
607
|
run_llm_tool_loop,
|
|
593
608
|
strip_ephemeral_message_fields,
|
|
594
609
|
)
|
|
595
|
-
from codeagent.runtime.prompt_enrichment import (
|
|
596
|
-
build_skills_suffix,
|
|
597
|
-
fresh_system_prompt,
|
|
598
|
-
get_cached_system_prompt,
|
|
599
|
-
record_chat_turn_diary,
|
|
600
|
-
)
|
|
601
610
|
from seed.core.llm_exec import LLMError
|
|
602
611
|
from seed.core.llm_presets import llm_executor_from_resolved, resolve_preset
|
|
603
612
|
from seed.core.llm_sess import (
|
|
@@ -624,7 +633,14 @@ def _cmd_chat_llm(args):
|
|
|
624
633
|
audio_preset_id = _cli_audio_preset_id(args)
|
|
625
634
|
music_preset_id = _cli_music_preset_id(args)
|
|
626
635
|
video_gen_preset_id = _cli_video_gen_preset_id(args)
|
|
627
|
-
|
|
636
|
+
# 项目归属:显式 --project-id 优先;其次沿用会话已存的 project_id,
|
|
637
|
+
# 让既有会话也能"重新归类"到新项目(不会清空历史)。
|
|
638
|
+
project_id = getattr(args, 'project_id', None)
|
|
639
|
+
chat_sess = load_or_create_chat_session(
|
|
640
|
+
name,
|
|
641
|
+
agent_id,
|
|
642
|
+
project_id=project_id,
|
|
643
|
+
)
|
|
628
644
|
fresh_sys = get_cached_system_prompt(chat_sess, agent_id=agent_id)
|
|
629
645
|
chat_sess.messages[:] = merge_fresh_system(chat_sess.messages, fresh_sys)
|
|
630
646
|
|
|
@@ -691,7 +707,6 @@ def _cmd_chat_llm(args):
|
|
|
691
707
|
message_has_video_attachments,
|
|
692
708
|
)
|
|
693
709
|
from codeagent.core.audio_models import preset_supports_audio_id
|
|
694
|
-
from codeagent.core.vision_models import preset_supports_vision_id
|
|
695
710
|
|
|
696
711
|
user_msg = build_user_message(
|
|
697
712
|
message_text,
|
|
@@ -700,21 +715,24 @@ def _cmd_chat_llm(args):
|
|
|
700
715
|
)
|
|
701
716
|
from codeagent.core.image_understanding import image_attachment_allowed, video_attachment_allowed
|
|
702
717
|
|
|
703
|
-
if message_has_image_attachments(user_msg) or pending_dir_tag
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
+
if (message_has_image_attachments(user_msg) or pending_dir_tag) and not image_attachment_allowed(
|
|
719
|
+
vision_preset_id or ""
|
|
720
|
+
):
|
|
721
|
+
print(
|
|
722
|
+
'[error] 发送图片需要 --vision-llm(supports_vision)'
|
|
723
|
+
' 或已配置 MiniMax MCP(understand_image)'
|
|
724
|
+
)
|
|
725
|
+
continue
|
|
726
|
+
if message_has_video_attachments(user_msg) and not video_attachment_allowed(
|
|
727
|
+
vision_preset_id or ""
|
|
728
|
+
):
|
|
729
|
+
print('[error] 发送视频需要有效的 --vision-llm 或 CODEAGENT_VISION_PRESET_ID')
|
|
730
|
+
continue
|
|
731
|
+
if message_has_audio_attachments(user_msg) and (
|
|
732
|
+
not audio_preset_id or not preset_supports_audio_id(audio_preset_id)
|
|
733
|
+
):
|
|
734
|
+
print('[error] 发送音频需要有效的 --audio-llm 或 CODEAGENT_AUDIO_PRESET_ID')
|
|
735
|
+
continue
|
|
718
736
|
|
|
719
737
|
pending_attachments = []
|
|
720
738
|
pending_dir_tag = ''
|
|
@@ -728,17 +746,33 @@ def _cmd_chat_llm(args):
|
|
|
728
746
|
chat_sess.messages,
|
|
729
747
|
skills_suffix=_skills_suffix,
|
|
730
748
|
)
|
|
731
|
-
|
|
749
|
+
_persisted_usage = (
|
|
750
|
+
chat_sess.metadata.get("context_usage")
|
|
751
|
+
if isinstance(chat_sess.metadata, dict)
|
|
752
|
+
else None
|
|
753
|
+
)
|
|
754
|
+
compact_result = maybe_compact_context_messages(
|
|
755
|
+
api_msgs,
|
|
756
|
+
llm,
|
|
757
|
+
persisted_context_usage=_persisted_usage,
|
|
758
|
+
)
|
|
732
759
|
persist_compact_summary(chat_sess.messages, compact_result)
|
|
733
760
|
strip_ephemeral_message_fields(api_msgs)
|
|
734
761
|
if not isinstance(chat_sess.metadata, dict):
|
|
735
762
|
chat_sess.metadata = {}
|
|
763
|
+
# CLI --project-id 优先;其次回退到会话已存的 project_id。
|
|
764
|
+
# finalize_episodic_for_llm 会保留既有项目归属(不会强行覆盖)。
|
|
765
|
+
effective_project_id = project_id
|
|
766
|
+
if effective_project_id is None and isinstance(chat_sess.metadata, dict):
|
|
767
|
+
existing = chat_sess.metadata.get('project_id')
|
|
768
|
+
if isinstance(existing, str) and existing:
|
|
769
|
+
effective_project_id = existing
|
|
736
770
|
finalize_episodic_for_llm(
|
|
737
771
|
api_msgs,
|
|
738
772
|
chat_sess.metadata,
|
|
739
773
|
agent_id=agent_id,
|
|
740
774
|
session_id=name,
|
|
741
|
-
project_id=
|
|
775
|
+
project_id=effective_project_id,
|
|
742
776
|
compact_happened=compact_result is not None,
|
|
743
777
|
)
|
|
744
778
|
set_active_llm_session(f'{agent_id}::{name}')
|
|
@@ -759,7 +793,25 @@ def _cmd_chat_llm(args):
|
|
|
759
793
|
max_tool_rounds=max_rounds,
|
|
760
794
|
)
|
|
761
795
|
)
|
|
762
|
-
|
|
796
|
+
merge_llm_tail_into_full(chat_sess.messages, api_msgs, n_before)
|
|
797
|
+
# 落盘本轮峰值用量,供下一轮 maybe_compact_context_messages 的
|
|
798
|
+
# persisted_context_usage 来源使用(CLI 路径此前完全缺失此来源)。
|
|
799
|
+
with contextlib.suppress(Exception):
|
|
800
|
+
if isinstance(_loop_meta, dict):
|
|
801
|
+
_peak = int(_loop_meta.get("peak_prompt_tokens") or 0)
|
|
802
|
+
if _peak > 0:
|
|
803
|
+
if not isinstance(chat_sess.metadata, dict):
|
|
804
|
+
chat_sess.metadata = {}
|
|
805
|
+
_prev = chat_sess.metadata.get("context_usage")
|
|
806
|
+
_prev_peak = (
|
|
807
|
+
int(_prev.get("peak_prompt_tokens") or 0)
|
|
808
|
+
if isinstance(_prev, dict)
|
|
809
|
+
else 0
|
|
810
|
+
)
|
|
811
|
+
chat_sess.metadata["context_usage"] = {
|
|
812
|
+
"peak_prompt_tokens": max(_peak, _prev_peak),
|
|
813
|
+
"compact_count": int(_loop_meta.get("compact_count") or 0),
|
|
814
|
+
}
|
|
763
815
|
print(reply)
|
|
764
816
|
if tools_used:
|
|
765
817
|
print(f" [tools] {', '.join(tools_used)}")
|
|
@@ -801,10 +853,9 @@ def _cmd_chat_llm(args):
|
|
|
801
853
|
def cmd_webui_token(args):
|
|
802
854
|
import secrets
|
|
803
855
|
|
|
804
|
-
from codeagent.web.auth_impl import TOKEN_FILENAME
|
|
805
|
-
|
|
806
856
|
# cmd_webui_token can be invoked directly; ensure env file is loaded.
|
|
807
857
|
from codeagent.core.bootstrap import bootstrap_codeagent_runtime
|
|
858
|
+
from codeagent.web.auth_impl import TOKEN_FILENAME
|
|
808
859
|
|
|
809
860
|
bootstrap_codeagent_runtime()
|
|
810
861
|
from seed.core.config_plane import project_root as _project_root
|
|
@@ -6,10 +6,10 @@ import fnmatch
|
|
|
6
6
|
import mimetypes
|
|
7
7
|
import os
|
|
8
8
|
import re
|
|
9
|
-
from dataclasses import asdict, dataclass
|
|
9
|
+
from dataclasses import asdict, dataclass
|
|
10
10
|
from datetime import datetime, timezone
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import Any
|
|
12
|
+
from typing import Any
|
|
13
13
|
|
|
14
14
|
from codeagent.core import env as ca_env
|
|
15
15
|
|
|
@@ -33,7 +33,7 @@ class AttachmentMeta:
|
|
|
33
33
|
filename: str
|
|
34
34
|
size_bytes: int
|
|
35
35
|
path: str = ""
|
|
36
|
-
extracted_text:
|
|
36
|
+
extracted_text: str | None = None
|
|
37
37
|
|
|
38
38
|
def to_dict(self) -> dict[str, Any]:
|
|
39
39
|
return {k: v for k, v in asdict(self).items() if v is not None}
|
|
@@ -101,9 +101,10 @@ def extract_document_text(raw: bytes, mime: str, filename: str = "") -> str:
|
|
|
101
101
|
return raw.decode("utf-8", errors="replace").strip()
|
|
102
102
|
if m == "application/pdf" or name.endswith(".pdf"):
|
|
103
103
|
try:
|
|
104
|
-
from pypdf import PdfReader
|
|
105
104
|
import io
|
|
106
105
|
|
|
106
|
+
from pypdf import PdfReader
|
|
107
|
+
|
|
107
108
|
reader = PdfReader(io.BytesIO(raw))
|
|
108
109
|
parts = []
|
|
109
110
|
for page in reader.pages:
|
|
@@ -159,14 +160,14 @@ def save_attachment(
|
|
|
159
160
|
)
|
|
160
161
|
|
|
161
162
|
|
|
162
|
-
def resolve_attachment_path(agent_id: str, session_id: str, attachment_id: str) ->
|
|
163
|
+
def resolve_attachment_path(agent_id: str, session_id: str, attachment_id: str) -> Path | None:
|
|
163
164
|
from seed.core.media_store import resolve_session_media_path
|
|
164
165
|
|
|
165
166
|
p = resolve_session_media_path(agent_id, session_id, attachment_id)
|
|
166
167
|
return p
|
|
167
168
|
|
|
168
169
|
|
|
169
|
-
def load_attachment_meta(agent_id: str, session_id: str, attachment_id: str) ->
|
|
170
|
+
def load_attachment_meta(agent_id: str, session_id: str, attachment_id: str) -> AttachmentMeta | None:
|
|
170
171
|
p = resolve_attachment_path(agent_id, session_id, attachment_id)
|
|
171
172
|
if not p or not p.is_file():
|
|
172
173
|
return None
|
|
@@ -245,8 +246,8 @@ def scan_image_directory(
|
|
|
245
246
|
workspace_root: Path,
|
|
246
247
|
rel_path: str,
|
|
247
248
|
*,
|
|
248
|
-
pattern:
|
|
249
|
-
max_files:
|
|
249
|
+
pattern: str | None = None,
|
|
250
|
+
max_files: int | None = None,
|
|
250
251
|
) -> tuple[list[Path], bool]:
|
|
251
252
|
"""Return (image paths, truncated). Paths resolved under workspace_root."""
|
|
252
253
|
root = workspace_root.resolve()
|
|
@@ -277,7 +278,7 @@ def scan_image_directory(
|
|
|
277
278
|
return found, truncated
|
|
278
279
|
|
|
279
280
|
|
|
280
|
-
def _parse_globs(pattern:
|
|
281
|
+
def _parse_globs(pattern: str | None) -> tuple[str, ...]:
|
|
281
282
|
if pattern and pattern.strip():
|
|
282
283
|
return tuple(g.strip() for g in pattern.split(",") if g.strip())
|
|
283
284
|
raw = ca_env.pick_default(
|
|
@@ -289,10 +290,7 @@ def _parse_globs(pattern: Optional[str]) -> tuple[str, ...]:
|
|
|
289
290
|
|
|
290
291
|
def _matches_globs(name: str, globs: tuple[str, ...]) -> bool:
|
|
291
292
|
low = name.lower()
|
|
292
|
-
for g in globs
|
|
293
|
-
if fnmatch.fnmatch(low, g.lower()):
|
|
294
|
-
return True
|
|
295
|
-
return False
|
|
293
|
+
return any(fnmatch.fnmatch(low, g.lower()) for g in globs)
|
|
296
294
|
|
|
297
295
|
|
|
298
296
|
def message_has_image_attachments(msg: dict[str, Any]) -> bool:
|
|
@@ -301,9 +299,7 @@ def message_has_image_attachments(msg: dict[str, Any]) -> bool:
|
|
|
301
299
|
for a in atts:
|
|
302
300
|
if isinstance(a, dict) and a.get("kind") == "image":
|
|
303
301
|
return True
|
|
304
|
-
|
|
305
|
-
return True
|
|
306
|
-
return False
|
|
302
|
+
return bool(IMAGE_DIR_TAG_RE.search(str(msg.get("content") or "")))
|
|
307
303
|
|
|
308
304
|
|
|
309
305
|
def message_has_video_attachments(msg: dict[str, Any]) -> bool:
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from typing import Any
|
|
5
|
+
from typing import Any
|
|
6
6
|
|
|
7
7
|
from codeagent.core import env as ca_env
|
|
8
8
|
|
|
@@ -29,7 +29,7 @@ def preset_supports_audio_id(preset_id: str) -> bool:
|
|
|
29
29
|
return False
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def resolve_audio_preset(preset_id:
|
|
32
|
+
def resolve_audio_preset(preset_id: str | None = None) -> dict[str, Any]:
|
|
33
33
|
from seed.core.llm_presets import load_presets
|
|
34
34
|
|
|
35
35
|
pid = (preset_id or "").strip()
|
|
@@ -5,7 +5,6 @@ from __future__ import annotations
|
|
|
5
5
|
import logging
|
|
6
6
|
import os
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Optional
|
|
9
8
|
|
|
10
9
|
from codeagent.core.env import apply_default_product_home
|
|
11
10
|
from codeagent.core.seed_bridge import bridge_codeagent_env_to_seed
|
|
@@ -127,7 +126,7 @@ def _ensure_codeagent_bootstrap_md(home: Path) -> None:
|
|
|
127
126
|
dest.write_text(_CODEAGENT_BOOTSTRAP_MD, encoding="utf-8")
|
|
128
127
|
|
|
129
128
|
|
|
130
|
-
def bootstrap_codeagent_runtime(base:
|
|
129
|
+
def bootstrap_codeagent_runtime(base: Path | None = None) -> Path:
|
|
131
130
|
"""
|
|
132
131
|
1. Default data root ``~/.codeagent`` (or ``CODEAGENT_HOME``)
|
|
133
132
|
2. Set ``SEED_PROJECT_ROOT`` so Seed / seed-tools use the same tree
|
|
@@ -16,7 +16,6 @@ from __future__ import annotations
|
|
|
16
16
|
import json
|
|
17
17
|
import logging
|
|
18
18
|
from pathlib import Path
|
|
19
|
-
from typing import Dict
|
|
20
19
|
|
|
21
20
|
logger = logging.getLogger(__name__)
|
|
22
21
|
|
|
@@ -70,7 +69,7 @@ def _read_legacy_single_id() -> str:
|
|
|
70
69
|
return ""
|
|
71
70
|
|
|
72
71
|
|
|
73
|
-
def get_default_preset_ids() ->
|
|
72
|
+
def get_default_preset_ids() -> dict[str, str]:
|
|
74
73
|
"""Return a mapping ``{slot: preset_id}`` for every slot that has a default.
|
|
75
74
|
|
|
76
75
|
Reads the new JSON map first; falls back to ``codeagent.default_preset_ids.json``
|
|
@@ -83,7 +82,7 @@ def get_default_preset_ids() -> Dict[str, str]:
|
|
|
83
82
|
except (json.JSONDecodeError, OSError):
|
|
84
83
|
data = {}
|
|
85
84
|
if isinstance(data, dict):
|
|
86
|
-
out:
|
|
85
|
+
out: dict[str, str] = {}
|
|
87
86
|
for slot in SLOTS:
|
|
88
87
|
v = data.get(slot)
|
|
89
88
|
if isinstance(v, str) and v.strip():
|
|
@@ -97,7 +96,7 @@ def get_default_preset_ids() -> Dict[str, str]:
|
|
|
97
96
|
except (json.JSONDecodeError, OSError):
|
|
98
97
|
data = {}
|
|
99
98
|
if isinstance(data, dict):
|
|
100
|
-
out:
|
|
99
|
+
out: dict[str, str] = {}
|
|
101
100
|
for slot in SLOTS:
|
|
102
101
|
v = data.get(slot)
|
|
103
102
|
if isinstance(v, str) and v.strip():
|
|
@@ -124,9 +123,9 @@ def set_default_preset_id_for_slot(slot: str, preset_id: str) -> None:
|
|
|
124
123
|
_write_default_preset_ids(cur)
|
|
125
124
|
|
|
126
125
|
|
|
127
|
-
def set_default_preset_ids(mapping:
|
|
126
|
+
def set_default_preset_ids(mapping: dict[str, str]) -> None:
|
|
128
127
|
"""Bulk-replace the entire default map (ignoring unknown slots)."""
|
|
129
|
-
out:
|
|
128
|
+
out: dict[str, str] = {}
|
|
130
129
|
for slot in SLOTS:
|
|
131
130
|
if slot in mapping:
|
|
132
131
|
v = mapping[slot]
|
|
@@ -135,7 +134,7 @@ def set_default_preset_ids(mapping: Dict[str, str]) -> None:
|
|
|
135
134
|
_write_default_preset_ids(out)
|
|
136
135
|
|
|
137
136
|
|
|
138
|
-
def _write_default_preset_ids(mapping:
|
|
137
|
+
def _write_default_preset_ids(mapping: dict[str, str]) -> None:
|
|
139
138
|
p = _new_path()
|
|
140
139
|
p.parent.mkdir(parents=True, exist_ok=True)
|
|
141
140
|
try:
|
|
@@ -6,7 +6,6 @@ import os
|
|
|
6
6
|
import subprocess
|
|
7
7
|
import sys
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
from typing import Optional, Tuple
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
def has_graphical_session() -> bool:
|
|
@@ -20,7 +19,7 @@ def has_graphical_session() -> bool:
|
|
|
20
19
|
)
|
|
21
20
|
|
|
22
21
|
|
|
23
|
-
def pick_directory_sync() ->
|
|
22
|
+
def pick_directory_sync() -> tuple[str, bool, str]:
|
|
24
23
|
"""
|
|
25
24
|
Blocking folder picker.
|
|
26
25
|
|
|
@@ -36,7 +35,7 @@ def pick_directory_sync() -> Tuple[str, bool, str]:
|
|
|
36
35
|
return _pick_linux()
|
|
37
36
|
|
|
38
37
|
|
|
39
|
-
def _pick_darwin() ->
|
|
38
|
+
def _pick_darwin() -> tuple[str, bool, str]:
|
|
40
39
|
script = (
|
|
41
40
|
'POSIX path of (choose folder with prompt '
|
|
42
41
|
'"选择目录" default location (path to desktop folder))'
|
|
@@ -63,7 +62,7 @@ def _pick_darwin() -> Tuple[str, bool, str]:
|
|
|
63
62
|
return "", False, ""
|
|
64
63
|
|
|
65
64
|
|
|
66
|
-
def _pick_windows() ->
|
|
65
|
+
def _pick_windows() -> tuple[str, bool, str]:
|
|
67
66
|
ps = r"""
|
|
68
67
|
Add-Type -AssemblyName System.Windows.Forms
|
|
69
68
|
$top = New-Object System.Windows.Forms.Form
|
|
@@ -103,7 +102,7 @@ try {
|
|
|
103
102
|
return "", True, "PowerShell not found for folder picker"
|
|
104
103
|
|
|
105
104
|
|
|
106
|
-
def _pick_linux() ->
|
|
105
|
+
def _pick_linux() -> tuple[str, bool, str]:
|
|
107
106
|
if not has_graphical_session():
|
|
108
107
|
return (
|
|
109
108
|
"",
|
|
@@ -145,7 +144,7 @@ def _pick_linux() -> Tuple[str, bool, str]:
|
|
|
145
144
|
return "", True, hint
|
|
146
145
|
|
|
147
146
|
|
|
148
|
-
def _which(name: str) ->
|
|
147
|
+
def _which(name: str) -> str | None:
|
|
149
148
|
from shutil import which as _w
|
|
150
149
|
|
|
151
150
|
return _w(name)
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import Any
|
|
6
|
+
from typing import Any
|
|
7
7
|
|
|
8
8
|
from seed.integrations.mcp_config import MINIMAX_MCP_SERVER_ID, get_server_config
|
|
9
9
|
|
|
@@ -12,7 +12,7 @@ MINIMAX_UNDERSTAND_IMAGE_TOOL = "understand_image"
|
|
|
12
12
|
MCP_QUALIFIED_UNDERSTAND_IMAGE = f"mcp__{MINIMAX_MCP_SERVER_ID}__{MINIMAX_UNDERSTAND_IMAGE_TOOL}"
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
def minimax_mcp_configured(base:
|
|
15
|
+
def minimax_mcp_configured(base: Path | None = None) -> bool:
|
|
16
16
|
"""MiniMax MCP server enabled in config with a non-empty API key."""
|
|
17
17
|
from seed.integrations.mcp_client import mcp_globally_enabled
|
|
18
18
|
|
|
@@ -26,10 +26,10 @@ def minimax_mcp_configured(base: Optional[Path] = None) -> bool:
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
def minimax_mcp_understand_image_ready(
|
|
29
|
-
base:
|
|
29
|
+
base: Path | None = None,
|
|
30
30
|
*,
|
|
31
31
|
probe: bool = False,
|
|
32
|
-
servers_status:
|
|
32
|
+
servers_status: list[dict[str, Any]] | None = None,
|
|
33
33
|
) -> bool:
|
|
34
34
|
"""True when MiniMax MCP can run ``understand_image`` (configured; optionally probed)."""
|
|
35
35
|
if not minimax_mcp_configured(base):
|
|
@@ -51,7 +51,7 @@ def minimax_mcp_understand_image_ready(
|
|
|
51
51
|
return False
|
|
52
52
|
|
|
53
53
|
|
|
54
|
-
def image_attachment_allowed(vision_llm_id: str, base:
|
|
54
|
+
def image_attachment_allowed(vision_llm_id: str, base: Path | None = None) -> bool:
|
|
55
55
|
"""User may send image attachments when a vision preset or MiniMax MCP is available."""
|
|
56
56
|
vid = (vision_llm_id or "").strip()
|
|
57
57
|
if vid == MCP_VISION_SENTINEL:
|
|
@@ -72,10 +72,10 @@ def video_attachment_allowed(vision_llm_id: str) -> bool:
|
|
|
72
72
|
|
|
73
73
|
|
|
74
74
|
def image_understanding_status(
|
|
75
|
-
base:
|
|
75
|
+
base: Path | None = None,
|
|
76
76
|
*,
|
|
77
77
|
probe: bool = False,
|
|
78
|
-
servers_status:
|
|
78
|
+
servers_status: list[dict[str, Any]] | None = None,
|
|
79
79
|
) -> dict[str, Any]:
|
|
80
80
|
configured = minimax_mcp_configured(base)
|
|
81
81
|
ready = minimax_mcp_understand_image_ready(
|