langbot-plugin 0.5.2__tar.gz → 0.5.4__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.
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/PKG-INFO +1 -1
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/pyproject.toml +1 -1
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/handler.py +5 -2
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/plugin/mgr.py +74 -33
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/plugin/restart_coordinator.py +17 -10
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/plugin/worker_launcher.py +4 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/security.py +1 -0
- langbot_plugin-0.5.4/src/langbot_plugin/version.py +1 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/io/test_handler.py +15 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/plugin/test_installation_manager.py +104 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/plugin/test_restart_coordinator.py +36 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/plugin/test_worker_launcher.py +2 -0
- langbot_plugin-0.5.2/src/langbot_plugin/version.py +0 -1
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/.github/workflows/cla.yml +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/.github/workflows/publish-pypi.yaml +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/.github/workflows/publish.yml +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/.github/workflows/test.yml +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/.gitignore +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/.python-version +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/AGENTS.md +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/ARCHITECTURE.md +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/CLAUDE.md +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/CONTRIBUTING.md +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/LICENSE +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/README.md +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/README_CN.md +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/data/.env.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/docs/Message.md +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/docs/PluginPages.md +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/docs/communication/apis/lb2rt.md +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/docs/communication/runtime_plugin.md +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/docs/dependency-management.md +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/docs/langbot-plugin-social.png +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/scripts/check_action_consistency.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/scripts/runtime_resource_probe.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/abstract/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/abstract/platform/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/abstract/platform/adapter.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/abstract/platform/event_logger.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/base.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/command/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/command/command.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/common/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/common/event_listener.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/knowledge_engine/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/knowledge_engine/engine.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/manifest.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/page/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/parser/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/parser/parser.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/tool/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/tool/tool.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/plugin.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/command/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/command/context.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/command/errors.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/pipeline/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/pipeline/query.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/platform/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/platform/entities.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/platform/events.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/platform/logger.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/platform/message.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/provider/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/provider/message.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/provider/prompt.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/provider/session.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/rag/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/rag/context.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/rag/enums.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/rag/errors.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/rag/models.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/resource/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/resource/tool.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/context.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/events.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/execution.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/proxies/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/proxies/base.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/proxies/event_context.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/proxies/execute_context.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/proxies/langbot_api.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/proxies/query_based_api.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/langbot-page-sdk.js +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/.env.example.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/.github/workflows/release.yml.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/.gitignore.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/.vscode/launch.json.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/README.md.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/assets/icon.svg.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/commands/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/commands/{cmd_name}.py.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/commands/{cmd_name}.yaml.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/event_listener/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/event_listener/default.py.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/event_listener/default.yaml.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/knowledge_engine/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/knowledge_engine/{knowledge_engine_name}.py.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/knowledge_engine/{knowledge_engine_name}.yaml.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/pages/{page_name}.html.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/pages/{page_name}.yaml.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/parser/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/parser/{parser_name}.py.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/parser/{parser_name}.yaml.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/tools/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/tools/{tool_name}.py.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/components/tools/{tool_name}.yaml.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/main.py.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/manifest.yaml.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/readme/README_zh_Hans.md.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/assets/templates/requirements.txt.example +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/box/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/box/actions.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/box/backend.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/box/client.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/box/e2b_backend.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/box/errors.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/box/models.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/box/nsjail_backend.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/box/runtime.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/box/security.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/box/server.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/box/skill_store.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/box/tenancy.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/__main__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/commands/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/commands/buildplugin.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/commands/gencomponent.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/commands/initplugin.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/commands/login.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/commands/logout.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/commands/publish.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/commands/runplugin.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/gen/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/gen/renderer.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/i18n.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/locales/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/locales/en_US.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/locales/es_ES.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/locales/ja_JP.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/locales/th_TH.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/locales/vi_VN.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/locales/zh_Hans.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/locales/zh_Hant.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/run/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/run/controller.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/run/handler.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/run/hotreload.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/utils/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/utils/cloudsv.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/utils/form.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/cli/utils/page_components.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/entities/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/entities/io/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/entities/io/actions/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/entities/io/actions/enums.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/entities/io/context.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/entities/io/errors.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/entities/io/req.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/entities/io/resp.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/entities/marketplace.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/LICENSE +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/README.md +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/app.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/bounded_executor.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/context.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/event_loop_monitor.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/helper/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/helper/marketplace.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/helper/pkgmgr.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/connection.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/connections/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/connections/stdio.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/connections/ws.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/controller.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/controllers/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/controllers/stdio/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/controllers/stdio/client.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/controllers/stdio/server.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/controllers/ws/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/controllers/ws/client.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/controllers/ws/server.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/handlers/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/handlers/control.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/io/handlers/plugin.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/plugin/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/plugin/artifact.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/plugin/container.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/plugin/dependency_environment.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/plugin/logbuffer.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/settings.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/utils/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/utils/discover/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/utils/discover/engine.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/utils/importutil.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/utils/log.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/utils/platform.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/api/definition/components/test_components.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/api/definition/test_manifest.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/api/entities/builtin/test_command_context.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/api/entities/builtin/test_platform_logger.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/api/entities/builtin/test_provider_message.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/api/entities/builtin/test_rag_models.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/api/entities/test_context.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/api/entities/test_events.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/api/proxies/test_base.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/api/proxies/test_langbot_api.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/api/proxies/test_query_based_api.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/box/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/box/test_admission.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/box/test_backend.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/box/test_backend_selection.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/box/test_client.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/box/test_e2b_backend.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/box/test_nsjail_backend.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/box/test_runtime.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/box/test_server.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/box/test_skill_store.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/cli/run/test_controller.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/cli/run/test_hotreload.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/cli/run/test_runtime_handler.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/cli/test_buildplugin.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/cli/test_gencomponent.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/cli/test_i18n_form.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/cli/test_initplugin.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/cli/test_login.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/cli/test_logout_publish.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/cli/test_page_components.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/cli/test_renderer.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/cli/test_runplugin.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/entities/io/test_dependency_errors.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/entities/io/test_protocol.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/helpers/__init__.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/helpers/protocol.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/packaging/test_installed_cli_blackbox.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/helper/test_marketplace.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/helper/test_pkgmgr.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/io/handlers/test_control_handler.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/io/handlers/test_import_contracts.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/io/handlers/test_plugin_handler.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/io/test_action_consistency.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/io/test_connections.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/io/test_controllers.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/plugin/test_artifact_store.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/plugin/test_container.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/plugin/test_dependency_environment.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/plugin/test_manager.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/test_app.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/test_bounded_executor.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/test_event_loop_monitor.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/test_log.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/test_message.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/test_plugin_logbuffer.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/utils/test_discovery.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/utils/test_importutil.py +0 -0
- {langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/utils/test_platform.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: langbot-plugin
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.4
|
|
4
4
|
Summary: This package contains the SDK, CLI for building plugins for LangBot, plus the runtime for hosting LangBot plugins
|
|
5
5
|
Project-URL: Homepage, https://langbot.app
|
|
6
6
|
Project-URL: Repository, https://github.com/langbot-app/langbot-plugin-sdk
|
|
@@ -34,7 +34,10 @@ from langbot_plugin.entities.io.errors import (
|
|
|
34
34
|
ActionCallError,
|
|
35
35
|
)
|
|
36
36
|
from langbot_plugin.entities.io.actions.enums import ActionType, CommonAction
|
|
37
|
-
from langbot_plugin.runtime.security import
|
|
37
|
+
from langbot_plugin.runtime.security import (
|
|
38
|
+
PLUGIN_FILE_STORAGE_DIR_ENV,
|
|
39
|
+
PLUGIN_RUNTIME_PROFILE_ENV,
|
|
40
|
+
)
|
|
38
41
|
from langbot_plugin.runtime.bounded_executor import blocking_work_scope
|
|
39
42
|
|
|
40
43
|
logger = logging.getLogger(__name__)
|
|
@@ -124,7 +127,7 @@ class Handler(abc.ABC):
|
|
|
124
127
|
|
|
125
128
|
if file_storage_dir is None:
|
|
126
129
|
runtime_profile = os.environ.get(PLUGIN_RUNTIME_PROFILE_ENV, "oss_dev")
|
|
127
|
-
file_storage_dir = (
|
|
130
|
+
file_storage_dir = os.environ.get(PLUGIN_FILE_STORAGE_DIR_ENV) or (
|
|
128
131
|
SHARED_WORKER_FILE_STORAGE_DIR
|
|
129
132
|
if runtime_profile == "shared"
|
|
130
133
|
else FILE_STORAGE_DIR
|
|
@@ -219,6 +219,23 @@ class PluginManager:
|
|
|
219
219
|
initial_policy.max_concurrent_restarts
|
|
220
220
|
)
|
|
221
221
|
|
|
222
|
+
async def _complete_installation_transition(
|
|
223
|
+
self,
|
|
224
|
+
operation: typing.Coroutine[typing.Any, typing.Any, None],
|
|
225
|
+
) -> None:
|
|
226
|
+
"""Join one lifecycle mutation through repeated caller cancellation."""
|
|
227
|
+
|
|
228
|
+
task = asyncio.create_task(operation)
|
|
229
|
+
cancelled = False
|
|
230
|
+
while not task.done():
|
|
231
|
+
try:
|
|
232
|
+
await asyncio.shield(task)
|
|
233
|
+
except asyncio.CancelledError:
|
|
234
|
+
cancelled = True
|
|
235
|
+
task.result()
|
|
236
|
+
if cancelled:
|
|
237
|
+
raise asyncio.CancelledError
|
|
238
|
+
|
|
222
239
|
@property
|
|
223
240
|
def installation_runtimes(
|
|
224
241
|
self,
|
|
@@ -1058,11 +1075,20 @@ class PluginManager:
|
|
|
1058
1075
|
self,
|
|
1059
1076
|
binding: InstallationBinding,
|
|
1060
1077
|
) -> dict[str, typing.Any]:
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1078
|
+
async def remove() -> None:
|
|
1079
|
+
removed_binding = self.context.deactivate_installation_binding(binding)
|
|
1080
|
+
async with self._installation_lifecycle_semaphore():
|
|
1081
|
+
await self._revoke_installation_runtime(removed_binding)
|
|
1082
|
+
if (
|
|
1083
|
+
self._active_binding_by_uuid.get(removed_binding.installation_uuid)
|
|
1084
|
+
== removed_binding
|
|
1085
|
+
):
|
|
1086
|
+
self._active_binding_by_uuid.pop(
|
|
1087
|
+
removed_binding.installation_uuid,
|
|
1088
|
+
None,
|
|
1089
|
+
)
|
|
1090
|
+
|
|
1091
|
+
await self._complete_installation_transition(remove())
|
|
1066
1092
|
return {
|
|
1067
1093
|
"installation_uuid": binding.installation_uuid,
|
|
1068
1094
|
"state": "removed",
|
|
@@ -1108,22 +1134,26 @@ class PluginManager:
|
|
|
1108
1134
|
lock = self._retain_installation_operation_lock(installation_uuid)
|
|
1109
1135
|
try:
|
|
1110
1136
|
async with lock:
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
self.context.deactivate_installation_binding(
|
|
1137
|
+
|
|
1138
|
+
async def remove_current() -> None:
|
|
1139
|
+
if self.context.is_current_installation_binding(
|
|
1115
1140
|
current_binding
|
|
1116
|
-
)
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
self.
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1141
|
+
):
|
|
1142
|
+
self.context.deactivate_installation_binding(
|
|
1143
|
+
current_binding
|
|
1144
|
+
)
|
|
1145
|
+
async with self._installation_lifecycle_semaphore():
|
|
1146
|
+
await self._revoke_installation_runtime(current_binding)
|
|
1147
|
+
if (
|
|
1148
|
+
self._active_binding_by_uuid.get(installation_uuid)
|
|
1149
|
+
== current_binding
|
|
1150
|
+
):
|
|
1151
|
+
self._active_binding_by_uuid.pop(
|
|
1152
|
+
installation_uuid,
|
|
1153
|
+
None,
|
|
1154
|
+
)
|
|
1155
|
+
|
|
1156
|
+
await self._complete_installation_transition(remove_current())
|
|
1127
1157
|
removed.append(installation_uuid)
|
|
1128
1158
|
finally:
|
|
1129
1159
|
self._forget_installation_operation_lock(
|
|
@@ -1469,10 +1499,12 @@ class PluginManager:
|
|
|
1469
1499
|
binding: InstallationBinding,
|
|
1470
1500
|
) -> None:
|
|
1471
1501
|
self._revoke_registration_capabilities_for_binding(binding)
|
|
1472
|
-
runtime = self._installations.
|
|
1502
|
+
runtime = self._installations.get(binding)
|
|
1473
1503
|
if runtime is None:
|
|
1474
1504
|
return
|
|
1475
1505
|
await self._stop_installation_worker(runtime)
|
|
1506
|
+
if self._installations.get(binding) is runtime:
|
|
1507
|
+
self._installations.pop(binding, None)
|
|
1476
1508
|
|
|
1477
1509
|
async def _stop_installation_worker(
|
|
1478
1510
|
self,
|
|
@@ -1486,20 +1518,29 @@ class PluginManager:
|
|
|
1486
1518
|
except Exception as exc:
|
|
1487
1519
|
logger.warning("Failed to notify revoked plugin worker: %s", exc)
|
|
1488
1520
|
close = getattr(handler, "close", None)
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1521
|
+
try:
|
|
1522
|
+
if close is not None:
|
|
1523
|
+
await close()
|
|
1524
|
+
else:
|
|
1525
|
+
await handler.conn.close()
|
|
1526
|
+
except Exception as exc:
|
|
1527
|
+
logger.warning("Failed to close revoked plugin worker: %s", exc)
|
|
1528
|
+
finally:
|
|
1529
|
+
if handler in self.plugin_handlers:
|
|
1530
|
+
self.plugin_handlers.remove(handler)
|
|
1531
|
+
runtime.plugin_handler = None
|
|
1495
1532
|
process = handler.stdio_process
|
|
1496
1533
|
if process is not None and process.returncode is None:
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1534
|
+
try:
|
|
1535
|
+
stopped = await stdio_client_controller.stop_process(process)
|
|
1536
|
+
except Exception as exc:
|
|
1537
|
+
logger.error("Failed to stop revoked plugin worker: %s", exc)
|
|
1538
|
+
else:
|
|
1539
|
+
if not stopped:
|
|
1540
|
+
logger.error(
|
|
1541
|
+
"Plugin worker process did not exit after SIGKILL: %s",
|
|
1542
|
+
runtime.binding.installation_uuid,
|
|
1543
|
+
)
|
|
1503
1544
|
runtime.plugin_handler = None
|
|
1504
1545
|
if runtime.plugin_container is not None:
|
|
1505
1546
|
self._binding_by_container_id.pop(id(runtime.plugin_container), None)
|
|
@@ -3,14 +3,16 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import collections
|
|
5
5
|
import time
|
|
6
|
-
from collections.abc import
|
|
6
|
+
from collections.abc import Coroutine
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
from typing import Callable
|
|
9
9
|
|
|
10
10
|
from langbot_plugin.entities.io.context import PluginWorkerPolicy
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
async def _complete_state_transition(
|
|
13
|
+
async def _complete_state_transition(
|
|
14
|
+
operation: Coroutine[object, object, None],
|
|
15
|
+
) -> None:
|
|
14
16
|
"""Finish one tiny coordinator mutation even if its caller is cancelled.
|
|
15
17
|
|
|
16
18
|
A supervisor cancellation must not strand the circuit in half-open state.
|
|
@@ -19,14 +21,19 @@ async def _complete_state_transition(operation: Awaitable[None]) -> None:
|
|
|
19
21
|
"""
|
|
20
22
|
|
|
21
23
|
task = asyncio.create_task(operation)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
cancelled = False
|
|
25
|
+
while not task.done():
|
|
26
|
+
try:
|
|
27
|
+
await asyncio.shield(task)
|
|
28
|
+
except asyncio.CancelledError:
|
|
29
|
+
# A caller can be cancelled repeatedly while the mutation is
|
|
30
|
+
# waiting for the state lock. Keep joining the shielded task until
|
|
31
|
+
# the transition is complete; otherwise a half-open probe can be
|
|
32
|
+
# stranded permanently.
|
|
33
|
+
cancelled = True
|
|
34
|
+
task.result()
|
|
35
|
+
if cancelled:
|
|
36
|
+
raise asyncio.CancelledError
|
|
30
37
|
|
|
31
38
|
|
|
32
39
|
@dataclass(slots=True)
|
{langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/runtime/plugin/worker_launcher.py
RENAMED
|
@@ -28,6 +28,7 @@ from langbot_plugin.runtime.plugin.dependency_environment import (
|
|
|
28
28
|
from langbot_plugin.runtime.helper import pkgmgr as pkgmgr_helper
|
|
29
29
|
from langbot_plugin.runtime import bounded_executor
|
|
30
30
|
from langbot_plugin.runtime.security import (
|
|
31
|
+
PLUGIN_FILE_STORAGE_DIR_ENV,
|
|
31
32
|
PLUGIN_REGISTRATION_CAPABILITY_ENV,
|
|
32
33
|
PLUGIN_RUNTIME_PROFILE_ENV,
|
|
33
34
|
)
|
|
@@ -140,6 +141,9 @@ class PluginWorkerLauncher:
|
|
|
140
141
|
"--prod",
|
|
141
142
|
],
|
|
142
143
|
env={
|
|
144
|
+
PLUGIN_FILE_STORAGE_DIR_ENV: str(
|
|
145
|
+
launch_spec.paths.root_path / "rpc-transfer"
|
|
146
|
+
),
|
|
143
147
|
PLUGIN_REGISTRATION_CAPABILITY_ENV: (
|
|
144
148
|
launch_spec.registration_capability
|
|
145
149
|
),
|
|
@@ -15,6 +15,7 @@ PLUGIN_DEBUG_KEY_HEADER = "X-LangBot-Plugin-Debug-Key"
|
|
|
15
15
|
PLUGIN_REGISTRATION_CAPABILITY_ENV = "LANGBOT_PLUGIN_REGISTRATION_CAPABILITY"
|
|
16
16
|
PLUGIN_REGISTRATION_CAPABILITY_HEADER = "X-LangBot-Plugin-Registration-Capability"
|
|
17
17
|
PLUGIN_RUNTIME_PROFILE_ENV = "LANGBOT_PLUGIN_RUNTIME_PROFILE"
|
|
18
|
+
PLUGIN_FILE_STORAGE_DIR_ENV = "LANGBOT_PLUGIN_FILE_STORAGE_DIR"
|
|
18
19
|
RUNTIME_SECRET_MIN_LENGTH = 32
|
|
19
20
|
WORKSPACE_DEBUG_TOKEN_TTL_SECONDS = 2 * 60 * 60
|
|
20
21
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.5.4"
|
|
@@ -511,6 +511,21 @@ def test_handler_file_storage_dir_is_created_for_instances(tmp_path, monkeypatch
|
|
|
511
511
|
assert (tmp_path / "data" / "temp" / "lbp").is_dir()
|
|
512
512
|
|
|
513
513
|
|
|
514
|
+
def test_managed_worker_file_storage_uses_launcher_directory(tmp_path, monkeypatch):
|
|
515
|
+
artifact = tmp_path / "artifact" / "code"
|
|
516
|
+
artifact.mkdir(parents=True)
|
|
517
|
+
artifact.chmod(0o555)
|
|
518
|
+
rpc_transfer = tmp_path / "installations" / "installation-a" / "rpc-transfer"
|
|
519
|
+
monkeypatch.chdir(artifact)
|
|
520
|
+
monkeypatch.setenv("LANGBOT_PLUGIN_FILE_STORAGE_DIR", str(rpc_transfer))
|
|
521
|
+
|
|
522
|
+
handler = Handler(QueueConnection())
|
|
523
|
+
|
|
524
|
+
assert handler.file_storage_dir == str(rpc_transfer)
|
|
525
|
+
assert rpc_transfer.is_dir()
|
|
526
|
+
assert not (artifact / "data").exists()
|
|
527
|
+
|
|
528
|
+
|
|
514
529
|
def test_shared_worker_file_storage_uses_private_writable_tmp(tmp_path, monkeypatch):
|
|
515
530
|
worker_tmp = tmp_path / "lbp-rpc"
|
|
516
531
|
monkeypatch.setenv(PLUGIN_RUNTIME_PROFILE_ENV, "shared")
|
{langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/plugin/test_installation_manager.py
RENAMED
|
@@ -131,6 +131,110 @@ async def test_manager_indexes_same_artifact_installations_by_complete_binding(
|
|
|
131
131
|
assert context.is_current_installation_binding(binding_b)
|
|
132
132
|
|
|
133
133
|
|
|
134
|
+
async def test_cancelled_remove_finishes_worker_revoke_before_propagating(
|
|
135
|
+
tmp_path,
|
|
136
|
+
):
|
|
137
|
+
context, manager = _manager(tmp_path)
|
|
138
|
+
package = _package()
|
|
139
|
+
digest = hashlib.sha256(package).hexdigest()
|
|
140
|
+
binding = _binding(
|
|
141
|
+
"installation-a",
|
|
142
|
+
digest,
|
|
143
|
+
workspace_uuid="workspace-a",
|
|
144
|
+
)
|
|
145
|
+
await manager.apply_plugin_installation(
|
|
146
|
+
binding,
|
|
147
|
+
artifact_package=package,
|
|
148
|
+
enabled=False,
|
|
149
|
+
)
|
|
150
|
+
runtime = manager.installation_runtimes[binding]
|
|
151
|
+
shutdown_started = asyncio.Event()
|
|
152
|
+
allow_shutdown = asyncio.Event()
|
|
153
|
+
|
|
154
|
+
class Handler:
|
|
155
|
+
stdio_process = None
|
|
156
|
+
conn = None
|
|
157
|
+
|
|
158
|
+
def cancel_inflight_messages(self):
|
|
159
|
+
return None
|
|
160
|
+
|
|
161
|
+
async def shutdown_plugin(self):
|
|
162
|
+
shutdown_started.set()
|
|
163
|
+
await allow_shutdown.wait()
|
|
164
|
+
|
|
165
|
+
async def close(self):
|
|
166
|
+
return None
|
|
167
|
+
|
|
168
|
+
handler = Handler()
|
|
169
|
+
runtime.plugin_handler = handler
|
|
170
|
+
manager.plugin_handlers.append(handler)
|
|
171
|
+
|
|
172
|
+
remove_task = asyncio.create_task(manager.remove_plugin_installation(binding))
|
|
173
|
+
await asyncio.wait_for(shutdown_started.wait(), timeout=1)
|
|
174
|
+
remove_task.cancel()
|
|
175
|
+
await asyncio.sleep(0)
|
|
176
|
+
remove_task.cancel()
|
|
177
|
+
allow_shutdown.set()
|
|
178
|
+
|
|
179
|
+
with pytest.raises(asyncio.CancelledError):
|
|
180
|
+
await remove_task
|
|
181
|
+
assert not context.is_current_installation_binding(binding)
|
|
182
|
+
assert binding not in manager.installation_runtimes
|
|
183
|
+
assert binding.installation_uuid not in manager._active_binding_by_uuid
|
|
184
|
+
assert handler not in manager.plugin_handlers
|
|
185
|
+
assert runtime.plugin_handler is None
|
|
186
|
+
|
|
187
|
+
with pytest.raises(ValueError, match="stale"):
|
|
188
|
+
await manager.reconcile_plugin_installations(
|
|
189
|
+
(PluginInstallationDesiredState(binding=binding, enabled=False),)
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
async def test_remove_finishes_state_cleanup_when_handler_close_fails(
|
|
194
|
+
tmp_path,
|
|
195
|
+
):
|
|
196
|
+
context, manager = _manager(tmp_path)
|
|
197
|
+
package = _package()
|
|
198
|
+
digest = hashlib.sha256(package).hexdigest()
|
|
199
|
+
binding = _binding(
|
|
200
|
+
"installation-a",
|
|
201
|
+
digest,
|
|
202
|
+
workspace_uuid="workspace-a",
|
|
203
|
+
)
|
|
204
|
+
await manager.apply_plugin_installation(
|
|
205
|
+
binding,
|
|
206
|
+
artifact_package=package,
|
|
207
|
+
enabled=False,
|
|
208
|
+
)
|
|
209
|
+
runtime = manager.installation_runtimes[binding]
|
|
210
|
+
|
|
211
|
+
class Handler:
|
|
212
|
+
stdio_process = None
|
|
213
|
+
conn = None
|
|
214
|
+
|
|
215
|
+
def cancel_inflight_messages(self):
|
|
216
|
+
return None
|
|
217
|
+
|
|
218
|
+
async def shutdown_plugin(self):
|
|
219
|
+
return None
|
|
220
|
+
|
|
221
|
+
async def close(self):
|
|
222
|
+
raise RuntimeError("close failed")
|
|
223
|
+
|
|
224
|
+
handler = Handler()
|
|
225
|
+
runtime.plugin_handler = handler
|
|
226
|
+
manager.plugin_handlers.append(handler)
|
|
227
|
+
|
|
228
|
+
result = await manager.remove_plugin_installation(binding)
|
|
229
|
+
|
|
230
|
+
assert result["state"] == "removed"
|
|
231
|
+
assert not context.is_current_installation_binding(binding)
|
|
232
|
+
assert binding not in manager.installation_runtimes
|
|
233
|
+
assert binding.installation_uuid not in manager._active_binding_by_uuid
|
|
234
|
+
assert handler not in manager.plugin_handlers
|
|
235
|
+
assert runtime.plugin_handler is None
|
|
236
|
+
|
|
237
|
+
|
|
134
238
|
async def test_desired_state_does_not_reject_on_aggregate_worker_capacity(
|
|
135
239
|
tmp_path,
|
|
136
240
|
monkeypatch,
|
{langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/tests/runtime/plugin/test_restart_coordinator.py
RENAMED
|
@@ -198,6 +198,42 @@ async def test_abandoned_probe_releases_slot_without_counting_failure():
|
|
|
198
198
|
await replacement_probe.abandon()
|
|
199
199
|
|
|
200
200
|
|
|
201
|
+
async def test_repeated_cancellation_cannot_strand_half_open_probe():
|
|
202
|
+
coordinator = PluginRestartCoordinator()
|
|
203
|
+
coordinator.configure(
|
|
204
|
+
_policy(
|
|
205
|
+
max_concurrent_restarts=1,
|
|
206
|
+
restart_failure_threshold=1,
|
|
207
|
+
restart_circuit_open_seconds=0.01,
|
|
208
|
+
)
|
|
209
|
+
)
|
|
210
|
+
failed = await coordinator.acquire("installation-a")
|
|
211
|
+
await failed.record_failure()
|
|
212
|
+
probe = await asyncio.wait_for(
|
|
213
|
+
coordinator.acquire("installation-a"),
|
|
214
|
+
timeout=1,
|
|
215
|
+
)
|
|
216
|
+
assert probe.is_half_open_probe is True
|
|
217
|
+
|
|
218
|
+
await coordinator._state_lock.acquire()
|
|
219
|
+
abandon_task = asyncio.create_task(probe.abandon())
|
|
220
|
+
await asyncio.sleep(0)
|
|
221
|
+
abandon_task.cancel()
|
|
222
|
+
await asyncio.sleep(0)
|
|
223
|
+
abandon_task.cancel()
|
|
224
|
+
coordinator._state_lock.release()
|
|
225
|
+
|
|
226
|
+
with pytest.raises(asyncio.CancelledError):
|
|
227
|
+
await abandon_task
|
|
228
|
+
assert coordinator.snapshot()["half_open_probe_inflight"] is False
|
|
229
|
+
|
|
230
|
+
replacement = await asyncio.wait_for(
|
|
231
|
+
coordinator.acquire("installation-a"),
|
|
232
|
+
timeout=1,
|
|
233
|
+
)
|
|
234
|
+
await replacement.abandon()
|
|
235
|
+
|
|
236
|
+
|
|
201
237
|
async def test_cancelled_acquire_does_not_leak_launch_slot():
|
|
202
238
|
coordinator = PluginRestartCoordinator()
|
|
203
239
|
coordinator.configure(
|
|
@@ -22,6 +22,7 @@ from langbot_plugin.runtime.plugin.worker_launcher import (
|
|
|
22
22
|
PluginWorkerLauncher,
|
|
23
23
|
)
|
|
24
24
|
from langbot_plugin.runtime.security import (
|
|
25
|
+
PLUGIN_FILE_STORAGE_DIR_ENV,
|
|
25
26
|
PLUGIN_REGISTRATION_CAPABILITY_ENV,
|
|
26
27
|
PLUGIN_RUNTIME_PROFILE_ENV,
|
|
27
28
|
)
|
|
@@ -327,6 +328,7 @@ def test_launcher_builds_profile_specific_controllers(tmp_path):
|
|
|
327
328
|
assert oss_controller.command == sys.executable
|
|
328
329
|
assert oss_controller.working_dir == str(launch_spec.artifact.code_path)
|
|
329
330
|
assert oss_controller.env == {
|
|
331
|
+
PLUGIN_FILE_STORAGE_DIR_ENV: str(launch_spec.paths.root_path / "rpc-transfer"),
|
|
330
332
|
PLUGIN_REGISTRATION_CAPABILITY_ENV: "capability-value",
|
|
331
333
|
PLUGIN_RUNTIME_PROFILE_ENV: "oss_dev",
|
|
332
334
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.5.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/abstract/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/definition/components/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/rag/context.py
RENAMED
|
File without changes
|
{langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/rag/enums.py
RENAMED
|
File without changes
|
{langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/rag/errors.py
RENAMED
|
File without changes
|
{langbot_plugin-0.5.2 → langbot_plugin-0.5.4}/src/langbot_plugin/api/entities/builtin/rag/models.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|