langbot-plugin 0.7.16__tar.gz → 0.7.18__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.
Files changed (399) hide show
  1. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/PKG-INFO +1 -1
  2. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/pyproject.toml +1 -1
  3. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/manifest.py +52 -7
  4. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/box/nsjail_backend.py +2 -2
  5. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/skill_store.py +137 -29
  6. langbot_plugin-0.7.18/src/langbot_plugin/version.py +1 -0
  7. langbot_plugin-0.7.18/tests/api/definition/test_manifest_component_path.py +183 -0
  8. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/box/test_nsjail_backend.py +18 -6
  9. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/box/test_skill_store.py +141 -7
  10. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/test_skill_store.py +1 -1
  11. langbot_plugin-0.7.16/src/langbot_plugin/version.py +0 -1
  12. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/.github/workflows/box-docker.yml +0 -0
  13. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/.github/workflows/cla.yml +0 -0
  14. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/.github/workflows/publish-pypi.yaml +0 -0
  15. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/.github/workflows/publish.yml +0 -0
  16. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/.github/workflows/test.yml +0 -0
  17. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/.gitignore +0 -0
  18. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/.python-version +0 -0
  19. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/AGENTS.md +0 -0
  20. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/ARCHITECTURE.md +0 -0
  21. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/CLAUDE.md +0 -0
  22. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/CONTRIBUTING.md +0 -0
  23. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/LICENSE +0 -0
  24. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/README.md +0 -0
  25. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/README_CN.md +0 -0
  26. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/data/.env.example +0 -0
  27. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/docs/Message.md +0 -0
  28. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/docs/PluginPages.md +0 -0
  29. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/docs/agent-runner-interactions.md +0 -0
  30. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/docs/agent-runner-pluginization/PROTOCOL_V1.md +0 -0
  31. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/docs/agent-runner-pluginization/README.md +0 -0
  32. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/docs/agent-runner-pluginization/SDK_RUNTIME_PLAN.md +0 -0
  33. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/docs/certified-plugins.md +0 -0
  34. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/docs/communication/apis/lb2rt.md +0 -0
  35. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/docs/communication/runtime_plugin.md +0 -0
  36. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/docs/dependency-management.md +0 -0
  37. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/docs/langbot-plugin-social.png +0 -0
  38. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/docs/runner.md +0 -0
  39. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/docs/stateless-components.md +0 -0
  40. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/local_e2e/acceptance.json +0 -0
  41. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/local_e2e/registration_fanin.py +0 -0
  42. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/local_e2e/run_acceptance.py +0 -0
  43. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/mypy.ini +0 -0
  44. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/scripts/check_action_consistency.py +0 -0
  45. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/scripts/runtime_resource_probe.py +0 -0
  46. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/__init__.py +0 -0
  47. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/__init__.py +0 -0
  48. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/agent_tools/__init__.py +0 -0
  49. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/agent_tools/asset_gateway.py +0 -0
  50. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/agent_tools/daemon.py +0 -0
  51. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/agent_tools/decorators.py +0 -0
  52. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/agent_tools/external_tools.py +0 -0
  53. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/agent_tools/mcp_access.py +0 -0
  54. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/agent_tools/mcp_bridge.py +0 -0
  55. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/agent_tools/mcp_config.py +0 -0
  56. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/agent_tools/mcp_protocol.py +0 -0
  57. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/agent_tools/mcp_stdio.py +0 -0
  58. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/__init__.py +0 -0
  59. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/abstract/__init__.py +0 -0
  60. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/abstract/platform/__init__.py +0 -0
  61. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/abstract/platform/adapter.py +0 -0
  62. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/abstract/platform/event_logger.py +0 -0
  63. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/__init__.py +0 -0
  64. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/base.py +0 -0
  65. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/command/__init__.py +0 -0
  66. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/command/command.py +0 -0
  67. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/common/__init__.py +0 -0
  68. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/common/event_listener.py +0 -0
  69. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/knowledge_engine/__init__.py +0 -0
  70. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/knowledge_engine/engine.py +0 -0
  71. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/page/__init__.py +0 -0
  72. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/parser/__init__.py +0 -0
  73. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/parser/parser.py +0 -0
  74. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/runner/__init__.py +0 -0
  75. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/runner/runner.py +0 -0
  76. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/tool/__init__.py +0 -0
  77. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/components/tool/tool.py +0 -0
  78. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/definition/plugin.py +0 -0
  79. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/__init__.py +0 -0
  80. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/__init__.py +0 -0
  81. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/command/__init__.py +0 -0
  82. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/command/context.py +0 -0
  83. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/command/errors.py +0 -0
  84. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/pipeline/__init__.py +0 -0
  85. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/pipeline/query.py +0 -0
  86. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/platform/__init__.py +0 -0
  87. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/platform/entities.py +0 -0
  88. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/platform/errors.py +0 -0
  89. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/platform/events.py +0 -0
  90. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/platform/logger.py +0 -0
  91. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/platform/message.py +0 -0
  92. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/provider/__init__.py +0 -0
  93. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/provider/message.py +0 -0
  94. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/provider/prompt.py +0 -0
  95. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/provider/reasoning.py +0 -0
  96. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/provider/session.py +0 -0
  97. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/rag/__init__.py +0 -0
  98. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/rag/context.py +0 -0
  99. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/rag/enums.py +0 -0
  100. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/rag/errors.py +0 -0
  101. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/rag/models.py +0 -0
  102. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/resource/__init__.py +0 -0
  103. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/resource/tool.py +0 -0
  104. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/__init__.py +0 -0
  105. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/box.py +0 -0
  106. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/capabilities.py +0 -0
  107. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/compat.py +0 -0
  108. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/context.py +0 -0
  109. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/context_access.py +0 -0
  110. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/delivery.py +0 -0
  111. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/errors.py +0 -0
  112. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/event.py +0 -0
  113. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/input.py +0 -0
  114. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/interaction.py +0 -0
  115. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/manifest.py +0 -0
  116. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/page_results.py +0 -0
  117. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/permissions.py +0 -0
  118. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/resources.py +0 -0
  119. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/result.py +0 -0
  120. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/run_ledger.py +0 -0
  121. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/runtime.py +0 -0
  122. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/runtime_registry.py +0 -0
  123. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/state.py +0 -0
  124. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/stats.py +0 -0
  125. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/steering.py +0 -0
  126. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/transcript.py +0 -0
  127. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/builtin/runner/trigger.py +0 -0
  128. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/context.py +0 -0
  129. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/events.py +0 -0
  130. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/entities/execution.py +0 -0
  131. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/__init__.py +0 -0
  132. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/base.py +0 -0
  133. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/event_context.py +0 -0
  134. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/execute_context.py +0 -0
  135. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/invocation.py +0 -0
  136. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/langbot_api.py +0 -0
  137. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/query_based_api.py +0 -0
  138. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/runner/__init__.py +0 -0
  139. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/runner/admin.py +0 -0
  140. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/runner/api.py +0 -0
  141. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/runner/box.py +0 -0
  142. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/runner/common.py +0 -0
  143. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/runner/context.py +0 -0
  144. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/runner/ledger.py +0 -0
  145. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/runner/platform.py +0 -0
  146. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/runner/reply_stream.py +0 -0
  147. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/runner/resources.py +0 -0
  148. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/runner/state.py +0 -0
  149. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/api/proxies/runner/tracing.py +0 -0
  150. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/artifact.py +0 -0
  151. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/__init__.py +0 -0
  152. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/langbot-page-sdk.js +0 -0
  153. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/.env.example.example +0 -0
  154. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/.github/workflows/release.yml.example +0 -0
  155. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/.gitignore.example +0 -0
  156. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/.vscode/launch.json.example +0 -0
  157. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/README.md.example +0 -0
  158. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/__init__.py +0 -0
  159. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/assets/icon.svg.example +0 -0
  160. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/__init__.py +0 -0
  161. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/commands/__init__.py +0 -0
  162. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/commands/{cmd_name}.py.example +0 -0
  163. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/commands/{cmd_name}.yaml.example +0 -0
  164. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/event_listener/__init__.py +0 -0
  165. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/event_listener/default.py.example +0 -0
  166. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/event_listener/default.yaml.example +0 -0
  167. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/knowledge_engine/__init__.py +0 -0
  168. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/knowledge_engine/{knowledge_engine_name}.py.example +0 -0
  169. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/knowledge_engine/{knowledge_engine_name}.yaml.example +0 -0
  170. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/pages/{page_name}.html.example +0 -0
  171. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/pages/{page_name}.yaml.example +0 -0
  172. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/parser/__init__.py +0 -0
  173. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/parser/{parser_name}.py.example +0 -0
  174. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/parser/{parser_name}.yaml.example +0 -0
  175. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/runner/__init__.py +0 -0
  176. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/runner/{runner_name}.py.example +0 -0
  177. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/runner/{runner_name}.yaml.example +0 -0
  178. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/tools/__init__.py +0 -0
  179. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/tools/{tool_name}.py.example +0 -0
  180. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/components/tools/{tool_name}.yaml.example +0 -0
  181. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/main.py.example +0 -0
  182. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/manifest.yaml.example +0 -0
  183. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/readme/README_zh_Hans.md.example +0 -0
  184. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/assets/templates/requirements.txt.example +0 -0
  185. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/box/__init__.py +0 -0
  186. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/box/actions.py +0 -0
  187. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/box/backend.py +0 -0
  188. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/box/client.py +0 -0
  189. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/box/e2b_backend.py +0 -0
  190. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/box/errors.py +0 -0
  191. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/box/host_backend.py +0 -0
  192. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/box/models.py +0 -0
  193. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/box/runtime.py +0 -0
  194. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/box/security.py +0 -0
  195. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/box/server.py +0 -0
  196. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/box/tenancy.py +0 -0
  197. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/certification.py +0 -0
  198. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/__init__.py +0 -0
  199. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/__main__.py +0 -0
  200. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/commands/__init__.py +0 -0
  201. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/commands/buildplugin.py +0 -0
  202. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/commands/gencomponent.py +0 -0
  203. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/commands/initplugin.py +0 -0
  204. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/commands/login.py +0 -0
  205. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/commands/logout.py +0 -0
  206. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/commands/publish.py +0 -0
  207. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/commands/runplugin.py +0 -0
  208. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/gen/__init__.py +0 -0
  209. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/gen/renderer.py +0 -0
  210. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/i18n.py +0 -0
  211. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/locales/__init__.py +0 -0
  212. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/locales/en_US.py +0 -0
  213. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/locales/es_ES.py +0 -0
  214. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/locales/ja_JP.py +0 -0
  215. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/locales/th_TH.py +0 -0
  216. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/locales/vi_VN.py +0 -0
  217. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/locales/zh_Hans.py +0 -0
  218. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/locales/zh_Hant.py +0 -0
  219. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/run/__init__.py +0 -0
  220. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/run/controller.py +0 -0
  221. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/run/handler.py +0 -0
  222. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/run/hotreload.py +0 -0
  223. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/utils/__init__.py +0 -0
  224. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/utils/cloudsv.py +0 -0
  225. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/utils/form.py +0 -0
  226. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/cli/utils/page_components.py +0 -0
  227. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/entities/__init__.py +0 -0
  228. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/entities/io/__init__.py +0 -0
  229. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/entities/io/actions/__init__.py +0 -0
  230. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/entities/io/actions/enums.py +0 -0
  231. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/entities/io/context.py +0 -0
  232. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/entities/io/errors.py +0 -0
  233. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/entities/io/req.py +0 -0
  234. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/entities/io/resp.py +0 -0
  235. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/entities/marketplace.py +0 -0
  236. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/LICENSE +0 -0
  237. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/README.md +0 -0
  238. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/__init__.py +0 -0
  239. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/app.py +0 -0
  240. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/bounded_executor.py +0 -0
  241. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/context.py +0 -0
  242. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/event_loop_monitor.py +0 -0
  243. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/helper/__init__.py +0 -0
  244. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/helper/marketplace.py +0 -0
  245. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/helper/pkgmgr.py +0 -0
  246. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/__init__.py +0 -0
  247. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/connection.py +0 -0
  248. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/connections/__init__.py +0 -0
  249. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/connections/stdio.py +0 -0
  250. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/connections/ws.py +0 -0
  251. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/controller.py +0 -0
  252. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/controllers/__init__.py +0 -0
  253. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/controllers/stdio/__init__.py +0 -0
  254. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/controllers/stdio/client.py +0 -0
  255. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/controllers/stdio/server.py +0 -0
  256. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/controllers/ws/__init__.py +0 -0
  257. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/controllers/ws/client.py +0 -0
  258. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/controllers/ws/server.py +0 -0
  259. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/handler.py +0 -0
  260. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/handlers/__init__.py +0 -0
  261. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/handlers/control.py +0 -0
  262. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/io/handlers/plugin.py +0 -0
  263. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/ops_metrics.py +0 -0
  264. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/plugin/__init__.py +0 -0
  265. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/plugin/artifact.py +0 -0
  266. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/plugin/container.py +0 -0
  267. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/plugin/dependency_environment.py +0 -0
  268. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/plugin/logbuffer.py +0 -0
  269. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/plugin/mgr.py +0 -0
  270. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/plugin/restart_coordinator.py +0 -0
  271. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/plugin/runner_service.py +0 -0
  272. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/plugin/worker_launcher.py +0 -0
  273. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/plugin/worker_observability.py +0 -0
  274. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/plugin/worker_watchdog.py +0 -0
  275. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/security.py +0 -0
  276. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/runtime/settings.py +0 -0
  277. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/storage.py +0 -0
  278. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/utils/__init__.py +0 -0
  279. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/utils/deadline.py +0 -0
  280. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/utils/discover/__init__.py +0 -0
  281. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/utils/discover/engine.py +0 -0
  282. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/utils/importutil.py +0 -0
  283. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/utils/log.py +0 -0
  284. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/utils/platform.py +0 -0
  285. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/src/langbot_plugin/workspace.py +0 -0
  286. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/__init__.py +0 -0
  287. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/definition/components/test_components.py +0 -0
  288. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/definition/components/test_imports.py +0 -0
  289. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/definition/test_manifest.py +0 -0
  290. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/entities/builtin/runner/test_context_result.py +0 -0
  291. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/entities/builtin/runner/test_history_event_entities.py +0 -0
  292. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/entities/builtin/runner/test_interaction.py +0 -0
  293. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/entities/builtin/runner/test_run_ledger_entities.py +0 -0
  294. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/entities/builtin/test_command_context.py +0 -0
  295. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/entities/builtin/test_platform_logger.py +0 -0
  296. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/entities/builtin/test_provider_message.py +0 -0
  297. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/entities/builtin/test_rag_models.py +0 -0
  298. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/entities/test_context.py +0 -0
  299. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/entities/test_events.py +0 -0
  300. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/proxies/__init__.py +0 -0
  301. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/proxies/test_agent_run_api_proxy.py +0 -0
  302. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/proxies/test_base.py +0 -0
  303. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/proxies/test_box_api.py +0 -0
  304. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/proxies/test_history_event_api_proxy.py +0 -0
  305. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/proxies/test_langbot_api.py +0 -0
  306. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/proxies/test_llm_stream_ownership.py +0 -0
  307. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/proxies/test_query_based_api.py +0 -0
  308. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/proxies/test_reasoning_parameter.py +0 -0
  309. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/test_agent_tools_mcp_bridge.py +0 -0
  310. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/test_runner_handlers.py +0 -0
  311. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/test_runner_handlers_matrix.py +0 -0
  312. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/api/test_runner_public_apis.py +0 -0
  313. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/box/__init__.py +0 -0
  314. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/box/test_admission.py +0 -0
  315. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/box/test_artifact_cache_root.py +0 -0
  316. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/box/test_backend.py +0 -0
  317. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/box/test_backend_selection.py +0 -0
  318. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/box/test_client.py +0 -0
  319. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/box/test_e2b_backend.py +0 -0
  320. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/box/test_host_backend.py +0 -0
  321. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/box/test_runtime.py +0 -0
  322. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/box/test_server.py +0 -0
  323. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/box/test_storage_analysis.py +0 -0
  324. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/cli/run/test_controller.py +0 -0
  325. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/cli/run/test_hotreload.py +0 -0
  326. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/cli/run/test_runtime_handler.py +0 -0
  327. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/cli/test_buildplugin.py +0 -0
  328. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/cli/test_gencomponent.py +0 -0
  329. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/cli/test_i18n_form.py +0 -0
  330. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/cli/test_initplugin.py +0 -0
  331. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/cli/test_login.py +0 -0
  332. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/cli/test_logout_publish.py +0 -0
  333. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/cli/test_page_components.py +0 -0
  334. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/cli/test_renderer.py +0 -0
  335. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/cli/test_runner_usages.py +0 -0
  336. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/cli/test_runplugin.py +0 -0
  337. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/e2e/Dockerfile.box-socket +0 -0
  338. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/e2e/Dockerfile.box-socket.dockerignore +0 -0
  339. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/e2e/standalone_runtime_eba_probe.py +0 -0
  340. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/e2e/test_box_socket_mounts.py +0 -0
  341. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/e2e/test_run_mount_isolation.py +0 -0
  342. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/entities/io/test_dependency_errors.py +0 -0
  343. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/entities/io/test_protocol.py +0 -0
  344. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/fixtures/eba_event_probe_plugin/.gitignore +0 -0
  345. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/fixtures/eba_event_probe_plugin/assets/icon.svg +0 -0
  346. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/fixtures/eba_event_probe_plugin/components/event_listener/default.py +0 -0
  347. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/fixtures/eba_event_probe_plugin/components/event_listener/default.yaml +0 -0
  348. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/fixtures/eba_event_probe_plugin/main.py +0 -0
  349. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/fixtures/eba_event_probe_plugin/manifest.yaml +0 -0
  350. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/helpers/__init__.py +0 -0
  351. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/helpers/protocol.py +0 -0
  352. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/packaging/test_installed_cli_blackbox.py +0 -0
  353. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/packaging/test_release_metadata.py +0 -0
  354. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/helper/test_marketplace.py +0 -0
  355. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/helper/test_pkgmgr.py +0 -0
  356. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/io/handlers/test_control_handler.py +0 -0
  357. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/io/handlers/test_import_contracts.py +0 -0
  358. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/io/handlers/test_legacy_file_chunk.py +0 -0
  359. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/io/handlers/test_plugin_handler.py +0 -0
  360. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/io/test_action_consistency.py +0 -0
  361. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/io/test_connections.py +0 -0
  362. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/io/test_controllers.py +0 -0
  363. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/io/test_handler.py +0 -0
  364. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/io/test_heartbeat_admission.py +0 -0
  365. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/io/test_stdio_server.py +0 -0
  366. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/io/test_stream_flow_control.py +0 -0
  367. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_artifact_store.py +0 -0
  368. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_container.py +0 -0
  369. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_dependency_environment.py +0 -0
  370. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_event_dispatch_real_worker.py +0 -0
  371. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_exact_dify_real_worker.py +0 -0
  372. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_exact_legacy_sdk_compat.py +0 -0
  373. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_installation_manager.py +0 -0
  374. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_legacy_shadow.py +0 -0
  375. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_manager.py +0 -0
  376. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_mgr_runner.py +0 -0
  377. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_mode_resource_limits.py +0 -0
  378. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_restart_coordinator.py +0 -0
  379. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_shared_worker_subprocess.py +0 -0
  380. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_worker_launcher.py +0 -0
  381. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_worker_plugin_identity.py +0 -0
  382. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/plugin/test_workload_isolation.py +0 -0
  383. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/test_app.py +0 -0
  384. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/test_bounded_executor.py +0 -0
  385. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/test_event_loop_monitor.py +0 -0
  386. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/test_ops_metrics.py +0 -0
  387. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/runtime/test_pull_api_handlers.py +0 -0
  388. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/test_artifact_materialization.py +0 -0
  389. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/test_certification.py +0 -0
  390. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/test_log.py +0 -0
  391. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/test_message.py +0 -0
  392. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/test_plugin_logbuffer.py +0 -0
  393. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/test_storage.py +0 -0
  394. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/test_worker_observability.py +0 -0
  395. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/test_worker_watchdog.py +0 -0
  396. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/utils/test_deadline.py +0 -0
  397. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/utils/test_discovery.py +0 -0
  398. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/utils/test_importutil.py +0 -0
  399. {langbot_plugin-0.7.16 → langbot_plugin-0.7.18}/tests/utils/test_platform.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: langbot-plugin
