langbot-plugin 0.7.12__tar.gz → 0.7.13__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.7.12 → langbot_plugin-0.7.13}/ARCHITECTURE.md +35 -6
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/PKG-INFO +1 -1
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/pyproject.toml +1 -1
- langbot_plugin-0.7.13/src/langbot_plugin/artifact.py +245 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/box/actions.py +0 -11
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/box/backend.py +63 -4
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/box/client.py +0 -227
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/box/e2b_backend.py +370 -20
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/box/host_backend.py +16 -1
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/box/models.py +53 -19
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/box/nsjail_backend.py +7 -6
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/box/runtime.py +117 -46
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/box/server.py +4 -145
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/box/tenancy.py +4 -8
- langbot_plugin-0.7.13/src/langbot_plugin/skill_store.py +1640 -0
- langbot_plugin-0.7.13/src/langbot_plugin/version.py +1 -0
- langbot_plugin-0.7.13/src/langbot_plugin/workspace.py +19 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/box/test_admission.py +62 -22
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/box/test_backend.py +36 -1
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/box/test_client.py +0 -180
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/box/test_e2b_backend.py +334 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/box/test_nsjail_backend.py +1 -1
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/box/test_runtime.py +113 -1
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/box/test_server.py +14 -295
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/box/test_skill_store.py +139 -136
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/box/test_storage_analysis.py +3 -4
- langbot_plugin-0.7.13/tests/e2e/test_run_mount_isolation.py +117 -0
- langbot_plugin-0.7.13/tests/test_artifact_materialization.py +77 -0
- langbot_plugin-0.7.13/tests/test_skill_store.py +300 -0
- langbot_plugin-0.7.12/src/langbot_plugin/box/skill_store.py +0 -1015
- langbot_plugin-0.7.12/src/langbot_plugin/version.py +0 -1
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/.github/workflows/cla.yml +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/.github/workflows/publish-pypi.yaml +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/.github/workflows/publish.yml +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/.github/workflows/test.yml +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/.gitignore +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/.python-version +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/AGENTS.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/CLAUDE.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/CONTRIBUTING.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/LICENSE +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/README.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/README_CN.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/data/.env.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/docs/Message.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/docs/PluginPages.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/docs/agent-runner-interactions.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/docs/agent-runner-pluginization/PROTOCOL_V1.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/docs/agent-runner-pluginization/README.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/docs/agent-runner-pluginization/SDK_RUNTIME_PLAN.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/docs/certified-plugins.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/docs/communication/apis/lb2rt.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/docs/communication/runtime_plugin.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/docs/dependency-management.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/docs/langbot-plugin-social.png +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/docs/runner.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/docs/stateless-components.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/local_e2e/acceptance.json +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/local_e2e/registration_fanin.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/local_e2e/run_acceptance.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/mypy.ini +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/scripts/check_action_consistency.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/scripts/runtime_resource_probe.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/agent_tools/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/agent_tools/asset_gateway.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/agent_tools/daemon.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/agent_tools/decorators.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/agent_tools/external_tools.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/agent_tools/mcp_access.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/agent_tools/mcp_bridge.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/agent_tools/mcp_config.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/agent_tools/mcp_protocol.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/agent_tools/mcp_stdio.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/abstract/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/abstract/platform/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/abstract/platform/adapter.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/abstract/platform/event_logger.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/base.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/command/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/command/command.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/common/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/common/event_listener.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/knowledge_engine/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/knowledge_engine/engine.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/manifest.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/page/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/parser/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/parser/parser.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/runner/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/runner/runner.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/tool/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/components/tool/tool.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/definition/plugin.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/command/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/command/context.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/command/errors.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/pipeline/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/pipeline/query.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/platform/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/platform/entities.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/platform/errors.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/platform/events.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/platform/logger.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/platform/message.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/provider/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/provider/message.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/provider/prompt.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/provider/reasoning.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/provider/session.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/rag/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/rag/context.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/rag/enums.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/rag/errors.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/rag/models.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/resource/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/resource/tool.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/box.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/capabilities.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/compat.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/context.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/context_access.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/delivery.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/errors.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/event.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/input.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/interaction.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/manifest.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/page_results.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/permissions.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/resources.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/result.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/run_ledger.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/runtime.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/runtime_registry.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/state.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/stats.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/steering.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/transcript.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/builtin/runner/trigger.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/context.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/events.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/entities/execution.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/base.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/event_context.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/execute_context.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/invocation.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/langbot_api.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/query_based_api.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/runner/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/runner/admin.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/runner/api.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/runner/box.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/runner/common.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/runner/context.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/runner/ledger.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/runner/platform.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/runner/reply_stream.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/runner/resources.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/runner/state.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/api/proxies/runner/tracing.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/langbot-page-sdk.js +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/.env.example.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/.github/workflows/release.yml.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/.gitignore.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/.vscode/launch.json.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/README.md.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/assets/icon.svg.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/commands/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/commands/{cmd_name}.py.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/commands/{cmd_name}.yaml.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/event_listener/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/event_listener/default.py.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/event_listener/default.yaml.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/knowledge_engine/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/knowledge_engine/{knowledge_engine_name}.py.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/knowledge_engine/{knowledge_engine_name}.yaml.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/pages/{page_name}.html.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/pages/{page_name}.yaml.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/parser/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/parser/{parser_name}.py.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/parser/{parser_name}.yaml.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/runner/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/runner/{runner_name}.py.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/runner/{runner_name}.yaml.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/tools/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/tools/{tool_name}.py.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/components/tools/{tool_name}.yaml.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/main.py.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/manifest.yaml.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/readme/README_zh_Hans.md.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/assets/templates/requirements.txt.example +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/box/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/box/errors.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/box/security.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/certification.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/__main__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/commands/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/commands/buildplugin.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/commands/gencomponent.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/commands/initplugin.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/commands/login.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/commands/logout.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/commands/publish.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/commands/runplugin.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/gen/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/gen/renderer.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/i18n.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/locales/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/locales/en_US.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/locales/es_ES.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/locales/ja_JP.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/locales/th_TH.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/locales/vi_VN.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/locales/zh_Hans.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/locales/zh_Hant.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/run/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/run/controller.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/run/handler.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/run/hotreload.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/utils/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/utils/cloudsv.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/utils/form.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/cli/utils/page_components.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/entities/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/entities/io/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/entities/io/actions/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/entities/io/actions/enums.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/entities/io/context.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/entities/io/errors.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/entities/io/req.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/entities/io/resp.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/entities/marketplace.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/LICENSE +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/README.md +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/app.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/bounded_executor.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/context.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/event_loop_monitor.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/helper/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/helper/marketplace.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/helper/pkgmgr.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/connection.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/connections/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/connections/stdio.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/connections/ws.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/controller.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/controllers/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/controllers/stdio/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/controllers/stdio/client.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/controllers/stdio/server.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/controllers/ws/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/controllers/ws/client.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/controllers/ws/server.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/handler.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/handlers/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/handlers/control.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/io/handlers/plugin.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/ops_metrics.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/plugin/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/plugin/artifact.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/plugin/container.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/plugin/dependency_environment.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/plugin/logbuffer.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/plugin/mgr.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/plugin/restart_coordinator.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/plugin/runner_service.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/plugin/worker_launcher.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/plugin/worker_observability.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/plugin/worker_watchdog.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/security.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/runtime/settings.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/storage.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/utils/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/utils/deadline.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/utils/discover/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/utils/discover/engine.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/utils/importutil.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/utils/log.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/src/langbot_plugin/utils/platform.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/definition/components/test_components.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/definition/components/test_imports.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/definition/test_manifest.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/entities/builtin/runner/test_context_result.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/entities/builtin/runner/test_history_event_entities.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/entities/builtin/runner/test_interaction.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/entities/builtin/runner/test_run_ledger_entities.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/entities/builtin/test_command_context.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/entities/builtin/test_platform_logger.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/entities/builtin/test_provider_message.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/entities/builtin/test_rag_models.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/entities/test_context.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/entities/test_events.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/proxies/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/proxies/test_agent_run_api_proxy.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/proxies/test_base.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/proxies/test_box_api.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/proxies/test_history_event_api_proxy.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/proxies/test_langbot_api.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/proxies/test_llm_stream_ownership.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/proxies/test_query_based_api.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/proxies/test_reasoning_parameter.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/test_agent_tools_mcp_bridge.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/test_runner_handlers.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/test_runner_handlers_matrix.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/api/test_runner_public_apis.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/box/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/box/test_backend_selection.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/box/test_host_backend.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/cli/run/test_controller.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/cli/run/test_hotreload.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/cli/run/test_runtime_handler.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/cli/test_buildplugin.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/cli/test_gencomponent.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/cli/test_i18n_form.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/cli/test_initplugin.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/cli/test_login.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/cli/test_logout_publish.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/cli/test_page_components.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/cli/test_renderer.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/cli/test_runner_usages.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/cli/test_runplugin.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/e2e/standalone_runtime_eba_probe.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/entities/io/test_dependency_errors.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/entities/io/test_protocol.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/fixtures/eba_event_probe_plugin/.gitignore +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/fixtures/eba_event_probe_plugin/assets/icon.svg +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/fixtures/eba_event_probe_plugin/components/event_listener/default.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/fixtures/eba_event_probe_plugin/components/event_listener/default.yaml +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/fixtures/eba_event_probe_plugin/main.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/fixtures/eba_event_probe_plugin/manifest.yaml +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/helpers/__init__.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/helpers/protocol.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/packaging/test_installed_cli_blackbox.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/packaging/test_release_metadata.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/helper/test_marketplace.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/helper/test_pkgmgr.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/io/handlers/test_control_handler.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/io/handlers/test_import_contracts.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/io/handlers/test_legacy_file_chunk.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/io/handlers/test_plugin_handler.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/io/test_action_consistency.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/io/test_connections.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/io/test_controllers.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/io/test_handler.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/io/test_heartbeat_admission.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/io/test_stdio_server.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/io/test_stream_flow_control.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_artifact_store.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_container.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_dependency_environment.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_exact_dify_real_worker.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_exact_legacy_sdk_compat.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_installation_manager.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_legacy_shadow.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_manager.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_mgr_runner.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_mode_resource_limits.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_restart_coordinator.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_shared_worker_subprocess.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_worker_launcher.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_worker_plugin_identity.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/plugin/test_workload_isolation.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/test_app.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/test_bounded_executor.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/test_event_loop_monitor.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/test_ops_metrics.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/runtime/test_pull_api_handlers.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/test_certification.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/test_log.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/test_message.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/test_plugin_logbuffer.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/test_storage.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/test_worker_observability.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/test_worker_watchdog.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/utils/test_deadline.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/utils/test_discovery.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/utils/test_importutil.py +0 -0
- {langbot_plugin-0.7.12 → langbot_plugin-0.7.13}/tests/utils/test_platform.py +0 -0
|
@@ -20,7 +20,7 @@ The runtime code under `src/langbot_plugin/runtime/` is AGPL; the rest of the re
|
|
|
20
20
|
This repo is coupled to LangBot but owns different things.
|
|
21
21
|
|
|
22
22
|
- The LangBot main repo owns product behavior, HTTP API, web UI, platform adapters, pipeline execution, model/tool orchestration, persistence, skills integration, and the LangBot-side runtime connectors.
|
|
23
|
-
- This SDK repo owns plugin author APIs, shared message/event/context entities, the action RPC protocol, `lbp`, Plugin Runtime implementation, and Box Runtime implementation.
|
|
23
|
+
- This SDK repo owns plugin author APIs, shared message/event/context entities, the action RPC protocol, the execution-independent filesystem Skill store, `lbp`, Plugin Runtime implementation, and Box Runtime implementation.
|
|
24
24
|
- Plugins import this package directly; LangBot also imports it for shared entities and runtime protocols.
|
|
25
25
|
|
|
26
26
|
If a change alters shared entities, component contracts, action names/payloads, runtime behavior, or Box models, update/test both repos in lockstep.
|
|
@@ -37,6 +37,8 @@ langbot-plugin-sdk/
|
|
|
37
37
|
│ ├── cli/ # `lbp` entrypoint and subcommands
|
|
38
38
|
│ ├── runtime/ # Plugin Runtime (`lbp rt`)
|
|
39
39
|
│ ├── box/ # Box Runtime (`lbp box`)
|
|
40
|
+
│ ├── skill_store.py # Execution-independent Skill package storage
|
|
41
|
+
│ ├── workspace.py # Neutral Workspace namespace identity
|
|
40
42
|
│ ├── entities/io/ # Action RPC request/response/error/action models
|
|
41
43
|
│ ├── assets/ # Scaffolding templates and page SDK asset
|
|
42
44
|
│ └── utils/
|
|
@@ -420,7 +422,7 @@ Important modules:
|
|
|
420
422
|
|
|
421
423
|
- `box/server.py`: CLI entrypoint, aiohttp WebSocket routes, `BoxServerHandler` action registration.
|
|
422
424
|
- `box/runtime.py`: session lifecycle, per-session locks, TTL cleanup, command execution, managed processes.
|
|
423
|
-
- `box/models.py`: `BoxSpec
|
|
425
|
+
- `box/models.py`: generic `BoxSpec`/read-only mount contracts, execution results, managed-process specs.
|
|
424
426
|
- `box/client.py`: action-RPC client used by LangBot-side connector/service.
|
|
425
427
|
- `box/actions.py`: `LangBotToBoxAction` enum.
|
|
426
428
|
- `box/backend.py`: backend abstraction and local backend selection.
|
|
@@ -428,7 +430,7 @@ Important modules:
|
|
|
428
430
|
trusted local development.
|
|
429
431
|
- `box/nsjail_backend.py`: nsjail backend.
|
|
430
432
|
- `box/e2b_backend.py`: E2B backend.
|
|
431
|
-
- `
|
|
433
|
+
- `skill_store.py`: generic Skill package CRUD, revision, and read-only resource helpers; it does not start or connect to Box.
|
|
432
434
|
- `box/security.py`: path/security helper logic.
|
|
433
435
|
|
|
434
436
|
Default Box WebSocket endpoints on port `5410`:
|
|
@@ -437,8 +439,34 @@ Default Box WebSocket endpoints on port `5410`:
|
|
|
437
439
|
- `/v1/sessions/{session_id}/managed-process/ws`: legacy default process stdio relay.
|
|
438
440
|
- `/v1/sessions/{session_id}/managed-process/{process_id}/ws`: named process stdio relay.
|
|
439
441
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
+
The Skill store keeps an authoritative registry in an `(instance, workspace)`
|
|
443
|
+
namespace. Each successful publication validates a complete staging tree,
|
|
444
|
+
computes one `sha256-tree-v1` digest, atomically installs an immutable revision,
|
|
445
|
+
and only then advances the registry pointer. Updates require the current
|
|
446
|
+
`base_revision`; deletion removes the pointer while retaining revisions for
|
|
447
|
+
active or recoverable runs. Former mutable package directories are only a
|
|
448
|
+
one-time online-upgrade import source.
|
|
449
|
+
|
|
450
|
+
LangBot Core composes pinned revisions into generic read-only `BoxMountSpec`
|
|
451
|
+
values. Ordinary fixed mounts include `content_digest` and `manifest_path` in
|
|
452
|
+
the session signature; supported digest-addressed packages are excluded from it.
|
|
453
|
+
Digest-addressed packages use the reserved
|
|
454
|
+
`/opt/langbot-artifacts/<digest>` namespace. Docker/Podman pre-mount a read-only
|
|
455
|
+
cache and atomically populate verified revisions before execution. E2B seals and
|
|
456
|
+
verifies packages before publishing stable digest projections. These packages can
|
|
457
|
+
be added after a Box is acquired, without replacing the session. nsjail applies
|
|
458
|
+
all mounts independently per execution. Fixed ordinary host mounts still reject
|
|
459
|
+
incompatible reuse; a conflict never implicitly destroys the existing session.
|
|
460
|
+
The unsafe host development backend maps each execution's paths without claiming
|
|
461
|
+
filesystem isolation. Cached artifacts are shared within a Box, just like its
|
|
462
|
+
Workspace; version pinning is not isolation between commands sharing that Box. Box
|
|
463
|
+
has no Skill model, CRUD API, or `SKILL.md` knowledge in its normal path; it only
|
|
464
|
+
validates and mounts artifacts. Copy-based backends prepare a digest-specific
|
|
465
|
+
staging tree, verify the complete manifest, and publish it before projecting the
|
|
466
|
+
mount path, so partial transfers and removed-file residue cannot be executed.
|
|
467
|
+
Core and the Box Runtime SDK are upgraded in lockstep; Box deliberately rejects
|
|
468
|
+
retired Skill-aware payload fields instead of carrying a mixed-version bridge.
|
|
469
|
+
Sandbox sessions and managed processes use an
|
|
442
470
|
`(instance, workspace, placement_generation)` namespace. Authenticated tenant
|
|
443
471
|
RPCs advance a monotonic generation fence, cancel in-flight older RPCs, and
|
|
444
472
|
retire older sessions. Managed-process relay handshakes carry Workspace and
|
|
@@ -484,5 +512,6 @@ The SDK `AGENTS.md` keeps the short command checklist; this file keeps the struc
|
|
|
484
512
|
- Keep plugin-author SDK APIs stable and explicit.
|
|
485
513
|
- Treat action enums and Pydantic models as cross-process API contracts.
|
|
486
514
|
- Keep runtime process management separate from LangBot product logic.
|
|
487
|
-
- Keep Box
|
|
515
|
+
- Keep Box limited to generic sandbox/session/mount semantics; Skill policy and
|
|
516
|
+
package orchestration belong to LangBot Core.
|
|
488
517
|
- Prefer tests around protocol shape and black-box CLI behavior when changing runtime boundaries.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: langbot-plugin
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.13
|
|
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
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import posixpath
|
|
7
|
+
import stat
|
|
8
|
+
from collections.abc import Collection
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
TREE_MANIFEST_ALGORITHM = "sha256-tree-v1"
|
|
12
|
+
_MAX_MANIFEST_BYTES = 4 * 1024 * 1024
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def validate_tree_manifest(
|
|
16
|
+
manifest: dict,
|
|
17
|
+
*,
|
|
18
|
+
max_files: int,
|
|
19
|
+
max_total_bytes: int,
|
|
20
|
+
subject: str = "Artifact",
|
|
21
|
+
) -> tuple[str, dict]:
|
|
22
|
+
"""Validate a persisted manifest and return its canonical digest."""
|
|
23
|
+
|
|
24
|
+
if not isinstance(manifest, dict) or set(manifest) != {
|
|
25
|
+
"algorithm",
|
|
26
|
+
"files",
|
|
27
|
+
"total_bytes",
|
|
28
|
+
}:
|
|
29
|
+
raise ValueError(f"{subject} manifest has an invalid shape")
|
|
30
|
+
if manifest["algorithm"] != TREE_MANIFEST_ALGORITHM:
|
|
31
|
+
raise ValueError(f"{subject} manifest uses an unsupported algorithm")
|
|
32
|
+
files = manifest["files"]
|
|
33
|
+
if not isinstance(files, list) or len(files) > max_files:
|
|
34
|
+
raise ValueError(f"{subject} manifest contains too many files")
|
|
35
|
+
seen: set[str] = set()
|
|
36
|
+
calculated_total = 0
|
|
37
|
+
for entry in files:
|
|
38
|
+
if not isinstance(entry, dict) or set(entry) != {
|
|
39
|
+
"path",
|
|
40
|
+
"size",
|
|
41
|
+
"sha256",
|
|
42
|
+
"executable",
|
|
43
|
+
}:
|
|
44
|
+
raise ValueError(f"{subject} manifest contains an invalid file entry")
|
|
45
|
+
path = entry["path"]
|
|
46
|
+
if (
|
|
47
|
+
not isinstance(path, str)
|
|
48
|
+
or not path
|
|
49
|
+
or "\0" in path
|
|
50
|
+
or "\\" in path
|
|
51
|
+
or posixpath.isabs(path)
|
|
52
|
+
or posixpath.normpath(path) != path
|
|
53
|
+
or path in {".", ".."}
|
|
54
|
+
or path.startswith("../")
|
|
55
|
+
or path in seen
|
|
56
|
+
):
|
|
57
|
+
raise ValueError(f"{subject} manifest contains an unsafe path")
|
|
58
|
+
seen.add(path)
|
|
59
|
+
size = entry["size"]
|
|
60
|
+
if isinstance(size, bool) or not isinstance(size, int) or size < 0:
|
|
61
|
+
raise ValueError(f"{subject} manifest contains an invalid file size")
|
|
62
|
+
calculated_total += size
|
|
63
|
+
digest = entry["sha256"]
|
|
64
|
+
if (
|
|
65
|
+
not isinstance(digest, str)
|
|
66
|
+
or len(digest) != 64
|
|
67
|
+
or any(ch not in "0123456789abcdef" for ch in digest)
|
|
68
|
+
):
|
|
69
|
+
raise ValueError(f"{subject} manifest contains an invalid file digest")
|
|
70
|
+
if not isinstance(entry["executable"], bool):
|
|
71
|
+
raise ValueError(f"{subject} manifest contains an invalid file mode")
|
|
72
|
+
|
|
73
|
+
declared_total = manifest["total_bytes"]
|
|
74
|
+
if (
|
|
75
|
+
isinstance(declared_total, bool)
|
|
76
|
+
or not isinstance(declared_total, int)
|
|
77
|
+
or declared_total != calculated_total
|
|
78
|
+
or declared_total > max_total_bytes
|
|
79
|
+
):
|
|
80
|
+
raise ValueError(f"{subject} manifest contains an invalid total size")
|
|
81
|
+
canonical = json.dumps(
|
|
82
|
+
manifest,
|
|
83
|
+
ensure_ascii=False,
|
|
84
|
+
separators=(",", ":"),
|
|
85
|
+
sort_keys=True,
|
|
86
|
+
).encode("utf-8")
|
|
87
|
+
return f"sha256:{hashlib.sha256(canonical).hexdigest()}", manifest
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def load_tree_manifest(
|
|
91
|
+
path: str,
|
|
92
|
+
*,
|
|
93
|
+
max_files: int,
|
|
94
|
+
max_total_bytes: int,
|
|
95
|
+
subject: str = "Artifact",
|
|
96
|
+
) -> tuple[str, dict]:
|
|
97
|
+
if os.path.getsize(path) > _MAX_MANIFEST_BYTES:
|
|
98
|
+
raise ValueError(f"{subject} manifest is too large")
|
|
99
|
+
with open(path, "rb") as file:
|
|
100
|
+
body = file.read(_MAX_MANIFEST_BYTES + 1)
|
|
101
|
+
if len(body) > _MAX_MANIFEST_BYTES:
|
|
102
|
+
raise ValueError(f"{subject} manifest is too large")
|
|
103
|
+
try:
|
|
104
|
+
manifest = json.loads(body)
|
|
105
|
+
except (UnicodeDecodeError, json.JSONDecodeError) as exc:
|
|
106
|
+
raise ValueError(f"{subject} manifest is invalid JSON") from exc
|
|
107
|
+
return validate_tree_manifest(
|
|
108
|
+
manifest,
|
|
109
|
+
max_files=max_files,
|
|
110
|
+
max_total_bytes=max_total_bytes,
|
|
111
|
+
subject=subject,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def build_tree_manifest(
|
|
116
|
+
root: str,
|
|
117
|
+
*,
|
|
118
|
+
max_files: int,
|
|
119
|
+
max_total_bytes: int,
|
|
120
|
+
skip_directories: Collection[str] = (),
|
|
121
|
+
subject: str = "Artifact",
|
|
122
|
+
) -> tuple[str, dict]:
|
|
123
|
+
"""Validate a regular-file tree and return its canonical content digest."""
|
|
124
|
+
|
|
125
|
+
resolved_root = os.path.realpath(str(root or "").strip())
|
|
126
|
+
if not resolved_root or not os.path.isdir(resolved_root):
|
|
127
|
+
raise ValueError(f"{subject} directory is unavailable")
|
|
128
|
+
|
|
129
|
+
files: list[dict] = []
|
|
130
|
+
total_bytes = 0
|
|
131
|
+
for current_root, dir_names, file_names in os.walk(
|
|
132
|
+
resolved_root,
|
|
133
|
+
followlinks=False,
|
|
134
|
+
):
|
|
135
|
+
dir_names[:] = [name for name in dir_names if name not in skip_directories]
|
|
136
|
+
dir_names.sort()
|
|
137
|
+
file_names.sort()
|
|
138
|
+
for directory_name in dir_names:
|
|
139
|
+
if os.path.islink(os.path.join(current_root, directory_name)):
|
|
140
|
+
raise ValueError(f"{subject} cannot contain symbolic links")
|
|
141
|
+
for file_name in file_names:
|
|
142
|
+
path = os.path.join(current_root, file_name)
|
|
143
|
+
file_stat = os.stat(path, follow_symlinks=False)
|
|
144
|
+
if os.path.islink(path):
|
|
145
|
+
raise ValueError(f"{subject} cannot contain symbolic links")
|
|
146
|
+
if not stat.S_ISREG(file_stat.st_mode):
|
|
147
|
+
raise ValueError(f"{subject} can contain regular files only")
|
|
148
|
+
if len(files) >= max_files:
|
|
149
|
+
raise ValueError(f"{subject} contains too many files")
|
|
150
|
+
total_bytes += file_stat.st_size
|
|
151
|
+
if total_bytes > max_total_bytes:
|
|
152
|
+
raise ValueError(f"{subject} is too large")
|
|
153
|
+
|
|
154
|
+
file_digest = hashlib.sha256()
|
|
155
|
+
with open(path, "rb") as file:
|
|
156
|
+
while True:
|
|
157
|
+
chunk = file.read(256 * 1024)
|
|
158
|
+
if not chunk:
|
|
159
|
+
break
|
|
160
|
+
file_digest.update(chunk)
|
|
161
|
+
files.append(
|
|
162
|
+
{
|
|
163
|
+
"path": os.path.relpath(path, resolved_root).replace(os.sep, "/"),
|
|
164
|
+
"size": file_stat.st_size,
|
|
165
|
+
"sha256": file_digest.hexdigest(),
|
|
166
|
+
"executable": bool(stat.S_IMODE(file_stat.st_mode) & 0o111),
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
manifest = {
|
|
171
|
+
"algorithm": TREE_MANIFEST_ALGORITHM,
|
|
172
|
+
"files": files,
|
|
173
|
+
"total_bytes": total_bytes,
|
|
174
|
+
}
|
|
175
|
+
return validate_tree_manifest(
|
|
176
|
+
manifest,
|
|
177
|
+
max_files=max_files,
|
|
178
|
+
max_total_bytes=max_total_bytes,
|
|
179
|
+
subject=subject,
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
__all__ = [
|
|
184
|
+
"TREE_MANIFEST_ALGORITHM",
|
|
185
|
+
"build_tree_manifest",
|
|
186
|
+
"load_tree_manifest",
|
|
187
|
+
"validate_tree_manifest",
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def materialize_tree(
|
|
192
|
+
source: str, manifest_path: str, expected_digest: str, cache_root: str
|
|
193
|
+
) -> str:
|
|
194
|
+
"""Publish a complete verified tree outside the sandbox before making it visible."""
|
|
195
|
+
import shutil
|
|
196
|
+
import tempfile
|
|
197
|
+
|
|
198
|
+
max_bytes = 256 * 1024 * 1024
|
|
199
|
+
digest, manifest = load_tree_manifest(
|
|
200
|
+
manifest_path, max_files=2048, max_total_bytes=max_bytes
|
|
201
|
+
)
|
|
202
|
+
if digest != expected_digest:
|
|
203
|
+
raise ValueError("Artifact manifest does not match content_digest")
|
|
204
|
+
target = os.path.join(cache_root, digest[7:])
|
|
205
|
+
if os.path.isdir(target) and not os.path.islink(target):
|
|
206
|
+
return target
|
|
207
|
+
used = sum(
|
|
208
|
+
os.path.getsize(os.path.join(root, name))
|
|
209
|
+
for root, _, names in os.walk(cache_root)
|
|
210
|
+
for name in names
|
|
211
|
+
)
|
|
212
|
+
if len(os.listdir(cache_root)) >= 256 or used + manifest["total_bytes"] > max_bytes:
|
|
213
|
+
raise ValueError("Immutable artifact cache limit reached; acquire a new Box")
|
|
214
|
+
staging = tempfile.mkdtemp(
|
|
215
|
+
prefix="langbot-artifact-stage-", dir=os.path.dirname(cache_root)
|
|
216
|
+
)
|
|
217
|
+
try:
|
|
218
|
+
for entry in manifest["files"]:
|
|
219
|
+
source_path = os.path.join(source, *entry["path"].split("/"))
|
|
220
|
+
descriptor = os.open(
|
|
221
|
+
source_path,
|
|
222
|
+
os.O_RDONLY
|
|
223
|
+
| getattr(os, "O_NOFOLLOW", 0)
|
|
224
|
+
| getattr(os, "O_NONBLOCK", 0),
|
|
225
|
+
)
|
|
226
|
+
with os.fdopen(descriptor, "rb") as stream:
|
|
227
|
+
if not stat.S_ISREG(os.fstat(stream.fileno()).st_mode):
|
|
228
|
+
raise ValueError("Artifact source must be a regular file")
|
|
229
|
+
body = stream.read(entry["size"] + 1)
|
|
230
|
+
if (
|
|
231
|
+
len(body) != entry["size"]
|
|
232
|
+
or hashlib.sha256(body).hexdigest() != entry["sha256"]
|
|
233
|
+
):
|
|
234
|
+
raise ValueError(f"Artifact source changed: {entry['path']}")
|
|
235
|
+
destination = os.path.join(staging, *entry["path"].split("/"))
|
|
236
|
+
os.makedirs(os.path.dirname(destination), exist_ok=True)
|
|
237
|
+
with open(destination, "xb") as stream:
|
|
238
|
+
stream.write(body)
|
|
239
|
+
os.chmod(destination, 0o555 if entry["executable"] else 0o444)
|
|
240
|
+
os.chmod(staging, 0o755)
|
|
241
|
+
os.rename(staging, target)
|
|
242
|
+
return target
|
|
243
|
+
finally:
|
|
244
|
+
if os.path.isdir(staging):
|
|
245
|
+
shutil.rmtree(staging)
|
|
@@ -24,15 +24,4 @@ class LangBotToBoxAction(ActionType):
|
|
|
24
24
|
STOP_MANAGED_PROCESS = "box_stop_managed_process"
|
|
25
25
|
GET_BACKEND_INFO = "box_get_backend_info"
|
|
26
26
|
GET_STORAGE_ANALYSIS = "box_get_storage_analysis"
|
|
27
|
-
LIST_SKILLS = "box_list_skills"
|
|
28
|
-
GET_SKILL = "box_get_skill"
|
|
29
|
-
CREATE_SKILL = "box_create_skill"
|
|
30
|
-
UPDATE_SKILL = "box_update_skill"
|
|
31
|
-
DELETE_SKILL = "box_delete_skill"
|
|
32
|
-
SCAN_SKILL_DIRECTORY = "box_scan_skill_directory"
|
|
33
|
-
LIST_SKILL_FILES = "box_list_skill_files"
|
|
34
|
-
READ_SKILL_FILE = "box_read_skill_file"
|
|
35
|
-
WRITE_SKILL_FILE = "box_write_skill_file"
|
|
36
|
-
PREVIEW_SKILL_ZIP = "box_preview_skill_zip"
|
|
37
|
-
INSTALL_SKILL_ZIP = "box_install_skill_zip"
|
|
38
27
|
SHUTDOWN = "box_shutdown"
|
|
@@ -10,9 +10,14 @@ import re
|
|
|
10
10
|
import shlex
|
|
11
11
|
import shutil
|
|
12
12
|
import uuid
|
|
13
|
+
import tempfile
|
|
14
|
+
|
|
15
|
+
from ..artifact import materialize_tree
|
|
16
|
+
from ..runtime import bounded_executor
|
|
13
17
|
|
|
14
18
|
from .errors import BoxError
|
|
15
19
|
from .models import (
|
|
20
|
+
ARTIFACT_MOUNT_ROOT,
|
|
16
21
|
BoxExecutionResult,
|
|
17
22
|
BoxExecutionStatus,
|
|
18
23
|
BoxHostMountMode,
|
|
@@ -41,6 +46,8 @@ class _CommandResult:
|
|
|
41
46
|
class BaseSandboxBackend(abc.ABC):
|
|
42
47
|
name: str
|
|
43
48
|
instance_id: str = ""
|
|
49
|
+
execution_scoped_mounts: bool = False
|
|
50
|
+
content_addressed_mounts: bool = False
|
|
44
51
|
|
|
45
52
|
def __init__(self, logger: logging.Logger):
|
|
46
53
|
self.logger = logger
|
|
@@ -87,7 +94,7 @@ class BaseSandboxBackend(abc.ABC):
|
|
|
87
94
|
"mount_isolation": False if strict else None,
|
|
88
95
|
"network_isolation": False if strict else None,
|
|
89
96
|
"hard_workspace_quota": False if strict else None,
|
|
90
|
-
"
|
|
97
|
+
"hard_read_only_mount_quota": False if strict else None,
|
|
91
98
|
"bounded_ephemeral_storage": False if strict else None,
|
|
92
99
|
"inode_quota": False if strict else None,
|
|
93
100
|
}
|
|
@@ -154,6 +161,7 @@ class BaseSandboxBackend(abc.ABC):
|
|
|
154
161
|
|
|
155
162
|
|
|
156
163
|
class CLISandboxBackend(BaseSandboxBackend):
|
|
164
|
+
content_addressed_mounts = True
|
|
157
165
|
command: str
|
|
158
166
|
|
|
159
167
|
def __init__(self, logger: logging.Logger, command: str, backend_name: str):
|
|
@@ -161,6 +169,7 @@ class CLISandboxBackend(BaseSandboxBackend):
|
|
|
161
169
|
self.command = command
|
|
162
170
|
self.name = backend_name
|
|
163
171
|
self.cpu_limit_enabled = True
|
|
172
|
+
self._artifact_roots: dict[str, str] = {}
|
|
164
173
|
|
|
165
174
|
async def is_available(self) -> bool:
|
|
166
175
|
if shutil.which(self.command) is None:
|
|
@@ -215,8 +224,12 @@ class CLISandboxBackend(BaseSandboxBackend):
|
|
|
215
224
|
)
|
|
216
225
|
args.extend(["-v", mount_spec])
|
|
217
226
|
|
|
227
|
+
artifact_root = tempfile.mkdtemp(prefix="langbot-box-artifacts-")
|
|
228
|
+
os.chmod(artifact_root, 0o755)
|
|
229
|
+
self._artifact_roots[container_name] = artifact_root
|
|
230
|
+
args.extend(["-v", f"{artifact_root}:{ARTIFACT_MOUNT_ROOT}:ro"])
|
|
218
231
|
for mount in spec.extra_mounts:
|
|
219
|
-
if mount.mode != BoxHostMountMode.NONE:
|
|
232
|
+
if mount.mode != BoxHostMountMode.NONE and not mount.is_content_addressed:
|
|
220
233
|
args.extend(
|
|
221
234
|
["-v", f"{mount.host_path}:{mount.mount_path}:{mount.mode.value}"]
|
|
222
235
|
)
|
|
@@ -233,7 +246,27 @@ class CLISandboxBackend(BaseSandboxBackend):
|
|
|
233
246
|
f"read_only_rootfs={spec.read_only_rootfs} workspace_quota_mb={spec.workspace_quota_mb}"
|
|
234
247
|
)
|
|
235
248
|
|
|
236
|
-
|
|
249
|
+
start_task = None
|
|
250
|
+
try:
|
|
251
|
+
await self._prepare_artifacts(container_name, spec)
|
|
252
|
+
start_task = asyncio.create_task(
|
|
253
|
+
self._run_command(args, timeout_sec=30, check=True)
|
|
254
|
+
)
|
|
255
|
+
await asyncio.shield(start_task)
|
|
256
|
+
except BaseException:
|
|
257
|
+
if start_task is not None:
|
|
258
|
+
try:
|
|
259
|
+
await start_task
|
|
260
|
+
except BaseException:
|
|
261
|
+
pass
|
|
262
|
+
await self._run_command(
|
|
263
|
+
[self.command, "rm", "-f", container_name],
|
|
264
|
+
timeout_sec=20,
|
|
265
|
+
check=False,
|
|
266
|
+
)
|
|
267
|
+
self._artifact_roots.pop(container_name, None)
|
|
268
|
+
shutil.rmtree(artifact_root)
|
|
269
|
+
raise
|
|
237
270
|
|
|
238
271
|
return BoxSessionInfo(
|
|
239
272
|
session_id=spec.session_id,
|
|
@@ -254,7 +287,29 @@ class CLISandboxBackend(BaseSandboxBackend):
|
|
|
254
287
|
last_used_at=now,
|
|
255
288
|
)
|
|
256
289
|
|
|
290
|
+
async def _prepare_artifacts(self, session_id: str, spec: BoxSpec) -> None:
|
|
291
|
+
for mount in spec.extra_mounts:
|
|
292
|
+
if mount.is_content_addressed:
|
|
293
|
+
root = self._artifact_roots.get(session_id)
|
|
294
|
+
if root is None:
|
|
295
|
+
raise BoxError(
|
|
296
|
+
"Immutable artifact cache is unavailable; acquire a new Box"
|
|
297
|
+
)
|
|
298
|
+
try:
|
|
299
|
+
await bounded_executor.run_blocking_atomic(
|
|
300
|
+
materialize_tree,
|
|
301
|
+
mount.host_path,
|
|
302
|
+
mount.manifest_path,
|
|
303
|
+
mount.content_digest,
|
|
304
|
+
root,
|
|
305
|
+
)
|
|
306
|
+
except (OSError, ValueError) as exc:
|
|
307
|
+
raise BoxError(
|
|
308
|
+
f"Immutable artifact preparation failed: {exc}"
|
|
309
|
+
) from exc
|
|
310
|
+
|
|
257
311
|
async def exec(self, session: BoxSessionInfo, spec: BoxSpec) -> BoxExecutionResult:
|
|
312
|
+
await self._prepare_artifacts(session.backend_session_id, spec)
|
|
258
313
|
start = dt.datetime.now(dt.timezone.utc)
|
|
259
314
|
args = [self.command, "exec"]
|
|
260
315
|
|
|
@@ -316,11 +371,15 @@ class CLISandboxBackend(BaseSandboxBackend):
|
|
|
316
371
|
f"LangBot Box backend stop_session: backend={self.name} "
|
|
317
372
|
f"session_id={session.session_id} container_name={session.backend_session_id}"
|
|
318
373
|
)
|
|
319
|
-
await self._run_command(
|
|
374
|
+
result = await self._run_command(
|
|
320
375
|
[self.command, "rm", "-f", session.backend_session_id],
|
|
321
376
|
timeout_sec=20,
|
|
322
377
|
check=False,
|
|
323
378
|
)
|
|
379
|
+
if result.return_code == 0:
|
|
380
|
+
root = self._artifact_roots.pop(session.backend_session_id, None)
|
|
381
|
+
if root is not None:
|
|
382
|
+
await bounded_executor.run_blocking_cleanup(shutil.rmtree, root)
|
|
324
383
|
|
|
325
384
|
async def is_session_alive(self, session: BoxSessionInfo) -> bool:
|
|
326
385
|
result = await self._run_command(
|