refactor: type storage value contracts

This commit is contained in:
jxxghp
2026-08-24 01:35:42 +08:00
parent e359bbace9
commit bb80c10a0b
3 changed files with 67 additions and 23 deletions
@@ -100,15 +100,20 @@ _METHOD_CONTRACTS = {
"mediaserver_librarys": ModuleMethodContract(family="media-server", input_contract="MediaServerLibrariesRequest", result_contract="list[MediaServerLibrary]", result_shape=ModuleResultShape.LIST, aggregation=ModuleResultAggregation.ORDERED_LIST_MERGE, required_parameters=("server", "username", "hidden")),
"mediaserver_playing": ModuleMethodContract(family="media-server", input_contract="MediaServerRecentRequest", result_contract="list[MediaServerPlayItem]", result_shape=ModuleResultShape.LIST, aggregation=ModuleResultAggregation.ORDERED_LIST_MERGE, required_parameters=("server", "count", "username")),
"mediaserver_season_episode_ids": ModuleMethodContract(family="media-server", input_contract="MediaServerSeasonEpisodesRequest", result_contract="dict[int, str] | None", result_shape=ModuleResultShape.MAPPING, aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("server", "item_id", "season")),
"any_files": ModuleMethodContract(family="storage", input_contract="StorageAnyFilesRequest", result_contract="bool | None", result_shape=ModuleResultShape.BOOLEAN, aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("fileitem", "extensions")),
"create_folder": ModuleMethodContract(family="storage", input_contract="StorageCreateFolderRequest", result_contract="FileItem | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("fileitem", "name")),
"delete_file": ModuleMethodContract(family="storage", input_contract="StorageDeleteRequest", result_contract="bool | None", result_shape=ModuleResultShape.BOOLEAN, aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("fileitem",)),
"download_file": ModuleMethodContract(family="storage", input_contract="StorageDownloadRequest", result_contract="FileItem | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("fileitem", "path")),
"upload_file": ModuleMethodContract(family="storage", input_contract="StorageUploadRequest", result_contract="FileItem | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("fileitem", "path", "new_name")),
"list_files": ModuleMethodContract(family="storage", input_contract="StorageListRequest", result_contract="list[FileItem]", result_shape=ModuleResultShape.LIST, aggregation=ModuleResultAggregation.ORDERED_LIST_MERGE, required_parameters=("fileitem", "recursion")),
"media_files": ModuleMethodContract(family="storage", input_contract="MediaFilesRequest", result_contract="list[FileItem]", result_shape=ModuleResultShape.LIST, aggregation=ModuleResultAggregation.ORDERED_LIST_MERGE, required_parameters=("mediainfo",)),
"get_file_item": ModuleMethodContract(family="storage", input_contract="StorageItemRequest", result_contract="FileItem | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("storage", "path")),
"get_folder": ModuleMethodContract(family="storage", input_contract="StorageFolderRequest", result_contract="FileItem | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("storage", "path")),
"get_parent_item": ModuleMethodContract(family="storage", input_contract="StorageParentRequest", result_contract="FileItem | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("fileitem",)),
"rename_file": ModuleMethodContract(family="storage", input_contract="StorageRenameRequest", result_contract="bool | FileItem", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("fileitem", "name")),
"storage_manage": ModuleMethodContract(family="storage", input_contract="StorageManageRequest", result_contract="StorageProviderResult", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("storage", "action")),
"snapshot_storage": ModuleMethodContract(family="storage", input_contract="StorageSnapshotRequest", result_contract="dict[str, dict] | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("storage", "path", "last_snapshot_time", "max_depth", "previous_snapshot")),
"transfer": ModuleMethodContract(family="storage", input_contract="TransferRequest", result_contract="TransferInfo | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("fileitem", "meta", "mediainfo", "target_directory", "target_storage", "target_path", "transfer_type", "scrape", "library_type_folder", "library_category_folder", "episodes_info", "source_oper", "target_oper", "preview")),
"send_message": ModuleMethodContract(family="messaging", input_contract="MessageSendRequest", result_contract="Message | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY),
"finalize_message": ModuleMethodContract(family="messaging", input_contract="MessageFinalizeRequest", result_contract="Message | None", aggregation=ModuleResultAggregation.FIRST_NON_EMPTY, required_parameters=("response",)),
"register_commands": ModuleMethodContract(family="messaging", input_contract="CommandRegistrationRequest", result_contract="None", required_parameters=("commands",)),
+48 -23
View File
@@ -2476,16 +2476,19 @@
"version": 1
},
"any_files": {
"aggregation": "legacy",
"aggregation": "first_non_empty",
"error_policy": "isolate_provider",
"execution": "sync_or_async",
"family": "storage",
"input_contract": "StorageKeywordArguments",
"input_contract": "StorageAnyFilesRequest",
"plugin_short_circuit": true,
"public_to_plugins": true,
"required_parameters": [],
"result_contract": "StorageProviderResult",
"result_shape": "any",
"required_parameters": [
"extensions",
"fileitem"
],
"result_contract": "bool | None",
"result_shape": "boolean",
"supports_async": true,
"supports_sync": true,
"timeout_policy": "caller_budget",
@@ -3576,15 +3579,18 @@
"version": 1
},
"create_folder": {
"aggregation": "legacy",
"aggregation": "first_non_empty",
"error_policy": "isolate_provider",
"execution": "sync_or_async",
"family": "storage",
"input_contract": "StorageKeywordArguments",
"input_contract": "StorageCreateFolderRequest",
"plugin_short_circuit": true,
"public_to_plugins": true,
"required_parameters": [],
"result_contract": "StorageProviderResult",
"required_parameters": [
"fileitem",
"name"
],
"result_contract": "FileItem | None",
"result_shape": "any",
"supports_async": true,
"supports_sync": true,
@@ -3592,16 +3598,18 @@
"version": 1
},
"delete_file": {
"aggregation": "legacy",
"aggregation": "first_non_empty",
"error_policy": "isolate_provider",
"execution": "sync_or_async",
"family": "storage",
"input_contract": "StorageKeywordArguments",
"input_contract": "StorageDeleteRequest",
"plugin_short_circuit": true,
"public_to_plugins": true,
"required_parameters": [],
"result_contract": "StorageProviderResult",
"result_shape": "any",
"required_parameters": [
"fileitem"
],
"result_contract": "bool | None",
"result_shape": "boolean",
"supports_async": true,
"supports_sync": true,
"timeout_policy": "caller_budget",
@@ -4405,16 +4413,18 @@
"version": 1
},
"media_files": {
"aggregation": "legacy",
"aggregation": "ordered_list_merge",
"error_policy": "isolate_provider",
"execution": "sync_or_async",
"family": "storage",
"input_contract": "StorageKeywordArguments",
"input_contract": "MediaFilesRequest",
"plugin_short_circuit": true,
"public_to_plugins": true,
"required_parameters": [],
"result_contract": "StorageProviderResult",
"result_shape": "any",
"required_parameters": [
"mediainfo"
],
"result_contract": "list[FileItem]",
"result_shape": "list",
"supports_async": true,
"supports_sync": true,
"timeout_policy": "caller_budget",
@@ -5707,15 +5717,30 @@
"version": 1
},
"transfer": {
"aggregation": "legacy",
"aggregation": "first_non_empty",
"error_policy": "isolate_provider",
"execution": "sync_or_async",
"family": "storage",
"input_contract": "StorageKeywordArguments",
"input_contract": "TransferRequest",
"plugin_short_circuit": true,
"public_to_plugins": true,
"required_parameters": [],
"result_contract": "StorageProviderResult",
"required_parameters": [
"episodes_info",
"fileitem",
"library_category_folder",
"library_type_folder",
"mediainfo",
"meta",
"preview",
"scrape",
"source_oper",
"target_directory",
"target_oper",
"target_path",
"target_storage",
"transfer_type"
],
"result_contract": "TransferInfo | None",
"result_shape": "any",
"supports_async": true,
"supports_sync": true,
+14
View File
@@ -189,6 +189,20 @@ def test_media_server_contracts_distinguish_streams_lists_and_scalar_routes() ->
assert items.result_shape is ModuleResultShape.ANY
def test_storage_value_contracts_use_explicit_provider_semantics() -> None:
"""存储值查询和动作应停止 legacy 接力,仅文件清单合并 provider 结果。"""
for method in ("any_files", "create_folder", "delete_file", "transfer"):
contract = get_module_method_contract(method)
assert contract.family == "storage"
assert contract.aggregation is ModuleResultAggregation.FIRST_NON_EMPTY
assert contract.required_parameters
media_files = get_module_method_contract("media_files")
assert media_files.aggregation is ModuleResultAggregation.ORDERED_LIST_MERGE
assert media_files.result_shape is ModuleResultShape.LIST
assert media_files.required_parameters == ("mediainfo",)
def test_heterogeneous_torrent_files_result_remains_legacy_compatible() -> None:
"""下载器文件集合尚未归一前不得声明虚假的列表聚合语义。"""
contract = get_module_method_contract("torrent_files")