3
- Version: 0.7.16
3
+ Version: 0.7.18
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "langbot-plugin"
3
- version = "0.7.16"
3
+ version = "0.7.18"
4
4
  description = "This package contains the SDK, CLI for building plugins for LangBot, plus the runtime for hosting LangBot plugins"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -231,17 +231,62 @@ class ComponentManifest(pydantic.BaseModel):
231
231
  else None
232
232
  )
233
233
 
234
+ def _resolve_component_module(self) -> tuple[str, str]:
235
+ """Return the plugin directory to import from and the module path.
236
+
237
+ ``execution.python.path`` comes from the plugin's own manifest, so it is
238
+ untrusted input. Only a module inside the plugin directory may be
239
+ imported: absolute paths, drive letters and ``..`` components are
240
+ rejected outright rather than relied on to fail later during import.
241
+ """
242
+ if self.execution is None:
243
+ raise ValueError("Execution is not set")
244
+ python = self.execution.python
245
+ declared = python.path or ""
246
+ if not declared or "\x00" in declared:
247
+ raise ValueError("execution.python.path is empty")
248
+
249
+ portable = declared.replace("\\", "/")
250
+ if portable.startswith("/") or os.path.isabs(declared):
251
+ raise ValueError(
252
+ f"execution.python.path must be relative to the plugin: {declared}"
253
+ )
254
+ if any(part == ".." for part in portable.split("/")):
255
+ raise ValueError(
256
+ f"execution.python.path escapes the plugin directory: {declared}"
257
+ )
258
+ if len(portable.split("/", 1)[0]) >= 2 and portable.split("/", 1)[0][1] == ":":
259
+ raise ValueError(f"execution.python.path uses a drive letter: {declared}")
260
+
261
+ # Workers run at the plugin root; _rel_dir is the manifest's directory.
262
+ # Keep that directory in the module name so relative imports still work.
263
+ plugin_dir = os.path.abspath(".")
264
+ target = os.path.abspath(os.path.join(plugin_dir, self._rel_dir, portable))
265
+ if os.path.commonpath([plugin_dir, target]) != plugin_dir:
266
+ raise ValueError(
267
+ f"execution.python.path escapes the plugin directory: {declared}"
268
+ )
269
+
270
+ if target.endswith(".py"):
271
+ target = target[: -len(".py")]
272
+ relative = os.path.relpath(target, plugin_dir)
273
+ return plugin_dir, relative.replace(os.sep, ".").replace("/", ".")
274
+
234
275
  def get_python_component_class(self) -> typing.Type[typing.Any]:
