@@ -257,7 +257,7 @@ def apply_plugin(
257257
258258 tracker = GeminiApiCallTracker (mock_responses )
259259 original_activities = GeminiApiCaller .activities
260- GeminiApiCaller .activities = lambda self : [
260+ GeminiApiCaller .activities = lambda self : [ # type: ignore[method-assign]
261261 tracker .gemini_api_client_async_request ,
262262 tracker .gemini_api_client_async_request_streamed ,
263263 tracker .gemini_files_upload ,
@@ -268,7 +268,7 @@ def apply_plugin(
268268 gemini = GeminiClient (api_key = "fake-test-key" )
269269 plugin = GeminiPlugin (gemini )
270270 finally :
271- GeminiApiCaller .activities = original_activities
271+ GeminiApiCaller .activities = original_activities # type: ignore[method-assign]
272272
273273 config = client .config ()
274274 config ["plugins" ] = [plugin ]
@@ -598,6 +598,24 @@ async def run(self, store_name: str, file_path: str) -> str:
598598 return op .name or ""
599599
600600
601+ @workflow .defn
602+ class RegisterFilesWorkflow :
603+ """Workflow that calls files.register_files."""
604+
605+ @workflow .run
606+ async def run (self , uris : list [str ]) -> str :
607+ client = gemini_client ()
608+ # auth arg is ignored by TemporalAsyncFiles — the activity uses
609+ # credentials from GeminiPlugin init. We pass a dummy here;
610+ # can't import google.auth.credentials in the sandbox so we
611+ # use a sentinel that satisfies the type at runtime.
612+ resp = await client .files .register_files (
613+ auth = None , # type: ignore[arg-type]
614+ uris = uris ,
615+ )
616+ return str (len (resp .files or []))
617+
618+
601619@workflow .defn
602620class ChatWorkflow :
603621 """Workflow that uses client.chats for multi-turn conversation."""
@@ -1095,15 +1113,15 @@ async def _gen():
10951113
10961114 # Mock file operations at the high-level SDK interface (these are what
10971115 # the real activities call).
1098- gemini .aio .files .upload = AsyncMock (
1116+ gemini .aio .files .upload = AsyncMock ( # type: ignore[method-assign]
10991117 return_value = types .File (
11001118 name = "files/mock-uploaded" ,
11011119 uri = "https://fake.uri/files/mock-uploaded" ,
11021120 size_bytes = 42 ,
11031121 )
11041122 )
1105- gemini .aio .files .download = AsyncMock (return_value = b"mock download content" )
1106- gemini .aio .file_search_stores .upload_to_file_search_store = AsyncMock (
1123+ gemini .aio .files .download = AsyncMock (return_value = b"mock download content" ) # type: ignore[method-assign]
1124+ gemini .aio .file_search_stores .upload_to_file_search_store = AsyncMock ( # type: ignore[method-assign]
11071125 return_value = types .UploadToFileSearchStoreOperation .model_construct (
11081126 name = "operations/mock-op"
11091127 )
@@ -1155,6 +1173,34 @@ async def test_full_integration_with_mock_client(client: Client):
11551173 assert result ["store_deleted" ] is True
11561174
11571175
1176+ async def test_register_files_without_credentials_fails (client : Client ):
1177+ """register_files raises when no credentials are available."""
1178+ # _apply_plugin_with_mock_client uses api_key auth with no
1179+ # extra_credentials, so the activity should raise ValueError.
1180+ new_client = _apply_plugin_with_mock_client (client , [])
1181+
1182+ async with new_worker (new_client , RegisterFilesWorkflow ) as worker :
1183+ with pytest .raises (WorkflowFailureError ) as exc_info :
1184+ await new_client .execute_workflow (
1185+ RegisterFilesWorkflow .run ,
1186+ ["gs://bucket/file.txt" ],
1187+ id = f"gemini-register-no-creds-{ uuid .uuid4 ()} " ,
1188+ task_queue = worker .task_queue ,
1189+ execution_timeout = timedelta (seconds = 10 ),
1190+ )
1191+
1192+ # The error is nested: WorkflowFailureError → ActivityError → ApplicationError
1193+ cause : BaseException | None = exc_info .value .cause
1194+ while (
1195+ cause is not None
1196+ and hasattr (cause , "__cause__" )
1197+ and cause .__cause__ is not None
1198+ ):
1199+ cause = cause .__cause__
1200+ assert cause is not None
1201+ assert "No credentials available for register_files" in str (cause )
1202+
1203+
11581204# ===========================================================================
11591205# TemporalAsyncClient wiring tests
11601206# ===========================================================================
0 commit comments