mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-04 21:06:03 +00:00
refactor(agent-runner): align config with agent semantics
This commit is contained in:
@@ -25,7 +25,7 @@ class ConfigMigration:
|
||||
Responsibilities:
|
||||
- Resolve runner ID from new ai.runner.id or old ai.runner.runner
|
||||
- Map old built-in runner names to official plugin runner IDs
|
||||
- Extract runtime runner config from ai.runner_config
|
||||
- Extract current Agent/runner config from ai.runner_config
|
||||
- Migrate old ai.<runner-name> blocks into ai.runner_config
|
||||
"""
|
||||
|
||||
@@ -74,7 +74,7 @@ class ConfigMigration:
|
||||
pipeline_config: dict[str, typing.Any],
|
||||
runner_id: str,
|
||||
) -> dict[str, typing.Any]:
|
||||
"""Resolve runner binding configuration from pipeline configuration.
|
||||
"""Resolve Agent/runner configuration from pipeline configuration.
|
||||
|
||||
Runtime code should only read the migrated format. Legacy
|
||||
ai.<runner-name> blocks are handled by migration helpers, not by the
|
||||
@@ -114,9 +114,6 @@ class ConfigMigration:
|
||||
if old_runner_name:
|
||||
old_config = ai_config.get(old_runner_name, {})
|
||||
if old_config:
|
||||
old_config = dict(old_config)
|
||||
if runner_id == OLD_RUNNER_TO_PLUGIN_RUNNER_ID['local-agent']:
|
||||
old_config.pop('max-round', None)
|
||||
return ConfigMigration.normalize_runner_config_for_migration(runner_id, old_config)
|
||||
|
||||
return {}
|
||||
@@ -126,7 +123,7 @@ class ConfigMigration:
|
||||
runner_id: str,
|
||||
runner_config: dict[str, typing.Any],
|
||||
) -> dict[str, typing.Any]:
|
||||
"""Normalize released legacy runner config before storing binding config.
|
||||
"""Normalize released legacy runner config before storing Agent/runner config.
|
||||
|
||||
Runtime code should not carry aliases. This helper is intentionally used
|
||||
only by config migration so AgentRunner implementations can consume the
|
||||
|
||||
@@ -22,7 +22,7 @@ class AgentTrigger(typing.TypedDict):
|
||||
"""Agent trigger information."""
|
||||
|
||||
type: str
|
||||
source: str # 'pipeline' or 'event_router'
|
||||
source: str
|
||||
timestamp: int | None
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ class ConversationContext(typing.TypedDict):
|
||||
bot_id: str | None
|
||||
workspace_id: str | None
|
||||
session_id: str | None
|
||||
pipeline_uuid: str | None
|
||||
|
||||
|
||||
class AgentInput(typing.TypedDict):
|
||||
@@ -128,8 +127,9 @@ class AgentRunContextPayload(typing.TypedDict):
|
||||
|
||||
Protocol v1 structure - matches SDK AgentRunContext.
|
||||
|
||||
Note: The 'config' field contains the binding config from ai.runner_config[runner_id],
|
||||
which is Pipeline's configuration for this specific runner binding (not plugin instance config).
|
||||
Note: The 'config' field contains the current Agent/runner config
|
||||
from ai.runner_config[runner_id] while Pipeline remains the temporary
|
||||
configuration container. It is not plugin instance config.
|
||||
"""
|
||||
|
||||
run_id: str
|
||||
@@ -144,9 +144,9 @@ class AgentRunContextPayload(typing.TypedDict):
|
||||
context: dict[str, typing.Any] # ContextAccess - REQUIRED for Protocol v1
|
||||
state: AgentRunState
|
||||
runtime: AgentRuntimeContext
|
||||
config: dict[str, typing.Any] # Binding config from ai.runner_config[runner_id]
|
||||
config: dict[str, typing.Any] # Agent/runner config from ai.runner_config[runner_id]
|
||||
bootstrap: dict[str, typing.Any] | None # Optional bootstrap context
|
||||
adapter: dict[str, typing.Any] | None # Pipeline adapter context
|
||||
adapter: dict[str, typing.Any] | None # Entry adapter context
|
||||
metadata: dict[str, typing.Any] # Additional metadata
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ class AgentRunContextBuilder:
|
||||
- Build input from event
|
||||
- Build state snapshot from PersistentStateStore
|
||||
- Build runtime context with host info, trace_id, deadline
|
||||
- Set config from runner binding configuration.
|
||||
- Set config from current Agent/runner configuration.
|
||||
|
||||
Pipeline Query adaptation belongs to PipelineAdapter, not this builder.
|
||||
"""
|
||||
@@ -184,7 +184,7 @@ class AgentRunContextBuilder:
|
||||
|
||||
Args:
|
||||
event: Event envelope
|
||||
binding: Agent binding configuration
|
||||
binding: Agent binding
|
||||
descriptor: Runner descriptor
|
||||
resources: Built resources
|
||||
|
||||
@@ -205,7 +205,7 @@ class AgentRunContextBuilder:
|
||||
conversation: ConversationContext | None = None
|
||||
if event.conversation_id:
|
||||
conversation = {
|
||||
'session_id': None, # Pipeline adapter field
|
||||
'session_id': None,
|
||||
'conversation_id': event.conversation_id,
|
||||
'thread_id': event.thread_id,
|
||||
'launcher_type': None, # Will be filled from actor/subject if needed
|
||||
@@ -213,7 +213,6 @@ class AgentRunContextBuilder:
|
||||
'sender_id': event.actor.actor_id if event.actor else None,
|
||||
'bot_id': event.bot_id,
|
||||
'workspace_id': event.workspace_id,
|
||||
'pipeline_uuid': binding.pipeline_uuid, # Pipeline adapter field
|
||||
}
|
||||
|
||||
# Build event context (Protocol v1 event-first)
|
||||
@@ -277,7 +276,7 @@ class AgentRunContextBuilder:
|
||||
'model_context_window_tokens': None,
|
||||
# TODO(model-info): populate model_context_window_tokens after
|
||||
# LiteLLM/model metadata lands. Runners fall back to their
|
||||
# binding config until Host can provide the real window.
|
||||
# ctx.config until Host can provide the real window.
|
||||
},
|
||||
}
|
||||
|
||||
@@ -295,7 +294,6 @@ class AgentRunContextBuilder:
|
||||
# Build adapter context (empty for event-first)
|
||||
adapter_context = {
|
||||
'query_id': None,
|
||||
'pipeline_uuid': binding.pipeline_uuid,
|
||||
'extra': {},
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class RunnerNotFoundError(AgentRunnerError):
|
||||
|
||||
|
||||
class RunnerNotAuthorizedError(AgentRunnerError):
|
||||
"""Runner not authorized for this pipeline."""
|
||||
"""Runner not authorized for this binding."""
|
||||
def __init__(self, runner_id: str, bound_plugins: list[str] | None):
|
||||
self.runner_id = runner_id
|
||||
self.bound_plugins = bound_plugins
|
||||
@@ -34,4 +34,4 @@ class RunnerExecutionError(AgentRunnerError):
|
||||
def __init__(self, runner_id: str, message: str, retryable: bool = False):
|
||||
self.runner_id = runner_id
|
||||
self.retryable = retryable
|
||||
super().__init__(f'Agent runner {runner_id} execution failed: {message}')
|
||||
super().__init__(f'Agent runner {runner_id} execution failed: {message}')
|
||||
|
||||
@@ -73,11 +73,11 @@ class AgentEventEnvelope(pydantic.BaseModel):
|
||||
class BindingScope(pydantic.BaseModel):
|
||||
"""Scope for agent binding."""
|
||||
|
||||
scope_type: typing.Literal["bot", "pipeline", "workspace", "global"] = "pipeline"
|
||||
scope_type: typing.Literal["agent", "bot", "workspace", "global"] = "agent"
|
||||
"""Scope type."""
|
||||
|
||||
scope_id: str | None = None
|
||||
"""Scope identifier (bot_uuid, pipeline_uuid, etc.)."""
|
||||
"""Scope identifier (agent_id, bot_uuid, etc.)."""
|
||||
|
||||
|
||||
class ResourcePolicy(pydantic.BaseModel):
|
||||
@@ -153,7 +153,7 @@ class AgentBinding(pydantic.BaseModel):
|
||||
"""Runner ID to invoke."""
|
||||
|
||||
runner_config: dict[str, typing.Any] = pydantic.Field(default_factory=dict)
|
||||
"""Runner binding configuration."""
|
||||
"""Current Agent/runner configuration."""
|
||||
|
||||
resource_policy: ResourcePolicy = pydantic.Field(default_factory=ResourcePolicy)
|
||||
"""Resource policy."""
|
||||
@@ -167,6 +167,5 @@ class AgentBinding(pydantic.BaseModel):
|
||||
enabled: bool = True
|
||||
"""Whether binding is enabled."""
|
||||
|
||||
# Fields for Pipeline adapter
|
||||
pipeline_uuid: str | None = None
|
||||
"""Pipeline UUID (for Pipeline adapter)."""
|
||||
agent_id: str | None = None
|
||||
"""Host-side Agent/config identifier for this binding."""
|
||||
|
||||
@@ -93,9 +93,9 @@ class AgentRunOrchestrator:
|
||||
|
||||
Args:
|
||||
event: Event envelope from event gateway
|
||||
binding: Agent binding configuration
|
||||
binding: Agent binding
|
||||
bound_plugins: Optional list of bound plugin identities for authorization
|
||||
adapter_context: Optional adapter context from Pipeline adapter
|
||||
adapter_context: Optional context from an entry adapter
|
||||
|
||||
Yields:
|
||||
Message or MessageChunk for pipeline response
|
||||
@@ -125,12 +125,12 @@ class AgentRunOrchestrator:
|
||||
resources=resources,
|
||||
)
|
||||
|
||||
# Merge adapter context if provided (for Pipeline adapter)
|
||||
# Merge adapter context if provided
|
||||
if adapter_context:
|
||||
# Merge params into adapter.extra
|
||||
if 'params' in adapter_context:
|
||||
context['adapter']['extra']['params'] = adapter_context['params']
|
||||
# Merge prompt into adapter.extra for Pipeline adapter consumers.
|
||||
# Merge prompt into adapter.extra for transitional adapter consumers.
|
||||
if 'prompt' in adapter_context:
|
||||
context['adapter']['extra']['prompt'] = adapter_context['prompt']
|
||||
# Set query_id if provided
|
||||
@@ -420,7 +420,7 @@ class AgentRunOrchestrator:
|
||||
Args:
|
||||
result_dict: Raw result dict with type='state.updated'
|
||||
event: Event envelope
|
||||
binding: Agent binding configuration
|
||||
binding: Agent binding
|
||||
descriptor: Runner descriptor
|
||||
"""
|
||||
data = result_dict.get('data', {})
|
||||
|
||||
@@ -114,12 +114,11 @@ class PipelineAdapter:
|
||||
pipeline_config = query.pipeline_config or {}
|
||||
ai_config = pipeline_config.get('ai', {})
|
||||
runner_config = ai_config.get('runner_config', {}).get(runner_id, {})
|
||||
pipeline_uuid = getattr(query, 'pipeline_uuid', None)
|
||||
agent_id = getattr(query, 'pipeline_uuid', None)
|
||||
|
||||
# Build scope
|
||||
scope = BindingScope(
|
||||
scope_type="pipeline",
|
||||
scope_id=pipeline_uuid,
|
||||
scope_type="agent",
|
||||
scope_id=agent_id,
|
||||
)
|
||||
|
||||
# Build resource policy from pipeline config
|
||||
@@ -142,7 +141,7 @@ class PipelineAdapter:
|
||||
)
|
||||
|
||||
return AgentBinding(
|
||||
binding_id=f"pipeline_{pipeline_uuid or 'default'}_{runner_id}",
|
||||
binding_id=f"agent_{agent_id or 'default'}_{runner_id}",
|
||||
scope=scope,
|
||||
event_types=[runner_events.MESSAGE_RECEIVED],
|
||||
runner_id=runner_id,
|
||||
@@ -151,7 +150,7 @@ class PipelineAdapter:
|
||||
state_policy=state_policy,
|
||||
delivery_policy=delivery_policy,
|
||||
enabled=True,
|
||||
pipeline_uuid=pipeline_uuid,
|
||||
agent_id=agent_id,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@@ -335,9 +334,6 @@ class PipelineAdapter:
|
||||
# Handle bot_uuid
|
||||
bot_uuid = getattr(query, 'bot_uuid', None)
|
||||
|
||||
# Handle pipeline_uuid
|
||||
pipeline_uuid = getattr(query, 'pipeline_uuid', None)
|
||||
|
||||
return ConversationContext(
|
||||
conversation_id=str(conversation_id) if conversation_id is not None else None,
|
||||
thread_id=None,
|
||||
@@ -347,7 +343,6 @@ class PipelineAdapter:
|
||||
bot_id=bot_uuid,
|
||||
workspace_id=None,
|
||||
session_id=session_id,
|
||||
pipeline_uuid=pipeline_uuid,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@@ -398,7 +393,6 @@ class PipelineAdapter:
|
||||
"launcher_id": getattr(query, 'launcher_id', None),
|
||||
"sender_id": str(getattr(query, 'sender_id', '')) if getattr(query, 'sender_id', None) else None,
|
||||
"bot_uuid": getattr(query, 'bot_uuid', None),
|
||||
"pipeline_uuid": getattr(query, 'pipeline_uuid', None),
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class AgentResourceBuilder:
|
||||
- Apply 3-layer permission filtering:
|
||||
1. Runner manifest declared permissions
|
||||
2. Pipeline extensions_preference (bound plugins/MCP servers)
|
||||
3. Runner binding config selected resources
|
||||
3. Agent/runner config selected resources
|
||||
- Build models list from authorized models
|
||||
- Build tools list from bound plugins/MCP servers
|
||||
- Build knowledge_bases list from config
|
||||
@@ -68,7 +68,7 @@ class AgentResourceBuilder:
|
||||
# Layer 2: Binding resource policy
|
||||
resource_policy = binding.resource_policy
|
||||
|
||||
# Layer 3: Runner binding config
|
||||
# Layer 3: Agent/runner config
|
||||
runner_config = binding.runner_config
|
||||
|
||||
# Build each resource category
|
||||
@@ -112,7 +112,7 @@ class AgentResourceBuilder:
|
||||
# Get additional model UUID grants from resource policy.
|
||||
allowed_uuids = resource_policy.allowed_model_uuids
|
||||
|
||||
# Add model resources from binding config schema
|
||||
# Add model resources from Agent/runner config schema
|
||||
await self._append_config_declared_model_resources(
|
||||
models=models,
|
||||
seen_model_ids=seen_model_ids,
|
||||
|
||||
Reference in New Issue
Block a user