235
276
  """获取Python组件类"""
236
277
  if self.execution is None:
237
278
  raise ValueError("Execution is not set")
238
- module_path = os.path.join(self._rel_dir, self.execution.python.path)
239
- if module_path.endswith(".py"):
240
- module_path = module_path[:-3]
241
- module_path = module_path.replace("/", ".").replace("\\", ".")
242
- pwd = os.getcwd()
243
- sys.path.append(pwd)
244
- module = importlib.import_module(module_path)
279
+ plugin_dir, module_path = self._resolve_component_module()
280
+ # Insert for the duration of the import only: a permanent append would
281
+ # let one plugin shadow modules for every plugin loaded after it.
282
+ sys.path.insert(0, plugin_dir)
283
+ try:
284
+ module = importlib.import_module(module_path)
285
+ finally:
286
+ try:
287
+ sys.path.remove(plugin_dir)
288
+ except ValueError: # pragma: no cover - defensive
289
+ pass
245
290
  return getattr(module, self.execution.python.attr)
246
291
 
247
292
  def to_plain_dict(self) -> dict:
@@ -780,9 +780,9 @@ class NsjailBackend(BaseSandboxBackend):
780
780
  try:
781
781
  await asyncio.wait_for(process.wait(), timeout=timeout_sec)
782
782
  except asyncio.TimeoutError:
