From 2ee55d25cc9ad34a8d02150a2a4f9a305a932c2d Mon Sep 17 00:00:00 2001 From: goulustis Date: Fri, 13 Mar 2026 16:09:26 +0800 Subject: [PATCH] bug fix: skill_dir show up correctly in frontend --- frontend/src/App.tsx | 67 ++++++++++++++++++-- frontend/src/types.ts | 1 + lang_agent/fastapi_server/front_apis.py | 83 +++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 5 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 7cb948a..805cf41 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -465,6 +465,62 @@ function normalizeDeepAgentActBackend(value: unknown): DeepAgentActBackend { return DEFAULT_DEEPAGENT_ACT_BACKEND; } +function getDefaultFileBackendConfig( + backend: DeepAgentActBackend +): FileBackendConfig { + return { ...DEFAULT_FILE_BACKEND_CONFIG[backend] }; +} + +function isRecord(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function readOptionalString( + record: Record, + key: keyof FileBackendConfig +): string | undefined { + const value = record[key]; + return typeof value === "string" ? value : undefined; +} + +function getDeepAgentEditorState(config: GraphConfigReadResponse): { + actBackend: DeepAgentActBackend; + fileBackendConfig: FileBackendConfig; +} { + const graphParams = isRecord(config.graph_params) ? config.graph_params : {}; + const actBackend = normalizeDeepAgentActBackend(graphParams.act_bkend); + const defaults = getDefaultFileBackendConfig(actBackend); + const rawFileBackendConfig = isRecord(graphParams.file_backend_config) + ? graphParams.file_backend_config + : null; + + if (!rawFileBackendConfig) { + return { + actBackend, + fileBackendConfig: defaults, + }; + } + + return { + actBackend, + fileBackendConfig: { + ...defaults, + ...(readOptionalString(rawFileBackendConfig, "skills_dir") !== undefined + ? { skills_dir: readOptionalString(rawFileBackendConfig, "skills_dir") as string } + : {}), + ...(readOptionalString(rawFileBackendConfig, "rt_skills_dir") !== undefined + ? { rt_skills_dir: readOptionalString(rawFileBackendConfig, "rt_skills_dir") as string } + : {}), + ...(readOptionalString(rawFileBackendConfig, "workspace_dir") !== undefined + ? { workspace_dir: readOptionalString(rawFileBackendConfig, "workspace_dir") as string } + : {}), + ...(readOptionalString(rawFileBackendConfig, "api_key") !== undefined + ? { api_key: readOptionalString(rawFileBackendConfig, "api_key") as string } + : {}), + }, + }; +} + function buildGraphParams(editor: EditableAgent): Record { if (editor.graphId === "deepagent") { return { @@ -479,6 +535,7 @@ function toEditable( config: GraphConfigReadResponse, draft: boolean ): EditableAgent { + const deepAgentState = getDeepAgentEditorState(config); return { id: draft ? `draft-${Date.now()}-${Math.random().toString(36).slice(2, 6)}` @@ -492,8 +549,8 @@ function toEditable( prompts: config.prompt_dict || {}, apiKey: config.api_key || DEFAULT_API_KEY, llmName: DEFAULT_LLM_NAME, - actBackend: DEFAULT_DEEPAGENT_ACT_BACKEND, - fileBackendConfig: DEFAULT_FILE_BACKEND_CONFIG[DEFAULT_DEEPAGENT_ACT_BACKEND], + actBackend: deepAgentState.actBackend, + fileBackendConfig: deepAgentState.fileBackendConfig, }; } @@ -788,8 +845,8 @@ export default function App() { : DEFAULT_DEEPAGENT_ACT_BACKEND, fileBackendConfig: graphId === "deepagent" - ? prev.fileBackendConfig || DEFAULT_FILE_BACKEND_CONFIG[DEFAULT_DEEPAGENT_ACT_BACKEND] - : DEFAULT_FILE_BACKEND_CONFIG[DEFAULT_DEEPAGENT_ACT_BACKEND], + ? prev.fileBackendConfig || getDefaultFileBackendConfig(DEFAULT_DEEPAGENT_ACT_BACKEND) + : getDefaultFileBackendConfig(DEFAULT_DEEPAGENT_ACT_BACKEND), }; if (next.isDraft) { setDraftAgents((drafts) => drafts.map((draft) => (draft.id === next.id ? next : draft))); @@ -827,7 +884,7 @@ export default function App() { setEditorAndSyncDraft((prev) => ({ ...prev, actBackend: newBackend, - fileBackendConfig: DEFAULT_FILE_BACKEND_CONFIG[newBackend], + fileBackendConfig: getDefaultFileBackendConfig(newBackend), })); } diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 5cb6297..23b85b0 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -23,6 +23,7 @@ export type GraphConfigReadResponse = { tool_keys: string[]; prompt_dict: Record; api_key: string; + graph_params?: Record; }; export type GraphConfigUpsertRequest = { diff --git a/lang_agent/fastapi_server/front_apis.py b/lang_agent/fastapi_server/front_apis.py index c9cdb48..0a9895f 100644 --- a/lang_agent/fastapi_server/front_apis.py +++ b/lang_agent/fastapi_server/front_apis.py @@ -20,6 +20,7 @@ from lang_agent.config.constants import ( MCP_CONFIG_DEFAULT_CONTENT, PIPELINE_REGISTRY_PATH, ) +from lang_agent.config.core_config import load_tyro_conf from lang_agent.front_api.build_server_utils import ( GRAPH_BUILD_FNCS, update_pipeline_registry, @@ -55,6 +56,7 @@ class GraphConfigReadResponse(BaseModel): tool_keys: List[str] prompt_dict: Dict[str, str] api_key: str = Field(default="") + graph_params: Dict[str, Any] = Field(default_factory=dict) class GraphConfigListItem(BaseModel): @@ -325,6 +327,81 @@ def _normalize_pipeline_spec(pipeline_id: str, spec: Dict[str, Any]) -> Pipeline ) +def _resolve_config_path(config_file: str) -> str: + if osp.isabs(config_file): + return config_file + return osp.join(_PROJECT_ROOT, config_file) + + +def _normalize_deepagent_backend_name(file_backend_config: Any) -> Optional[str]: + if file_backend_config is None: + return None + + type_names = { + type(file_backend_config).__name__.lower(), + getattr(getattr(file_backend_config, "_target", None), "__name__", "").lower(), + } + if any("statebk" in name for name in type_names): + return "state_bk" + if any("localshell" in name for name in type_names): + return "local_shell" + if any("daytona" in name for name in type_names): + return "daytona_sandbox" + return None + + +def _extract_graph_params_from_config(graph_id: Optional[str], loaded_cfg: Any) -> Dict[str, Any]: + if graph_id != "deepagent": + return {} + + graph_config = getattr(loaded_cfg, "graph_config", None) + file_backend_config = getattr(graph_config, "file_backend_config", None) + if file_backend_config is None: + return {} + + graph_params: Dict[str, Any] = {} + act_bkend = _normalize_deepagent_backend_name(file_backend_config) + if act_bkend: + graph_params["act_bkend"] = act_bkend + + serialized_backend_config: Dict[str, Any] = {} + for key in ("skills_dir", "rt_skills_dir", "workspace_dir", "api_key"): + value = getattr(file_backend_config, key, None) + if value is not None: + serialized_backend_config[key] = value + + if serialized_backend_config: + graph_params["file_backend_config"] = serialized_backend_config + + return graph_params + + +def _load_graph_params_for_pipeline( + pipeline_id: str, graph_id: Optional[str] +) -> Dict[str, Any]: + try: + registry = _read_pipeline_registry() + pipeline_spec = registry.get("pipelines", {}).get(pipeline_id, {}) + config_file = "" + if isinstance(pipeline_spec, dict): + config_file = str(pipeline_spec.get("config_file") or "").strip() + if not config_file: + fallback = osp.join(_PROJECT_ROOT, "configs", "pipelines", f"{pipeline_id}.yaml") + if osp.exists(fallback): + config_file = fallback + if not config_file: + return {} + + config_path = _resolve_config_path(config_file) + if not osp.exists(config_path): + return {} + + loaded_cfg = load_tyro_conf(config_path) + return _extract_graph_params_from_config(graph_id, loaded_cfg) + except Exception: + return {} + + def _normalize_api_key_policy(api_key: str, policy: Dict[str, Any]) -> ApiKeyPolicyItem: if not isinstance(policy, dict): raise ValueError(f"api key policy for '{api_key}' must be an object") @@ -428,6 +505,9 @@ async def get_default_graph_config(pipeline_id: str): tool_keys=tool_keys, prompt_dict=prompt_dict, api_key=(active.get("api_key") or ""), + graph_params=_load_graph_params_for_pipeline( + pipeline_id, active.get("graph_id") + ), ) @@ -466,6 +546,9 @@ async def get_graph_config(pipeline_id: str, prompt_set_id: str): tool_keys=tool_keys, prompt_dict=prompt_dict, api_key=(meta.get("api_key") or ""), + graph_params=_load_graph_params_for_pipeline( + pipeline_id, meta.get("graph_id") + ), )