mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-11-04 14:52:12 +08:00
fix(plugin): persist v4 runtime state and tolerate runner registration gaps (#2774)
Persist the v4 plugin runtime state so recreating the runtime container no longer discards installed plugins' artifacts, dependency environments and installation-private data, and stop a transient Runner registry miss during steering from dropping the message. - docker-compose: bind-mount ./data/plugin-runtime for the plugin runtime alongside ./data/plugins. - kubernetes: add the langbot-plugin-runtime-state claim (5Gi) mounted at /app/data/plugin-runtime, kept separate from the plugin data claim so runtime state does not land inside the plugin directory. - chat handler: treat RunnerNotFoundError while claiming steering as "steering unavailable" and continue with a normal run; every other error keeps propagating. The runner error imports move to module scope, which the new early reference requires. - tests: cover the steering fallback, the claimed-steering interrupt, and the lasting-gap path that still reports runner-not-found. The steering fallback buys one extra uncached registry lookup while a runtime reconnects; it does not recover a gap that outlasts the message.
This commit is contained in:
@@ -15,6 +15,11 @@ from ... import plugin_diagnostics
|
||||
import langbot_plugin.api.entities.events as events
|
||||
from ....agent.runner.config_resolver import RunnerConfigResolver
|
||||
from ....agent.runner import config_schema
|
||||
from ....agent.runner.errors import (
|
||||
RunnerExecutionError,
|
||||
RunnerNotFoundError,
|
||||
RunnerNotAuthorizedError,
|
||||
)
|
||||
from ....utils import runner as runner_utils
|
||||
import langbot_plugin.api.entities.builtin.provider.session as provider_session
|
||||
import langbot_plugin.api.entities.builtin.pipeline.query as pipeline_query
|
||||
@@ -119,9 +124,24 @@ class ChatMessageHandler(handler.MessageHandler):
|
||||
'try_claim_steering_from_query',
|
||||
None,
|
||||
)
|
||||
if try_claim_steering and await try_claim_steering(query):
|
||||
yield entities.StageProcessResult(result_type=entities.ResultType.INTERRUPT, new_query=query)
|
||||
return
|
||||
if try_claim_steering:
|
||||
try:
|
||||
claimed = await try_claim_steering(query)
|
||||
except RunnerNotFoundError as steering_error:
|
||||
# Steering is an optimization for an already-running
|
||||
# agent. A runtime reconnect can temporarily remove the
|
||||
# selected Runner from the registry; that must not
|
||||
# prevent the message from starting a normal run.
|
||||
self.ap.logger.warning(
|
||||
'Skipping steering for query %s because Runner %s is not registered',
|
||||
query.query_id,
|
||||
steering_error.runner_id,
|
||||
)
|
||||
claimed = False
|
||||
|
||||
if claimed:
|
||||
yield entities.StageProcessResult(result_type=entities.ResultType.INTERRUPT, new_query=query)
|
||||
return
|
||||
|
||||
try:
|
||||
is_stream = await query.adapter.is_stream_output_supported()
|
||||
@@ -228,13 +248,6 @@ class ChatMessageHandler(handler.MessageHandler):
|
||||
yield entities.StageProcessResult(result_type=entities.ResultType.CONTINUE, new_query=query)
|
||||
|
||||
except Exception as e:
|
||||
# Import orchestrator errors for specific handling
|
||||
from ....agent.runner.errors import (
|
||||
RunnerNotFoundError,
|
||||
RunnerNotAuthorizedError,
|
||||
RunnerExecutionError,
|
||||
)
|
||||
|
||||
error_info = f'{traceback.format_exc()}'
|
||||
self.ap.logger.error(f'Conversation({query.query_id}) Request Failed: {error_info}')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user