783
- process.kill()
784
783
  timed_out = True
785
- await process.wait()
784
+ # Let nsjail reap its children and remove their cgroups before exit.
785
+ await self._terminate_process(process)
786
786
  except asyncio.CancelledError:
787
787
  await self._terminate_process(process)
788
788
  await asyncio.gather(
@@ -8,6 +8,7 @@ import json
8
8
  import mimetypes
9
9
  import os
10
10
  import posixpath
11
+ import re
11
12
  import shutil
12
13
  import stat
13
14
  import tempfile
@@ -22,16 +23,11 @@ from .artifact import build_tree_manifest
22
23
  from .workspace import workspace_namespace
23
24
 
24
25
 
25
- _FRONTMATTER_FIELDS = (
26
- "name",
27
- "display_name",
28
- "description",
29
- )
30
-
31
26
  _PUBLIC_SKILL_FIELDS = (
32
27
  "name",
33
28
  "display_name",
34
29
  "description",
30
+ "metadata",
35
31
  "instructions",
36
32
  "package_root",
37
33
  "manifest_path",
@@ -151,9 +147,21 @@ def parse_frontmatter(content: str) -> tuple[dict, str]:
151
147
 
152
148
 
153
149
  def build_skill_md(metadata: dict, instructions: str) -> str:
150
+ # Preserve complete extensible Agent Skills frontmatter.
154
151
  frontmatter = {}
155
- for key in _FRONTMATTER_FIELDS:
156
- value = metadata.get(key)
152
+ for key, value in (metadata or {}).items():
153
+ if key in {
154
+ "package_root",
155
+ "manifest_path",
156
+ "entry_file",
157
+ "instructions",
158
+ "revision",
159
+ "created_at",
160
+ "updated_at",
161
+ "source_path",
162
+ "python_project",
163
+ }:
164
+ continue
157
165
  if value is None:
158
166
  continue
159
167
  if isinstance(value, str) and not value.strip():
@@ -220,9 +228,20 @@ class SkillStore:
220
228
  skill = self._load_published_skill(skill_name)
221
229
  retained_text_bytes += sum(
222
230
  len(value.encode("utf-8"))
223
- for value in skill.values()
224
- if isinstance(value, str)
231
+ for key, value in skill.items()
232
+ if key != "metadata" and isinstance(value, str)
225
233
  )
234
+ metadata = skill.get("metadata")
235
+ if metadata is not None:
236
+ retained_text_bytes += len(
237
+ json.dumps(
238
+ metadata,
239
+ ensure_ascii=False,
240
+ sort_keys=True,
241
+ default=str,
242
+ separators=(",", ":"),
243
+ ).encode("utf-8")
244
+ )
226
245
  if retained_text_bytes > _MAX_SKILL_LIST_TOTAL_TEXT_BYTES:
227
246
  raise ValueError("Skill listing exceeds the configured text limit")
228
247
  skills.append(skill)
@@ -352,7 +371,9 @@ class SkillStore:
352
371
  )
353
372
 
354
373
  package_root, entry_file = discovered[0]
355
- return self._load_skill_package(package_root, entry_file)
374
+ skill = self._load_skill_package(package_root, entry_file)
375
+ self._validate_agent_skill_package(package_root, skill.get("metadata") or {})
376
+ return skill
356
377
 
357
378
  def scan_import_directory(self, path: str, *, source_root: str) -> dict:
358
379
  """Scan a trusted import source without granting arbitrary host access."""
@@ -611,12 +632,16 @@ class SkillStore:
611
632
 
612
633
  tmp_dir = tempfile.mkdtemp(prefix="langbot_skill_preview_")
613
634
  try:
614
- skill_root = self._extract_uploaded_skill_to_temp(file_bytes, tmp_dir)
635
+ skill_root, allow_root_package = self._extract_uploaded_skill_to_temp(
636
+ file_bytes, tmp_dir
637
+ )
615
638
  skill_root = self._resolve_source_subdir_root(skill_root, source_subdir)
639
+ allow_root_package = allow_root_package and not source_subdir.strip()
616
640
  return self._preview_skill_candidates(
617
641
  skill_root,
618
642
  base_target_name=self._uploaded_skill_target_stem(filename),
619
643
  suffix=target_suffix,
644
+ allow_root_package=allow_root_package,
620
645
  )
621
646
  finally:
622
647
  shutil.rmtree(tmp_dir, ignore_errors=True)
@@ -637,18 +662,24 @@ class SkillStore:
637
662
 
638
663
  tmp_dir = tempfile.mkdtemp(prefix="langbot_skill_upload_")
639
664
  try:
640
- skill_root = self._extract_uploaded_skill_to_temp(file_bytes, tmp_dir)
665
+ skill_root, allow_root_package = self._extract_uploaded_skill_to_temp(
666
+ file_bytes, tmp_dir
667
+ )
641
668
  skill_root = self._resolve_source_subdir_root(skill_root, source_subdir)
669
+ allow_root_package = allow_root_package and not source_subdir.strip()
642
670
  previews = self._preview_skill_candidates(
643
671
  skill_root,
644
672
  base_target_name=self._uploaded_skill_target_stem(filename),
645
673
  suffix=target_suffix,
674
+ allow_root_package=allow_root_package,
646
675
  )
647
676
  selected_previews = self._select_preview_candidates(
648
677
  previews,
649
678
  {"source_paths": source_paths or [], "source_path": source_path},
650
679
  )
651
- scanned = self._install_preview_candidates(skill_root, selected_previews)
680
+ scanned = self._install_preview_candidates(
681
+ skill_root, selected_previews, allow_root_package=allow_root_package
682
+ )
652
683
  return scanned
653
684
  finally:
654
685
  shutil.rmtree(tmp_dir, ignore_errors=True)
@@ -881,15 +912,31 @@ class SkillStore:
881
912
  imported = self._read_skill_package(source_root) if source_root else None
882
913
  staging_root, package_root = self._stage_package(source_root or None)
883
914
  try:
884
- metadata = {
885
- "name": skill_name,
886
- "display_name": self._resolve_create_field(
887
- data, "display_name", imported, default=""
888
- ),
889
- "description": self._resolve_create_field(
890
- data, "description", imported, default=""
891
- ),
892
- }
915
+ metadata = dict((imported or {}).get("metadata") or {})
916
+ metadata.update(
917
+ {
918
+ "name": skill_name,
919
+ "display_name": self._resolve_create_field(
920
+ data, "display_name", imported, default=""
921
+ ),
922
+ "description": self._resolve_create_field(
923
+ data, "description", imported, default=""
924
+ ),
925
+ }
926
+ )
927
+ for key, value in data.items():
928
+ if (
929
+ key
930
+ not in {
931
+ "name",
932
+ "display_name",
933
+ "description",
934
+ "instructions",
935
+ "package_root",
936
+ }
937
+ and value is not None
938
+ ):
939
+ metadata[key] = value
893
940
  instructions = self._resolve_create_field(
894
941
  data, "instructions", imported, default=""
895
942
  )
@@ -1137,6 +1184,7 @@ class SkillStore:
1137
1184
  "name": skill_name,
1138
1185
  "display_name": str(metadata.get("display_name") or skill_name).strip(),
1139
1186
  "description": str(metadata.get("description") or "").strip(),
1187
+ "metadata": dict(metadata),
1140
1188
  "instructions": instructions,
1141
1189
  "package_root": package_root,
1142
1190
  "entry_file": entry_file,
@@ -1168,6 +1216,7 @@ class SkillStore:
1168
1216
  "entry_file": skill.get("entry_file", "SKILL.md"),
1169
1217
  "display_name": skill.get("display_name", ""),
1170
1218
  "description": skill.get("description", ""),
1219
+ "metadata": dict(skill.get("metadata") or {}),
1171
1220
  "instructions": skill.get("instructions", ""),
1172
1221
  }
