sycommon-python-lib 0.2.7a55__tar.gz → 0.2.8a0__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.
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/PKG-INFO +4 -4
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/pyproject.toml +4 -4
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/sandbox/file_ops.py +5 -1
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/sandbox/http_sandbox_backend.py +16 -2
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/auth/wecom_ldap_service.py +154 -15
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/sandbox.py +79 -13
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/models/sandbox.py +5 -0
- sycommon_python_lib-0.2.8a0/src/sycommon/tools/user_id.py +106 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon_python_lib.egg-info/PKG-INFO +4 -4
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon_python_lib.egg-info/SOURCES.txt +1 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon_python_lib.egg-info/requires.txt +3 -3
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/README.md +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/setup.cfg +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/cli.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/core/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/core/console.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/core/models.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/core/project.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/core/utils.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/agent/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/agent/main_agent.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/agent/nodes/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/agent/nodes/example_node.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/agent/states/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/agent/states/agent_state.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/api/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/api/query.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/api/sse/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/api/sse/agent.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/db/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/db/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/db/model/entity.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/db/service.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/model/parse.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/agent/tools/mq.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/base/.env.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/base/.gitignore.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/base/Dockerfile.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/base/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/base/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/base/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/base/app.yaml.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/base/client/FileServiceClient.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/base/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/base/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/base/model/file_info.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/base/requirements.txt.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/cli/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/cli/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/cli/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/cli/commands/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/cli/commands/hello.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/cli/pyproject.toml.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/cli/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/web/README.md.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/web/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/web/api/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/web/api/echo.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/web/api/sse/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/web/api/sse/echo.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/web/app.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/web/client/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/web/model/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/web/tools/__init__.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/command/templates/web/tools/mq.py.tpl +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/nexus/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/__main__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/acp/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/acp/config.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/acp/executor.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/acp/registry.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/acp/server.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/agents/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/agents/factory.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/agents/prompts.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/cdp/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/cdp/browser.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/cdp/capabilities/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/cdp/capabilities/console.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/cdp/capabilities/dom.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/cdp/capabilities/network.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/cdp/capabilities/page_errors.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/cdp/capabilities/performance.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/cdp/capabilities/screenshot.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/cdp/client.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/cdp/protocol.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/cdp/repl.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/cli.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/commands/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/commands/acp_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/commands/cdp_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/commands/chat_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/commands/create_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/commands/evaluate_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/commands/init_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/commands/memory_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/commands/resume_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/commands/rollback_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/commands/run_cmd.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/core/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/core/backend.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/core/config.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/core/display.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/core/git_integration.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/core/llm.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/core/state.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/evaluate/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/evaluate/api_evaluator.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/memory/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/memory/compressor.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/memory/full.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/memory/hot.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/memory/manager.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/memory/warm.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/mode/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/mode/create.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/mode/optimize.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/models/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/models/config_models.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/baseline_tests.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/checkpoint.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/convergence.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/diagnosis.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/engine.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/environment.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/experience.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/harness_prompts.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/history.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/optimization_logger.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/pre_validation.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/reward.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/strategy_bandit.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/strategy_generator.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/rl/strategy_prompts.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/simple_chat_agent.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycli/skills/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/acp/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/acp/client.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/acp/fetch.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/acp/ssh_init.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/acp/tool.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/agent_manager.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/chat_events.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/deep_agent.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/mcp/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/mcp/models.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/mcp/tool_loader.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/middleware/model_request_prep.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/middleware/sandbox_path_guard.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/middleware/sensitive_guard.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/middleware/sitecustomize.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/middleware/skill_api_whitelist.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/middleware/skill_wl_check.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/middleware/skill_write_guard.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/multi_agent_team.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/reasoning_content_patch.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/resume_compactor.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/sandbox/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/sandbox/consistent_hash.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/sandbox/minio_sync.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/sandbox/sandbox_pool.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/sandbox/sandbox_recovery.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/sandbox/session.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/summarization_utils.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/auth/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/auth/ldap_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/auth/oa_cache.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/auth/oa_crypto.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/auth/oa_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/ACPAgentConfig.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/Config.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/DatabaseConfig.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/ElasticsearchConfig.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/EmbeddingConfig.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/LLMConfig.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/LangfuseConfig.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/MQConfig.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/PgConfig.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/RedisConfig.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/RerankerConfig.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/SentryConfig.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/SkillApiWhitelistConfig.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/XxlJobConfig.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/config/config_change_notifier.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/database/async_base_db_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/database/async_database_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/database/base_db_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/database/database_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/database/elasticsearch_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/database/pg_checkpoint_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/database/redis_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/database/resilient_pg_saver.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/database/token_usage_db_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/health/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/health/health_check.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/health/metrics.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/health/ping.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/heartbeat_process/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/heartbeat_process/heartbeat_config.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/heartbeat_process/heartbeat_process_manager.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/heartbeat_process/heartbeat_process_worker.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/embedding.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/get_llm.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/llm_logger.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/llm_tokens.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/llm_with_token_tracking.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/native_with_fallback_runnable.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/output_fixing_runnable.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/struct_token.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/sy_langfuse.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/tiktoken_cache/fb374d419588a4632f3f557e76b4b70aebbca790 +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/token_usage_es_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/token_usage_mysql_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/token_utils.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/llm/usage_token.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/logging/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/logging/async_sql_logger.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/logging/kafka_log.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/logging/log_masker.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/logging/logger_levels.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/logging/logger_wrapper.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/logging/process_logger.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/logging/sql_logger.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/mcp_server/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/mcp_server/server.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/context.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/cors.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/docs.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/exception.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/middleware.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/monitor_memory.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/mq.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/timeout.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/token_tracking.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/tool_result_truncation.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/traceid.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/models/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/models/base_http.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/models/log.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/models/mcp_server_config.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/models/mqlistener_config.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/models/mqmsg_model.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/models/mqsend_config.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/models/sso_user.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/models/token_usage.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/models/token_usage_mysql.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/models/xxljob_handler_config.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/notice/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/notice/uvicorn_monitor.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/notice/wecom_message.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/rabbitmq/process_pool_consumer.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/rabbitmq/rabbitmq_client.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/rabbitmq/rabbitmq_pool.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/rabbitmq/rabbitmq_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/rabbitmq/rabbitmq_service_client_manager.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/rabbitmq/rabbitmq_service_connection_monitor.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/rabbitmq/rabbitmq_service_consumer_manager.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/rabbitmq/rabbitmq_service_core.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/rabbitmq/rabbitmq_service_producer_manager.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/sentry/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/sentry/sy_sentry.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/services.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/sse/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/sse/event.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/sse/sse.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/synacos/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/synacos/example.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/synacos/example2.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/synacos/feign.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/synacos/feign_client.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/synacos/nacos_client_base.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/synacos/nacos_config_manager.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/synacos/nacos_heartbeat_manager.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/synacos/nacos_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/synacos/nacos_service_discovery.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/synacos/nacos_service_registration.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/synacos/param.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/deep_agent_server.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_consistent_hash.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_consume_dedup.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_consumer_loss_rootcause.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_consumer_recovery.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_consumer_recovery_fix.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_consumer_tags_sync.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_deep_agent.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_dynamic_max_tokens.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_email.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_encoding_cache.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_exp_concurrent_migrate.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_exp_delete_queue_with_consumers.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_fault_injection_real.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_fix_verification.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_heartbeat_timeout.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_integration_real_broker.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_mcp_server.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_minimax_reasoning.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_mq.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_mq_config_driven.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_oa_login.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_queue_priority_fallback.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_queue_priority_upgrade_timing.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_real_summarization.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_reconnect_scenarios.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_summarization_config.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_summarization_real.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_summary_leak_e2e.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_upgrade_aio_pika.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_upgrade_langgraph_stream.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tests/test_upgrade_verification.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tools/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tools/async_utils.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tools/docs.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tools/env.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tools/merge_headers.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tools/snowflake.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tools/syemail.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/tools/timing.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/xxljob/__init__.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/xxljob/xxljob_service.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon_python_lib.egg-info/dependency_links.txt +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon_python_lib.egg-info/entry_points.txt +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon_python_lib.egg-info/top_level.txt +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_acp_tool.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_asyncio_logging.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_config_change_notifier.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_hotreload_snapshot.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_llm_apikey_contextvar.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_log_masker.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_resilient_pg_saver.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_sandbox_path_guard.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_sensitive_guard.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_simple_chat_agent.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_skill_regex_upgrade.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_skill_write_guard.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_streaming_e2e.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_sycli.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_sync_skills_to_sandbox.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_upload_concurrency.py +0 -0
- {sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/tests/test_upload_e2e_http.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sycommon-python-lib
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8a0
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -9,11 +9,11 @@ Requires-Dist: aiohttp==3.14.3
|
|
|
9
9
|
Requires-Dist: aiomysql==0.3.2
|
|
10
10
|
Requires-Dist: anyio==4.14.2
|
|
11
11
|
Requires-Dist: decorator==5.3.1
|
|
12
|
-
Requires-Dist: deepagents==0.7.
|
|
13
|
-
Requires-Dist: elasticsearch==9.
|
|
12
|
+
Requires-Dist: deepagents==0.7.4
|
|
13
|
+
Requires-Dist: elasticsearch==9.5.0
|
|
14
14
|
Requires-Dist: fastapi==0.141.1
|
|
15
15
|
Requires-Dist: jinja2==3.1.6
|
|
16
|
-
Requires-Dist: kafka-python==3.0.
|
|
16
|
+
Requires-Dist: kafka-python==3.0.10
|
|
17
17
|
Requires-Dist: langchain==1.3.14
|
|
18
18
|
Requires-Dist: langchain-core==1.5.3
|
|
19
19
|
Requires-Dist: langchain-openai==1.4.1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sycommon-python-lib"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.8a0"
|
|
4
4
|
description = "Add your description here"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -10,11 +10,11 @@ dependencies = [
|
|
|
10
10
|
"aiomysql==0.3.2",
|
|
11
11
|
"anyio==4.14.2",
|
|
12
12
|
"decorator==5.3.1",
|
|
13
|
-
"deepagents==0.7.
|
|
14
|
-
"elasticsearch==9.
|
|
13
|
+
"deepagents==0.7.4",
|
|
14
|
+
"elasticsearch==9.5.0",
|
|
15
15
|
"fastapi==0.141.1",
|
|
16
16
|
"jinja2==3.1.6",
|
|
17
|
-
"kafka-python==3.0.
|
|
17
|
+
"kafka-python==3.0.10",
|
|
18
18
|
"langchain==1.3.14",
|
|
19
19
|
"langchain-core==1.5.3",
|
|
20
20
|
"langchain-openai==1.4.1",
|
{sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/agent/sandbox/file_ops.py
RENAMED
|
@@ -389,13 +389,15 @@ class FileOperationsMixin:
|
|
|
389
389
|
)
|
|
390
390
|
# 对齐 deepagents 0.7.1 ReadResult 分页字段:服务端按行切片后回传
|
|
391
391
|
# start_line/end_line/total_lines/next_offset,框架据此渲染分页提示。
|
|
392
|
-
# no_lines_requested(limit<=0 早退):服务端返回空 content
|
|
392
|
+
# no_lines_requested(limit<=0 早退):服务端返回空 content + 该标志;
|
|
393
|
+
# 透传给 ReadResult,让 FilesystemMiddleware 区分「零行窗口」与「空文件」。
|
|
393
394
|
return ReadResult(
|
|
394
395
|
file_data=file_data,
|
|
395
396
|
start_line=result.get("start_line"),
|
|
396
397
|
end_line=result.get("end_line"),
|
|
397
398
|
total_lines=result.get("total_lines"),
|
|
398
399
|
next_offset=result.get("next_offset"),
|
|
400
|
+
no_lines_requested=bool(result.get("no_lines_requested")),
|
|
399
401
|
)
|
|
400
402
|
except Exception as e:
|
|
401
403
|
SYLogger.error(f"[Sandbox] 读取文件异常: {e}")
|
|
@@ -471,12 +473,14 @@ class FileOperationsMixin:
|
|
|
471
473
|
encoding=encoding,
|
|
472
474
|
)
|
|
473
475
|
# 对齐 deepagents 0.7.1 ReadResult 分页字段(与同步 read 一致)。
|
|
476
|
+
# no_lines_requested 透传:区分零行窗口与空文件(见同步版注释)。
|
|
474
477
|
return ReadResult(
|
|
475
478
|
file_data=file_data,
|
|
476
479
|
start_line=result.get("start_line"),
|
|
477
480
|
end_line=result.get("end_line"),
|
|
478
481
|
total_lines=result.get("total_lines"),
|
|
479
482
|
next_offset=result.get("next_offset"),
|
|
483
|
+
no_lines_requested=bool(result.get("no_lines_requested")),
|
|
480
484
|
)
|
|
481
485
|
except Exception as e:
|
|
482
486
|
SYLogger.error(f"[Sandbox] 异步读取文件异常: {e}")
|
|
@@ -60,8 +60,8 @@ class FileDownloadResult:
|
|
|
60
60
|
from sycommon.logging.kafka_log import SYLogger
|
|
61
61
|
from sycommon.agent.sandbox.file_ops import FileOperationsMixin, SANDBOX_API_PREFIX
|
|
62
62
|
|
|
63
|
+
from deepagents.backends.sandbox import BaseSandbox
|
|
63
64
|
from deepagents.backends.protocol import (
|
|
64
|
-
SandboxBackendProtocol,
|
|
65
65
|
ExecuteResponse,
|
|
66
66
|
FileDownloadResponse,
|
|
67
67
|
FileUploadResponse,
|
|
@@ -219,10 +219,24 @@ def filter_instances_by_owner(instances: list, user_id: str, timeout: float = 3.
|
|
|
219
219
|
return filtered
|
|
220
220
|
|
|
221
221
|
|
|
222
|
-
class HTTPSandboxBackend(FileOperationsMixin,
|
|
222
|
+
class HTTPSandboxBackend(FileOperationsMixin, BaseSandbox):
|
|
223
223
|
"""
|
|
224
224
|
通过 HTTP API 连接远程沙箱容器
|
|
225
225
|
|
|
226
|
+
继承 BaseSandbox(而非 SandboxBackendProtocol)以解锁 deepagents
|
|
227
|
+
capture-at-source offload:execute 大输出在沙箱源端截成 head/tail 预览,
|
|
228
|
+
完整结果落盘 /large_tool_results/<tool_call_id>,模型可经 read_file 翻页恢复,
|
|
229
|
+
不必重跑命令。落盘目录由 SandboxRecoveryManager/minio_sync cleanup 兜底清理。
|
|
230
|
+
FileOperationsMixin 在 MRO 最前,read/ls/grep/edit/delete 等仍走本类自定义
|
|
231
|
+
实现(HTTP 远程调用),BaseSandbox 的 shell 默认实现不会被触发。
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
# capture-at-source offload:opt-in,依赖沙箱镜像含 POSIX sh + head/tail/wc/cat。
|
|
235
|
+
# 生产 Linux 沙箱走 bash heredoc 执行命令(见 _build_execute_command),必然满足。
|
|
236
|
+
enable_capture_offload = True
|
|
237
|
+
|
|
238
|
+
"""
|
|
239
|
+
|
|
226
240
|
支持两种模式:
|
|
227
241
|
1. 直接 URL: 直接指定沙箱服务地址
|
|
228
242
|
2. Nacos 服务发现: 通过服务名从 Nacos 获取实例(支持自动故障转移)
|
{sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/auth/wecom_ldap_service.py
RENAMED
|
@@ -26,6 +26,7 @@ from pydantic import BaseModel
|
|
|
26
26
|
|
|
27
27
|
from sycommon.config.Config import SingletonMeta
|
|
28
28
|
from sycommon.logging.kafka_log import SYLogger
|
|
29
|
+
from sycommon.tools.user_id import normalize_user_id
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
# ─── 模型定义 ───
|
|
@@ -70,6 +71,16 @@ class LDAPFullUser(BaseModel):
|
|
|
70
71
|
ou_chain: List[str] = [] # OU 层级路径
|
|
71
72
|
|
|
72
73
|
|
|
74
|
+
# match_method -> 可信度(越大越可信)。用于域账号冲突时择优保留正确映射。
|
|
75
|
+
# 中文名唯一命中(by_cn len==1)最可信;英文名前缀(by_sam_prefix)最易误命中。
|
|
76
|
+
_MATCH_TRUST: dict = {
|
|
77
|
+
"chinese_name": 30,
|
|
78
|
+
"english_name_surname": 20,
|
|
79
|
+
"english_name_position": 15,
|
|
80
|
+
"english_name": 10,
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
73
84
|
class WeComLDAPUser(BaseModel):
|
|
74
85
|
"""企微-LDAP 关联用户(最终返回结果)"""
|
|
75
86
|
|
|
@@ -92,7 +103,7 @@ class _LDAPIndex:
|
|
|
92
103
|
|
|
93
104
|
def __init__(self):
|
|
94
105
|
# cn(中文名) -> LDAPFullUser
|
|
95
|
-
self.by_cn: Dict[str, LDAPFullUser] =
|
|
106
|
+
self.by_cn: Dict[str, List[LDAPFullUser]] = defaultdict(list)
|
|
96
107
|
# sAMAccountName 前缀(小写) -> [LDAPFullUser]
|
|
97
108
|
self.by_sam_prefix: Dict[str, List[LDAPFullUser]] = defaultdict(list)
|
|
98
109
|
# "en_prefix.sn_pinyin" -> [LDAPFullUser]
|
|
@@ -130,8 +141,9 @@ class _LDAPIndex:
|
|
|
130
141
|
dn=dn or None,
|
|
131
142
|
ou_chain=ou_chain,
|
|
132
143
|
)
|
|
133
|
-
# 中文名 key
|
|
134
|
-
|
|
144
|
+
# 中文名 key 小写化;同名(如两个"张伟"、内地+香港重复账号)保留多候选,
|
|
145
|
+
# 由 lookup 做唯一性校验,避免后写覆盖前写导致同名两人 resolve 到同一域账号串会话。
|
|
146
|
+
self.by_cn[cn.lower()].append(ldap_user)
|
|
135
147
|
|
|
136
148
|
# sAMAccountName 如 "sussie.xia" -> 前缀 "sussie"(小写)
|
|
137
149
|
prefix = sam.split(".")[0].lower()
|
|
@@ -164,9 +176,13 @@ class _LDAPIndex:
|
|
|
164
176
|
Returns:
|
|
165
177
|
(LDAPFullUser | None, match_method | None)
|
|
166
178
|
"""
|
|
167
|
-
#
|
|
168
|
-
|
|
169
|
-
|
|
179
|
+
# 第一优先级:中文名直接匹配(小写化比较)。
|
|
180
|
+
# 🔑 唯一性校验:LDAP 里同名(cn 相同)多人时返回 None,绝不让"后写覆盖前写"
|
|
181
|
+
# 把同名两人 resolve 到同一个域账号——那会导致企微 agent/沙箱/checkpoint 全维度串。
|
|
182
|
+
# 多候选时不命中,由调用方回退到各自原始 wecom_userid(独立、不串)。
|
|
183
|
+
cn_candidates = self.by_cn.get(chinese_name.lower(), [])
|
|
184
|
+
if len(cn_candidates) == 1:
|
|
185
|
+
return cn_candidates[0], "chinese_name"
|
|
170
186
|
|
|
171
187
|
en_first = english_name.lower().split()[0] if english_name else ""
|
|
172
188
|
|
|
@@ -660,12 +676,74 @@ class WeComLDAPService(metaclass=SingletonMeta):
|
|
|
660
676
|
result.employee_id = result.wecom_userid
|
|
661
677
|
results.append(result)
|
|
662
678
|
|
|
679
|
+
# 3. 🔑 全量域账号唯一性校验(根治串会话):
|
|
680
|
+
# 单看每个用户的匹配都没错,但多个企微用户可能因中文名/英文名交叉匹配撞到
|
|
681
|
+
# 同一 LDAP 域账号(实测 Derrick.zhang 被「张仲都」中文名匹配 +「Derrick Du」
|
|
682
|
+
# 英文名匹配同时占用)。扫一遍匹配结果,若同一域账号被 ≥2 个企微用户占用,
|
|
683
|
+
# 把这些人的 matched 全部降级为 False(回退各自工号,独立、不串)。
|
|
684
|
+
self._dedup_ldap_conflicts(results)
|
|
685
|
+
|
|
663
686
|
matched = sum(1 for r in results if r.matched)
|
|
664
687
|
logging.info(
|
|
665
|
-
f"[WeComLDAP] 全量匹配完成: {matched}/{len(results)} 已关联"
|
|
666
|
-
)
|
|
688
|
+
f"[WeComLDAP] 全量匹配完成: {matched}/{len(results)} 已关联")
|
|
667
689
|
return results
|
|
668
690
|
|
|
691
|
+
@staticmethod
|
|
692
|
+
def _dedup_ldap_conflicts(results: List["WeComLDAPUser"]) -> None:
|
|
693
|
+
"""就地消解「同一域账号被多个企微用户占用」的匹配,保证域账号唯一占用。
|
|
694
|
+
|
|
695
|
+
策略:按匹配可信度择优保留,只降级不可信者(而非全部降级)——这样既治串
|
|
696
|
+
(误命中者不再占用别人的域账号),又不误伤正确映射(保企微/Web 沙箱一致)。
|
|
697
|
+
|
|
698
|
+
可信度排序(match_method 决定):
|
|
699
|
+
chinese_name(中文名唯一命中) > english_name_surname(英文名+姓拼音)
|
|
700
|
+
> english_name_position > english_name(英文名前缀,最易误命中)
|
|
701
|
+
冲突组内:保留可信度最高者;若最高者并列(如两人都是中文名,不可能——中文名
|
|
702
|
+
同名已被 by_cn 唯一性校验挡掉)或最高也是低可信(都是 english_name),则全部降级。
|
|
703
|
+
|
|
704
|
+
为什么不全降级:企微与 Web 共用域账号体系,同一人企微/Web userid 必须一致
|
|
705
|
+
(沙箱目录、文件互通)。中文名唯一匹配者几乎确定是真主,降级他会破坏跨端一致性。
|
|
706
|
+
"""
|
|
707
|
+
from collections import defaultdict
|
|
708
|
+
# match_method -> 可信度,复用模块级 _MATCH_TRUST(与 resolve_unified_user_id
|
|
709
|
+
# 单点校验用同一份,避免两条择优路径阈值漂移导致「实时降级、全量保留」抖动)
|
|
710
|
+
TRUST = _MATCH_TRUST
|
|
711
|
+
ldap_to_users: dict = defaultdict(list)
|
|
712
|
+
for r in results:
|
|
713
|
+
if r.matched and r.ldap_user and r.ldap_user.username:
|
|
714
|
+
ldap_to_users[r.ldap_user.username.lower()].append(r)
|
|
715
|
+
for ldap_uname, group in ldap_to_users.items():
|
|
716
|
+
if len(group) <= 1:
|
|
717
|
+
continue
|
|
718
|
+
# 计算每人可信度,找最高
|
|
719
|
+
scored = [(TRUST.get(r.match_method, 0), idx, r)
|
|
720
|
+
for idx, r in enumerate(group)]
|
|
721
|
+
max_trust = max(s[0] for s in scored)
|
|
722
|
+
# 仅当「最高可信者唯一」且「最高可信度 >= chinese_name」才保留它
|
|
723
|
+
# (中文名唯一命中几乎确定真主;英文名前缀即使唯一也不足以独占,全降级)
|
|
724
|
+
winners = [s[2] for s in scored if s[0] == max_trust]
|
|
725
|
+
if len(winners) == 1 and max_trust >= TRUST["chinese_name"]:
|
|
726
|
+
keep = winners[0]
|
|
727
|
+
downgraded = [r for r in group if r is not keep]
|
|
728
|
+
owners = ", ".join(
|
|
729
|
+
f"{r.wecom_userid}({r.wecom_name}/{r.match_method})" for r in group)
|
|
730
|
+
SYLogger.warning(
|
|
731
|
+
f"[WeComLDAP] 🟡域账号冲突择优: ldap={ldap_uname} [{owners}],"
|
|
732
|
+
f"保留可信度最高 {keep.wecom_userid}({keep.match_method}),"
|
|
733
|
+
f"降级其余 {len(downgraded)} 人回退工号")
|
|
734
|
+
else:
|
|
735
|
+
# 最高者并列、或最高也是低可信 → 全部降级(无法判断真主)
|
|
736
|
+
downgraded = list(group)
|
|
737
|
+
owners = ", ".join(
|
|
738
|
+
f"{r.wecom_userid}({r.wecom_name}/{r.match_method})" for r in group)
|
|
739
|
+
SYLogger.warning(
|
|
740
|
+
f"[WeComLDAP] 🔴域账号冲突全降级: ldap={ldap_uname} [{owners}],"
|
|
741
|
+
f"最高可信度={max_trust}不足,全部降级回退工号(不串)")
|
|
742
|
+
for r in downgraded:
|
|
743
|
+
r.matched = False
|
|
744
|
+
r.match_method = None
|
|
745
|
+
r.ldap_user = None
|
|
746
|
+
|
|
669
747
|
async def refresh_cache(self):
|
|
670
748
|
"""手动刷新缓存(access_token + LDAP 索引 + 部门映射)"""
|
|
671
749
|
self._access_token = None
|
|
@@ -732,6 +810,21 @@ class WeComLDAPService(metaclass=SingletonMeta):
|
|
|
732
810
|
pass
|
|
733
811
|
return None
|
|
734
812
|
|
|
813
|
+
async def _get_cached_mapping_reverse(self, unified_id: str) -> Optional[str]:
|
|
814
|
+
"""从 Redis 反查 unified_id(域账号) -> 占用它的 wecom_userid(工号)。
|
|
815
|
+
|
|
816
|
+
用于 resolve_unified_user_id 的域账号唯一性校验:若某域账号已被别的企微工号
|
|
817
|
+
占用,说明多人撞到同一域账号(串会话风险),需降级。
|
|
818
|
+
"""
|
|
819
|
+
try:
|
|
820
|
+
rs = self._get_redis()
|
|
821
|
+
val = await rs.get(f"{self._LDAP_TO_WECOM_PREFIX}{unified_id}")
|
|
822
|
+
if val:
|
|
823
|
+
return val
|
|
824
|
+
except Exception:
|
|
825
|
+
pass
|
|
826
|
+
return None
|
|
827
|
+
|
|
735
828
|
async def _set_cached_mapping(self, wecom_userid: str, unified_id: str):
|
|
736
829
|
"""将 wecom_userid <-> unified_id 双向映射写入 Redis,同时保存工号"""
|
|
737
830
|
try:
|
|
@@ -800,13 +893,17 @@ class WeComLDAPService(metaclass=SingletonMeta):
|
|
|
800
893
|
# 2. 查企微 + LDAP
|
|
801
894
|
unified_id = wecom_userid
|
|
802
895
|
employee_id = wecom_userid # 默认用工号就是原始 userid
|
|
896
|
+
matched_ldap_username = None # 真正匹配到的域账号(用于唯一性校验)
|
|
897
|
+
match_method = None # 匹配方法(决定可信度)
|
|
803
898
|
try:
|
|
804
899
|
result = await self.get_user_info(wecom_userid)
|
|
805
900
|
employee_id = result.wecom_userid # get_user_info 返回解码后的明文工号
|
|
806
901
|
if result.matched and result.ldap_user and result.ldap_user.username:
|
|
807
|
-
|
|
902
|
+
matched_ldap_username = result.ldap_user.username
|
|
903
|
+
match_method = result.match_method
|
|
904
|
+
unified_id = matched_ldap_username
|
|
808
905
|
SYLogger.info(
|
|
809
|
-
f"[WeComLDAP] 用户映射: wecom={wecom_userid} -> ldap={unified_id}")
|
|
906
|
+
f"[WeComLDAP] 用户映射: wecom={wecom_userid} -> ldap={unified_id} ({match_method})")
|
|
810
907
|
else:
|
|
811
908
|
SYLogger.info(
|
|
812
909
|
f"[WeComLDAP] 用户映射: wecom={wecom_userid} -> 未匹配LDAP,回退={unified_id}")
|
|
@@ -814,9 +911,51 @@ class WeComLDAPService(metaclass=SingletonMeta):
|
|
|
814
911
|
SYLogger.warning(
|
|
815
912
|
f"[WeComLDAP] 解析统一 user_id 失败: wecom_userid={wecom_userid}, error={e}")
|
|
816
913
|
|
|
817
|
-
# 3.
|
|
818
|
-
|
|
819
|
-
|
|
914
|
+
# 3. 🔑 域账号唯一性校验(根治串会话,按可信度择优):
|
|
915
|
+
# 多个企微用户可能因中文名/英文名交叉匹配撞到同一域账号。这里在写入缓存前
|
|
916
|
+
# 做反向校验:查 Redis 该域账号是否已被别的企微工号占用。若被占用,按可信度
|
|
917
|
+
# 择优——中文名唯一匹配(最可信)优先保留,英文名前缀(最易误命中)让步降级。
|
|
918
|
+
# 这样既治串又不误伤正确映射(保企微/Web 沙箱一致)。
|
|
919
|
+
if matched_ldap_username:
|
|
920
|
+
normalized_ldap = normalize_user_id(matched_ldap_username)
|
|
921
|
+
owner = await self._get_cached_mapping_reverse(normalized_ldap)
|
|
922
|
+
if owner and owner != employee_id:
|
|
923
|
+
# 该域账号已被别的企微工号占用 → 冲突,按可信度择优
|
|
924
|
+
my_trust = _MATCH_TRUST.get(match_method, 0)
|
|
925
|
+
if my_trust >= _MATCH_TRUST["chinese_name"]:
|
|
926
|
+
# 我是高可信(中文名唯一命中)→ 我才是真主,保留本次映射。
|
|
927
|
+
# 🔑 必须同时 DEL 掉低可信者(owner)残留在 Redis 的【正向】映射
|
|
928
|
+
# wecom_uid_map:{owner}=ldap,否则 owner 下次 resolve 会 L2 正向命中
|
|
929
|
+
# 直接返回 ldap、跳过本段反向校验 → 错误映射存活到次日定时任务才修
|
|
930
|
+
# → 期间两人共享 thread_id 串会话(最长 24h)。删后 owner 下次 L2 miss
|
|
931
|
+
# 走慢路径自查、发现自己被高可信者占用而降级。
|
|
932
|
+
try:
|
|
933
|
+
rs = self._get_redis()
|
|
934
|
+
await rs.delete(f"{self._UID_MAP_PREFIX}{owner}")
|
|
935
|
+
# L1 是进程内、无法跨进程清,但 owner 多半是别的请求/进程;
|
|
936
|
+
# 其 L1 5min TTL 自然过期即可。
|
|
937
|
+
except Exception:
|
|
938
|
+
pass
|
|
939
|
+
SYLogger.warning(
|
|
940
|
+
f"[WeComLDAP] 🟡域账号冲突择优: ldap={normalized_ldap} "
|
|
941
|
+
f"已被 wecom={owner} 占用,但本次 wecom={employee_id} "
|
|
942
|
+
f"可信度更高({match_method}),保留本次映射并清除 {owner} 的正向缓存")
|
|
943
|
+
else:
|
|
944
|
+
# 我是低可信(英文名前缀等)→ 让步降级,回退自己的工号
|
|
945
|
+
SYLogger.warning(
|
|
946
|
+
f"[WeComLDAP] 🔴域账号冲突降级: ldap={normalized_ldap} "
|
|
947
|
+
f"已被 wecom={owner} 占用,本次 wecom={employee_id} "
|
|
948
|
+
f"可信度不足({match_method}),降级回退工号(不串)")
|
|
949
|
+
unified_id = employee_id
|
|
950
|
+
matched_ldap_username = None
|
|
951
|
+
|
|
952
|
+
# 4. 写入 Redis 缓存(统一小写)
|
|
953
|
+
# 降级时不写正向 wecom→ldap(避免错误映射固化),只写 wecom→工号。
|
|
954
|
+
unified_id = normalize_user_id(unified_id)
|
|
955
|
+
if matched_ldap_username:
|
|
956
|
+
await self._set_cached_mapping(employee_id, unified_id)
|
|
957
|
+
else:
|
|
958
|
+
await self._set_cached_mapping(employee_id, employee_id)
|
|
820
959
|
|
|
821
960
|
# 写入 L1
|
|
822
961
|
self._resolve_cache[wecom_userid] = (
|
|
@@ -834,7 +973,7 @@ class WeComLDAPService(metaclass=SingletonMeta):
|
|
|
834
973
|
"""
|
|
835
974
|
try:
|
|
836
975
|
rs = self._get_redis()
|
|
837
|
-
uid = unified_id
|
|
976
|
+
uid = normalize_user_id(unified_id)
|
|
838
977
|
val = await rs.get(f"{self._EMPLOYEE_ID_PREFIX}{uid}")
|
|
839
978
|
if val:
|
|
840
979
|
return val
|
|
@@ -855,7 +994,7 @@ class WeComLDAPService(metaclass=SingletonMeta):
|
|
|
855
994
|
client = rs.get_client()
|
|
856
995
|
async with client.pipeline(transaction=True) as pipe:
|
|
857
996
|
for wecom_userid, unified_id in mapping.items():
|
|
858
|
-
uid = unified_id
|
|
997
|
+
uid = normalize_user_id(unified_id)
|
|
859
998
|
# 正向
|
|
860
999
|
pipe.set(f"{self._UID_MAP_PREFIX}{wecom_userid}",
|
|
861
1000
|
uid, ex=self._MAP_TTL)
|
{sycommon_python_lib-0.2.7a55 → sycommon_python_lib-0.2.8a0}/src/sycommon/middleware/sandbox.py
RENAMED
|
@@ -340,6 +340,10 @@ _GREP_TIMEOUT = 60
|
|
|
340
340
|
# read 文本路径服务端字节上限(对齐 deepagents _READ_COMMAND_TEMPLATE 的
|
|
341
341
|
# MAX_OUTPUT_BYTES=500KiB):超大文本文件不会把整包塞进 HTTP 响应/内存。
|
|
342
342
|
_READ_MAX_OUTPUT_BYTES = 500 * 1024
|
|
343
|
+
# read 提前停止后补数 total_lines 的文件大小闸门(对齐 deepagents sandbox.py:499
|
|
344
|
+
# MAX_LINE_COUNT_BYTES=1MiB):超过此大小的文件不数总行数(total_lines=None),
|
|
345
|
+
# 避免 GB 级文件的逐行计数把 read 拖成慢操作。
|
|
346
|
+
_READ_TOTAL_LINE_MAX_BYTES = 1024 * 1024
|
|
343
347
|
# 默认工作目录配置
|
|
344
348
|
# - Linux: /data/sycommon_sandbox (固定路径,自动创建)
|
|
345
349
|
# - macOS/Windows: 使用系统临时目录
|
|
@@ -443,9 +447,16 @@ cd "$SANDBOX_ROOT"
|
|
|
443
447
|
'''
|
|
444
448
|
|
|
445
449
|
def _sanitize_user_id(user_id: str) -> str:
|
|
446
|
-
"""
|
|
450
|
+
"""将用户名归一化(lower + 去空格)并把其余特殊字符替换为下划线,确保路径安全。
|
|
451
|
+
|
|
452
|
+
用 normalize_user_id 做第一步(与主项目/企微端同一份归一化,保证同一人在
|
|
453
|
+
沙箱侧的工作目录与主项目侧的 user_id 一致 → 企微/Web 沙箱目录互通),
|
|
454
|
+
再把剩余不安全字符替换为下划线。
|
|
455
|
+
"""
|
|
447
456
|
import re
|
|
448
|
-
|
|
457
|
+
from sycommon.tools.user_id import normalize_user_id
|
|
458
|
+
norm = normalize_user_id(user_id)
|
|
459
|
+
return re.sub(r'[^a-zA-Z0-9._\-]', '_', norm)
|
|
449
460
|
|
|
450
461
|
|
|
451
462
|
def get_user_workspace(user_id: str) -> str:
|
|
@@ -1020,8 +1031,10 @@ def setup_sandbox_handler(app: FastAPI, config: dict = None):
|
|
|
1020
1031
|
|
|
1021
1032
|
# limit<=0:协议 no_lines_requested —— 不读文件,返回空内容 + 标志位,
|
|
1022
1033
|
# 不带任何分页字段(客户端填 ReadResult.no_lines_requested=True)。
|
|
1034
|
+
# 对齐 deepagents _build_read_cmd 的 limit<=0 早退分支。区别于空文件
|
|
1035
|
+
# (空文件走上面的 "File exists but has empty contents" 提示)。
|
|
1023
1036
|
if limit is not None and limit <= 0:
|
|
1024
|
-
return ReadResponse(content="", error=None, encoding="utf-8")
|
|
1037
|
+
return ReadResponse(content="", error=None, encoding="utf-8", no_lines_requested=True)
|
|
1025
1038
|
|
|
1026
1039
|
lines = []
|
|
1027
1040
|
lines_read = 0
|
|
@@ -1075,12 +1088,18 @@ def setup_sandbox_handler(app: FastAPI, config: dict = None):
|
|
|
1075
1088
|
next_offset = None
|
|
1076
1089
|
else:
|
|
1077
1090
|
# 提前停止(limit 到顶 / 字节截断):需要 total_lines 才能算「剩余」。
|
|
1078
|
-
#
|
|
1079
|
-
# (对齐 deepagents
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1091
|
+
# 大文件全量计数代价高——先比 st_size 与 _READ_TOTAL_LINE_MAX_BYTES
|
|
1092
|
+
# (对齐 deepagents sandbox.py:499 的 MAX_LINE_COUNT_BYTES=1MiB 闸门),
|
|
1093
|
+
# 超过则不数(返回 None,next_offset 退化为 end_line),避免无界扫描
|
|
1094
|
+
# 把 read 变成对 GB 级文件的逐行计数慢操作。
|
|
1095
|
+
file_size = os.path.getsize(file_path)
|
|
1096
|
+
if file_size <= _READ_TOTAL_LINE_MAX_BYTES:
|
|
1097
|
+
try:
|
|
1098
|
+
with open(file_path, 'r', encoding='utf-8', newline=None) as f:
|
|
1099
|
+
total_lines = sum(1 for _ in f)
|
|
1100
|
+
except OSError:
|
|
1101
|
+
total_lines = None
|
|
1102
|
+
else:
|
|
1084
1103
|
total_lines = None
|
|
1085
1104
|
# next_offset = end_line(0-indexed 下一行 = 1-indexed 末行号),
|
|
1086
1105
|
# 仅当确实还有后续行时设置;否则视为读到末尾。
|
|
@@ -1717,19 +1736,65 @@ def setup_sandbox_handler(app: FastAPI, config: dict = None):
|
|
|
1717
1736
|
grep_opts = "-rHnFZ" if use_null_separator else "-rHnF"
|
|
1718
1737
|
|
|
1719
1738
|
# 安全处理 glob_pattern,使用 shlex.quote 防止命令注入
|
|
1720
|
-
glob_pattern = f"--include={shlex.quote(req.glob)}" if req.glob else ""
|
|
1721
1739
|
pattern_escaped = shlex.quote(req.pattern)
|
|
1722
1740
|
|
|
1723
|
-
#
|
|
1724
|
-
|
|
1741
|
+
# glob 含 '/'(如 src/**/*.py)时,GNU grep --include 只匹配 basename,
|
|
1742
|
+
# 会静默返回 0 条(对齐 deepagents sandbox.py:684 _build_grep_cmd 的判定)。
|
|
1743
|
+
# 这种路径 glob 改走 Python glob 预筛文件清单 + grep -F 逐文件/批量,
|
|
1744
|
+
# 避免「带路径 glob 搜不到东西」的隐蔽 bug。
|
|
1745
|
+
path_glob = req.glob
|
|
1746
|
+
use_path_glob = bool(path_glob and "/" in path_glob)
|
|
1747
|
+
if not use_path_glob:
|
|
1748
|
+
glob_pattern = f"--include={shlex.quote(req.glob)}" if req.glob else ""
|
|
1749
|
+
# 注意:不再用 2>/dev/null || true,以便捕获 stderr 用于错误诊断
|
|
1750
|
+
cmd = f"grep {grep_opts} {glob_pattern} -e {pattern_escaped} {quoted_path}"
|
|
1751
|
+
else:
|
|
1752
|
+
glob_pattern = "" # 不用 --include;文件清单由 Python glob 预筛后喂给 grep
|
|
1753
|
+
|
|
1725
1754
|
# 对齐 deepagents 0.7.1 max_count:服务端用 head 早停,多取 1 条用于判断是否截断。
|
|
1726
1755
|
# (grep -r 没有真正的全局计数上限,head -n N+1 截 stdout 后,客户端按 N 裁剪、
|
|
1727
1756
|
# 超过即 truncated=True。与 deepagents BaseSandbox._build_grep_cmd 同款思路。)
|
|
1728
1757
|
max_count = req.max_count
|
|
1729
|
-
if max_count is not None and max_count >= 0:
|
|
1758
|
+
if not use_path_glob and max_count is not None and max_count >= 0:
|
|
1730
1759
|
# || true 兜底 SIGPIPE(head 读够后关闭管道,grep 收到 SIGPIPE 退出码非 0)
|
|
1731
1760
|
cmd = f"{cmd} | head -n {int(max_count) + 1} || true"
|
|
1732
1761
|
|
|
1762
|
+
# 含路径 glob 的分支:Python glob 预筛出匹配文件清单(仅文件,递归),
|
|
1763
|
+
# 经 xargs 批量喂给 grep -F。沿用 -Z/-Hn 与正文相同的 NUL/冒号解析,故
|
|
1764
|
+
# 下游 _parse_grep_results 无需改动。文件清单为空时直接返回 0 条,避免起
|
|
1765
|
+
# `grep -e pat`(无文件参数)误把 stdin 当搜索源。
|
|
1766
|
+
def _resolve_path_glob_files():
|
|
1767
|
+
import glob as glob_module
|
|
1768
|
+
full_pattern = os.path.join(search_path, path_glob)
|
|
1769
|
+
try:
|
|
1770
|
+
files = sorted(glob_module.glob(full_pattern, recursive=True))
|
|
1771
|
+
except (FileNotFoundError, NotADirectoryError, PermissionError) as e:
|
|
1772
|
+
SYLogger.warning(f"[Sandbox Server] grep 路径 glob 异常: {e}")
|
|
1773
|
+
return []
|
|
1774
|
+
workspace_resolved_g = os.path.realpath(workspace)
|
|
1775
|
+
safe = []
|
|
1776
|
+
for m in files:
|
|
1777
|
+
if os.path.isdir(m):
|
|
1778
|
+
continue # grep 按文件搜,目录跳过
|
|
1779
|
+
try:
|
|
1780
|
+
if not _is_path_within(m, workspace_resolved_g):
|
|
1781
|
+
continue
|
|
1782
|
+
except OSError:
|
|
1783
|
+
continue
|
|
1784
|
+
safe.append(m)
|
|
1785
|
+
return safe
|
|
1786
|
+
|
|
1787
|
+
if use_path_glob:
|
|
1788
|
+
path_glob_files = await asyncio.to_thread(_resolve_path_glob_files)
|
|
1789
|
+
if not path_glob_files:
|
|
1790
|
+
return GrepResponse(matches=[])
|
|
1791
|
+
# xargs -0:文件名以 NUL 分隔喂入,文件名含空格/引号/换行也安全。
|
|
1792
|
+
# find ... -print0 | grep -FZne pattern --files-from=... 也行,但 xargs 最 portable。
|
|
1793
|
+
files_argv = " ".join(shlex.quote(f) for f in path_glob_files)
|
|
1794
|
+
# 不加 -r(已显式给文件清单,无需递归);保留 -H(始终带文件名) -n(行号) -F(字面量) -Z(NUL)。
|
|
1795
|
+
path_glob_grep_opts = "-HnFZ" if use_null_separator else "-HnF"
|
|
1796
|
+
cmd = f"printf '%s\\0' {files_argv} | xargs -0 grep {path_glob_grep_opts} -e {pattern_escaped}"
|
|
1797
|
+
|
|
1733
1798
|
# 使用 asyncio.create_subprocess_shell 异步执行
|
|
1734
1799
|
proc = await asyncio.create_subprocess_shell(
|
|
1735
1800
|
cmd,
|
|
@@ -1824,6 +1889,7 @@ def setup_sandbox_handler(app: FastAPI, config: dict = None):
|
|
|
1824
1889
|
|
|
1825
1890
|
matches = await asyncio.to_thread(_parse_grep_results)
|
|
1826
1891
|
# 对齐 deepagents 0.7.1:超出 max_count 即置 truncated(多取的 1 条在这里裁掉)。
|
|
1892
|
+
# 路径 glob 分支没在服务端 head 早停(直接 grep 文件清单),这里统一兜底裁剪。
|
|
1827
1893
|
truncated = False
|
|
1828
1894
|
if max_count is not None and len(matches) > max_count:
|
|
1829
1895
|
matches = matches[:max_count]
|
|
@@ -143,6 +143,11 @@ class ReadResponse(BaseModel):
|
|
|
143
143
|
end_line: Optional[int] = None
|
|
144
144
|
total_lines: Optional[int] = None
|
|
145
145
|
next_offset: Optional[int] = None
|
|
146
|
+
# limit<=0 早退标志(对齐 deepagents ReadResult.no_lines_requested):
|
|
147
|
+
# True 表示「文件未检视、零行窗口」,与「空文件」区分开。客户端据此
|
|
148
|
+
# 填 ReadResult.no_lines_requested,让 FilesystemMiddleware 给出与框架
|
|
149
|
+
# 合成实现一致的分页提示(NO_LINES_REQUESTED_WARNING)而非空文件提示。
|
|
150
|
+
no_lines_requested: bool = False
|
|
146
151
|
|
|
147
152
|
|
|
148
153
|
class WriteRequest(BaseModel):
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""用户标识派生(跨服务共享)。
|
|
2
|
+
|
|
3
|
+
本模块是【唯一】的用户标识派生入口,主项目和沙箱项目都必须从这里导入,保证
|
|
4
|
+
同一人在不同服务/不同接口派生出【同一个】标识:
|
|
5
|
+
|
|
6
|
+
- 沙箱目录一致(企微传的文件 Web 能看到,反之亦然)
|
|
7
|
+
- MinIO 对象 key / PG checkpointer thread_id / Redis key 全部一致
|
|
8
|
+
|
|
9
|
+
提供两类标识:
|
|
10
|
+
|
|
11
|
+
1. **常规标识 user_id**(``normalize_user_id``):取自 LDAP 域账号,用于沙箱目录、
|
|
12
|
+
MinIO key、PG thread_id、LLM apiKey、大部分 Redis key。
|
|
13
|
+
规则:``lower()`` + 去全部空格。
|
|
14
|
+
|
|
15
|
+
2. **边界标识 redis_uid**(``redis_uid_from_str`` / ``redis_uid_from_user``):用于
|
|
16
|
+
跨越「登录侧」与「POST /api/token 回调侧」的两个 Redis key ——
|
|
17
|
+
``digital_work:user_token:{redis_uid}`` 和 ``digital_work:pending_auth_retry:{redis_uid}``。
|
|
18
|
+
为什么单独一层:``/api/token`` 是无登录态回调,只能从请求体 email 反推用户
|
|
19
|
+
(``email.split("@")[0]``);而登录侧拿到的是 ``LDAPUser.username``(域账号)。
|
|
20
|
+
两者要落到同一个 Redis key,必须用同一套归一化规则。历史上两边各自写死,靠
|
|
21
|
+
「域账号 == 邮箱本地名」的隐含约定;一旦某员工两者不一致(域账号 ``lisi``、
|
|
22
|
+
邮箱 ``li.si@…``)就断链——token 写到了读侧永远查不到的 key 下,表现为
|
|
23
|
+
「已授权却报未授权」。集中到一处彻底消除该隐含约定。
|
|
24
|
+
"""
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from typing import Any
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def normalize_user_id(s: str | None) -> str:
|
|
31
|
+
"""把域账号/登录名归一化成统一的 user_id:lower() + 去全部空格。
|
|
32
|
+
|
|
33
|
+
主项目(api/chat.py、files.py、redis_session.py、health.py)与企微
|
|
34
|
+
(wecom_ldap_service.resolve_unified_user_id)都用它,消除各自硬编码
|
|
35
|
+
``.lower().replace(" ","")`` 的散落写法,避免一处漏改导致两端不一致
|
|
36
|
+
→ 沙箱目录错位 → 企微/Web 文件不互通。
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
s: 域账号(sAMAccountName)或登录名,可能带大小写/空格。
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
归一化后的 user_id(小写、无空格);入参为空返回 ``""``。
|
|
43
|
+
"""
|
|
44
|
+
if not s:
|
|
45
|
+
return ""
|
|
46
|
+
return s.lower().replace(" ", "")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def redis_uid_from_str(s: str | None) -> str:
|
|
50
|
+
"""把字符串归一化成边界键用的 redis_uid。
|
|
51
|
+
|
|
52
|
+
规则:取 ``@`` 前的邮箱本地名,再 ``lower()`` + 去空格。
|
|
53
|
+
与 ``POST /api/token`` 写入侧(``email.split("@")[0]``)完全对齐。
|
|
54
|
+
|
|
55
|
+
- ``"Zhang.San@shengye.com"`` → ``"zhang.san"``
|
|
56
|
+
- ``"lisi@shengye.com"`` → ``"lisi"``
|
|
57
|
+
- ``"lisi"``(无 @) → ``"lisi"``(原样归一化)
|
|
58
|
+
- ``""`` / ``None`` → ``""``
|
|
59
|
+
"""
|
|
60
|
+
if not s:
|
|
61
|
+
return ""
|
|
62
|
+
return s.split("@")[0].lower().replace(" ", "")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def redis_uid_from_user(user: Any) -> str:
|
|
66
|
+
"""从 LDAPUser(或带 email/username 属性的对象)派生边界键用的 redis_uid。
|
|
67
|
+
|
|
68
|
+
优先取 ``email`` 的本地名;无 email 时回退 ``username``(= 现状,
|
|
69
|
+
不会比改动前更差——改动前所有读侧本来就用 username)。
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
user: ``sycommon.auth.LDAPUser`` 实例,或 ``None``。
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
归一化后的 redis_uid 字符串;入参为 ``None`` 时返回 ``""``。
|
|
76
|
+
"""
|
|
77
|
+
if user is None:
|
|
78
|
+
return ""
|
|
79
|
+
raw = getattr(user, "email", None) or getattr(user, "username", "") or ""
|
|
80
|
+
return redis_uid_from_str(raw)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def make_thread_id(user_id: str, session_id: str | None) -> str:
|
|
84
|
+
"""构造 LangGraph checkpointer 的 thread_id(Web 端会话隔离核心)。
|
|
85
|
+
|
|
86
|
+
规则:``session_id`` 非空 → ``f"{user_id}:{session_id}"``;为空 → ``user_id``。
|
|
87
|
+
这是 PG checkpoint 表里【唯一】的用户隔离维度(langgraph 按
|
|
88
|
+
``WHERE thread_id = %s`` 读写),两个请求 thread_id 相同 = 共用同一对话历史。
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
user_id: 已归一化的 user_id(``normalize_user_id`` 产物)。
|
|
92
|
+
session_id: 前端会话 ID。为空/None 时退化为单会话模式(thread_id=user_id)。
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
thread_id 字符串。
|
|
96
|
+
|
|
97
|
+
⚠️ 调用方职责:
|
|
98
|
+
- user_id 必须先经 normalize_user_id 归一化(否则大小写/空格漂移会串)。
|
|
99
|
+
- session_id 的唯一性由前端保证;后端不强制,但若前端重复传同一 session_id,
|
|
100
|
+
同一用户的两会话会合并历史(前端 bug 即后端串)。如需更强隔离,可在
|
|
101
|
+
session_id 为空时强制生成 uuid(当前保持「退化为 user_id」的旧行为,不破坏
|
|
102
|
+
既有单会话语义)。
|
|
103
|
+
"""
|
|
104
|
+
if session_id:
|
|
105
|
+
return f"{user_id}:{session_id}"
|
|
106
|
+
return user_id
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sycommon-python-lib
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8a0
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -9,11 +9,11 @@ Requires-Dist: aiohttp==3.14.3
|
|
|
9
9
|
Requires-Dist: aiomysql==0.3.2
|
|
10
10
|
Requires-Dist: anyio==4.14.2
|
|
11
11
|
Requires-Dist: decorator==5.3.1
|
|
12
|
-
Requires-Dist: deepagents==0.7.
|
|
13
|
-
Requires-Dist: elasticsearch==9.
|
|
12
|
+
Requires-Dist: deepagents==0.7.4
|
|
13
|
+
Requires-Dist: elasticsearch==9.5.0
|
|
14
14
|
Requires-Dist: fastapi==0.141.1
|
|
15
15
|
Requires-Dist: jinja2==3.1.6
|
|
16
|
-
Requires-Dist: kafka-python==3.0.
|
|
16
|
+
Requires-Dist: kafka-python==3.0.10
|
|
17
17
|
Requires-Dist: langchain==1.3.14
|
|
18
18
|
Requires-Dist: langchain-core==1.5.3
|
|
19
19
|
Requires-Dist: langchain-openai==1.4.1
|