fix(lightweight-extension): 输出前缀绑定、拖拽导入与前端入口修复
- runtime_binding: 验证时排除输入 sidecar 输出,目录参数跟随输出前缀重命名 - import-folder: 改 multipart 二进制上传,规避大文件 base64 报 Invalid string length - main: 前端入口切回 index.html,conda 路径兜底 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1004,6 +1004,33 @@ def resolve_runtime_bindings(
|
||||
binding["original_path"]: binding["runtime_path"]
|
||||
for binding in input_bindings or []
|
||||
}
|
||||
direct_output_fact_ids = {
|
||||
fact_id
|
||||
for target in contract.get("patch_targets", [])
|
||||
if isinstance(target, dict)
|
||||
and target.get("patch_kind") in {"output_path", "output_reference_path"}
|
||||
for fact_id in target.get("fact_ids", [])
|
||||
if isinstance(fact_id, str)
|
||||
}
|
||||
# Outputs owned by an input (the input itself or a sidecar like
|
||||
# ``Pfam-A.WRKY-subset.hmm.h3f`` next to ``Pfam-A.WRKY-subset.hmm``) do not
|
||||
# belong to the output-prefix namespace; they are renamed via their input
|
||||
# relationship. Excluding them keeps the shared-prefix derivation from
|
||||
# being dragged to ``.`` by a top-level sidecar while the remaining outputs
|
||||
# live under a common directory.
|
||||
input_owned_paths = {
|
||||
output["path"]
|
||||
for output in output_files
|
||||
if _runtime_input_owned_output(
|
||||
output["path"],
|
||||
runtime_by_original,
|
||||
allow_sidecar=output["fact_id"] not in direct_output_fact_ids,
|
||||
)
|
||||
is not None
|
||||
}
|
||||
prefix_output_files = [
|
||||
output for output in output_files if output["path"] not in input_owned_paths
|
||||
]
|
||||
participant_options: list[set[tuple[str, str]]] = []
|
||||
participating_paths: set[str] = set()
|
||||
for output in output_files:
|
||||
@@ -1055,11 +1082,11 @@ def resolve_runtime_bindings(
|
||||
*[{old for old, _new in options} for options in participant_options]
|
||||
)
|
||||
if not common_old:
|
||||
old_prefix = _shared_output_prefix(output_files)
|
||||
old_prefix = _shared_output_prefix(prefix_output_files)
|
||||
else:
|
||||
old_prefix = max(common_old, key=lambda value: (len(value), value))
|
||||
else:
|
||||
old_prefix = _shared_output_prefix(output_files)
|
||||
old_prefix = _shared_output_prefix(prefix_output_files)
|
||||
if old_prefix is None:
|
||||
return _blocked_result(
|
||||
contract,
|
||||
@@ -1069,14 +1096,6 @@ def resolve_runtime_bindings(
|
||||
parameter_bindings=parameter_bindings,
|
||||
)
|
||||
new_prefix = explicit_prefix or "output"
|
||||
direct_output_fact_ids = {
|
||||
fact_id
|
||||
for target in contract.get("patch_targets", [])
|
||||
if isinstance(target, dict)
|
||||
and target.get("patch_kind") in {"output_path", "output_reference_path"}
|
||||
for fact_id in target.get("fact_ids", [])
|
||||
if isinstance(fact_id, str)
|
||||
}
|
||||
unpatchable_fact_ids = {
|
||||
fact_id
|
||||
for target in contract.get("unpatchable_targets", [])
|
||||
@@ -1412,6 +1431,17 @@ def _binding_replacements(
|
||||
raise RuntimeBindingError(
|
||||
"PARAMETER_VALUE_INVALID", f"unsafe runtime parameter: {fact_id}"
|
||||
)
|
||||
# 输出目录参数(--outdir / -oc / mkdir -p 的值)跟随输出前缀重命名,
|
||||
# 否则渲染后的 run.sh 里目录参数与 file 输出路径指向不一致的目录。
|
||||
if isinstance(prefix, dict):
|
||||
old_prefix = prefix.get("old_prefix")
|
||||
new_prefix = prefix.get("new_prefix")
|
||||
if (
|
||||
isinstance(old_prefix, str)
|
||||
and isinstance(new_prefix, str)
|
||||
and _output_has_prefix(runtime, old_prefix)
|
||||
):
|
||||
runtime = _replace_output_prefix(runtime, old_prefix, new_prefix)
|
||||
add(f"parameter:{fact_id}", original, runtime)
|
||||
|
||||
targets_by_key = {
|
||||
|
||||
Reference in New Issue
Block a user