1173
1222
 
@@ -1193,7 +1242,12 @@ class SkillStore:
1193
1242
  return os.path.join(self.root, target_name)
1194
1243
 
1195
1244
  def _preview_skill_candidates(
1196
- self, root_path: str, *, base_target_name: str, suffix: str
1245
+ self,
1246
+ root_path: str,
1247
+ *,
1248
+ base_target_name: str,
1249
+ suffix: str,
1250
+ allow_root_package: bool = False,
1197
1251
  ) -> list[dict]:
1198
1252
  discovered = self._discover_skill_directories(root_path, max_depth=2)
1199
1253
  if not discovered:
@@ -1205,6 +1259,12 @@ class SkillStore:
1205
1259
  for package_root, entry_file in discovered:
1206
1260
  skill = self._load_skill_package(package_root, entry_file)
1207
1261
  relative_path = os.path.relpath(package_root, root_path)
1262
+ is_archive_root_skill = allow_root_package and relative_path in ("", ".")
1263
+ self._validate_agent_skill_package(
1264
+ package_root,
1265
+ skill.get("metadata") or {},
1266
+ require_directory_name=not is_archive_root_skill,
1267
+ )
1208
1268
  if relative_path in ("", "."):
1209
1269
  relative_path = ""
1210
1270
  skill["source_path"] = relative_path.replace(os.sep, "/")
