feat(agent-runner): finalize 4.x processor integration

This commit is contained in:
huanghuoguoguo
2026-07-12 15:44:05 +08:00
parent 457408ad7f
commit 9aa71d54e3
109 changed files with 2200 additions and 1204 deletions
@@ -1,88 +0,0 @@
"""Normalize AgentRunner config containers
Revision ID: 0005_migrate_runner_config
Revises: 0005_add_llm_context_length
Create Date: 2026-05-10
"""
import json
import sqlalchemy as sa
from alembic import op
from langbot.pkg.agent.runner.config_migration import ConfigMigration
revision = '0005_migrate_runner_config'
down_revision = '0005_add_llm_context_length'
branch_labels = None
depends_on = None
def migrate_pipeline_config(config: dict) -> dict:
"""Migrate persisted pipeline config to the AgentRunner plugin shape."""
return ConfigMigration.migrate_pipeline_config(config)
def _load_config(config_value):
if isinstance(config_value, dict):
return config_value
if isinstance(config_value, str):
return json.loads(config_value)
return None
def _update_config(conn, table_name: str, pipeline_uuid: str, migrated_config: dict) -> None:
"""Write JSON config using a dialect-compatible bind."""
config_json = json.dumps(migrated_config)
if conn.dialect.name == 'postgresql':
conn.execute(
sa.text(
f'UPDATE {table_name} '
'SET config = CAST(:config AS JSON) '
'WHERE uuid = :uuid'
),
{'config': config_json, 'uuid': pipeline_uuid},
)
return
conn.execute(
sa.text(f'UPDATE {table_name} SET config = :config WHERE uuid = :uuid'),
{'config': config_json, 'uuid': pipeline_uuid},
)
def upgrade() -> None:
"""Normalize existing pipeline config containers."""
conn = op.get_bind()
inspector = sa.inspect(conn)
table_name = 'legacy_pipelines'
# Check if pipeline table exists (may not exist in fresh install)
if table_name not in inspector.get_table_names():
return
# Get all pipelines
result = conn.execute(sa.text(f'SELECT uuid, config FROM {table_name}'))
pipelines = result.fetchall()
for pipeline_uuid, config_json in pipelines:
if not config_json:
continue
try:
config = _load_config(config_json)
if not isinstance(config, dict):
continue
migrated_config = migrate_pipeline_config(config)
# Only update if config changed
if json.dumps(config, sort_keys=True) != json.dumps(migrated_config, sort_keys=True):
_update_config(conn, table_name, pipeline_uuid, migrated_config)
except Exception:
# Skip invalid configs
continue
def downgrade() -> None:
"""Downgrade is not supported for data migration."""
# No downgrade - keep configs in new format
pass
@@ -1,4 +1,7 @@
"""migrate use_pipeline_uuid and pipeline_routing_rules into event_bindings
"""Migrate legacy Bot routes into Pipeline event bindings.
Bindings keep referencing the original Pipeline UUIDs. This migration never
creates Agent rows or copies Pipeline runner configuration.
Revision ID: 0009_migrate_routing_to_event_bindings
Revises: 0008_agent_product_surface
@@ -1,7 +1,7 @@
"""add_event_log_and_transcript_tables
Revision ID: 58846a8d7a81
Revises: 0005_migrate_runner_config
Revises: 0005_add_llm_context_length
Create Date: 2026-05-23 15:41:47.030841
"""
from alembic import op
@@ -9,7 +9,7 @@ import sqlalchemy as sa
# revision identifiers
revision = '58846a8d7a81'
down_revision = '0005_migrate_runner_config'
down_revision = '0005_add_llm_context_length'
branch_labels = None
depends_on = None
@@ -11,7 +11,6 @@ from ...entity.persistence import (
pipeline as persistence_pipeline,
bot as persistence_bot,
)
from ...agent.runner.config_migration import LEGACY_RUNNER_ID_MAP
@migration.migration_class(1)
@@ -114,47 +113,6 @@ class DBMigrateV3Config(migration.DBMigration):
pipeline_config = default_pipeline['config']
# ai
ai_config = pipeline_config.setdefault('ai', {})
runner_name = self.ap.provider_cfg.data['runner']
runner_id = LEGACY_RUNNER_ID_MAP.get(runner_name, '')
ai_config['runner'] = {
'id': runner_id,
}
runner_configs = ai_config.setdefault('runner_config', {})
local_agent_runner_id = LEGACY_RUNNER_ID_MAP['local-agent']
local_agent_config = runner_configs.setdefault(local_agent_runner_id, {})
local_agent_config['model'] = {
'primary': model_uuid,
'fallbacks': [],
}
local_agent_config['prompt'] = [
{
'role': 'system',
'content': self.ap.provider_cfg.data['prompt']['default'],
}
]
runner_configs[LEGACY_RUNNER_ID_MAP['dify-service-api']] = {
'base-url': self.ap.provider_cfg.data['dify-service-api']['base-url'],
'app-type': self.ap.provider_cfg.data['dify-service-api']['app-type'],
'api-key': self.ap.provider_cfg.data['dify-service-api'][
self.ap.provider_cfg.data['dify-service-api']['app-type']
]['api-key'],
'thinking-convert': self.ap.provider_cfg.data['dify-service-api']['options']['convert-thinking-tips'],
'timeout': self.ap.provider_cfg.data['dify-service-api'][
self.ap.provider_cfg.data['dify-service-api']['app-type']
]['timeout'],
}
runner_configs[LEGACY_RUNNER_ID_MAP['dashscope-app-api']] = {
'app-type': self.ap.provider_cfg.data['dashscope-app-api']['app-type'],
'api-key': self.ap.provider_cfg.data['dashscope-app-api']['api-key'],
'references_quote': self.ap.provider_cfg.data['dashscope-app-api'][
self.ap.provider_cfg.data['dashscope-app-api']['app-type']
]['references_quote'],
}
# trigger
pipeline_config['trigger']['group-respond-rules'] = self.ap.pipeline_cfg.data['respond-rules']['default']
pipeline_config['trigger']['access-control'] = self.ap.pipeline_cfg.data['access-control']