langbot-plugin 0.4.2b4__tar.gz → 0.4.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. langbot_plugin-0.4.4/.github/workflows/cla.yml +41 -0
  2. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/AGENTS.md +46 -22
  3. langbot_plugin-0.4.4/CONTRIBUTING.md +15 -0
  4. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/PKG-INFO +2 -1
  5. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/pyproject.toml +2 -1
  6. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/proxies/langbot_api.py +37 -0
  7. langbot_plugin-0.4.4/src/langbot_plugin/assets/templates/.github/workflows/release.yml.example +77 -0
  8. langbot_plugin-0.4.4/src/langbot_plugin/assets/templates/README.md.example +15 -0
  9. langbot_plugin-0.4.4/src/langbot_plugin/assets/templates/readme/README_zh_Hans.md.example +15 -0
  10. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/box/nsjail_backend.py +83 -36
  11. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/commands/initplugin.py +4 -0
  12. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/gen/renderer.py +2 -0
  13. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/entities/io/actions/enums.py +2 -0
  14. langbot_plugin-0.4.4/src/langbot_plugin/entities/io/errors.py +91 -0
  15. langbot_plugin-0.4.4/src/langbot_plugin/runtime/helper/pkgmgr.py +369 -0
  16. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/controllers/stdio/client.py +3 -0
  17. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/handlers/control.py +11 -0
  18. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/handlers/plugin.py +24 -0
  19. langbot_plugin-0.4.4/src/langbot_plugin/runtime/plugin/logbuffer.py +125 -0
  20. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/plugin/mgr.py +99 -12
  21. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/api/proxies/test_langbot_api.py +18 -0
  22. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/box/test_nsjail_backend.py +78 -20
  23. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/cli/test_initplugin.py +2 -0
  24. langbot_plugin-0.4.4/tests/entities/io/test_dependency_errors.py +59 -0
  25. langbot_plugin-0.4.4/tests/runtime/helper/test_pkgmgr.py +388 -0
  26. langbot_plugin-0.4.4/tests/runtime/io/test_handler.py +578 -0
  27. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/runtime/plugin/test_manager.py +62 -2
  28. langbot_plugin-0.4.4/tests/test_plugin_logbuffer.py +78 -0
  29. langbot_plugin-0.4.2b4/src/langbot_plugin/assets/templates/README.md.example +0 -3
  30. langbot_plugin-0.4.2b4/src/langbot_plugin/entities/io/errors.py +0 -31
  31. langbot_plugin-0.4.2b4/src/langbot_plugin/runtime/helper/pkgmgr.py +0 -141
  32. langbot_plugin-0.4.2b4/tests/runtime/helper/test_pkgmgr.py +0 -109
  33. langbot_plugin-0.4.2b4/tests/runtime/io/test_handler.py +0 -228
  34. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/.github/workflows/publish-pypi.yaml +0 -0
  35. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/.github/workflows/test.yml +0 -0
  36. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/.gitignore +0 -0
  37. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/.python-version +0 -0
  38. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/CLAUDE.md +0 -0
  39. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/LICENSE +0 -0
  40. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/README.md +0 -0
  41. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/data/.env.example +0 -0
  42. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/docs/Message.md +0 -0
  43. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/docs/PluginPages.md +0 -0
  44. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/docs/communication/apis/lb2rt.md +0 -0
  45. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/docs/communication/runtime_plugin.md +0 -0
  46. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/docs/dependency-management.md +0 -0
  47. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/docs/langbot-plugin-social.png +0 -0
  48. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/__init__.py +0 -0
  49. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/__init__.py +0 -0
  50. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/__init__.py +0 -0
  51. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/abstract/__init__.py +0 -0
  52. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/abstract/platform/__init__.py +0 -0
  53. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/abstract/platform/adapter.py +0 -0
  54. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/abstract/platform/event_logger.py +0 -0
  55. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/__init__.py +0 -0
  56. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/base.py +0 -0
  57. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/command/__init__.py +0 -0
  58. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/command/command.py +0 -0
  59. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/common/__init__.py +0 -0
  60. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/common/event_listener.py +0 -0
  61. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/knowledge_engine/__init__.py +0 -0
  62. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/knowledge_engine/engine.py +0 -0
  63. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/manifest.py +0 -0
  64. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/page/__init__.py +0 -0
  65. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/parser/__init__.py +0 -0
  66. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/parser/parser.py +0 -0
  67. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/tool/__init__.py +0 -0
  68. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/components/tool/tool.py +0 -0
  69. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/definition/plugin.py +0 -0
  70. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/__init__.py +0 -0
  71. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/__init__.py +0 -0
  72. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/command/__init__.py +0 -0
  73. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/command/context.py +0 -0
  74. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/command/errors.py +0 -0
  75. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/pipeline/__init__.py +0 -0
  76. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/pipeline/query.py +0 -0
  77. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/platform/__init__.py +0 -0
  78. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/platform/entities.py +0 -0
  79. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/platform/events.py +0 -0
  80. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/platform/logger.py +0 -0
  81. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/platform/message.py +0 -0
  82. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/provider/__init__.py +0 -0
  83. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/provider/message.py +0 -0
  84. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/provider/prompt.py +0 -0
  85. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/provider/session.py +0 -0
  86. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/rag/__init__.py +0 -0
  87. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/rag/context.py +0 -0
  88. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/rag/enums.py +0 -0
  89. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/rag/errors.py +0 -0
  90. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/rag/models.py +0 -0
  91. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/resource/__init__.py +0 -0
  92. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/builtin/resource/tool.py +0 -0
  93. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/context.py +0 -0
  94. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/entities/events.py +0 -0
  95. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/proxies/__init__.py +0 -0
  96. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/proxies/base.py +0 -0
  97. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/proxies/event_context.py +0 -0
  98. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/proxies/execute_context.py +0 -0
  99. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/api/proxies/query_based_api.py +0 -0
  100. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/__init__.py +0 -0
  101. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/langbot-page-sdk.js +0 -0
  102. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/.env.example.example +0 -0
  103. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/.gitignore.example +0 -0
  104. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/.vscode/launch.json.example +0 -0
  105. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/__init__.py +0 -0
  106. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/assets/icon.svg.example +0 -0
  107. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/__init__.py +0 -0
  108. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/commands/__init__.py +0 -0
  109. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/commands/{cmd_name}.py.example +0 -0
  110. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/commands/{cmd_name}.yaml.example +0 -0
  111. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/event_listener/__init__.py +0 -0
  112. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/event_listener/default.py.example +0 -0
  113. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/event_listener/default.yaml.example +0 -0
  114. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/knowledge_engine/__init__.py +0 -0
  115. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/knowledge_engine/{knowledge_engine_name}.py.example +0 -0
  116. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/knowledge_engine/{knowledge_engine_name}.yaml.example +0 -0
  117. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/pages/{page_name}.html.example +0 -0
  118. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/pages/{page_name}.yaml.example +0 -0
  119. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/parser/__init__.py +0 -0
  120. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/parser/{parser_name}.py.example +0 -0
  121. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/parser/{parser_name}.yaml.example +0 -0
  122. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/tools/__init__.py +0 -0
  123. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/tools/{tool_name}.py.example +0 -0
  124. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/components/tools/{tool_name}.yaml.example +0 -0
  125. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/main.py.example +0 -0
  126. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/manifest.yaml.example +0 -0
  127. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/assets/templates/requirements.txt.example +0 -0
  128. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/box/__init__.py +0 -0
  129. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/box/actions.py +0 -0
  130. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/box/backend.py +0 -0
  131. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/box/client.py +0 -0
  132. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/box/e2b_backend.py +0 -0
  133. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/box/errors.py +0 -0
  134. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/box/models.py +0 -0
  135. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/box/runtime.py +0 -0
  136. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/box/security.py +0 -0
  137. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/box/server.py +0 -0
  138. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/box/skill_store.py +0 -0
  139. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/__init__.py +0 -0
  140. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/__main__.py +0 -0
  141. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/commands/__init__.py +0 -0
  142. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/commands/buildplugin.py +0 -0
  143. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/commands/gencomponent.py +0 -0
  144. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/commands/login.py +0 -0
  145. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/commands/logout.py +0 -0
  146. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/commands/publish.py +0 -0
  147. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/commands/runplugin.py +0 -0
  148. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/gen/__init__.py +0 -0
  149. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/i18n.py +0 -0
  150. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/locales/__init__.py +0 -0
  151. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/locales/en_US.py +0 -0
  152. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/locales/es_ES.py +0 -0
  153. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/locales/ja_JP.py +0 -0
  154. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/locales/th_TH.py +0 -0
  155. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/locales/vi_VN.py +0 -0
  156. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/locales/zh_Hans.py +0 -0
  157. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/locales/zh_Hant.py +0 -0
  158. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/run/__init__.py +0 -0
  159. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/run/controller.py +0 -0
  160. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/run/handler.py +0 -0
  161. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/run/hotreload.py +0 -0
  162. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/utils/__init__.py +0 -0
  163. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/utils/cloudsv.py +0 -0
  164. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/utils/form.py +0 -0
  165. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/cli/utils/page_components.py +0 -0
  166. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/entities/__init__.py +0 -0
  167. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/entities/io/__init__.py +0 -0
  168. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/entities/io/actions/__init__.py +0 -0
  169. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/entities/io/req.py +0 -0
  170. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/entities/io/resp.py +0 -0
  171. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/entities/marketplace.py +0 -0
  172. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/LICENSE +0 -0
  173. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/README.md +0 -0
  174. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/__init__.py +0 -0
  175. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/app.py +0 -0
  176. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/context.py +0 -0
  177. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/helper/__init__.py +0 -0
  178. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/helper/marketplace.py +0 -0
  179. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/__init__.py +0 -0
  180. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/connection.py +0 -0
  181. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/connections/__init__.py +0 -0
  182. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/connections/stdio.py +0 -0
  183. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/connections/ws.py +0 -0
  184. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/controller.py +0 -0
  185. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/controllers/__init__.py +0 -0
  186. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/controllers/stdio/__init__.py +0 -0
  187. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/controllers/stdio/server.py +0 -0
  188. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/controllers/ws/__init__.py +0 -0
  189. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/controllers/ws/client.py +0 -0
  190. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/controllers/ws/server.py +0 -0
  191. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/handler.py +0 -0
  192. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/io/handlers/__init__.py +0 -0
  193. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/plugin/__init__.py +0 -0
  194. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/plugin/container.py +0 -0
  195. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/runtime/settings.py +0 -0
  196. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/utils/__init__.py +0 -0
  197. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/utils/discover/__init__.py +0 -0
  198. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/utils/discover/engine.py +0 -0
  199. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/utils/importutil.py +0 -0
  200. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/utils/log.py +0 -0
  201. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/utils/platform.py +0 -0
  202. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/src/langbot_plugin/version.py +0 -0
  203. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/__init__.py +0 -0
  204. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/api/definition/components/test_components.py +0 -0
  205. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/api/definition/test_manifest.py +0 -0
  206. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/api/entities/builtin/test_command_context.py +0 -0
  207. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/api/entities/builtin/test_platform_logger.py +0 -0
  208. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/api/entities/builtin/test_provider_message.py +0 -0
  209. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/api/entities/builtin/test_rag_models.py +0 -0
  210. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/api/entities/test_context.py +0 -0
  211. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/api/entities/test_events.py +0 -0
  212. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/api/proxies/test_base.py +0 -0
  213. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/api/proxies/test_query_based_api.py +0 -0
  214. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/box/__init__.py +0 -0
  215. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/box/test_backend.py +0 -0
  216. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/box/test_backend_selection.py +0 -0
  217. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/box/test_client.py +0 -0
  218. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/box/test_e2b_backend.py +0 -0
  219. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/box/test_runtime.py +0 -0
  220. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/box/test_server.py +0 -0
  221. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/box/test_skill_store.py +0 -0
  222. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/cli/run/test_controller.py +0 -0
  223. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/cli/run/test_runtime_handler.py +0 -0
  224. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/cli/test_buildplugin.py +0 -0
  225. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/cli/test_gencomponent.py +0 -0
  226. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/cli/test_i18n_form.py +0 -0
  227. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/cli/test_login.py +0 -0
  228. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/cli/test_logout_publish.py +0 -0
  229. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/cli/test_page_components.py +0 -0
  230. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/cli/test_renderer.py +0 -0
  231. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/cli/test_runplugin.py +0 -0
  232. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/entities/io/test_protocol.py +0 -0
  233. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/helpers/__init__.py +0 -0
  234. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/helpers/protocol.py +0 -0
  235. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/runtime/helper/test_marketplace.py +0 -0
  236. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/runtime/io/handlers/test_control_handler.py +0 -0
  237. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/runtime/io/handlers/test_import_contracts.py +0 -0
  238. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/runtime/io/handlers/test_plugin_handler.py +0 -0
  239. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/runtime/io/test_connections.py +0 -0
  240. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/runtime/io/test_controllers.py +0 -0
  241. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/runtime/plugin/test_container.py +0 -0
  242. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/runtime/test_app.py +0 -0
  243. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/test_log.py +0 -0
  244. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/test_message.py +0 -0
  245. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/utils/test_discovery.py +0 -0
  246. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/utils/test_importutil.py +0 -0
  247. {langbot_plugin-0.4.2b4 → langbot_plugin-0.4.4}/tests/utils/test_platform.py +0 -0