@@ -1216,6 +1276,37 @@ class SkillStore:
1216
1276
  previews.sort(key=lambda item: item["source_path"])
1217
1277
  return [self._serialize_skill_with_source(preview) for preview in previews]
1218
1278
 
1279
+ @staticmethod
1280
+ def _validate_agent_skill_package(
1281
+ package_root: str, metadata: dict, *, require_directory_name: bool = True
1282
+ ) -> None:
1283
+ name = metadata.get("name")
1284
+ if not isinstance(name, str) or not name.strip():
1285
+ raise ValueError(
1286
+ f"Skill package {package_root} must declare a frontmatter name"
1287
+ )
1288
+ name = name.strip()
1289
+ if not re.fullmatch(r"[a-z0-9]+(?:-[a-z0-9]+)*", name):
1290
+ raise ValueError(
1291
+ "Skill name must use lowercase letters, numbers, and hyphens"
1292
+ )
1293
+ if len(name) > 64:
1294
+ raise ValueError("Skill name cannot exceed 64 characters")
1295
+ directory_name = os.path.basename(os.path.normpath(package_root))
1296
+ if require_directory_name and name != directory_name:
1297
+ raise ValueError(
1298
+ f'Skill frontmatter name "{name}" must match directory "{directory_name}"'
1299
+ )
1300
+ description = metadata.get("description")
1301
+ if not isinstance(description, str) or not description.strip():
1302
+ raise ValueError(
1303
+ f'Skill "{name}" must declare a non-empty frontmatter description'
1304
+ )
1305
+ if len(description) > 1024:
1306
+ raise ValueError(
1307
+ f'Skill "{name}" description cannot exceed 1024 characters'
1308
+ )
1309
+
1219
1310
  @staticmethod
1220
1311
  def _serialize_skill_with_source(skill: dict) -> dict:
1221
1312
  data = SkillStore._serialize_skill(skill)
