@@ -105,17 +105,20 @@ class Artifact(_AuthenticatedResource):
105105 ``GET /api/v1/runs/{run_id}/artifacts/{artifact_id}/file`` endpoint.
106106 """
107107
108- def __init__ (self , api : _AuthenticatedApi , run_id : str , artifact_id : str ) -> None :
108+ def __init__ (self , api : _AuthenticatedApi , run_id : str , artifact_id : str , share_token : str | None = None ) -> None :
109109 """Initializes an Artifact instance.
110110
111111 Args:
112112 api (_AuthenticatedApi): The configured API client.
113113 run_id (str): The ID of the parent run.
114114 artifact_id (str): The ID of the output artifact.
115+ share_token (str | None): Optional share token secret forwarded as the
116+ ``share_token`` query parameter on the /file endpoint request.
115117 """
116118 super ().__init__ (api )
117119 self .run_id = run_id
118120 self .artifact_id = artifact_id
121+ self ._share_token = share_token
119122
120123 def get_download_url (self ) -> str :
121124 """Resolve a fresh presigned download URL for this artifact.
@@ -143,6 +146,8 @@ def get_download_url(self) -> str:
143146 configuration = self ._api .api_client .configuration
144147 host = configuration .host .rstrip ("/" )
145148 endpoint_url = f"{ host } /api/v1/runs/{ self .run_id } /artifacts/{ self .artifact_id } /file"
149+ if self ._share_token :
150+ endpoint_url += f"?share_token={ self ._share_token } "
146151 proxy = getattr (configuration , "proxy" , None )
147152 ssl_ca_cert = getattr (configuration , "ssl_ca_cert" , None )
148153 verify_ssl = getattr (configuration , "verify_ssl" , True )
@@ -248,30 +253,57 @@ class Run(_AuthenticatedResource):
248253 Provides operations to check status, retrieve results, and download artifacts.
249254 """
250255
251- def __init__ (self , api : _AuthenticatedApi , run_id : str ) -> None :
256+ def __init__ (self , api : _AuthenticatedApi , run_id : str , share_token : str | None = None ) -> None :
252257 """Initializes a Run instance.
253258
254259 Args:
255260 api (_AuthenticatedApi): The configured API client.
256261 run_id (str): The ID of the application run.
262+ share_token (str | None): Optional share token secret. When supplied the
263+ token is forwarded as the ``share_token`` query parameter on every API
264+ request, granting access without an OAuth Bearer token.
257265 """
258266 super ().__init__ (api )
259267 self .run_id = run_id
268+ self ._share_token = share_token
260269
261270 @classmethod
262- def for_run_id (cls , run_id : str , cache_token : bool = True ) -> "Run" :
263- """Creates an Run instance for an existing run.
271+ def for_run_id (cls , run_id : str , cache_token : bool = True , share_token : str | None = None ) -> "Run" :
272+ """Creates a Run instance for an existing run.
273+
274+ When *share_token* is provided the run is accessed via the ``share_token``
275+ query parameter on every API request without an OAuth Bearer token.
264276
265277 Args:
266278 run_id (str): The ID of the application run.
267- cache_token (bool): Whether to cache the API token.
279+ cache_token (bool): Whether to use the cached OAuth token. Ignored
280+ when *share_token* is supplied.
281+ share_token (str | None): Optional share token secret. When provided
282+ no OAuth login is required.
268283
269284 Returns:
270285 Run: The initialized Run instance.
286+
287+ Example::
288+
289+ # Authenticated access
290+ run = Run.for_run_id("run-abc123")
291+
292+ # Share-token access (no OAuth required)
293+ run = Run.for_run_id("run-abc123", share_token="shr_xxxx")
294+ details = run.details()
295+ for item in run.results():
296+ print(item.external_id)
271297 """
272298 from aignostics .platform ._client import Client # noqa: PLC0415
273299
274- return cls (Client .get_api_client (cache_token = cache_token ), run_id )
300+ if share_token is not None :
301+ # Use an empty token provider so no Authorization header is sent.
302+ # The share token is forwarded as a query parameter instead.
303+ api = Client .get_api_client (token_provider = lambda : "" )
304+ else :
305+ api = Client .get_api_client (cache_token = cache_token )
306+ return cls (api , run_id , share_token = share_token )
275307
276308 def details (self , nocache : bool = False , hide_platform_queue_position : bool = False ) -> RunData :
277309 """Retrieves the current status of the application run.
@@ -292,9 +324,10 @@ def details(self, nocache: bool = False, hide_platform_queue_position: bool = Fa
292324 NotFoundException: If the run is not found after retries.
293325 Exception: If the API request fails.
294326 """
327+ share_token = self ._share_token
295328
296329 @cached_operation (ttl = settings ().run_cache_ttl , token_provider = self ._api .token_provider )
297- def details_with_retry (run_id : str ) -> RunData :
330+ def details_with_retry (run_id : str , _share_token : str | None = None ) -> RunData :
298331 def _fetch () -> RunData :
299332 return Retrying (
300333 retry = retry_if_exception_type (exception_types = RETRYABLE_EXCEPTIONS ),
@@ -307,6 +340,7 @@ def _fetch() -> RunData:
307340 )(
308341 lambda : self ._api .get_run_v1_runs_run_id_get (
309342 run_id ,
343+ share_token = _share_token ,
310344 _request_timeout = settings ().run_timeout ,
311345 _headers = {"User-Agent" : user_agent ()},
312346 )
@@ -321,7 +355,7 @@ def _fetch() -> RunData:
321355 reraise = True ,
322356 )(_fetch )
323357
324- run_data : RunData = details_with_retry (self .run_id , nocache = nocache ) # type: ignore[call-arg]
358+ run_data : RunData = details_with_retry (self .run_id , _share_token = share_token , nocache = nocache ) # type: ignore[call-arg]
325359 if hide_platform_queue_position :
326360 run_data = run_data .model_copy (deep = True )
327361 run_data .num_preceding_items_platform = None
@@ -386,11 +420,12 @@ def results( # noqa: PLR0913
386420 Raises:
387421 Exception: If the API request fails.
388422 """
423+ share_token = self ._share_token
389424
390425 # Create a wrapper function that applies retry logic and caching to each API call
391426 # Caching at this level ensures having a fresh iterator on cache hits
392427 @cached_operation (ttl = settings ().run_cache_ttl , token_provider = self ._api .token_provider )
393- def results_with_retry (run_id : str , ** kwargs : object ) -> list [ItemResultData ]:
428+ def results_with_retry (run_id : str , _share_token : str | None = None , ** kwargs : object ) -> list [ItemResultData ]:
394429 return Retrying (
395430 retry = retry_if_exception_type (exception_types = RETRYABLE_EXCEPTIONS ),
396431 stop = stop_after_attempt (settings ().run_retry_attempts ),
@@ -400,6 +435,7 @@ def results_with_retry(run_id: str, **kwargs: object) -> list[ItemResultData]:
400435 )(
401436 lambda : self ._api .list_run_items_v1_runs_run_id_items_get (
402437 run_id = run_id ,
438+ share_token = _share_token ,
403439 _request_timeout = settings ().run_timeout ,
404440 _headers = {"User-Agent" : user_agent ()},
405441 ** kwargs , # pyright: ignore[reportArgumentType]
@@ -418,7 +454,11 @@ def results_with_retry(run_id: str, **kwargs: object) -> list[ItemResultData]:
418454 if custom_metadata is not None :
419455 filter_kwargs ["custom_metadata" ] = custom_metadata
420456
421- return paginate (lambda ** kwargs : results_with_retry (self .run_id , nocache = nocache , ** filter_kwargs , ** kwargs ))
457+ return paginate (
458+ lambda ** kwargs : results_with_retry (
459+ self .run_id , _share_token = share_token , nocache = nocache , ** filter_kwargs , ** kwargs
460+ )
461+ )
422462
423463 def download_to_folder ( # noqa: C901
424464 self ,
@@ -511,7 +551,7 @@ def artifact(self, artifact_id: str) -> Artifact:
511551 Returns:
512552 Artifact: A handle bound to this run and the given artifact.
513553 """
514- return Artifact (self ._api , self .run_id , artifact_id )
554+ return Artifact (self ._api , self .run_id , artifact_id , share_token = self . _share_token )
515555
516556 def get_artifact_download_url (self , artifact_id : str ) -> str :
517557 """Resolve a fresh presigned download URL for an artifact of this run.
0 commit comments