@@ -0,0 +1,41 @@
1
+ name: "CLA Assistant"
2
+ on:
3
+ issue_comment:
4
+ types: [created]
5
+ pull_request_target:
6
+ types: [opened, closed, synchronize, reopened]
7
+
8
+ permissions:
9
+ actions: write # re-run the failed CLA check after signing
10
+ contents: read # signatures are stored in the remote langbot-app/cla repo
11
+ pull-requests: write # post guidance comments, lock PR after merge
12
+ statuses: write # set the commit status
13
+
14
+ jobs:
15
+ CLAAssistant:
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - name: "CLA Assistant"
19
+ if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
20
+ # Upstream repo was archived in 2026-03; pin to the v2.6.1 commit SHA.
21
+ uses: contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08 # v2.6.1
22
+ env:
23
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
24
+ # repo-scope PAT with write access to langbot-app/cla
25
+ PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_PAT }}
26
+ with:
27
+ path-to-document: 'https://github.com/langbot-app/LangBot/blob/master/CLA.md'
28
+ remote-organization-name: 'langbot-app'
29
+ remote-repository-name: 'cla'
30
+ path-to-signatures: 'signatures/version1/cla.json'
31
+ branch: 'main'
32
+ allowlist: 'dependabot[bot],github-actions[bot],devin-ai-integration[bot],Copilot,renovate[bot],bot*'
33
+ custom-notsigned-prcomment: |
34
+ Thank you for your contribution! :heart: Before we can merge this pull request, we need you to sign the [LangBot Contributor License Agreement (CLA)](https://github.com/langbot-app/LangBot/blob/master/CLA.md). You keep full copyright of your code — the CLA grants us a license to use and distribute your contribution. Signing takes 10 seconds and covers all repositories in this organization, permanently.
35
+
36
+ 感谢您的贡献!合并前请阅读并签署[贡献者许可协议(CLA)](https://github.com/langbot-app/LangBot/blob/master/CLA.md)。您保留代码的全部版权,签署仅需回复下方指定内容,一次签署对本组织全部仓库永久有效。
37
+ custom-allsigned-prcomment: 'All contributors have signed the CLA. :white_check_mark: 所有贡献者均已签署 CLA。'
38
+ lock-pullrequest-aftermerge: true
39
+ # SECURITY: this workflow runs on pull_request_target (it holds secrets and has
40
+ # write access to the base repository). NEVER add an actions/checkout step that
41
+ # checks out the PR's code here.
@@ -816,34 +816,49 @@ Encapsulates plugin instance with:
816
816
 
817
817
  ### Communication Protocol (`runtime/io/`)
818
818
 
819
- **Action-Based Protocol**:
820
- - Bidirectional JSON messages
821
- - Request-response with sequence IDs
822
- - Streaming support via chunk status
823
- - File transfer (16KB chunks)
824
-
825
- **Action Structure**:
819
+ This protocol is **JSON-RPC 2.0 in all but field names** — a bidirectional, action-based
820
+ RPC carried over a single connection. It is the same shape the Language Server Protocol
821
+ (LSP) and the Model Context Protocol (MCP) use: JSON-RPC 2.0 over stdio / WebSocket, with
822
+ either peer free to initiate calls. We did not adopt the spec verbatim, but the semantics
823
+ map 1:1, and it is useful to think of it that way:
824
+
825
+ | Our field (`entities/io`) | JSON-RPC 2.0 | Meaning |
826
+ |----------------------------|--------------------------|---------|
827
+ | `seq_id` | `id` | Correlates a response back to its request |
828
+ | `action` | `method` | Which action to invoke |
829
+ | `data` (in a request) | `params` | Call arguments |
830
+ | `data` (in a response) | `result` | Return value (when `code == 0`) |
831
+ | `code` + `message` | `error.{code,message}` | `code == 0` is success; non-zero carries the failure in `message` |
832
+ | `chunk_status` | (MCP-style streaming ext.) | `continue` per chunk, `end` closes a streamed response |
833
+
834
+ Both peers share one connection and may call each other's actions. Requests and responses
835
+ are told apart by shape: a message carrying `action` is an inbound request, one carrying
836
+ `code` is a response. Each side allocates `seq_id` from its own incrementing counter, so the
837
+ two id spaces are dispatched independently and never collide.
838
+
839
+ **Request** (`ActionRequest`, `entities/io/req.py`):
826
840
  ```json
827
- {
828
- "action": "action_name",
829
- "seq": 12345,
830
- "data": {...},
831
- "chunk_status": "start|continue|end"
832
- }
841
+ { "seq_id": 12345, "action": "action_name", "data": {} }
833
842
  ```
834
843
 
835
- **Response Structure**:
844
+ **Response** (`ActionResponse`, `entities/io/resp.py`):
836
845
  ```json
837
- {
838
- "seq": 12345,
839
- "ok": true,
840
- "data": {...}
841
- }
846
+ { "seq_id": 12345, "code": 0, "message": "success", "data": {}, "chunk_status": "continue" }
842
847
  ```
843
848
 
844
- **Transport Implementations**:
845
- - `StdioHandler`: stdin/stdout communication
846
- - `WebSocketHandler`: WebSocket client/server
849
+ - `code == 0` → success, payload in `data`; non-zero → error, human-readable text in `message`.
850
+ - **Streaming**: the responder emits N chunks with `chunk_status: "continue"`, then a final
851
+ `chunk_status: "end"` (consumed by `Handler.call_action_generator`).
852
+ - **File transfer**: large blobs travel as `__file_chunk` actions — 16KB base64 chunks,
853
+ reassembled to `data/temp/lbp/<file_key>` on the receiving side.
854
+
855
+ **Core engine**: `runtime/io/handler.py` (`Handler`) owns `seq_id` allocation, the
856
+ `resp_waiters` (single response) and `resp_queues` (streamed response) correlation maps,
857
+ timeouts, and the receive loop (`Handler.run`).
858
+
859
+ **Transport Implementations** (`Connection` subclasses, `runtime/io/connections/`):
860
+ - `stdio.py`: stdin/stdout — default for subprocess (personal / lightweight) plugins
861
+ - `ws.py`: WebSocket — for containerized / remote plugin deployments
847
862
 
848
863
  ## CLI Tools
849
864
 
@@ -946,6 +961,15 @@ Box selects the first available sandbox backend among **Docker / nsjail / E2B**.
946
961
 
947
962
  To make LangBot connect to a standalone Box runtime (mirrors the plugin-runtime flow): in LangBot's `data/config.yaml` set `box.runtime.endpoint` to the runtime's base URL (e.g. `ws://127.0.0.1:5410`), pick `box.backend` (`'local'`/`'docker'`/`'nsjail'`/`'e2b'`), and start LangBot with `--standalone-box`. In Docker deployments LangBot reaches the Box runtime at host `langbot_box:5410`.
948
963
 
964
+ #### nsjail backend in containers — cgroup namespace requirement
965
+
966
+ The official `docker/docker-compose.yaml` runs the Box container with the **Docker (docker.sock) backend**, which has no cgroup requirements. The **nsjail backend** is different and has a non-obvious deployment requirement when run inside a container (e.g. a per-pod Box sidecar, or `BOX__BACKEND=nsjail`):
967
+
968
+ - nsjail with cgroup v2 limits (`--use_cgroupv2`) creates a child cgroup and enables controllers by writing `+memory`/`+pids`/`+cpu` to the cgroup root's `cgroup.subtree_control`. Inside a **private cgroup namespace** (Docker/k8s default) the container's own cgroup root already holds live processes (the Box runtime itself), so the kernel's *no-internal-process* rule rejects that write with **EBUSY** and every sandbox launch aborts with **exit 255**.
969
+ - **Fix: run the Box container in the host cgroup namespace** — compose `cgroup: host` (or `docker run --cgroupns=host`), plus `privileged: true` (nsjail also needs clone-namespaces/chroot). Then `_detect_cgroup_v2()` succeeds and nsjail applies precise cgroup memory/pid/cpu caps.
970
+ - `NsjailBackend._detect_cgroup_v2()` probes the **authoritative** operation (a real `cgroup.subtree_control` write), not just a `mkdir` under the cgroup root — a mkdir probe false-positives in a private cgroupns because mkdir succeeds while the subtree_control write later EBUSYs.
971
+ - **Without cgroups there is no hard memory cap.** When cgroup v2 is unavailable the backend falls back to rlimits but **deliberately does NOT set `--rlimit_as`**: RLIMIT_AS limits *virtual* address space, which `uv`/`node`/Rust/JVM reserve in gigabytes, so a small RLIMIT_AS aborts them instantly (`memory allocation of N bytes failed`, exit 255) — this is what silently broke uvx-based stdio MCP servers. There is no RSS-based rlimit on modern Linux, so accurate memory capping **requires** cgroups (host cgroupns) or a container-level memory limit (compose `mem_limit`). The rlimit fallback still applies safe caps (pids/fsize/nofile).
972
+
949
973
  ### Plugin development loop
950
974
 
951
975
  ```bash
@@ -0,0 +1,15 @@
1
+ # Contributing to langbot-plugin-sdk
2
+
3
+ Thank you for your interest in contributing! For general contribution guidelines, please refer to the [LangBot contribution guide](https://github.com/langbot-app/LangBot/blob/master/CONTRIBUTING.md).
4
+
5
+ 感谢您有意参与贡献!通用贡献指引请参阅 [LangBot 贡献指南](https://github.com/langbot-app/LangBot/blob/master/CONTRIBUTING.md)。
6
+
7
+ ## Contributor License Agreement (CLA)
8
+
9
+ To protect the project and every contributor, we require all code contributors to sign the [LangBot Contributor License Agreement](https://github.com/langbot-app/LangBot/blob/master/CLA.md). You keep full copyright of your code — the CLA only grants us a license to use and distribute your contribution.
10
+
11
+ Signing takes 10 seconds: when you open your first PR, a bot will guide you to reply with a single comment. One signature covers all repositories in this organization, permanently.
12
+
13
+ 为了保护项目和每一位贡献者,我们要求所有代码贡献者签署 [LangBot 贡献者许可协议(CLA)](https://github.com/langbot-app/LangBot/blob/master/CLA.md)。您保留自己代码的全部版权,CLA 仅授予项目使用、分发您贡献的许可。
14
+
15
+ 签署只需 10 秒:首次提交 PR 时,机器人会自动评论提示,按提示回复一句话即完成签署,此后对本组织所有仓库永久有效。
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: langbot-plugin
3
- Version: 0.4.2b4
3
+ Version: 0.4.4
4
4
  Summary: This package contains the SDK, CLI for building plugins for LangBot, plus the runtime for hosting LangBot plugins
5
5
  Project-URL: Homepage, https://langbot.app
6
6
  Project-URL: Repository, https://github.com/langbot-app/langbot-plugin-sdk
@@ -14,6 +14,7 @@ Requires-Dist: dotenv>=0.9.9
14
14
  Requires-Dist: e2b>=2.15
15
15
  Requires-Dist: httpx>=0.28.1
16
16
  Requires-Dist: jinja2>=3.1.6
17
+ Requires-Dist: packaging>=24.0
17
18
  Requires-Dist: pip>=25.2
18
19
  Requires-Dist: pydantic-settings>=2.10.1
19
20
  Requires-Dist: pydantic>=2.11.5
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "langbot-plugin"
3
- version = "0.4.2b4"
3
+ version = "0.4.4"
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 = [
@@ -14,6 +14,7 @@ dependencies = [
14
14
  "e2b>=2.15",
15
15
  "httpx>=0.28.1",
16
16
  "jinja2>=3.1.6",
17
+ "packaging>=24.0",
17
18
  "pip>=25.2",
18
19
  "pydantic>=2.11.5",
19
20
  "pydantic-settings>=2.10.1",
@@ -284,6 +284,43 @@ class LangBotAPIProxy:
284
284
  )
285
285
  )["vectors"]
286
286
 
287
+ async def invoke_rerank(
288
+ self,
289
+ rerank_model_uuid: str,
290
+ query: str,
291
+ documents: list[str],
292
+ top_k: int | None = None,
293
+ extra_args: dict[str, Any] | None = None,
294
+ timeout: float = 60.0,
295
+ ) -> list[dict[str, Any]]:
296
+ """Rerank documents using Host's rerank model.
297
+
298
+ Args:
299
+ rerank_model_uuid: The UUID of the rerank model to use.
300
+ query: Query text used to score document relevance.
301
+ documents: Candidate document texts to rerank.
302
+ top_k: Optional number of scored results to return.
303
+ extra_args: Optional provider-specific arguments.
304
+ timeout: Request timeout in seconds.
305
+
306
+ Returns:
307
+ List of score dicts, usually containing ``index`` and
308
+ ``relevance_score``.
309
+ """
310
+ return (
311
+ await self.plugin_runtime_handler.call_action(
312
+ PluginToRuntimeAction.INVOKE_RERANK,
313
+ {
314
+ "rerank_model_uuid": rerank_model_uuid,
315
+ "query": query,
316
+ "documents": documents,
317
+ "top_k": top_k,
318
+ "extra_args": extra_args or {},
319
+ },
320
+ timeout=timeout,
321
+ )
322
+ )["results"]
323
+
287
324
  async def vector_upsert(
288
325
  self,
289
326
  collection_id: str,
@@ -0,0 +1,77 @@
1
+ {% raw %}name: Release Plugin
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - master
8
+ paths:
9
+ - "manifest.yaml"
10
+ workflow_dispatch:
11
+ inputs:
12
+ release:
13
+ description: "Create a new release"
14
+ required: true
15
+ type: boolean
16
+ default: true
17
+
18
+ permissions:
19
+ contents: write
20
+
21
+ jobs:
22
+ release:
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - name: Checkout
26
+ uses: actions/checkout@v4
27
+
28
+ - name: Setup Python
29
+ uses: actions/setup-python@v5
30
+ with:
31
+ python-version: "3.12"
32
+
33
+ - name: Install lbp CLI
34
+ run: pip install langbot-plugin
35
+
36
+ - name: Get metadata
37
+ id: meta
38
+ run: |
39
+ PLUGIN_NAME=$(grep -m1 'name:' manifest.yaml | awk '{print $2}' | tr -d '"'"'"'')
40
+ VERSION=$(grep -m1 'version:' manifest.yaml | awk '{print $2}' | tr -d '"'"'"'')
41
+ AUTHOR=$(grep -m1 'author:' manifest.yaml | awk '{print $2}' | tr -d '"'"'"'')
42
+ echo "name=$PLUGIN_NAME" >> "$GITHUB_OUTPUT"
43
+ echo "version=$VERSION" >> "$GITHUB_OUTPUT"
44
+ echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
45
+ echo "artifact=${AUTHOR}-${PLUGIN_NAME}-${VERSION}" >> "$GITHUB_OUTPUT"
46
+
47
+ - name: Check release exists
48
+ id: check
49
+ run: |
50
+ if gh release view "$TAG" --json tagName > /dev/null 2>&1; then
51
+ echo "exists=true" >> "$GITHUB_OUTPUT"
52
+ else
53
+ echo "exists=false" >> "$GITHUB_OUTPUT"
54
+ fi
55
+ env:
56
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
57
+ TAG: ${{ steps.meta.outputs.tag }}
58
+
59
+ - name: Build plugin
60
+ if: steps.check.outputs.exists == 'false'
61
+ run: lbp build -o dist
62
+
63
+ - name: Create release
64
+ if: steps.check.outputs.exists == 'false'
65
+ uses: softprops/action-gh-release@v2
66
+ with:
67
+ tag_name: ${{ steps.meta.outputs.tag }}
68
+ name: ${{ steps.meta.outputs.artifact }}
69
+ body: |
70
+ ## ${{ steps.meta.outputs.artifact }}
71
+
72
+ ### Installation
73
+ Download `${{ steps.meta.outputs.artifact }}.lbpkg` and install via LangBot plugin marketplace.
74
+ files: dist/${{ steps.meta.outputs.artifact }}.lbpkg
75
+ draft: false
76
+ prerelease: false
77
+ {% endraw %}
@@ -0,0 +1,15 @@
1
+ # {{ plugin_name }}
2
+
3
+ {{ plugin_description }}
4
+
5
+ ## Installation
6
+
7
+ Install this plugin via the LangBot plugin marketplace.
8
+
9
+ ## Configuration
10
+
11
+ Configure the plugin parameters in the LangBot admin panel.
12
+
13
+ ## Usage
14
+
15
+ <!-- TODO: Add usage instructions for your plugin here -->
@@ -0,0 +1,15 @@
1
+ # {{ plugin_name }}
2
+
3
+ {{ plugin_description }}
4
+
5
+ ## 安装
6
+
7
+ 通过 LangBot 插件市场安装本插件。
8
+
9
+ ## 配置
10
+
11
+ 在 LangBot 管理面板中配置此插件的参数。
12
+
13
+ ## 使用方法
14
+
15
+ <!-- TODO: 在此添加插件的使用说明 -->
@@ -110,8 +110,13 @@ class NsjailBackend(BaseSandboxBackend):
110
110
  self._cgroup_v2_available = self._detect_cgroup_v2()
111
111
  if not self._cgroup_v2_available:
112
112
  self.logger.warning(
113
- 'cgroup v2 not available for nsjail; '
114
- 'falling back to rlimit-based resource limits'
113
+ 'nsjail cgroup v2 limits unavailable (private cgroup namespace '
114
+ 'or read-only /sys/fs/cgroup); falling back to rlimit-based '
115
+ 'limits WITHOUT a hard memory cap. RLIMIT_AS is intentionally '
116
+ 'not used because it kills uv/node/etc. To enforce a memory '
117
+ 'cap, run the Box container in the host cgroup namespace '
118
+ '(--cgroupns=host / compose `cgroup: host`) or set a '
119
+ 'container-level memory limit.'
115
120
  )
116
121
 
117
122
  self._base_dir.mkdir(parents=True, exist_ok=True)
@@ -475,16 +480,27 @@ class NsjailBackend(BaseSandboxBackend):
475
480
  cpu_ms = int(spec.cpus * 1000)
476
481
  args.extend(['--cgroup_cpu_ms_per_sec', str(cpu_ms)])
477
482
  else:
478
- # rlimit fallback – best-effort. Used whenever the cgroup v2 root is
479
- # not writable (the typical containerized case: /sys/fs/cgroup is
480
- # mounted read-only), so the sandbox still launches with coarse
481
- # resource caps instead of failing outright.
482
- # --rlimit_as takes a value in MB (nsjail interprets the bare number
483
- # as megabytes), matching spec.memory_mb directly.
484
- args.extend(['--rlimit_as', str(spec.memory_mb)])
483
+ # rlimit fallback – used whenever cgroup v2 delegation is not usable
484
+ # (private cgroup namespace -> EBUSY, or read-only /sys/fs/cgroup).
485
+ #
486
+ # We deliberately do NOT set --rlimit_as for the memory cap.
487
+ # RLIMIT_AS limits *virtual* address space, not resident memory, and
488
+ # modern runtimes reserve huge virtual mappings up front: uv/Rust
489
+ # (and Go/JVM/Node) mmap gigabytes of address space even to do tiny
490
+ # work, so a 512 MB --rlimit_as aborts them instantly with
491
+ # "memory allocation of N bytes failed" (exit 255) — which is what
492
+ # silently broke every uvx-based stdio MCP server in containerized
493
+ # nsjail deployments. There is no RSS-based rlimit on modern Linux
494
+ # (RLIMIT_RSS is ignored), so accurate memory capping REQUIRES
495
+ # cgroups. Operators who need a hard memory cap must run the Box
496
+ # container in the host cgroup namespace (--cgroupns=host /
497
+ # compose `cgroup: host`); otherwise bound memory at the container
498
+ # level (e.g. compose `mem_limit`). We still apply the pid cap,
499
+ # which is a real rlimit that does not break runtimes.
485
500
  args.extend(['--rlimit_nproc', str(spec.pids_limit)])
486
501
 
487
- # Always set these rlimits regardless of cgroup mode.
502
+ # Always set these rlimits regardless of cgroup mode. These are safe
503
+ # for modern runtimes (unlike RLIMIT_AS).
488
504
  args.extend(['--rlimit_fsize', '512']) # max file size 512 MB
489
505
  args.extend(['--rlimit_nofile', '256']) # max open fds
490
506
 
@@ -527,42 +543,73 @@ class NsjailBackend(BaseSandboxBackend):
527
543
 
528
544
  @staticmethod
529
545
  def _detect_cgroup_v2() -> bool:
530
- """Check whether cgroup v2 is present AND nsjail can create a cgroup.
531
-
532
- nsjail (with ``--use_cgroupv2``) creates its own child cgroup by
533
- ``mkdir``-ing directly under the cgroup v2 mount root, then writes to
534
- ``cgroup.subtree_control``. Merely detecting a cgroup v2 hierarchy is
535
- not enough: inside most containers (Docker/k8s default) ``/sys/fs/cgroup``
536
- is mounted **read-only**, so the mkdir fails and the whole sandbox
537
- aborts. We must therefore probe real writability running as root is
538
- NOT sufficient, because a read-only bind mount denies root too.
539
-
540
- Returns True only when we can actually create (and remove) a directory
541
- under the cgroup v2 root, which is exactly what nsjail needs.
546
+ """Check whether nsjail's ``--use_cgroupv2`` path will actually work.
547
+
548
+ nsjail (with ``--use_cgroupv2``) moves itself into a fresh child cgroup
549
+ it ``mkdir``s under the cgroup v2 mount root, then enables controllers
550
+ for that child by writing ``+memory`` (etc.) to the ROOT's
551
+ ``cgroup.subtree_control``. BOTH operations must succeed.
552
+
553
+ Probing ``mkdir`` alone is NOT sufficient and produces a false positive
554
+ in the common containerized case: inside a **private** cgroup namespace
555
+ (Docker/k8s default) the container's own cgroup root already contains
556
+ live processes (the Box runtime itself), so the kernel's
557
+ "no-internal-process" rule rejects the ``cgroup.subtree_control`` write
558
+ with ``EBUSY`` even though ``mkdir`` under the root succeeds. nsjail then
559
+ aborts and every sandbox launch exits 255. Conversely a read-only
560
+ ``/sys/fs/cgroup`` (another common case) fails the ``mkdir``.
561
+
562
+ So we probe the AUTHORITATIVE operation: a real write to
563
+ ``cgroup.subtree_control``. We only consider it available when that
564
+ write succeeds, which is exactly nsjail's requirement. Containerized
565
+ deployments that need cgroup limits must run the Box container in the
566
+ host cgroup namespace (``--cgroupns=host`` / compose ``cgroup: host``);
567
+ otherwise this returns False and the backend uses the rlimit fallback.
542
568
  """
543
569
  cgroup_mount = pathlib.Path('/sys/fs/cgroup')
544
570
  if not cgroup_mount.exists():
545
571
  return False
546
572
  # cgroup v2 has a single hierarchy with a cgroup.controllers file.
547
573
  controllers = cgroup_mount / 'cgroup.controllers'
548
- if not controllers.exists():
574
+ subtree_control = cgroup_mount / 'cgroup.subtree_control'
575
+ if not controllers.exists() or not subtree_control.exists():
549
576
  return False
550
- # Authoritative writability probe: try to create and remove a throwaway
551
- # cgroup directory under the root, mirroring what nsjail does. This
552
- # correctly reports False on a read-only /sys/fs/cgroup (the common
553
- # containerized case) so the backend falls back to rlimit limits
554
- # instead of selecting a cgroup path that is guaranteed to fail.
555
- probe = cgroup_mount / f'.langbot-box-probe-{os.getpid()}'
577
+ # nsjail enables the controllers it needs (memory, pids, cpu) on the
578
+ # child cgroup, which requires them to be delegated via the root's
579
+ # subtree_control. Only probe controllers actually present here.
556
580
  try:
557
- probe.mkdir(mode=0o700)
581
+ available = set(controllers.read_text().split())
558
582
  except Exception:
559
583
  return False
560
- else:
561
- try:
562
- probe.rmdir()
563
- except Exception:
564
- pass
565
- return True
584
+ wanted = [c for c in ('memory', 'pids', 'cpu') if c in available]
585
+ if not wanted:
586
+ return False
587
+ # Authoritative writability probe: re-arm a controller that is already
588
+ # enabled (idempotent no-op), or briefly toggle one that is not. A
589
+ # successful write proves nsjail's subtree_control write will also
590
+ # succeed; EBUSY (private cgroupns) or EACCES/EROFS (read-only mount)
591
+ # all surface here and correctly select the rlimit fallback.
592
+ try:
593
+ enabled = set(subtree_control.read_text().split())
594
+ except Exception:
595
+ return False
596
+ probe_controller = wanted[0]
597
+ try:
598
+ if probe_controller in enabled:
599
+ # Already delegated: re-writing the same enable is a harmless
600
+ # no-op that still exercises the write permission + EBUSY rule.
601
+ subtree_control.write_text(f'+{probe_controller}')
602
+ else:
603
+ # Not yet delegated: enable then immediately disable to leave
604
+ # the host configuration untouched.
605
+ subtree_control.write_text(f'+{probe_controller}')
606
+ try:
607
+ subtree_control.write_text(f'-{probe_controller}')
608
+ except Exception:
609
+ pass
610
+ except Exception:
611
+ return False
612
+ return True
566
613
 
567
614
  async def _kill_session_processes(self, session_dir: pathlib.Path) -> None:
568
615
  """Best-effort kill of nsjail processes associated with a session dir.
@@ -155,6 +155,10 @@ def init_plugin_process(
155
155
  os.makedirs(assets_dir, exist_ok=True)
156
156
  vscode_dir = os.path.join(plugin_dir, ".vscode")
157
157
  os.makedirs(vscode_dir, exist_ok=True)
158
+ readme_dir = os.path.join(plugin_dir, "readme")
159
+ os.makedirs(readme_dir, exist_ok=True)
160
+ github_workflows_dir = os.path.join(plugin_dir, ".github", "workflows")
161
+ os.makedirs(github_workflows_dir, exist_ok=True)
158
162
 
159
163
  # Create all files from templates
160
164
  for file in init_plugin_files:
@@ -42,11 +42,13 @@ init_plugin_files = [
42
42
  "manifest.yaml",
43
43
  "main.py",
44
44
  "README.md",
45
+ "readme/README_zh_Hans.md",
45
46
  "requirements.txt",
46
47
  ".env.example",
47
48
  ".gitignore",
48
49
  "assets/icon.svg",
49
50
  ".vscode/launch.json",
51
+ ".github/workflows/release.yml",
50
52
  ]
51
53
 
52
54
 
@@ -61,6 +61,7 @@ class PluginToRuntimeAction(ActionType):
61
61
  CALL_TOOL = "call_tool"
62
62
 
63
63
  INVOKE_EMBEDDING = "invoke_embedding"
64
+ INVOKE_RERANK = "invoke_rerank"
64
65
  VECTOR_UPSERT = "vector_upsert"
65
66
  VECTOR_SEARCH = "vector_search"
66
67
  VECTOR_DELETE = "vector_delete"
@@ -111,6 +112,7 @@ class LangBotToRuntimeAction(ActionType):
111
112
  GET_PLUGIN_INFO = "get_plugin_info"
112
113
  GET_PLUGIN_ICON = "get_plugin_icon"
113
114
  GET_PLUGIN_README = "get_plugin_readme"
115
+ GET_PLUGIN_LOGS = "get_plugin_logs"
114
116
  GET_PLUGIN_ASSETS_FILE = "get_plugin_assets_file"
115
117
  INSTALL_PLUGIN = "install_plugin"
116
118
  RESTART_PLUGIN = "restart_plugin"
@@ -0,0 +1,91 @@
1
+ from __future__ import annotations
2
+
3
+
4
+ class ConnectionClosedError(Exception):
5
+ """The connection is closed."""
6
+
7
+ def __init__(self, message: str):
8
+ self.message = message
9
+
10
+ def __str__(self):
11
+ return self.message
12
+
13
+
14
+ class ActionCallTimeoutError(Exception):
15
+ """The action call timed out."""
16
+
17
+ def __init__(self, message: str):
18
+ self.message = message
19
+
20
+ def __str__(self):
21
+ return self.message
22
+
23
+
24
+ class DependencyInstallError(Exception):
25
+ """One or more plugin dependencies failed to install via pip.
26
+
27
+ Carries enough structure for callers to log per-package diagnostics or
28
+ surface them to the UI, instead of a single flattened string.
29
+ """
30
+
31
+ def __init__(
32
+ self,
33
+ failed: list[str],
34
+ plugin: str | None = None,
35
+ details: dict[str, str] | None = None,
36
+ ):
37
+ # List of requirement specs that pip could not install (after retries).
38
+ self.failed = failed
39
+ # "<author>/<name>" of the plugin being installed, when known.
40
+ self.plugin = plugin
41
+ # Optional per-package error text (requirement spec -> pip stderr tail).
42
+ self.details = details or {}
43
+ prefix = f"Plugin {plugin} " if plugin else ""
44
+ super().__init__(
45
+ f"{prefix}failed to install {len(failed)} dependencies: {failed}"
46
+ )
47
+
48
+ def __str__(self):
49
+ prefix = f"Plugin {self.plugin} " if self.plugin else ""
50
+ return f"{prefix}failed to install {len(self.failed)} dependencies: {self.failed}"
51
+
52
+
53
+ class DependencyVerificationError(Exception):
54
+ """Dependencies were installed but could not be verified afterwards.
55
+
56
+ ``missing`` holds requirement specs whose distribution/import could not be
57
+ resolved after pip reported success; ``version_mismatch`` holds specs whose
58
+ installed version does not satisfy the requested specifier.
59
+ """
60
+
61
+ def __init__(
62
+ self,
63
+ missing: list[str],
64
+ version_mismatch: list[str] | None = None,
65
+ plugin: str | None = None,
66
+ ):
67
+ self.missing = missing
68
+ self.version_mismatch = version_mismatch or []
69
+ self.plugin = plugin
70
+ prefix = f"Plugin {plugin}: " if plugin else ""
71
+ super().__init__(
72
+ f"{prefix}missing dependencies: {missing}, "
73
+ f"version mismatch: {self.version_mismatch}"
74
+ )
75
+
76
+ def __str__(self):
77
+ prefix = f"Plugin {self.plugin}: " if self.plugin else ""
78
+ return (
79
+ f"{prefix}missing dependencies: {self.missing}, "
80
+ f"version mismatch: {self.version_mismatch}"
81
+ )
82
+
83
+
84
+ class ActionCallError(Exception):
85
+ """The action call failed."""
86
+
87
+ def __init__(self, message: str):
88
+ self.message = message
89
+
90
+ def __str__(self):
91
+ return self.message