@@ -1265,7 +1356,11 @@ class SkillStore:
1265
1356
  return selected
1266
1357
 
1267
1358
  def _install_preview_candidates(
1268
- self, root_path: str, selected_previews: list[dict]
1359
+ self,
1360
+ root_path: str,
1361
+ selected_previews: list[dict],
1362
+ *,
1363
+ allow_root_package: bool = False,
1269
1364
  ) -> list[dict]:
1270
1365
  installed: list[dict] = []
1271
1366
  try:
@@ -1273,7 +1368,18 @@ class SkillStore:
1273
1368
  source_root = self._preview_source_root(
1274
1369
  root_path, preview["source_path"]
1275
1370
  )
1276
- scanned = SkillStore(self.root).scan_directory(source_root)
1371
+ if preview["source_path"] or not allow_root_package:
1372
+ scanned = SkillStore(self.root).scan_directory(source_root)
1373
+ else:
1374
+ entry = self._find_skill_entry(source_root)
1375
+ if entry is None:
1376
+ raise ValueError(f"No SKILL.md found in {source_root}")
1377
+ scanned = self._load_skill_package(entry[0], entry[1])
1378
+ self._validate_agent_skill_package(
1379
+ source_root,
1380
+ scanned.get("metadata") or {},
1381
+ require_directory_name=False,
1382
+ )
1277
1383
  skill_name = self._validate_skill_name(scanned["name"])
1278
1384
  self._ensure_legacy_packages_published()
1279
1385
  with self._skill_lock(skill_name):
@@ -1303,7 +1409,9 @@ class SkillStore:
1303
1409
 
1304
1410
  return installed
1305
1411
 
1306
- def _extract_uploaded_skill_to_temp(self, file_bytes: bytes, tmp_dir: str) -> str:
1412
+ def _extract_uploaded_skill_to_temp(
1413
+ self, file_bytes: bytes, tmp_dir: str
1414
+ ) -> tuple[str, bool]:
1307
1415
  extract_dir = os.path.join(tmp_dir, "extracted")
1308
1416
  try:
1309
1417
  with zipfile.ZipFile(io.BytesIO(file_bytes), "r") as zf:
@@ -1313,8 +1421,8 @@ class SkillStore:
1313
1421
 
1314
1422
  entries = os.listdir(extract_dir)
1315
1423
  if len(entries) == 1 and os.path.isdir(os.path.join(extract_dir, entries[0])):
1316
- return os.path.join(extract_dir, entries[0])
1317
- return extract_dir
1424
+ return os.path.join(extract_dir, entries[0]), False
1425
+ return extract_dir, True
1318
1426
 
1319
1427
  @staticmethod
1320
1428
  def _validate_zip_upload_size(file_bytes: bytes) -> None:
