whatap-python 2.2.0__tar.gz → 2.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.
- {whatap_python-2.2.0 → whatap_python-2.2.1}/PKG-INFO +1 -1
- {whatap_python-2.2.0 → whatap_python-2.2.1}/setup.py +5 -1
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/__init__.py +180 -33
- whatap_python-2.2.1/whatap/build.py +4 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/conf/configuration.py +72 -1
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/counter/tasks/llm_stat_task.py +10 -0
- whatap_python-2.2.1/whatap/doctor.py +402 -0
- whatap_python-2.2.1/whatap/llm/control/__init__.py +59 -0
- whatap_python-2.2.1/whatap/llm/control/cut.py +519 -0
- whatap_python-2.2.1/whatap/llm/control/guard.py +217 -0
- whatap_python-2.2.1/whatap/llm/control/trajectory.py +524 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/definitions.py +21 -1
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/instrument/_boundary.py +136 -22
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/log_sink_packs/llm_step_status.py +9 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/pricing.py +16 -1
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/anthropic/messages/messages.py +3 -2
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/anthropic/messages/messages_stream.py +3 -2
- whatap_python-2.2.1/whatap/llm/providers/bedrock/__init__.py +92 -0
- whatap_python-2.2.1/whatap/llm/providers/bedrock/_content.py +81 -0
- whatap_python-2.2.1/whatap/llm/providers/bedrock/converse/__init__.py +2 -0
- whatap_python-2.2.1/whatap/llm/providers/bedrock/converse/converse_context.py +155 -0
- whatap_python-2.2.1/whatap/llm/providers/bedrock/converse/converse_extractor.py +196 -0
- whatap_python-2.2.1/whatap/llm/providers/bedrock/event_stream.py +254 -0
- whatap_python-2.2.1/whatap/llm/providers/bedrock/http.py +395 -0
- whatap_python-2.2.1/whatap/llm/providers/bedrock/invoke_model/__init__.py +2 -0
- whatap_python-2.2.1/whatap/llm/providers/bedrock/invoke_model/invoke_model_context.py +126 -0
- whatap_python-2.2.1/whatap/llm/providers/bedrock/invoke_model/invoke_model_extractor.py +763 -0
- whatap_python-2.2.1/whatap/llm/providers/bedrock/runtime.py +291 -0
- whatap_python-2.2.1/whatap/llm/providers/bedrock/step.py +76 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/interceptor.py +10 -1
- whatap_python-2.2.1/whatap/llm/providers/openai/chat/chat.py +160 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/chat/chat_extractor.py +8 -1
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/completions/completions.py +3 -2
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/embeddings/embeddings.py +3 -2
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/responses/responses.py +3 -2
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/stream_accumulator.py +11 -1
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/workflow.py +87 -5
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/traj_actx_stat.py +50 -1
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/net/async_sender.py +22 -9
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/net/param_def.py +6 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/net/udp_session.py +33 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/scripts/__init__.py +89 -0
- whatap_python-2.2.1/whatap/skills/whatap-python-install/AGENTS.md +29 -0
- whatap_python-2.2.1/whatap/skills/whatap-python-install/INSTALL.md +96 -0
- whatap_python-2.2.1/whatap/skills/whatap-python-install/SKILL.md +42 -0
- whatap_python-2.2.1/whatap/skills/whatap-python-install/references/config-keys.md +59 -0
- whatap_python-2.2.1/whatap/skills/whatap-python-install/references/frameworks.md +55 -0
- whatap_python-2.2.1/whatap/skills/whatap-python-install/references/llm-api-usage.md +81 -0
- whatap_python-2.2.1/whatap/skills/whatap-python-install/references/llm-evaluation.md +114 -0
- whatap_python-2.2.1/whatap/skills/whatap-python-install/references/llm-observability.md +123 -0
- whatap_python-2.2.1/whatap/skills/whatap-python-install/references/troubleshooting.md +41 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/httpc/httpx.py +26 -3
- whatap_python-2.2.1/whatap/trace/mod/httpc/httpx2.py +23 -0
- whatap_python-2.2.1/whatap/trace/mod/httpc/requests.py +33 -0
- whatap_python-2.2.1/whatap/trace/mod/httpc/stream_end.py +136 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/httpc/util.py +231 -13
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/trace_error.py +9 -2
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/trace_module_definition.py +15 -0
- whatap_python-2.2.1/whatap/util/native_process.py +458 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap_python.egg-info/PKG-INFO +1 -1
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap_python.egg-info/SOURCES.txt +29 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap_python.egg-info/entry_points.txt +2 -0
- whatap_python-2.2.0/whatap/build.py +0 -4
- whatap_python-2.2.0/whatap/llm/providers/openai/chat/chat.py +0 -103
- whatap_python-2.2.0/whatap/trace/mod/httpc/requests.py +0 -20
- {whatap_python-2.2.0 → whatap_python-2.2.1}/README.md +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/pyproject.toml +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/setup.cfg +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/LICENSE +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/README.rst +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/__main__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/agent/darwin/amd64/whatap_python +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/agent/darwin/arm64/whatap_python +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/agent/linux/amd64/whatap_python +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/agent/linux/arm64/whatap_python +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/agent/windows/whatap_python.exe +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/bootstrap/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/bootstrap/sitecustomize.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/conf/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/conf/configure.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/conf/license.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/control/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/counter/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/counter/counter_manager.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/counter/tasks/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/counter/tasks/base_task.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/counter/tasks/llm_evaluator_task.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/counter/tasks/llm_log_sink_task.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/counter/tasks/openfiledescriptor.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/io/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/io/data_inputx.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/io/data_outputx.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/api/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/api/agent_name.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/api/prompt_meta.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/api/session.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/api/turn.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/api/user.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/api/workflow.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/base.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/builtins/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/builtins/_json_repair.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/builtins/answer_relevance.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/builtins/combined_judge.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/builtins/factuality.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/builtins/hallucination.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/builtins/judge_factories.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/builtins/llm_judge.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/builtins/pii_leak.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/builtins/prompt_injection.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/builtins/toxicity.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/builtins/url_scan.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/registry.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/sampler.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/evaluators/scope.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/features.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/instrument/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/instrument/agent.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/instrument/llm_api.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/instrument/workflow.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/log_sink_packs/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/log_sink_packs/llm_input_message.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/log_sink_packs/llm_log_sink_pack.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/log_sink_packs/llm_output_message.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/log_sink_packs/llm_step_eval_status.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/log_sink_packs/llm_system_message.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/log_sink_packs/llm_tool_calls.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/log_sink_packs/llm_tool_results.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/log_sink_packs/llm_tx_status.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/orchestration/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/orchestration/hermes/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/orchestration/hermes/gateway.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/orchestration/hermes/kanban.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/orchestration/langgraph/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/anthropic/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/anthropic/messages/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/anthropic/messages/messages_context.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/anthropic/messages/messages_extractor.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/chat/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/chat/chat_context.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/completions/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/completions/completions_context.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/completions/completions_extractor.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/content_parser.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/embeddings/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/embeddings/embeddings_context.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/embeddings/embeddings_extractor.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/responses/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/responses/responses_context.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/providers/openai/responses/responses_extractor.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/active_agent_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/active_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/actx_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/answer_relevance_eval_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/api_status_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/base_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/combined_judge_eval_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/error_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/eval_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/factuality_eval_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/feature_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/finish_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/hallucination_eval_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/perf_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/pii_leak_eval_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/prompt_injection_eval_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/token_usage_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/toxicity_eval_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/llm/stats/url_scan_eval_stat.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/net/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/net/packet_enum.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/net/packet_type_enum.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/net/stackhelper.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/net/udp_thread.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/pack/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/pack/logSinkPack.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/pack/pack.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/pack/pack_enum.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/pack/tagCountPack.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/amqp/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/amqp/kombu.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/amqp/pika.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/bottle.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/celery.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/cherrypy.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/django.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/django_asgi.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/django_py3.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/fastapi/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/fastapi/endpoint.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/fastapi/exception_log.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/fastapi/instrumentation.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/fastapi/scope.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/fastapi/transaction.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/flask.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/frappe.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/graphql.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/nameko.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/odoo.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/starlette.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/tornado.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/application/wsgi.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/database/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/database/cxoracle.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/database/mongo.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/database/mysql.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/database/neo4j.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/database/psycopg2.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/database/psycopg3.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/database/redis.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/database/sqlalchemy.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/database/sqlite3.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/database/util.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/email/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/email/smtp.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/hook_service_patterns.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/httpc/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/httpc/django.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/httpc/httplib.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/httpc/urllib3.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/logging.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/pattern_targets.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/plugin.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/process/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/process/subprocess_spawn.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/standalone/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/standalone/multiple.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/standalone/single.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/thread_context.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mod/workflow_plugin.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/mtrace_env.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/patch.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/simple_trace_context.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/trace_context.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/trace_context_manager.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/trace_handler.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/trace/trace_import.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/bit_util.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/cardinality/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/cardinality/hyperloglog.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/cardinality/murmurhash.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/cardinality/registerset.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/compare_util.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/date_util.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/debug_util.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/escape_literal_sql.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/frame_util.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/hash_util.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/hexa32.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/int_set.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/ip_util.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/keygen.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/linked_list.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/linked_map.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/metering_util.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/request_double_queue.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/request_queue.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/string_util.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/throttle_util.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/util/userid_util.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/__init__.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/blob_value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/boolean_value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/decimal_value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/double_summary.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/double_value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/float_array.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/float_value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/int_array.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/ip4_value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/list_value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/long_array.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/long_summary.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/map_value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/null_value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/number_value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/summary_value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/text_array.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/text_hash_value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/text_value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/value.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/value/value_enum.py +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap/whatap.conf +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap_python.egg-info/dependency_links.txt +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap_python.egg-info/not-zip-safe +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap_python.egg-info/requires.txt +0 -0
- {whatap_python-2.2.0 → whatap_python-2.2.1}/whatap_python.egg-info/top_level.txt +0 -0
|
@@ -20,7 +20,9 @@ setup(name=build.name,
|
|
|
20
20
|
url='https://www.whatap.io',
|
|
21
21
|
packages=find_packages(exclude=('sample','sample.*')),
|
|
22
22
|
package_data={
|
|
23
|
-
'whatap': ['LICENSE', '*.rst', '*.conf', '*.json', 'agent/*/*/whatap_python', 'agent/windows/*.exe'
|
|
23
|
+
'whatap': ['LICENSE', '*.rst', '*.conf', '*.json', 'agent/*/*/whatap_python', 'agent/windows/*.exe',
|
|
24
|
+
'skills/whatap-python-install/*.md',
|
|
25
|
+
'skills/whatap-python-install/references/*.md']
|
|
24
26
|
},
|
|
25
27
|
entry_points={
|
|
26
28
|
'console_scripts': [
|
|
@@ -28,6 +30,8 @@ setup(name=build.name,
|
|
|
28
30
|
'whatap-stop-agent=whatap.scripts:stop_agent',
|
|
29
31
|
'whatap-setting-config=whatap.scripts:setting_config',
|
|
30
32
|
'whatap-llm-setting-config=whatap.scripts:llm_setting_config',
|
|
33
|
+
'whatap-doctor=whatap.doctor:main',
|
|
34
|
+
'whatap-install-agent-guide=whatap.scripts:install_agent_guide',
|
|
31
35
|
|
|
32
36
|
'whatap-start-batch-agent=whatap:start_batch_agent',
|
|
33
37
|
],
|
|
@@ -378,11 +378,20 @@ def _is_instrumentation_ignored(definition_key, ignore_set):
|
|
|
378
378
|
def hooks(home):
|
|
379
379
|
ignore_set = _build_ignore_instrumentation_set()
|
|
380
380
|
skipped_keys = []
|
|
381
|
+
# LLM 계측은 llm_enabled 일 때만 **등록**한다. instrument_* 함수들도 각자
|
|
382
|
+
# llm_enabled 를 보고 되돌아가지만, 등록만 해둬도 대상 모듈이 로드되는 순간
|
|
383
|
+
# import 훅이 ``whatap.llm.*`` 서브트리를 통째로 끌어온다 — 켜지도 않은 기능
|
|
384
|
+
# 때문에. ``botocore.client``(Bedrock) 처럼 LLM 과 무관한 앱도 흔히 쓰는 모듈이
|
|
385
|
+
# 대상에 들어오면서 이 비용이 실제로 문제가 된다.
|
|
386
|
+
# conf.init() 이 hooks() 보다 먼저 돌므로 여기서 llm_enabled 는 이미 확정이다.
|
|
387
|
+
llm_enabled = bool(getattr(conf, 'llm_enabled', False))
|
|
381
388
|
try:
|
|
382
389
|
for key, value_list in DEFINITION.items():
|
|
383
390
|
if _is_instrumentation_ignored(key, ignore_set):
|
|
384
391
|
skipped_keys.append(key)
|
|
385
392
|
continue
|
|
393
|
+
if key.startswith('llm.') and not llm_enabled:
|
|
394
|
+
continue
|
|
386
395
|
for value in value_list:
|
|
387
396
|
if len(value) >= 3 and isinstance(value[2], str):
|
|
388
397
|
module_path = value[2]
|
|
@@ -537,9 +546,14 @@ def agent():
|
|
|
537
546
|
llm_enabled = preview_whatap_conf("llm_enabled")
|
|
538
547
|
|
|
539
548
|
if apm_enabled == 'true':
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
549
|
+
if sys.platform.startswith('linux'):
|
|
550
|
+
# Publish native ownership before a short-lived interpreter
|
|
551
|
+
# can exit. This does not wait for collector/TCP readiness.
|
|
552
|
+
go()
|
|
553
|
+
else:
|
|
554
|
+
t = threading.Thread(target=go)
|
|
555
|
+
t.setDaemon(True)
|
|
556
|
+
t.start()
|
|
543
557
|
|
|
544
558
|
if llm_enabled == 'true':
|
|
545
559
|
# llm_enabled=true 라도 LLM 채널 자격증명(llm_accesskey)이 없으면 LLM
|
|
@@ -564,24 +578,134 @@ ARCH = {
|
|
|
564
578
|
'ARM': 'arm',
|
|
565
579
|
'AArch64': 'arm64',
|
|
566
580
|
'arm64': 'arm64',
|
|
567
|
-
'aarch64': 'arm64'
|
|
581
|
+
'aarch64': 'arm64',
|
|
582
|
+
# Windows 의 platform.machine() 은 **대문자**로 돌려준다('AMD64'/'ARM64').
|
|
583
|
+
# Windows 는 arch 하위 디렉토리를 쓰지 않아 지금은 이 표를 안 타지만, 빠져 있으면
|
|
584
|
+
# 누가 조회하는 순간 KeyError 로 기동이 통째로 죽는 종류의 구멍이라 채워 둔다.
|
|
585
|
+
'AMD64': 'amd64',
|
|
586
|
+
'ARM64': 'arm64',
|
|
587
|
+
'i386': '386',
|
|
568
588
|
}
|
|
569
589
|
|
|
570
590
|
AGENT_NAME = 'whatap_python'
|
|
571
591
|
|
|
572
592
|
|
|
593
|
+
def agent_binary_name():
|
|
594
|
+
"""OS 별 에이전트 실행 파일 이름."""
|
|
595
|
+
return AGENT_NAME + '.exe' if sys.platform == 'win32' else AGENT_NAME
|
|
596
|
+
|
|
597
|
+
|
|
598
|
+
def llm_agent_reldir():
|
|
599
|
+
"""LLM 전용 ``whatap_python`` 이 놓이는 ``$WHATAP_HOME`` 하위 상대경로.
|
|
600
|
+
|
|
601
|
+
Unix 계열은 ``<os>/<arch>`` (linux/amd64, linux/arm64, darwin/amd64, darwin/arm64).
|
|
602
|
+
**Windows 는 arch 하위를 쓰지 않는다** — x64 하나면 ARM64 Windows 에서도 에뮬레이션
|
|
603
|
+
으로 돌아서 아키텍처별 빌드를 나눌 이유가 없다. 번들 APM 쪽
|
|
604
|
+
``whatap/agent/windows/`` 가 평평한 것과 같은 이유이고, 같은 모양이다.
|
|
605
|
+
|
|
606
|
+
반환: ``(상대경로, 사유)``. 상대경로가 None 이면 사유에 왜 못 구하는지가 담긴다.
|
|
607
|
+
"""
|
|
608
|
+
system = platform.system().lower()
|
|
609
|
+
if sys.platform == 'win32':
|
|
610
|
+
return system, ''
|
|
611
|
+
machine = platform.machine()
|
|
612
|
+
arch = ARCH.get(machine)
|
|
613
|
+
if not arch:
|
|
614
|
+
return None, ('unsupported architecture {0!r} for the LLM agent '
|
|
615
|
+
'(known: {1})'.format(machine, ', '.join(sorted(set(ARCH.values())))))
|
|
616
|
+
return os.path.join(system, arch), ''
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
def llm_agent_path():
|
|
620
|
+
"""LLM 전용 ``whatap_python`` 의 배포 위치. @see ``llm_agent_reldir``
|
|
621
|
+
|
|
622
|
+
반환: ``(경로, 사유)``. 경로가 None 이면 사유에 왜 못 쓰는지가 담긴다.
|
|
623
|
+
"""
|
|
624
|
+
reldir, reason = llm_agent_reldir()
|
|
625
|
+
if reldir is None:
|
|
626
|
+
return None, reason
|
|
627
|
+
home_path = os.environ.get('WHATAP_HOME')
|
|
628
|
+
if not home_path:
|
|
629
|
+
return None, 'WHATAP_HOME is not set'
|
|
630
|
+
path = os.path.join(home_path, reldir, agent_binary_name())
|
|
631
|
+
if not os.path.exists(path):
|
|
632
|
+
return None, ('LLM agent binary not found: {0} '
|
|
633
|
+
'(place the LLM {1} under $WHATAP_HOME/{2}/)'.format(
|
|
634
|
+
path, agent_binary_name(), reldir.replace(os.sep, '/')))
|
|
635
|
+
return path, ''
|
|
636
|
+
|
|
637
|
+
|
|
638
|
+
|
|
639
|
+
def _native_agent_spec(opts):
|
|
640
|
+
from whatap.util.native_process import AgentSpec
|
|
641
|
+
source = os.path.join(os.path.dirname(__file__), 'agent', 'linux',
|
|
642
|
+
ARCH[platform.machine()], AGENT_NAME)
|
|
643
|
+
env = os.environ.copy()
|
|
644
|
+
env.update(opts)
|
|
645
|
+
return AgentSpec(os.environ['WHATAP_HOME'], source, env)
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
def _native_agent_log_path():
|
|
649
|
+
return os.path.join(os.environ.get('WHATAP_HOME', '.'), 'logs', AGENT_NAME + '.log')
|
|
650
|
+
|
|
651
|
+
|
|
652
|
+
def _open_native_agent_log():
|
|
653
|
+
# managed 경로는 PIPE 를 읽지 않으므로 네이티브 stdout/stderr 를 파일로 남겨
|
|
654
|
+
# 기동 직후 실패 원인을 추적할 수 있게 한다.
|
|
655
|
+
try:
|
|
656
|
+
log_path = _native_agent_log_path()
|
|
657
|
+
os.makedirs(os.path.dirname(log_path), exist_ok=True)
|
|
658
|
+
return open(log_path, 'ab')
|
|
659
|
+
except Exception as e:
|
|
660
|
+
whatap_print('WHATAP: native agent log open failed: %s' % e)
|
|
661
|
+
return subprocess.DEVNULL
|
|
662
|
+
|
|
573
663
|
|
|
574
664
|
def go(batch=False, opts={}, llm=False):
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
665
|
+
if sys.platform.startswith('linux') and not batch and not llm:
|
|
666
|
+
from whatap.util.native_process import FAILED, ensure_agent_running
|
|
667
|
+
|
|
668
|
+
def on_child_exit(pid, exit_code):
|
|
669
|
+
whatap_error_log(
|
|
670
|
+
'WHATAP: native APM exited (PID: {}, exit code: {}, log: {})'.format(
|
|
671
|
+
pid, exit_code, _native_agent_log_path()),
|
|
672
|
+
log_id='WHATAP_AGENT_EXITED')
|
|
673
|
+
|
|
674
|
+
try:
|
|
675
|
+
spec = _native_agent_spec(opts)
|
|
676
|
+
result = ensure_agent_running(
|
|
677
|
+
spec, lambda: _start_go(batch, opts, llm, managed=True),
|
|
678
|
+
on_child_exit=on_child_exit)
|
|
679
|
+
if result.status == FAILED:
|
|
680
|
+
whatap_error_log('WHATAP: native APM startup failed',
|
|
681
|
+
log_id='WHATAP_AGENT_START_FAILED')
|
|
682
|
+
else:
|
|
683
|
+
whatap_print('WHATAP: native APM {} (PID: {})'.format(
|
|
684
|
+
result.status, result.pid))
|
|
685
|
+
except Exception as e:
|
|
686
|
+
whatap_error_log('WHATAP: native APM startup failed: {}'.format(e),
|
|
687
|
+
log_id='WHATAP_AGENT_START_FAILED')
|
|
584
688
|
return
|
|
689
|
+
return _start_go(batch, opts, llm)
|
|
690
|
+
|
|
691
|
+
|
|
692
|
+
def _start_go(batch=False, opts={}, llm=False, managed=False):
|
|
693
|
+
# LLM 에이전트는 전용 whatap_python 이 $WHATAP_HOME 하위에 따로 배포된다
|
|
694
|
+
# (unix 는 <os>/<arch>, windows 는 windows/ — @see llm_agent_reldir).
|
|
695
|
+
# **OS 로 막지 않는다** — 그 자리에 바이너리가 놓였는지로 판단한다(그래야 windows
|
|
696
|
+
# 빌드가 배포되는 순간 코드 변경 없이 살아난다).
|
|
697
|
+
#
|
|
698
|
+
# 여기서 미리 걸러야 하는 이유: 그냥 흘려보내면 배포 분기로 빠져 **번들 APM
|
|
699
|
+
# 바이너리**를 골라 ``--llm`` 으로 띄우고, 심지어 APM 과 같은
|
|
700
|
+
# ``$WHATAP_HOME/whatap_python`` 에 배포해 서로를 덮는다(둘은 다른 바이너리다).
|
|
701
|
+
llm_agent_cmd = None
|
|
702
|
+
if llm:
|
|
703
|
+
llm_agent_cmd, reason = llm_agent_path()
|
|
704
|
+
if llm_agent_cmd is None:
|
|
705
|
+
whatap_error_log(
|
|
706
|
+
'WHATAP: skipping LLM agent start — {0}'.format(reason),
|
|
707
|
+
log_id='WHATAP_LLM_AGENT_UNAVAILABLE')
|
|
708
|
+
return
|
|
585
709
|
|
|
586
710
|
newenv=os.environ.copy()
|
|
587
711
|
newenv['WHATAP_VERSION'] = build.version
|
|
@@ -625,7 +749,7 @@ def go(batch=False, opts={}, llm=False):
|
|
|
625
749
|
return ''
|
|
626
750
|
|
|
627
751
|
pid = read_file(home, file_name)
|
|
628
|
-
if pid and get_pname(pid).find('whatap_python') >= 0:
|
|
752
|
+
if not managed and pid and get_pname(pid).find('whatap_python') >= 0:
|
|
629
753
|
if sys.platform == 'win32':
|
|
630
754
|
# Windows: Don't kill, just skip
|
|
631
755
|
whatap_print('WHATAP: Agent already running (PID: {}). Skipping duplicate execution.'.format(pid))
|
|
@@ -642,24 +766,20 @@ def go(batch=False, opts={}, llm=False):
|
|
|
642
766
|
home_path= os.environ.get(home)
|
|
643
767
|
|
|
644
768
|
# Windows uses .exe extension
|
|
645
|
-
|
|
769
|
+
binary_name = agent_binary_name()
|
|
646
770
|
|
|
647
|
-
# LLM mode
|
|
648
|
-
#
|
|
649
|
-
# It is executed in place from there rather than deployed
|
|
650
|
-
# package into $WHATAP_HOME/whatap_python, which the APM
|
|
651
|
-
# are
|
|
652
|
-
|
|
771
|
+
# LLM mode runs a dedicated whatap_python binary that ships separately under
|
|
772
|
+
# $WHATAP_HOME (unix: <os>/<arch>, windows: windows/ — @see llm_agent_reldir).
|
|
773
|
+
# It is executed in place from there rather than deployed
|
|
774
|
+
# from the bundled package into $WHATAP_HOME/whatap_python, which the APM
|
|
775
|
+
# agent uses (the two are distinct binaries and would otherwise clobber each
|
|
776
|
+
# other). **OS 로 가르지 않는다** — Windows 만 빼면 거기서 APM 바이너리를
|
|
777
|
+
# 골라 --llm 으로 띄우고 APM 의 배포 경로까지 덮어쓴다.
|
|
778
|
+
run_in_place = llm
|
|
653
779
|
|
|
654
780
|
if run_in_place:
|
|
655
|
-
|
|
656
|
-
source_agent =
|
|
657
|
-
if not os.path.exists(source_agent):
|
|
658
|
-
raise FileNotFoundError(
|
|
659
|
-
'LLM agent binary not found: {0} '
|
|
660
|
-
'(place the LLM {1} under $WHATAP_HOME/{2}/{3}/)'.format(
|
|
661
|
-
source_agent, agent_binary_name,
|
|
662
|
-
platform.system().lower(), ARCH[platform.machine()]))
|
|
781
|
+
# 경로·존재 확인은 _start_go() 진입부의 llm_agent_path() 가 이미 했다(단일 소스).
|
|
782
|
+
source_agent = llm_agent_cmd
|
|
663
783
|
# Ensure executable (best effort; ignore on read-only locations)
|
|
664
784
|
if not os.access(source_agent, os.X_OK):
|
|
665
785
|
try:
|
|
@@ -668,7 +788,7 @@ def go(batch=False, opts={}, llm=False):
|
|
|
668
788
|
whatap_print('WHATAP: chmod LLM agent binary failed: %s' % e)
|
|
669
789
|
agent_cmd = source_agent
|
|
670
790
|
else:
|
|
671
|
-
dest_agent = os.path.join(home_path,
|
|
791
|
+
dest_agent = os.path.join(home_path, binary_name)
|
|
672
792
|
|
|
673
793
|
# Try to remove existing binary
|
|
674
794
|
# Windows: File may still be locked even after waiting, ignore error and use existing binary
|
|
@@ -695,7 +815,7 @@ def go(batch=False, opts={}, llm=False):
|
|
|
695
815
|
source_cwd = os.path.join(os.path.join(os.path.dirname(__file__), 'agent'), platform.system().lower(),
|
|
696
816
|
ARCH[platform.machine()])
|
|
697
817
|
|
|
698
|
-
source_agent = os.path.join(source_cwd,
|
|
818
|
+
source_agent = os.path.join(source_cwd, binary_name)
|
|
699
819
|
|
|
700
820
|
# Deploy agent binary only if needed
|
|
701
821
|
if needs_deployment:
|
|
@@ -712,9 +832,9 @@ def go(batch=False, opts={}, llm=False):
|
|
|
712
832
|
|
|
713
833
|
# Windows uses absolute path, Unix/Linux uses relative path
|
|
714
834
|
if sys.platform == 'win32':
|
|
715
|
-
agent_cmd = os.path.join(home_path,
|
|
835
|
+
agent_cmd = os.path.join(home_path, binary_name)
|
|
716
836
|
else:
|
|
717
|
-
agent_cmd = './{0}'.format(
|
|
837
|
+
agent_cmd = './{0}'.format(binary_name)
|
|
718
838
|
|
|
719
839
|
sockfile_path = os.path.join(home_path, 'run')
|
|
720
840
|
if not os.path.exists(sockfile_path):
|
|
@@ -774,6 +894,17 @@ def go(batch=False, opts={}, llm=False):
|
|
|
774
894
|
cwd=home_path, env=newenv,
|
|
775
895
|
creationflags=DETACHED_PROCESS,
|
|
776
896
|
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
897
|
+
elif managed:
|
|
898
|
+
go_out = _open_native_agent_log()
|
|
899
|
+
try:
|
|
900
|
+
process = subprocess.Popen(cmd_args,
|
|
901
|
+
cwd=home_path, env=newenv,
|
|
902
|
+
start_new_session=True,
|
|
903
|
+
stdout=go_out, stderr=go_out)
|
|
904
|
+
finally:
|
|
905
|
+
if go_out is not subprocess.DEVNULL:
|
|
906
|
+
go_out.close()
|
|
907
|
+
return process
|
|
777
908
|
else:
|
|
778
909
|
process = subprocess.Popen(cmd_args,
|
|
779
910
|
cwd=home_path, env=newenv,
|
|
@@ -1086,6 +1217,22 @@ def get_port_number(port=6600, home=os.environ.get('WHATAP_HOME'), lock_file=Non
|
|
|
1086
1217
|
|
|
1087
1218
|
|
|
1088
1219
|
def configPort():
|
|
1220
|
+
if sys.platform.startswith('linux') and preview_whatap_conf('apm_enabled') == 'true':
|
|
1221
|
+
from whatap.util.native_process import acquire_start_lock, configured_channel, find_existing_agent
|
|
1222
|
+
try:
|
|
1223
|
+
spec = _native_agent_spec({})
|
|
1224
|
+
with acquire_start_lock(spec):
|
|
1225
|
+
if find_existing_agent(spec):
|
|
1226
|
+
# CLI allocation must not rewrite a live bootstrap agent's channel.
|
|
1227
|
+
return configured_channel(spec.home, spec.environment, include_unix=False)[1]
|
|
1228
|
+
return _config_port()
|
|
1229
|
+
except Exception as e:
|
|
1230
|
+
# 락 타임아웃/다중 인스턴스 등은 CLI 를 죽이지 말고 기존 포트 할당으로 폴백
|
|
1231
|
+
whatap_print('WHATAP: live agent check skipped, falling back to port file: %s' % e)
|
|
1232
|
+
return _config_port()
|
|
1233
|
+
|
|
1234
|
+
|
|
1235
|
+
def _config_port():
|
|
1089
1236
|
# force_net_udp_port가 설정된 경우 lock 파일 무시하고 해당 포트 강제 사용
|
|
1090
1237
|
force_port_str = preview_whatap_conf("force_net_udp_port")
|
|
1091
1238
|
if force_port_str and force_port_str not in ('false', 'False'):
|
|
@@ -39,7 +39,7 @@ Configuration = {
|
|
|
39
39
|
# 해당 메서드 실행이 워크플로우가 되고 내부 LLM 호출은 스텝. workflow_plugin 참조.
|
|
40
40
|
"workflow_method_patterns": "",
|
|
41
41
|
# 트랜잭션(서비스) 진입점으로 자동 래핑할 메서드 패턴 (module:Class.method, 콤마 구분).
|
|
42
|
-
# 해당 메서드 호출이 하나의 트랜잭션이 된다(
|
|
42
|
+
# 해당 메서드 호출이 하나의 트랜잭션이 된다(구 @method_profiling 데코레이터 대체).
|
|
43
43
|
# 프레임워크 자동계측이 안 되는 진입점용. hook_service_patterns 모듈 참조.
|
|
44
44
|
"hook_service_patterns": "",
|
|
45
45
|
|
|
@@ -144,6 +144,26 @@ Configuration = {
|
|
|
144
144
|
# APM Go Agent 가 떠 있는 배포(apm_enabled=true)에서만 의미가 있다.
|
|
145
145
|
"llm_apm_txn_enabled": False,
|
|
146
146
|
|
|
147
|
+
# ── LLM 계측 킬스위치 (문제 발생 시 에이전트 다운그레이드 없이 되돌릴 레버) ──
|
|
148
|
+
#
|
|
149
|
+
# **여기 등록돼 있어야 whatap.conf 의 false 가 먹는다.** ``Configure.setProperty`` 는
|
|
150
|
+
# 이 표에 bool 기본값이 있는 키만 문자열 'false' → False 로 강제 변환한다. 미등록 키는
|
|
151
|
+
# ``'false'`` 문자열로 남고 ``bool('false') == True`` 라 게이트가 계속 열려 있다
|
|
152
|
+
# (실측으로 확인: 등록 키는 False, 미등록 키는 'false'/truthy).
|
|
153
|
+
#
|
|
154
|
+
# llm_workflow_enabled : 워크플로우/에이전트 경계 계측 전체 (구 키 llm_trajectory_enabled
|
|
155
|
+
# 와 AND — 어느 쪽을 false 로 줘도 꺼진다)
|
|
156
|
+
# mtrace_kanban_enabled: hermes 칸반 카드 경계 전파
|
|
157
|
+
# llm_thread_pool_propagation_enabled:
|
|
158
|
+
# Thread/ThreadPoolExecutor 컨텍스트 전파 몽키패치
|
|
159
|
+
# llm_httpc_step_enabled: 워크플로우 안의 httpc 스텝을 **전부** LLM 채널에도 싣는다
|
|
160
|
+
# (APM 쪽은 무관하게 그대로). false 면 LLM API httpc 만.
|
|
161
|
+
"llm_workflow_enabled": True,
|
|
162
|
+
"llm_trajectory_enabled": True,
|
|
163
|
+
"mtrace_kanban_enabled": True,
|
|
164
|
+
"llm_thread_pool_propagation_enabled": True,
|
|
165
|
+
"llm_httpc_step_enabled": True,
|
|
166
|
+
|
|
147
167
|
# 프로세스 종료 시 송출 큐를 비우는 최대 대기(초, 0 이면 대기 안 함). sender 스레드는
|
|
148
168
|
# daemon 이라 exit 시 즉사하므로, 원샷 CLI 에이전트처럼 단명하는 프로세스는 마지막
|
|
149
169
|
# TX_END 가 큐에 남은 채 사라질 수 있다. standalone 모듈은 자체 atexit 로 이걸
|
|
@@ -369,6 +389,50 @@ Configuration = {
|
|
|
369
389
|
# (llm_actx_bands)만 붙는다.
|
|
370
390
|
"llm_traj_actx_enabled": True,
|
|
371
391
|
|
|
392
|
+
# ── LLM 트래젝토리 제어 (ParamPack 905) ──
|
|
393
|
+
# 실행 중인 트래젝토리(mtid 가족)를 서버에서 중지시킨다. 스코프는 트랜잭션 되감기가
|
|
394
|
+
# 아니라 **진행 중 LLM 호출 끊기 + 이후 LLM 호출 차단** 이다 — 앱은 평범한 연결오류를
|
|
395
|
+
# 받고 스스로 응답한다(되감기는 gthread 에서 클라이언트 60초 행을 만들었다).
|
|
396
|
+
#
|
|
397
|
+
# llm_control_enabled: 기능 킬스위치. false 면 표시도 끊기도 하지 않고 905 에
|
|
398
|
+
# 204(지원하지 않음)로 답한다 — 400(대상 없음)으로 답하면 "왜 안 되지" 를 데이터
|
|
399
|
+
# 문제로 오독하게 된다.
|
|
400
|
+
# llm_control_async_cut_enabled: async 호출을 우리 태스크로 감쌀지. 코루틴은 소켓이
|
|
401
|
+
# 스택에 없어(sync 는 있다) 취소 핸들을 **미리** 만들어 두는 것이 유일한 수단이라,
|
|
402
|
+
# 중지 요청이 없어도 모든 async LLM 호출에 적용된다. 의심스러운 환경(비-asyncio
|
|
403
|
+
# 런타임 등)에서 이것만 끄면 async 는 "이후 호출 차단" 만 남는다(진행 중 호출은
|
|
404
|
+
# 그대로 끝난다). sync 경로는 이 값과 무관하게 동작한다.
|
|
405
|
+
# llm_control_stop_transaction_enabled: 중지 스코프. true(기본)면 진행 중 LLM 호출을
|
|
406
|
+
# 끊은 뒤 **그 트랜잭션을 실행 중인 주체까지 끝낸다**(async=태스크 취소,
|
|
407
|
+
# sync=스레드에 BaseException 주입). false 면 LLM 호출만 끊고 앱은 계속 돈다
|
|
408
|
+
# (이후 LLM 호출은 전부 실패하므로 LLM 작업량은 0).
|
|
409
|
+
# **끄는 것이 나은 경우: gunicorn gthread 워커.** 이전 PoC 실측에서 그 조합만 응답
|
|
410
|
+
# 없이 클라이언트가 60초 대기했다(sync/uvicorn 은 그 요청 500, 워커·옆 요청 무사).
|
|
411
|
+
"llm_control_enabled": True,
|
|
412
|
+
# llm_control_stop_thread_enabled: sync 스레드에 **예외 주입**까지 할 것인가(기본 off).
|
|
413
|
+
# 다른 종료 수단과 안전성이 다르다 — asyncio 취소는 await 지점, greenlet kill 은
|
|
414
|
+
# switch 지점, 협조적 체크포인트는 우리 프레임에서 발동하지만, 스레드 주입만
|
|
415
|
+
# **임의 바이트코드**에서 터진다(실측: 수동 락 구간에 걸리면 락이 영구 점유되고,
|
|
416
|
+
# 블로킹 시스템콜 중에는 아예 발동하지 않는다). 끄더라도 sync 앱은 협조적
|
|
417
|
+
# 체크포인트로 멈춘다 — 계측 경계(LLM 호출/HTTP/워크플로우)를 지나면 끝난다.
|
|
418
|
+
# 비계측 블로킹에 갇힌 스레드까지 강제 종료해야 하는 운영자만 켠다.
|
|
419
|
+
"llm_control_stop_transaction_enabled": True,
|
|
420
|
+
"llm_control_stop_thread_enabled": False,
|
|
421
|
+
"llm_control_async_cut_enabled": True,
|
|
422
|
+
# llm_blocked_users: **사용자 단위 차단**(콤마 구분 user_id 목록). 905 가 서버에서
|
|
423
|
+
# mtid 하나를 지목하는 일회성 사건이라면, 이쪽은 **설정이 곧 상태**다 — 여기 올라
|
|
424
|
+
# 있는 동안 그 사용자의 LLM 호출은 계속 막히고, 빼면 즉시 풀린다(설정 핫리로드
|
|
425
|
+
# 주기 30초). 집행 지점은 905 와 같다: 새 호출은 가드에서, SDK/앱 재시도는 httpc
|
|
426
|
+
# 체크포인트에서, 진행 중 호출은 1초 틱 스윕에서 끊는다.
|
|
427
|
+
# 대상 값은 ``ctx.login_id`` — set_user_id()/llm_user_header/llm_user_meta_key/
|
|
428
|
+
# hermes 4경로로 채워지는 그 user_id 이고, 로그싱크 팩의 user_id 태그와 같은 값이라
|
|
429
|
+
# 화면에서 본 값을 그대로 옮겨 적으면 된다. 대소문자 무시, 미식별('0')은 대상 아님.
|
|
430
|
+
# llm_blocked_users=u-1024,abuse@example.com
|
|
431
|
+
# **해제는 줄을 지우는 게 아니라 값을 비우는 것**(`llm_blocked_users=`)이다. 핫리로드
|
|
432
|
+
# (`Configure.load`)는 파일에 있는 키만 다시 세팅하고 사라진 키를 기본값으로 되돌리지
|
|
433
|
+
# 않는다 — 줄을 지우면 재기동 전까지 마지막 값이 그대로 남아 계속 차단된다.
|
|
434
|
+
"llm_blocked_users": "",
|
|
435
|
+
|
|
372
436
|
# ── LLM Evaluation ──
|
|
373
437
|
# 평가 파이프라인 마스터 토글. false면 enqueue/worker가 동작하지 않음.
|
|
374
438
|
"llm_eval_enabled": False,
|
|
@@ -417,6 +481,13 @@ Configuration = {
|
|
|
417
481
|
# 평가자만 적용되고 이 전역 목록은 적용되지 않는다.
|
|
418
482
|
"llm_eval_evaluators": "",
|
|
419
483
|
|
|
484
|
+
# 정형 평가자(pii_leak / url_scan)의 스캔 범위. 기본은 output_text(모델 응답)만 —
|
|
485
|
+
# "모델이 응답에 PII/URL 을 흘렸나(leak)" 관점이라 사용자가 프롬프트에 넣은 값은
|
|
486
|
+
# 대상이 아니다. true 로 두면 같은 LLM 호출을 input+output 한 덩어리로 보고
|
|
487
|
+
# input_text 도 함께 스캔 — 입력에만 있어도(예: 프롬프트에 붙은 카드번호/URL) 검출된다
|
|
488
|
+
# (프롬프트-사이드 DLP). LLM judge(combined_judge 등)에는 영향 없음.
|
|
489
|
+
"llm_eval_scan_input": False,
|
|
490
|
+
|
|
420
491
|
# ── conf 기반 default judge (앱 코드 0) ──
|
|
421
492
|
# llm-as-judge 평가자(combined_judge 등)는 평가용 LLM 호출에 자체 자격증명이 필요하다.
|
|
422
493
|
# judge 해석 순서: ① evaluator(judge_fn=) → ② set_default_judge_fn() → ③ 계측이
|
|
@@ -28,6 +28,16 @@ class LlmStatTask(Thread):
|
|
|
28
28
|
while True:
|
|
29
29
|
current_time = time.time()
|
|
30
30
|
time.sleep(1)
|
|
31
|
+
# 차단 사용자(llm_blocked_users)의 **진행 중** LLM 호출 끊기. 가드/체크포인트는
|
|
32
|
+
# "다음 호출" 만 막으므로, 설정으로 차단을 건 순간 이미 돌고 있는 스트리밍은
|
|
33
|
+
# 여기서 끊어야 운영자가 본 대로 동작한다. 목록이 비면(기본) getattr 한 번에
|
|
34
|
+
# 끝나고, 모집단도 진행 중 호출 레지스트리(0~수 개)라 틱 비용이 없다.
|
|
35
|
+
# 통계와 무관한 일이지만 LLM 모드에서 도는 주기 스레드가 여기뿐이다.
|
|
36
|
+
try:
|
|
37
|
+
from whatap.llm.control import enforce_blocked_users
|
|
38
|
+
enforce_blocked_users()
|
|
39
|
+
except Exception as e:
|
|
40
|
+
logging.debug(e, extra={'id': 'WA186'}, exc_info=True)
|
|
31
41
|
for stat in self.stats:
|
|
32
42
|
last_executed_time = self.last_executed[stat.name()]
|
|
33
43
|
interval = stat.interval()
|