langbot-plugin 0.6.1b2__tar.gz → 0.6.2__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.6.1b2 → langbot_plugin-0.6.2}/ARCHITECTURE.md +29 -7
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/PKG-INFO +1 -1
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/pyproject.toml +1 -1
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/run/controller.py +104 -17
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/run/handler.py +65 -1
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/entities/io/actions/enums.py +3 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/entities/io/context.py +10 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/handler.py +86 -17
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/handlers/control.py +7 -2
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/handlers/plugin.py +94 -17
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/plugin/artifact.py +22 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/plugin/mgr.py +600 -7
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/plugin/worker_launcher.py +45 -0
- langbot_plugin-0.6.2/src/langbot_plugin/version.py +1 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/cli/run/test_controller.py +180 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/entities/io/test_protocol.py +19 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/packaging/test_release_metadata.py +3 -3
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/io/handlers/test_legacy_file_chunk.py +17 -4
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/io/handlers/test_plugin_handler.py +45 -6
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/io/test_handler.py +122 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/plugin/test_installation_manager.py +1058 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/plugin/test_manager.py +59 -1
- langbot_plugin-0.6.2/tests/runtime/plugin/test_shared_worker_subprocess.py +320 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/plugin/test_worker_launcher.py +36 -0
- langbot_plugin-0.6.1b2/src/langbot_plugin/version.py +0 -1
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/.github/workflows/cla.yml +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/.github/workflows/publish-pypi.yaml +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/.github/workflows/publish.yml +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/.github/workflows/test.yml +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/.gitignore +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/.python-version +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/AGENTS.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/CLAUDE.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/CONTRIBUTING.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/LICENSE +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/README.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/README_CN.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/data/.env.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/docs/Message.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/docs/PluginPages.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/docs/agent-runner-interactions.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/docs/agent-runner-pluginization/PROTOCOL_V1.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/docs/agent-runner-pluginization/README.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/docs/agent-runner-pluginization/SDK_RUNTIME_PLAN.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/docs/certified-plugins.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/docs/communication/apis/lb2rt.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/docs/communication/runtime_plugin.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/docs/dependency-management.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/docs/langbot-plugin-social.png +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/docs/runner.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/mypy.ini +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/scripts/check_action_consistency.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/scripts/runtime_resource_probe.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/agent_tools/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/agent_tools/asset_gateway.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/agent_tools/daemon.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/agent_tools/decorators.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/agent_tools/external_tools.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/agent_tools/mcp_access.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/agent_tools/mcp_bridge.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/agent_tools/mcp_config.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/agent_tools/mcp_protocol.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/agent_tools/mcp_stdio.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/abstract/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/abstract/platform/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/abstract/platform/adapter.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/abstract/platform/event_logger.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/base.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/command/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/command/command.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/common/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/common/event_listener.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/knowledge_engine/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/knowledge_engine/engine.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/manifest.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/page/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/parser/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/parser/parser.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/runner/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/runner/runner.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/tool/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/components/tool/tool.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/definition/plugin.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/command/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/command/context.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/command/errors.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/pipeline/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/pipeline/query.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/platform/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/platform/entities.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/platform/errors.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/platform/events.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/platform/logger.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/platform/message.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/provider/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/provider/message.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/provider/prompt.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/provider/reasoning.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/provider/session.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/rag/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/rag/context.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/rag/enums.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/rag/errors.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/rag/models.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/resource/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/resource/tool.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/box.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/capabilities.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/compat.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/context.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/context_access.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/delivery.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/errors.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/event.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/input.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/interaction.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/manifest.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/page_results.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/permissions.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/resources.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/result.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/run_ledger.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/runtime.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/runtime_registry.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/state.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/stats.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/steering.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/transcript.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/builtin/runner/trigger.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/context.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/events.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/entities/execution.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/base.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/event_context.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/execute_context.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/invocation.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/langbot_api.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/query_based_api.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/runner/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/runner/admin.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/runner/api.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/runner/box.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/runner/common.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/runner/context.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/runner/ledger.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/runner/platform.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/runner/reply_stream.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/runner/resources.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/runner/state.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/api/proxies/runner/tracing.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/langbot-page-sdk.js +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/.env.example.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/.github/workflows/release.yml.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/.gitignore.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/.vscode/launch.json.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/README.md.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/assets/icon.svg.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/commands/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/commands/{cmd_name}.py.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/commands/{cmd_name}.yaml.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/event_listener/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/event_listener/default.py.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/event_listener/default.yaml.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/knowledge_engine/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/knowledge_engine/{knowledge_engine_name}.py.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/knowledge_engine/{knowledge_engine_name}.yaml.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/pages/{page_name}.html.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/pages/{page_name}.yaml.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/parser/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/parser/{parser_name}.py.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/parser/{parser_name}.yaml.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/runner/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/runner/{runner_name}.py.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/runner/{runner_name}.yaml.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/tools/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/tools/{tool_name}.py.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/components/tools/{tool_name}.yaml.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/main.py.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/manifest.yaml.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/readme/README_zh_Hans.md.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/assets/templates/requirements.txt.example +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/actions.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/backend.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/client.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/e2b_backend.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/errors.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/host_backend.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/models.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/nsjail_backend.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/runtime.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/security.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/server.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/skill_store.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/box/tenancy.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/certification.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/__main__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/commands/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/commands/buildplugin.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/commands/gencomponent.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/commands/initplugin.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/commands/login.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/commands/logout.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/commands/publish.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/commands/runplugin.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/gen/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/gen/renderer.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/i18n.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/locales/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/locales/en_US.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/locales/es_ES.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/locales/ja_JP.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/locales/th_TH.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/locales/vi_VN.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/locales/zh_Hans.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/locales/zh_Hant.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/run/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/run/hotreload.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/utils/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/utils/cloudsv.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/utils/form.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/cli/utils/page_components.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/entities/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/entities/io/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/entities/io/actions/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/entities/io/errors.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/entities/io/req.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/entities/io/resp.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/entities/marketplace.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/LICENSE +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/README.md +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/app.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/bounded_executor.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/context.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/event_loop_monitor.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/helper/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/helper/marketplace.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/helper/pkgmgr.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/connection.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/connections/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/connections/stdio.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/connections/ws.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/controller.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/controllers/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/controllers/stdio/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/controllers/stdio/client.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/controllers/stdio/server.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/controllers/ws/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/controllers/ws/client.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/controllers/ws/server.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/handlers/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/plugin/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/plugin/container.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/plugin/dependency_environment.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/plugin/logbuffer.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/plugin/restart_coordinator.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/plugin/runner_service.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/security.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/settings.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/storage.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/utils/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/utils/deadline.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/utils/discover/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/utils/discover/engine.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/utils/importutil.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/utils/log.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/utils/platform.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/definition/components/test_components.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/definition/components/test_imports.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/definition/test_manifest.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/entities/builtin/runner/test_context_result.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/entities/builtin/runner/test_history_event_entities.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/entities/builtin/runner/test_interaction.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/entities/builtin/runner/test_run_ledger_entities.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/entities/builtin/test_command_context.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/entities/builtin/test_platform_logger.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/entities/builtin/test_provider_message.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/entities/builtin/test_rag_models.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/entities/test_context.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/entities/test_events.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/proxies/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/proxies/test_agent_run_api_proxy.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/proxies/test_base.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/proxies/test_box_api.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/proxies/test_history_event_api_proxy.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/proxies/test_langbot_api.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/proxies/test_query_based_api.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/proxies/test_reasoning_parameter.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/test_agent_tools_mcp_bridge.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/test_runner_handlers.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/test_runner_handlers_matrix.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/api/test_runner_public_apis.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/box/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/box/test_admission.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/box/test_backend.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/box/test_backend_selection.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/box/test_client.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/box/test_e2b_backend.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/box/test_host_backend.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/box/test_nsjail_backend.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/box/test_runtime.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/box/test_server.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/box/test_skill_store.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/box/test_storage_analysis.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/cli/run/test_hotreload.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/cli/run/test_runtime_handler.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/cli/test_buildplugin.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/cli/test_gencomponent.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/cli/test_i18n_form.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/cli/test_initplugin.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/cli/test_login.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/cli/test_logout_publish.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/cli/test_page_components.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/cli/test_renderer.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/cli/test_runner_usages.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/cli/test_runplugin.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/e2e/standalone_runtime_eba_probe.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/entities/io/test_dependency_errors.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/fixtures/eba_event_probe_plugin/.gitignore +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/fixtures/eba_event_probe_plugin/assets/icon.svg +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/fixtures/eba_event_probe_plugin/components/event_listener/default.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/fixtures/eba_event_probe_plugin/components/event_listener/default.yaml +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/fixtures/eba_event_probe_plugin/main.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/fixtures/eba_event_probe_plugin/manifest.yaml +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/helpers/__init__.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/helpers/protocol.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/packaging/test_installed_cli_blackbox.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/helper/test_marketplace.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/helper/test_pkgmgr.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/io/handlers/test_control_handler.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/io/handlers/test_import_contracts.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/io/test_action_consistency.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/io/test_connections.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/io/test_controllers.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/io/test_heartbeat_admission.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/io/test_stdio_server.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/plugin/test_artifact_store.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/plugin/test_container.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/plugin/test_dependency_environment.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/plugin/test_legacy_shadow.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/plugin/test_mgr_runner.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/plugin/test_restart_coordinator.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/plugin/test_workload_isolation.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/test_app.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/test_bounded_executor.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/test_event_loop_monitor.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/runtime/test_pull_api_handlers.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/test_certification.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/test_log.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/test_message.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/test_plugin_logbuffer.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/test_storage.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/utils/test_deadline.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/utils/test_discovery.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/utils/test_importutil.py +0 -0
- {langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/tests/utils/test_platform.py +0 -0
|
@@ -161,13 +161,27 @@ actions reject tenant context. Plugin payload fields are never authoritative
|
|
|
161
161
|
for these bindings.
|
|
162
162
|
|
|
163
163
|
In the `shared` profile, `PluginManager` indexes desired state by the complete
|
|
164
|
-
installation binding.
|
|
164
|
+
installation binding. Each desired-state entry has an additive
|
|
165
|
+
`execution_mode`: omission or `dedicated` preserves the historical one-process
|
|
166
|
+
per installation behavior, while `shared-runtime-v1` opts a certified
|
|
167
|
+
`shared-runtime-v1` installation into a digest-scoped worker pool. Core is
|
|
168
|
+
responsible for selecting `shared-runtime-v1` only after certification succeeds;
|
|
169
|
+
the Runtime never infers shared authority from tenant-controlled manifest data.
|
|
170
|
+
The instance-scoped `RECONCILE_PLUGIN_INSTALLATIONS`
|
|
165
171
|
action replays the authoritative set, while tenant-scoped
|
|
166
172
|
`APPLY_PLUGIN_INSTALLATION` and `REMOVE_PLUGIN_INSTALLATION` actions change one
|
|
167
173
|
installation. Newer placement generations or Runtime revisions fence the old
|
|
168
174
|
worker immediately; stale or cross-Workspace transitions fail closed.
|
|
169
175
|
|
|
170
|
-
|
|
176
|
+
Dedicated enabled installations remain owned by installation-scoped
|
|
177
|
+
Supervisors. A certified shared worker is keyed by the raw artifact digest and
|
|
178
|
+
currently has pool size one: the first slot attach starts it and the last slot
|
|
179
|
+
detach stops it. Installations sharing that process retain separate
|
|
180
|
+
`BasePlugin`, component, config, Host authority, and lifecycle slots. Updating
|
|
181
|
+
one slot reinitializes that slot without restarting siblings. Revision and
|
|
182
|
+
generation fencing remove the exact stale slot, cancel its in-flight actions,
|
|
183
|
+
and prevent background calls after detach.
|
|
184
|
+
|
|
171
185
|
Unexpected worker exit is recovered with bounded exponential backoff. Disable,
|
|
172
186
|
remove, placement generation changes, Runtime revision changes, and shutdown
|
|
173
187
|
fence the old Supervisor before it can relaunch, while reconcile and control
|
|
@@ -183,9 +197,14 @@ installation or Workspace identity.
|
|
|
183
197
|
|
|
184
198
|
Plugin packages are verified against `artifact_digest` and extracted once into
|
|
185
199
|
a read-only `artifacts/sha256/<digest>/code` tree. Installations may share that
|
|
186
|
-
code tree
|
|
187
|
-
|
|
188
|
-
|
|
200
|
+
code tree. Dedicated mode gives each installation a separate process and private
|
|
201
|
+
`home`, `tmp`, and `data` directories. Certified shared workers mount no
|
|
202
|
+
installation or tenant-writable directory; their writable scratch belongs to
|
|
203
|
+
the digest process and tenant state must go through Host actions. A dedicated
|
|
204
|
+
worker capability is bound to one complete installation tuple. A shared worker
|
|
205
|
+
capability is additionally bound to its digest; after registration, every slot
|
|
206
|
+
RPC carries an exact current `InstallationBinding` and cannot select or rebind
|
|
207
|
+
tenant scope.
|
|
189
208
|
|
|
190
209
|
Before any desired-state artifact worker is launched, the Runtime prepares an
|
|
191
210
|
immutable dependency tree. The resulting `site-packages` tree is keyed by the
|
|
@@ -197,7 +216,8 @@ stable `dependency_prepare_failed` desired-state failure. Pip control options in
|
|
|
197
216
|
an artifact's `requirements.txt` are rejected because only Runtime configuration
|
|
198
217
|
may select indexes or trusted hosts.
|
|
199
218
|
|
|
200
|
-
|
|
219
|
+
Workers in the shared Runtime profile launch through nsjail with policy-owned
|
|
220
|
+
cgroup CPU, memory, and
|
|
201
221
|
PID limits plus file/process rlimits. If `require_hard_limits` is true, missing
|
|
202
222
|
nsjail or cgroup v2 delegation makes configuration fail closed. Their dependency
|
|
203
223
|
tree is prepared in a separate nsjail and mounted read-only into the worker.
|
|
@@ -305,7 +325,9 @@ An OSS-only exception permits legacy knowledge `FILE_CHUNK` replies carrying
|
|
|
305
325
|
instance and already-bound Workspace/generation, and its installation capability
|
|
306
326
|
must exactly match a live registered plugin connection. Payload scope is ignored.
|
|
307
327
|
Shared transfers still require a complete binding; candidate artifact pretransfer
|
|
308
|
-
validates that binding without activating desired state.
|
|
328
|
+
validates that binding without activating desired state. Transfer ownership and
|
|
329
|
+
tenant-visible plugin containers/log routing remain installation scoped even
|
|
330
|
+
when several slots use one process.
|
|
309
331
|
|
|
310
332
|
Legacy OSS plugins are stored under `data/plugins/{author}__{name}`. Runtime
|
|
311
333
|
plugin processes normally run as separate Python processes and connect back via
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: langbot-plugin
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.2
|
|
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
|
|
@@ -4,6 +4,7 @@ import asyncio
|
|
|
4
4
|
import os
|
|
5
5
|
import typing
|
|
6
6
|
import logging
|
|
7
|
+
import copy
|
|
7
8
|
|
|
8
9
|
from langbot_plugin.api.definition.components.manifest import ComponentManifest
|
|
9
10
|
from langbot_plugin.runtime.plugin.container import (
|
|
@@ -32,6 +33,7 @@ from langbot_plugin.api.definition.components.page import Page
|
|
|
32
33
|
from langbot_plugin.api.definition.components.parser.parser import Parser
|
|
33
34
|
from langbot_plugin.api.definition.components.runner.runner import Runner
|
|
34
35
|
from langbot_plugin.entities.io.errors import ConnectionClosedError
|
|
36
|
+
from langbot_plugin.entities.io.context import InstallationBinding
|
|
35
37
|
from langbot_plugin.cli.run.hotreload import HotReloader, reload_plugin_modules
|
|
36
38
|
from langbot_plugin.runtime.security import (
|
|
37
39
|
PLUGIN_DEBUG_KEY_ENV,
|
|
@@ -44,6 +46,39 @@ from langbot_plugin.runtime.security import (
|
|
|
44
46
|
logger = logging.getLogger(__name__)
|
|
45
47
|
|
|
46
48
|
|
|
49
|
+
class _SlotHandlerProxy:
|
|
50
|
+
"""Bind every worker-to-Runtime call to one exact installation slot."""
|
|
51
|
+
|
|
52
|
+
def __init__(self, handler: PluginRuntimeHandler, binding: InstallationBinding):
|
|
53
|
+
self._handler = handler
|
|
54
|
+
self._binding = binding
|
|
55
|
+
|
|
56
|
+
async def call_action(self, action, data, timeout=15.0, **kwargs):
|
|
57
|
+
kwargs["action_context"] = self._binding
|
|
58
|
+
return await self._handler.call_action(action, data, timeout=timeout, **kwargs)
|
|
59
|
+
|
|
60
|
+
def call_action_generator(self, action, data, timeout=15.0, **kwargs):
|
|
61
|
+
kwargs["action_context"] = self._binding
|
|
62
|
+
return self._handler.call_action_generator(
|
|
63
|
+
action, data, timeout=timeout, **kwargs
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
async def send_file(self, file_bytes, file_extension, **kwargs):
|
|
67
|
+
kwargs["action_context"] = self._binding
|
|
68
|
+
return await self._handler.send_file(file_bytes, file_extension, **kwargs)
|
|
69
|
+
|
|
70
|
+
async def read_local_file(self, file_key, **kwargs):
|
|
71
|
+
kwargs["action_context"] = self._binding
|
|
72
|
+
return await self._handler.read_local_file(file_key, **kwargs)
|
|
73
|
+
|
|
74
|
+
async def delete_local_file(self, file_key, **kwargs):
|
|
75
|
+
kwargs["action_context"] = self._binding
|
|
76
|
+
return await self._handler.delete_local_file(file_key, **kwargs)
|
|
77
|
+
|
|
78
|
+
def __getattr__(self, name):
|
|
79
|
+
return getattr(self._handler, name)
|
|
80
|
+
|
|
81
|
+
|
|
47
82
|
def _apply_runner_class_defaults(
|
|
48
83
|
component_manifest: ComponentManifest,
|
|
49
84
|
component_impl_cls: type[Runner],
|
|
@@ -119,6 +154,7 @@ class PluginRuntimeController:
|
|
|
119
154
|
status=RuntimeContainerStatus.UNMOUNTED,
|
|
120
155
|
components=components_containers,
|
|
121
156
|
)
|
|
157
|
+
self._slot_containers: dict[str, PluginContainer] = {}
|
|
122
158
|
|
|
123
159
|
async def run(self) -> None:
|
|
124
160
|
await self._controller_task
|
|
@@ -167,6 +203,8 @@ class PluginRuntimeController:
|
|
|
167
203
|
|
|
168
204
|
async def new_connection_callback(connection: Connection):
|
|
169
205
|
self.handler = PluginRuntimeHandler(connection, self.initialize)
|
|
206
|
+
self.handler._slot_initialize_callback = self.initialize_slot
|
|
207
|
+
self.handler._slot_detach_callback = self.detach_slot
|
|
170
208
|
|
|
171
209
|
async def disconnect_callback(hdl: PluginRuntimeHandler):
|
|
172
210
|
if self.prod_mode:
|
|
@@ -304,18 +342,30 @@ class PluginRuntimeController:
|
|
|
304
342
|
)
|
|
305
343
|
logger.debug(f"plugin_settings: {plugin_settings}")
|
|
306
344
|
|
|
307
|
-
self.
|
|
308
|
-
|
|
309
|
-
|
|
345
|
+
await self._initialize_container(
|
|
346
|
+
self.plugin_container,
|
|
347
|
+
self.handler,
|
|
348
|
+
plugin_settings,
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
async def _initialize_container(
|
|
352
|
+
self,
|
|
353
|
+
plugin_container: PluginContainer,
|
|
354
|
+
runtime_handler: typing.Any,
|
|
355
|
+
plugin_settings: dict[str, typing.Any],
|
|
356
|
+
) -> None:
|
|
357
|
+
"""Initialize one object graph without mutating controller-global routing."""
|
|
358
|
+
|
|
359
|
+
plugin_container.enabled = plugin_settings["enabled"]
|
|
360
|
+
plugin_container.priority = plugin_settings["priority"]
|
|
361
|
+
plugin_container.plugin_config = plugin_settings["plugin_config"]
|
|
310
362
|
# initialize plugin instance
|
|
311
|
-
plugin_cls =
|
|
363
|
+
plugin_cls = plugin_container.manifest.get_python_component_class()
|
|
312
364
|
assert isinstance(plugin_cls, type(BasePlugin))
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
)
|
|
317
|
-
self.plugin_container.plugin_instance.plugin_runtime_handler = self.handler
|
|
318
|
-
await self.plugin_container.plugin_instance.initialize()
|
|
365
|
+
plugin_container.plugin_instance = plugin_cls()
|
|
366
|
+
plugin_container.plugin_instance.config = plugin_container.plugin_config
|
|
367
|
+
plugin_container.plugin_instance.plugin_runtime_handler = runtime_handler
|
|
368
|
+
await plugin_container.plugin_instance.initialize()
|
|
319
369
|
|
|
320
370
|
preinitialize_component_classes: list[type[BaseComponent]] = [
|
|
321
371
|
EventListener,
|
|
@@ -328,7 +378,7 @@ class PluginRuntimeController:
|
|
|
328
378
|
]
|
|
329
379
|
|
|
330
380
|
for component_cls in preinitialize_component_classes:
|
|
331
|
-
for component_container in
|
|
381
|
+
for component_container in plugin_container.components:
|
|
332
382
|
logger.debug(
|
|
333
383
|
f"Checking component {component_container.manifest.metadata.name}: "
|
|
334
384
|
f"kind={component_container.manifest.kind}, expected={component_cls.__kind__}"
|
|
@@ -349,15 +399,15 @@ class PluginRuntimeController:
|
|
|
349
399
|
component_impl_cls,
|
|
350
400
|
)
|
|
351
401
|
component_container.component_instance.bind_runtime(
|
|
352
|
-
plugin_runtime_handler=
|
|
353
|
-
plugin_config=
|
|
402
|
+
plugin_runtime_handler=runtime_handler,
|
|
403
|
+
plugin_config=plugin_container.plugin_config,
|
|
354
404
|
plugin_identity=(
|
|
355
|
-
f"{
|
|
356
|
-
f"{
|
|
405
|
+
f"{plugin_container.manifest.metadata.author}/"
|
|
406
|
+
f"{plugin_container.manifest.metadata.name}"
|
|
357
407
|
),
|
|
358
408
|
)
|
|
359
409
|
component_container.component_instance.plugin = (
|
|
360
|
-
|
|
410
|
+
plugin_container.plugin_instance
|
|
361
411
|
)
|
|
362
412
|
await component_container.component_instance.initialize()
|
|
363
413
|
logger.info(
|
|
@@ -369,12 +419,49 @@ class PluginRuntimeController:
|
|
|
369
419
|
f"Plugin {self.plugin_container.manifest.metadata.author}/{self.plugin_container.manifest.metadata.name} initialized"
|
|
370
420
|
)
|
|
371
421
|
|
|
372
|
-
|
|
422
|
+
plugin_container.status = RuntimeContainerStatus.INITIALIZED
|
|
423
|
+
|
|
424
|
+
async def initialize_slot(
|
|
425
|
+
self,
|
|
426
|
+
installation_uuid: str | InstallationBinding,
|
|
427
|
+
plugin_settings: dict[str, typing.Any],
|
|
428
|
+
) -> PluginContainer:
|
|
429
|
+
"""Create or replace one installation's independent object graph."""
|
|
430
|
+
|
|
431
|
+
slot_key = (
|
|
432
|
+
installation_uuid.installation_uuid
|
|
433
|
+
if isinstance(installation_uuid, InstallationBinding)
|
|
434
|
+
else installation_uuid
|
|
435
|
+
)
|
|
436
|
+
slot = PluginContainer.from_dict(
|
|
437
|
+
copy.deepcopy(self.plugin_container.model_dump())
|
|
438
|
+
)
|
|
439
|
+
slot.plugin_instance = NonePlugin()
|
|
440
|
+
for component in slot.components:
|
|
441
|
+
component.component_instance = NoneComponent()
|
|
442
|
+
runtime_handler: typing.Any = self.handler
|
|
443
|
+
if isinstance(installation_uuid, InstallationBinding):
|
|
444
|
+
runtime_handler = _SlotHandlerProxy(self.handler, installation_uuid)
|
|
445
|
+
await self._initialize_container(slot, runtime_handler, plugin_settings)
|
|
446
|
+
self._slot_containers[slot_key] = slot
|
|
447
|
+
return slot
|
|
448
|
+
|
|
449
|
+
def plugin_container_for_slot(
|
|
450
|
+
self,
|
|
451
|
+
installation_uuid: str,
|
|
452
|
+
) -> PluginContainer | None:
|
|
453
|
+
return self._slot_containers.get(installation_uuid)
|
|
454
|
+
|
|
455
|
+
async def detach_slot(self, installation_uuid: str) -> None:
|
|
456
|
+
"""Drop exactly one slot; sibling instances remain resident."""
|
|
457
|
+
|
|
458
|
+
self._slot_containers.pop(installation_uuid, None)
|
|
373
459
|
|
|
374
460
|
async def cleanup_instances(self) -> None:
|
|
375
461
|
"""Clean up all plugin and component instances."""
|
|
376
462
|
logger.info("Cleaning up plugin instances...")
|
|
377
463
|
|
|
464
|
+
self._slot_containers.clear()
|
|
378
465
|
# Clear component instances
|
|
379
466
|
for component_container in self.plugin_container.components:
|
|
380
467
|
# Reset component instance
|
|
@@ -19,6 +19,7 @@ from langbot_plugin.api.definition.components.base import NoneComponent
|
|
|
19
19
|
from langbot_plugin.api.definition.components.common.event_listener import EventListener
|
|
20
20
|
from langbot_plugin.entities.io.actions.enums import PluginToRuntimeAction
|
|
21
21
|
from langbot_plugin.entities.io.actions.enums import RuntimeToPluginAction
|
|
22
|
+
from langbot_plugin.entities.io.context import InstallationBinding
|
|
22
23
|
from langbot_plugin.api.definition.components.tool.tool import Tool
|
|
23
24
|
from langbot_plugin.api.definition.components.command.command import Command
|
|
24
25
|
from langbot_plugin.api.definition.components.knowledge_engine.engine import (
|
|
@@ -138,7 +139,7 @@ async def _iter_runner_results_with_deadline(
|
|
|
138
139
|
class PluginRuntimeHandler(Handler):
|
|
139
140
|
"""The handler for running plugins."""
|
|
140
141
|
|
|
141
|
-
|
|
142
|
+
_base_plugin_container: PluginContainer
|
|
142
143
|
|
|
143
144
|
shutdown_callback: (
|
|
144
145
|
typing.Callable[[], typing.Coroutine[typing.Any, typing.Any, None]] | None
|
|
@@ -155,6 +156,18 @@ class PluginRuntimeHandler(Handler):
|
|
|
155
156
|
super().__init__(connection)
|
|
156
157
|
self.name = "FromRuntime"
|
|
157
158
|
self._shutdown_task: asyncio.Task[None] | None = None
|
|
159
|
+
self._slot_containers: dict[str, PluginContainer] = {}
|
|
160
|
+
self._slot_initialize_callback: (
|
|
161
|
+
typing.Callable[
|
|
162
|
+
[InstallationBinding, dict[str, typing.Any]],
|
|
163
|
+
typing.Coroutine[typing.Any, typing.Any, PluginContainer],
|
|
164
|
+
]
|
|
165
|
+
| None
|
|
166
|
+
) = None
|
|
167
|
+
self._slot_detach_callback: (
|
|
168
|
+
typing.Callable[[str], typing.Coroutine[typing.Any, typing.Any, None]]
|
|
169
|
+
| None
|
|
170
|
+
) = None
|
|
158
171
|
|
|
159
172
|
@self.action(RuntimeToPluginAction.INITIALIZE_PLUGIN)
|
|
160
173
|
async def initialize_plugin(data: dict[str, typing.Any]) -> ActionResponse:
|
|
@@ -164,6 +177,44 @@ class PluginRuntimeHandler(Handler):
|
|
|
164
177
|
await plugin_initialize_callback(data["plugin_settings"])
|
|
165
178
|
return ActionResponse.success({})
|
|
166
179
|
|
|
180
|
+
@self.action(RuntimeToPluginAction.ATTACH_PLUGIN_SLOT)
|
|
181
|
+
async def attach_plugin_slot(data: dict[str, typing.Any]) -> ActionResponse:
|
|
182
|
+
binding = self.current_action_context
|
|
183
|
+
if not isinstance(binding, InstallationBinding):
|
|
184
|
+
raise ValueError("Shared slot attach requires InstallationBinding")
|
|
185
|
+
if self._slot_initialize_callback is None:
|
|
186
|
+
raise ValueError("Shared slot initialization is unavailable")
|
|
187
|
+
container = await self._slot_initialize_callback(
|
|
188
|
+
binding,
|
|
189
|
+
data["plugin_settings"],
|
|
190
|
+
)
|
|
191
|
+
self._slot_containers[binding.installation_uuid] = container
|
|
192
|
+
return ActionResponse.success({})
|
|
193
|
+
|
|
194
|
+
@self.action(RuntimeToPluginAction.DETACH_PLUGIN_SLOT)
|
|
195
|
+
async def detach_plugin_slot(data: dict[str, typing.Any]) -> ActionResponse:
|
|
196
|
+
del data
|
|
197
|
+
binding = self.current_action_context
|
|
198
|
+
if not isinstance(binding, InstallationBinding):
|
|
199
|
+
raise ValueError("Shared slot detach requires InstallationBinding")
|
|
200
|
+
if self._slot_detach_callback is not None:
|
|
201
|
+
await self._slot_detach_callback(binding.installation_uuid)
|
|
202
|
+
self._slot_containers.pop(binding.installation_uuid, None)
|
|
203
|
+
return ActionResponse.success({})
|
|
204
|
+
|
|
205
|
+
@self.action(RuntimeToPluginAction.GET_PLUGIN_SLOT_CONTAINER)
|
|
206
|
+
async def get_plugin_slot_container(
|
|
207
|
+
data: dict[str, typing.Any],
|
|
208
|
+
) -> ActionResponse:
|
|
209
|
+
del data
|
|
210
|
+
binding = self.current_action_context
|
|
211
|
+
if not isinstance(binding, InstallationBinding):
|
|
212
|
+
raise ValueError("Shared slot lookup requires InstallationBinding")
|
|
213
|
+
container = self._slot_containers.get(binding.installation_uuid)
|
|
214
|
+
if container is None:
|
|
215
|
+
raise ValueError("Shared plugin slot is not attached")
|
|
216
|
+
return ActionResponse.success(container.model_dump())
|
|
217
|
+
|
|
167
218
|
@self.action(RuntimeToPluginAction.GET_PLUGIN_CONTAINER)
|
|
168
219
|
async def get_plugin_container(data: dict[str, typing.Any]) -> ActionResponse:
|
|
169
220
|
return ActionResponse.success(self.plugin_container.model_dump())
|
|
@@ -713,6 +764,19 @@ class PluginRuntimeHandler(Handler):
|
|
|
713
764
|
|
|
714
765
|
return ActionResponse.success(result.model_dump(mode="json"))
|
|
715
766
|
|
|
767
|
+
@property
|
|
768
|
+
def plugin_container(self) -> PluginContainer:
|
|
769
|
+
binding = self.current_action_context
|
|
770
|
+
if isinstance(binding, InstallationBinding):
|
|
771
|
+
slot = self._slot_containers.get(binding.installation_uuid)
|
|
772
|
+
if slot is not None:
|
|
773
|
+
return slot
|
|
774
|
+
return self._base_plugin_container
|
|
775
|
+
|
|
776
|
+
@plugin_container.setter
|
|
777
|
+
def plugin_container(self, value: PluginContainer) -> None:
|
|
778
|
+
self._base_plugin_container = value
|
|
779
|
+
|
|
716
780
|
async def register_plugin(
|
|
717
781
|
self,
|
|
718
782
|
prod_mode: bool = False,
|
{langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/entities/io/actions/enums.py
RENAMED
|
@@ -134,6 +134,9 @@ class RuntimeToPluginAction(ActionType):
|
|
|
134
134
|
"""The action from runtime to plugin."""
|
|
135
135
|
|
|
136
136
|
INITIALIZE_PLUGIN = "initialize_plugin"
|
|
137
|
+
ATTACH_PLUGIN_SLOT = "attach_plugin_slot"
|
|
138
|
+
DETACH_PLUGIN_SLOT = "detach_plugin_slot"
|
|
139
|
+
GET_PLUGIN_SLOT_CONTAINER = "get_plugin_slot_container"
|
|
137
140
|
GET_PLUGIN_CONTAINER = "get_plugin_container"
|
|
138
141
|
GET_PLUGIN_ICON = "get_plugin_icon"
|
|
139
142
|
GET_PLUGIN_README = "get_plugin_readme"
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import json
|
|
4
4
|
import math
|
|
5
5
|
import re
|
|
6
|
+
from enum import Enum
|
|
6
7
|
from typing import Literal
|
|
7
8
|
|
|
8
9
|
import pydantic
|
|
@@ -11,6 +12,13 @@ import pydantic
|
|
|
11
12
|
_SHA256_DIGEST_PATTERN = re.compile(r"^[0-9a-f]{64}$")
|
|
12
13
|
|
|
13
14
|
|
|
15
|
+
class PluginExecutionMode(str, Enum):
|
|
16
|
+
"""Process placement selected by the trusted control plane."""
|
|
17
|
+
|
|
18
|
+
DEDICATED = "dedicated"
|
|
19
|
+
SHARED_CERTIFIED = "shared-runtime-v1"
|
|
20
|
+
|
|
21
|
+
|
|
14
22
|
class RuntimeIdentity(pydantic.BaseModel):
|
|
15
23
|
"""Stable instance scope plus this Runtime process' short-lived identity."""
|
|
16
24
|
|
|
@@ -333,6 +341,7 @@ class PluginInstallationDesiredState(pydantic.BaseModel):
|
|
|
333
341
|
|
|
334
342
|
binding: InstallationBinding
|
|
335
343
|
enabled: bool = True
|
|
344
|
+
execution_mode: PluginExecutionMode = PluginExecutionMode.DEDICATED
|
|
336
345
|
|
|
337
346
|
model_config = pydantic.ConfigDict(extra="forbid", frozen=True)
|
|
338
347
|
|
|
@@ -364,6 +373,7 @@ class ReconcilePluginInstallationsRequest(pydantic.BaseModel):
|
|
|
364
373
|
class ApplyPluginInstallationRequest(pydantic.BaseModel):
|
|
365
374
|
artifact_file_key: str | None = None
|
|
366
375
|
enabled: bool = True
|
|
376
|
+
execution_mode: PluginExecutionMode = PluginExecutionMode.DEDICATED
|
|
367
377
|
|
|
368
378
|
model_config = pydantic.ConfigDict(extra="forbid", frozen=True)
|
|
369
379
|
|
|
@@ -68,8 +68,11 @@ async def _run_small_protocol_work(fn: Callable[..., Any], *args: Any) -> Any:
|
|
|
68
68
|
def _file_storage_path(
|
|
69
69
|
file_key: str,
|
|
70
70
|
file_storage_dir: str | os.PathLike[str] = FILE_STORAGE_DIR,
|
|
71
|
+
*,
|
|
72
|
+
action_context: ActionEnvelopeContext | None = None,
|
|
73
|
+
create_namespace: bool = False,
|
|
71
74
|
) -> str:
|
|
72
|
-
"""Resolve one opaque
|
|
75
|
+
"""Resolve one opaque key inside its durable authority namespace."""
|
|
73
76
|
|
|
74
77
|
if not isinstance(file_key, str):
|
|
75
78
|
raise ValueError("Invalid file transfer key")
|
|
@@ -85,7 +88,20 @@ def _file_storage_path(
|
|
|
85
88
|
or _SAFE_FILE_KEY_PATTERN.fullmatch(key) is None
|
|
86
89
|
):
|
|
87
90
|
raise ValueError("Invalid file transfer key")
|
|
88
|
-
|
|
91
|
+
if action_context is None:
|
|
92
|
+
namespace = "unbound"
|
|
93
|
+
else:
|
|
94
|
+
serialized_context = json.dumps(
|
|
95
|
+
action_context.model_dump(mode="json"),
|
|
96
|
+
sort_keys=True,
|
|
97
|
+
separators=(",", ":"),
|
|
98
|
+
).encode("utf-8")
|
|
99
|
+
namespace = hashlib.sha256(serialized_context).hexdigest()
|
|
100
|
+
namespace_path = os.path.join(os.fspath(file_storage_dir), namespace)
|
|
101
|
+
if create_namespace:
|
|
102
|
+
os.makedirs(namespace_path, mode=0o700, exist_ok=True)
|
|
103
|
+
os.chmod(namespace_path, 0o700)
|
|
104
|
+
return os.path.join(namespace_path, key)
|
|
89
105
|
|
|
90
106
|
|
|
91
107
|
class Handler(abc.ABC):
|
|
@@ -123,6 +139,9 @@ class Handler(abc.ABC):
|
|
|
123
139
|
self.resp_waiters = {}
|
|
124
140
|
self.resp_queues = {}
|
|
125
141
|
self._action_tasks: set[asyncio.Task[None]] = set()
|
|
142
|
+
self._action_task_contexts: dict[
|
|
143
|
+
asyncio.Task[None], ActionEnvelopeContext | None
|
|
144
|
+
] = {}
|
|
126
145
|
self._active_tasks: set[asyncio.Task[None]] = set()
|
|
127
146
|
# Reserved tasks remain in the common set for cancellation and accounting.
|
|
128
147
|
self._reserved_action_tasks: set[asyncio.Task[None]] = set()
|
|
@@ -162,10 +181,6 @@ class Handler(abc.ABC):
|
|
|
162
181
|
|
|
163
182
|
@self.action(CommonAction.FILE_CHUNK)
|
|
164
183
|
async def file_chunk(data: dict[str, Any]) -> ActionResponse:
|
|
165
|
-
file_path = _file_storage_path(
|
|
166
|
-
data["file_key"],
|
|
167
|
-
self.file_storage_dir,
|
|
168
|
-
)
|
|
169
184
|
chunk_base64 = data["chunk_base64"]
|
|
170
185
|
chunk_index = data["chunk_index"]
|
|
171
186
|
chunk_amount = data["chunk_amount"]
|
|
@@ -188,12 +203,19 @@ class Handler(abc.ABC):
|
|
|
188
203
|
if len(chunk_bytes) > FILE_CHUNK_LENGTH:
|
|
189
204
|
raise ValueError("File transfer chunk exceeds the protocol limit")
|
|
190
205
|
async with self._file_transfer_lock:
|
|
206
|
+
transfer_context = self.resolve_effective_action_context()
|
|
207
|
+
file_path = _file_storage_path(
|
|
208
|
+
data["file_key"],
|
|
209
|
+
self.file_storage_dir,
|
|
210
|
+
action_context=transfer_context,
|
|
211
|
+
create_namespace=True,
|
|
212
|
+
)
|
|
191
213
|
if (
|
|
192
|
-
|
|
214
|
+
file_path not in self._owned_transfer_files
|
|
193
215
|
and len(self._owned_transfer_files) >= MAX_ACTIVE_FILE_TRANSFERS
|
|
194
216
|
):
|
|
195
217
|
raise ValueError("Active file transfer capacity reached")
|
|
196
|
-
self._owned_transfer_files.add(
|
|
218
|
+
self._owned_transfer_files.add(file_path)
|
|
197
219
|
# The first chunk replaces stale partial data for the same
|
|
198
220
|
# opaque transfer id; later chunks append. Runtime-side
|
|
199
221
|
# installation handlers cap the aggregate bytes written on
|
|
@@ -440,6 +462,9 @@ class Handler(abc.ABC):
|
|
|
440
462
|
request.context,
|
|
441
463
|
)
|
|
442
464
|
context_token = self._current_action_context.set(action_context)
|
|
465
|
+
current_task = asyncio.current_task()
|
|
466
|
+
if current_task is not None:
|
|
467
|
+
self._action_task_contexts[current_task] = action_context
|
|
443
468
|
|
|
444
469
|
with blocking_work_scope(getattr(action_context, "workspace_uuid", None)):
|
|
445
470
|
response = self.actions[action_name](request.data)
|
|
@@ -476,6 +501,9 @@ class Handler(abc.ABC):
|
|
|
476
501
|
finally:
|
|
477
502
|
if context_token is not None:
|
|
478
503
|
self._current_action_context.reset(context_token)
|
|
504
|
+
current_task = asyncio.current_task()
|
|
505
|
+
if current_task is not None:
|
|
506
|
+
self._action_task_contexts.pop(current_task, None)
|
|
479
507
|
if action_name and not action_name.startswith("__"):
|
|
480
508
|
logger.debug("[Action] %s", action_name)
|
|
481
509
|
|
|
@@ -532,6 +560,16 @@ class Handler(abc.ABC):
|
|
|
532
560
|
for action_task in tuple(self._action_tasks):
|
|
533
561
|
action_task.cancel()
|
|
534
562
|
|
|
563
|
+
def cancel_inflight_messages_for_context(
|
|
564
|
+
self,
|
|
565
|
+
action_context: ActionEnvelopeContext,
|
|
566
|
+
) -> None:
|
|
567
|
+
"""Cancel only requests owned by one exact installation revision."""
|
|
568
|
+
|
|
569
|
+
for action_task, owned_context in tuple(self._action_task_contexts.items()):
|
|
570
|
+
if owned_context == action_context:
|
|
571
|
+
action_task.cancel()
|
|
572
|
+
|
|
535
573
|
async def call_action(
|
|
536
574
|
self,
|
|
537
575
|
action: ActionType,
|
|
@@ -753,6 +791,16 @@ class Handler(abc.ABC):
|
|
|
753
791
|
)
|
|
754
792
|
return context
|
|
755
793
|
|
|
794
|
+
def resolve_effective_action_context(
|
|
795
|
+
self,
|
|
796
|
+
action_context: ActionEnvelopeContext | dict[str, Any] | None = None,
|
|
797
|
+
) -> ActionEnvelopeContext | None:
|
|
798
|
+
"""Resolve explicit, task-local, then connection-bound authority."""
|
|
799
|
+
|
|
800
|
+
if action_context is not None:
|
|
801
|
+
return self.resolve_outbound_action_context(action_context)
|
|
802
|
+
return self._current_action_context.get() or self._bound_action_context
|
|
803
|
+
|
|
756
804
|
# decorator to register an action
|
|
757
805
|
def action(
|
|
758
806
|
self, name: ActionType
|
|
@@ -847,8 +895,18 @@ class Handler(abc.ABC):
|
|
|
847
895
|
)
|
|
848
896
|
return file_key
|
|
849
897
|
|
|
850
|
-
async def read_local_file(
|
|
851
|
-
|
|
898
|
+
async def read_local_file(
|
|
899
|
+
self,
|
|
900
|
+
file_key: str,
|
|
901
|
+
*,
|
|
902
|
+
action_context: ActionEnvelopeContext | dict[str, Any] | None = None,
|
|
903
|
+
) -> bytes:
|
|
904
|
+
transfer_context = self.resolve_effective_action_context(action_context)
|
|
905
|
+
file_path = _file_storage_path(
|
|
906
|
+
file_key,
|
|
907
|
+
self.file_storage_dir,
|
|
908
|
+
action_context=transfer_context,
|
|
909
|
+
)
|
|
852
910
|
|
|
853
911
|
def read_file() -> bytes:
|
|
854
912
|
if self.max_file_bytes is not None:
|
|
@@ -866,33 +924,44 @@ class Handler(abc.ABC):
|
|
|
866
924
|
await run_blocking_with_backpressure(os.path.getsize, file_path)
|
|
867
925
|
return content
|
|
868
926
|
|
|
869
|
-
async def delete_local_file(
|
|
927
|
+
async def delete_local_file(
|
|
928
|
+
self,
|
|
929
|
+
file_key: str,
|
|
930
|
+
*,
|
|
931
|
+
action_context: ActionEnvelopeContext | dict[str, Any] | None = None,
|
|
932
|
+
) -> None:
|
|
933
|
+
transfer_context = self.resolve_effective_action_context(action_context)
|
|
934
|
+
file_path = _file_storage_path(
|
|
935
|
+
file_key,
|
|
936
|
+
self.file_storage_dir,
|
|
937
|
+
action_context=transfer_context,
|
|
938
|
+
)
|
|
870
939
|
async with self._file_transfer_lock:
|
|
871
940
|
try:
|
|
872
941
|
await run_blocking_with_backpressure(
|
|
873
942
|
os.remove,
|
|
874
|
-
|
|
943
|
+
file_path,
|
|
875
944
|
)
|
|
876
945
|
except FileNotFoundError:
|
|
877
946
|
pass
|
|
878
947
|
finally:
|
|
879
|
-
self._owned_transfer_files.discard(
|
|
948
|
+
self._owned_transfer_files.discard(file_path)
|
|
880
949
|
|
|
881
950
|
async def _cleanup_owned_transfers(self) -> None:
|
|
882
951
|
async with self._file_transfer_lock:
|
|
883
|
-
|
|
952
|
+
file_paths = tuple(self._owned_transfer_files)
|
|
884
953
|
self._owned_transfer_files.clear()
|
|
885
|
-
for
|
|
954
|
+
for file_path in file_paths:
|
|
886
955
|
try:
|
|
887
956
|
await run_blocking_cleanup(
|
|
888
957
|
os.remove,
|
|
889
|
-
|
|
958
|
+
file_path,
|
|
890
959
|
)
|
|
891
960
|
except FileNotFoundError:
|
|
892
961
|
pass
|
|
893
962
|
except OSError as exc:
|
|
894
963
|
logger.warning(
|
|
895
964
|
"Failed to clean runtime transfer file %s: %s",
|
|
896
|
-
|
|
965
|
+
os.path.basename(file_path),
|
|
897
966
|
exc,
|
|
898
967
|
)
|
{langbot_plugin-0.6.1b2 → langbot_plugin-0.6.2}/src/langbot_plugin/runtime/io/handlers/control.py
RENAMED
|
@@ -167,10 +167,15 @@ class ControlConnectionHandler(handler.Handler):
|
|
|
167
167
|
if request.artifact_file_key is not None:
|
|
168
168
|
artifact_package = await self.read_local_file(request.artifact_file_key)
|
|
169
169
|
await self.delete_local_file(request.artifact_file_key)
|
|
170
|
+
apply_kwargs: dict[str, Any] = {
|
|
171
|
+
"artifact_package": artifact_package,
|
|
172
|
+
"enabled": request.enabled,
|
|
173
|
+
}
|
|
174
|
+
if request.execution_mode.value != "dedicated":
|
|
175
|
+
apply_kwargs["execution_mode"] = request.execution_mode
|
|
170
176
|
result = await self.context.plugin_mgr.apply_plugin_installation(
|
|
171
177
|
binding,
|
|
172
|
-
|
|
173
|
-
enabled=request.enabled,
|
|
178
|
+
**apply_kwargs,
|
|
174
179
|
)
|
|
175
180
|
return handler.ActionResponse.success(result)
|
|
176
181
|
|