@@ -0,0 +1 @@
1
+ __version__ = "0.7.18"
@@ -0,0 +1,183 @@
1
+ """Component module resolution must stay inside the plugin directory.
2
+
3
+ ``execution.python.path`` is plugin-authored manifest data, so it is untrusted.
4
+ These tests pin the resolver to the plugin directory and check that importing a
5
+ component no longer leaves the plugin directory on ``sys.path``.
6
+ """
7
+
8
+ import sys
9
+ import textwrap
10
+
11
+ import pytest
12
+
13
+ from langbot_plugin.api.definition.components.manifest import ComponentManifest
14
+
15
+
16
+ @pytest.fixture(autouse=True)
17
+ def _clean_component_modules(tmp_path, monkeypatch):
18
+ """Drop cached component modules so each test resolves its own plugin dir."""
19
+ monkeypatch.chdir(tmp_path)
20
+ before = {
21
+ name
22
+ for name in sys.modules
23
+ if name == "components" or name.startswith("components.")
24
+ }
25
+ for name in before:
26
+ sys.modules.pop(name, None)
27
+ yield
28
+ for name in [
29
+ n for n in sys.modules if n == "components" or n.startswith("components.")
30
+ ]:
31
+ sys.modules.pop(name, None)
32
+
33
+
34
+ def _manifest(rel_path: str, python_path: str, attr: str = "Component"):
35
+ return ComponentManifest(
36
+ owner="plugin",
37
+ manifest={
38
+ "apiVersion": "v1",
39
+ "kind": "Command",
40
+ "metadata": {
41
+ "name": "probe",
42
+ "label": {"en_US": "probe"},
43
+ "description": {"en_US": "probe"},
44
+ },
45
+ "spec": {},
46
+ "execution": {"python": {"path": python_path, "attr": attr}},
47
+ },
48
+ rel_path=rel_path,
49
+ )
50
+
51
+
52
+ def _plugin(tmp_path, files: dict[str, str]):
53
+ for name, content in files.items():
54
+ target = tmp_path / name
55
+ target.parent.mkdir(parents=True, exist_ok=True)
56
+ target.write_text(textwrap.dedent(content))
57
+ return tmp_path
58
+
59
+
60
+ @pytest.mark.parametrize(
61
+ "declared",
62
+ [
63
+ "../outside.py",
64
+ "../../etc/evil.py",
65
+ "components/../../outside.py",
66
+ "/etc/passwd.py",
67
+ "C:/windows/evil.py",
68
+ "c:evil.py",
69
+ "",
70
+ ],
71
+ )
72
+ def test_paths_outside_the_plugin_are_rejected(tmp_path, declared):
73
+ plugin = _plugin(tmp_path, {"manifest.yaml": ""})
74
+ manifest = _manifest(str(plugin / "manifest.yaml"), declared)
75
+ with pytest.raises(ValueError):
76
+ manifest.get_python_component_class()
77
+
78
+
79
+ def test_component_inside_the_plugin_is_imported(tmp_path, monkeypatch):
80
+ plugin = _plugin(
81
+ tmp_path,
82
+ {
83
+ "components/__init__.py": "",
84
+ "components/inside_once.py": """
85
+ class Component:
86
+ marker = "INSIDE"
87
+ """,
88
+ },
89
+ )
90
+ manifest = _manifest(str(plugin / "manifest.yaml"), "components/inside_once.py")
91
+
92
+ component = manifest.get_python_component_class()
93
+
94
+ assert component.marker == "INSIDE"
95
+
96
+
97
+ def test_import_does_not_leave_the_plugin_dir_on_sys_path(tmp_path, monkeypatch):
98
+ """A leaked path would let one plugin shadow modules for later plugins."""
99
+ plugin = _plugin(
100
+ tmp_path,
101
+ {
102
+ "components/__init__.py": "",
103
+ "components/leak_check.py": """
104
+ class Component:
105
+ marker = "INSIDE"
106
+ """,
107
+ },
108
+ )
109
+ manifest = _manifest(str(plugin / "manifest.yaml"), "components/leak_check.py")
110
+ before = list(sys.path)
111
+
112
+ manifest.get_python_component_class()
113
+
114
+ assert str(plugin) not in sys.path
115
+ assert len(sys.path) == len(before)
116
+
117
+
118
+ def test_relative_path_without_py_suffix_works(tmp_path, monkeypatch):
119
+ plugin = _plugin(
120
+ tmp_path,
121
+ {
122
+ "components/__init__.py": "",
123
+ "components/no_suffix_mod.py": """
124
+ class Component:
125
+ marker = "NO_SUFFIX"
126
+ """,
127
+ },
128
+ )
129
+ manifest = _manifest(str(plugin / "manifest.yaml"), "components/no_suffix_mod")
130
+
131
+ assert manifest.get_python_component_class().marker == "NO_SUFFIX"
132
+
133
+
134
+ def test_importing_a_missing_component_leaves_sys_path_clean(tmp_path, monkeypatch):
135
+ plugin = _plugin(tmp_path, {"manifest.yaml": ""})
136
+ manifest = _manifest(str(plugin / "manifest.yaml"), "components/missing.py")
137
+ before = list(sys.path)
138
+
139
+ with pytest.raises(ModuleNotFoundError):
140
+ manifest.get_python_component_class()
141
+
142
+ assert str(plugin) not in sys.path
143
+ assert len(sys.path) == len(before)
144
+
145
+
146
+ @pytest.mark.parametrize("packages", [True, False])
147
+ def test_nested_component_preserves_package_and_relative_imports(tmp_path, packages):
148
+ files = {
149
+ "components/knowledge_engine/parser.py": 'VALUE = "parsed"',
150
+ "components/knowledge_engine/engine.py": """
151
+ from .parser import VALUE
152
+
153
+ class Component:
154
+ marker = VALUE
155
+
156
+ def lazy_import(self):
157
+ from .parser import VALUE
158
+ return VALUE
159
+ """,
160
+ }
161
+ if packages:
162
+ files.update(
163
+ {
164
+ "components/__init__.py": "",
165
+ "components/knowledge_engine/__init__.py": "",
166
+ }
167
+ )
168
+ _plugin(tmp_path, files)
169
+ manifest = _manifest("components/knowledge_engine/engine.yaml", "engine.py")
170
+ before = list(sys.path)
171
+
172
+ component = manifest.get_python_component_class()
173
+
174
+ assert component.__module__ == "components.knowledge_engine.engine"
175
+ assert component.marker == "parsed"
176
+ assert component().lazy_import() == "parsed"
177
+ assert sys.path == before
178
+
179
+
180
+ def test_manifest_outside_plugin_root_is_rejected(tmp_path):
181
+ manifest = _manifest(str(tmp_path.parent / "outside.yaml"), "outside.py")
182
+ with pytest.raises(ValueError, match="escapes the plugin directory"):
183
+ manifest.get_python_component_class()
@@ -573,9 +573,11 @@ async def test_exec_timeout(backend, tmp_base):
573
573
 
574
574
 
575
575
  @pytest.mark.anyio
576
- async def test_run_nsjail_cancellation_terminates_and_reaps_process(
576
+ @pytest.mark.parametrize("stop_reason", ["timeout", "cancel"])
577
+ async def test_run_nsjail_termination_allows_cleanup(
577
578
  backend,
578
579
  monkeypatch,
580
+ stop_reason,
579
581
  ):
580
582
  class EmptyStream:
581
583
  async def read(self, _size):
@@ -589,6 +591,7 @@ async def test_run_nsjail_cancellation_terminates_and_reaps_process(
589
591
  self.wait_started = asyncio.Event()
590
592
  self.exit_requested = asyncio.Event()
591
593
  self.terminated = False
594
+ self.killed = False
592
595
 
593
596
  async def wait(self):
594
597
  self.wait_started.set()
@@ -601,6 +604,7 @@ async def test_run_nsjail_cancellation_terminates_and_reaps_process(
601
604
  self.exit_requested.set()
602
605
 
603
606
  def kill(self):
607
+ self.killed = True
604
608
  self.exit_requested.set()
605
609
 
606
610
  process = HangingProcess()
@@ -614,14 +618,22 @@ async def test_run_nsjail_cancellation_terminates_and_reaps_process(
614
618
  create_subprocess_exec,
615
619
  )
616
620
  task = asyncio.create_task(
617
- backend._run_nsjail(["nsjail", "--help"], timeout_sec=60)
621
+ backend._run_nsjail(
622
+ ["nsjail", "--help"],
623
+ timeout_sec=0.01 if stop_reason == "timeout" else 60,
624
+ )
618
625
  )
619
626
  await process.wait_started.wait()
620
- task.cancel()
621
-
622
- with pytest.raises(asyncio.CancelledError):
623
- await task
627
+ if stop_reason == "cancel":
628
+ task.cancel()
629
+ with pytest.raises(asyncio.CancelledError):
630
+ await task
631
+ else:
632
+ result = await task
633
+ assert result.timed_out is True
634
+ assert result.return_code == -1
624
635
  assert process.terminated is True
636
+ assert process.killed is False
625
637
  assert process.returncode == -15
626
638
 
627
639