pltr-cli 0.11.0__py3-none-any.whl → 0.13.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. pltr/__init__.py +1 -1
  2. pltr/cli.py +40 -0
  3. pltr/commands/admin.py +565 -11
  4. pltr/commands/aip_agents.py +333 -0
  5. pltr/commands/connectivity.py +309 -1
  6. pltr/commands/cp.py +103 -0
  7. pltr/commands/dataset.py +104 -4
  8. pltr/commands/functions.py +503 -0
  9. pltr/commands/language_models.py +515 -0
  10. pltr/commands/mediasets.py +176 -0
  11. pltr/commands/models.py +362 -0
  12. pltr/commands/ontology.py +44 -13
  13. pltr/commands/orchestration.py +167 -11
  14. pltr/commands/project.py +231 -22
  15. pltr/commands/resource.py +416 -17
  16. pltr/commands/space.py +25 -303
  17. pltr/commands/sql.py +54 -7
  18. pltr/commands/streams.py +616 -0
  19. pltr/commands/third_party_applications.py +82 -0
  20. pltr/services/admin.py +331 -3
  21. pltr/services/aip_agents.py +147 -0
  22. pltr/services/base.py +104 -1
  23. pltr/services/connectivity.py +139 -0
  24. pltr/services/copy.py +391 -0
  25. pltr/services/dataset.py +77 -4
  26. pltr/services/folder.py +6 -1
  27. pltr/services/functions.py +223 -0
  28. pltr/services/language_models.py +281 -0
  29. pltr/services/mediasets.py +144 -9
  30. pltr/services/models.py +179 -0
  31. pltr/services/ontology.py +48 -1
  32. pltr/services/orchestration.py +133 -1
  33. pltr/services/project.py +213 -39
  34. pltr/services/resource.py +229 -60
  35. pltr/services/space.py +24 -175
  36. pltr/services/sql.py +44 -20
  37. pltr/services/streams.py +290 -0
  38. pltr/services/third_party_applications.py +53 -0
  39. pltr/utils/formatting.py +195 -1
  40. pltr/utils/pagination.py +325 -0
  41. {pltr_cli-0.11.0.dist-info → pltr_cli-0.13.0.dist-info}/METADATA +55 -4
  42. pltr_cli-0.13.0.dist-info/RECORD +70 -0
  43. {pltr_cli-0.11.0.dist-info → pltr_cli-0.13.0.dist-info}/WHEEL +1 -1
  44. pltr_cli-0.11.0.dist-info/RECORD +0 -55
  45. {pltr_cli-0.11.0.dist-info → pltr_cli-0.13.0.dist-info}/entry_points.txt +0 -0
  46. {pltr_cli-0.11.0.dist-info → pltr_cli-0.13.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,362 @@
1
+ """
2
+ Models management commands for Foundry.
3
+ Provides commands for managing ML models and model versions in the registry.
4
+
5
+ Note: This is distinct from LanguageModels, which handles LLM chat/embeddings operations.
6
+ """
7
+
8
+ import typer
9
+ from typing import Optional
10
+ from rich.console import Console
11
+
12
+ from ..services.models import ModelsService
13
+ from ..utils.formatting import OutputFormatter
14
+ from ..utils.progress import SpinnerProgressTracker
15
+ from ..auth.base import ProfileNotFoundError, MissingCredentialsError
16
+ from ..utils.completion import (
17
+ complete_rid,
18
+ complete_profile,
19
+ complete_output_format,
20
+ )
21
+
22
+ # Create main app and sub-apps
23
+ app = typer.Typer(help="Manage ML models and versions")
24
+ model_app = typer.Typer(help="Manage models")
25
+ version_app = typer.Typer(help="Manage model versions")
26
+
27
+ # Add sub-apps
28
+ app.add_typer(model_app, name="model")
29
+ app.add_typer(version_app, name="version")
30
+
31
+ console = Console()
32
+ formatter = OutputFormatter(console)
33
+
34
+
35
+ @model_app.command("create")
36
+ def create_model(
37
+ name: str = typer.Argument(
38
+ ...,
39
+ help="Model name",
40
+ ),
41
+ folder: str = typer.Option(
42
+ ...,
43
+ "--folder",
44
+ "-f",
45
+ help="Parent folder RID (e.g., ri.compass.main.folder.xxx)",
46
+ autocompletion=complete_rid,
47
+ ),
48
+ profile: Optional[str] = typer.Option(
49
+ None,
50
+ "--profile",
51
+ "-p",
52
+ help="Profile name",
53
+ autocompletion=complete_profile,
54
+ ),
55
+ format: str = typer.Option(
56
+ "table",
57
+ "--format",
58
+ help="Output format (table, json, csv)",
59
+ autocompletion=complete_output_format,
60
+ ),
61
+ output: Optional[str] = typer.Option(
62
+ None,
63
+ "--output",
64
+ "-o",
65
+ help="Output file path (writes to file instead of stdout)",
66
+ ),
67
+ preview: bool = typer.Option(
68
+ False,
69
+ "--preview",
70
+ help="Enable preview mode",
71
+ ),
72
+ ):
73
+ """
74
+ Create a new ML model in the registry.
75
+
76
+ Creates a model container that can hold multiple versions.
77
+
78
+ Note: SDK does not support listing all models. Use the Foundry web UI
79
+ or Ontology API to discover existing models.
80
+
81
+ Examples:
82
+
83
+ # Create a new model
84
+ pltr models model create "fraud-detector" \\
85
+ --folder ri.compass.main.folder.xxx
86
+
87
+ # Create with JSON output
88
+ pltr models model create "recommendation-engine" \\
89
+ --folder ri.compass.main.folder.xxx \\
90
+ --format json
91
+
92
+ # Save to file
93
+ pltr models model create "anomaly-detector" \\
94
+ --folder ri.compass.main.folder.xxx \\
95
+ --output model-info.json
96
+ """
97
+ try:
98
+ with SpinnerProgressTracker().track_spinner("Creating model"):
99
+ service = ModelsService(profile=profile)
100
+ result = service.create_model(
101
+ name=name,
102
+ parent_folder_rid=folder,
103
+ preview=preview,
104
+ )
105
+
106
+ console.print(f"[green]✓[/green] Created model: {result.get('name')}")
107
+ console.print(f" Model RID: {result.get('rid')}")
108
+
109
+ formatter.format_output(result, format, output)
110
+
111
+ if output:
112
+ console.print(f"[green]✓[/green] Model information saved to {output}")
113
+
114
+ except (ProfileNotFoundError, MissingCredentialsError) as e:
115
+ console.print(f"[red]Authentication Error: {e}[/red]")
116
+ raise typer.Exit(1)
117
+ except Exception as e:
118
+ console.print(f"[red]Error: {e}[/red]")
119
+ raise typer.Exit(1)
120
+
121
+
122
+ @model_app.command("get")
123
+ def get_model(
124
+ model_rid: str = typer.Argument(
125
+ ...,
126
+ help="Model RID (e.g., ri.foundry.main.model.xxx)",
127
+ autocompletion=complete_rid,
128
+ ),
129
+ profile: Optional[str] = typer.Option(
130
+ None,
131
+ "--profile",
132
+ "-p",
133
+ help="Profile name",
134
+ autocompletion=complete_profile,
135
+ ),
136
+ format: str = typer.Option(
137
+ "table",
138
+ "--format",
139
+ help="Output format (table, json, csv)",
140
+ autocompletion=complete_output_format,
141
+ ),
142
+ output: Optional[str] = typer.Option(
143
+ None,
144
+ "--output",
145
+ "-o",
146
+ help="Output file path (writes to file instead of stdout)",
147
+ ),
148
+ preview: bool = typer.Option(
149
+ False,
150
+ "--preview",
151
+ help="Enable preview mode",
152
+ ),
153
+ ):
154
+ """
155
+ Get information about a model.
156
+
157
+ Retrieves model metadata including name, folder location, and other properties.
158
+
159
+ Examples:
160
+
161
+ # Get model details
162
+ pltr models model get ri.foundry.main.model.abc123
163
+
164
+ # Get as JSON
165
+ pltr models model get ri.foundry.main.model.abc123 --format json
166
+
167
+ # Save to file
168
+ pltr models model get ri.foundry.main.model.abc123 \\
169
+ --format json \\
170
+ --output model-details.json
171
+ """
172
+ try:
173
+ with SpinnerProgressTracker().track_spinner("Fetching model information"):
174
+ service = ModelsService(profile=profile)
175
+ result = service.get_model(
176
+ model_rid=model_rid,
177
+ preview=preview,
178
+ )
179
+
180
+ formatter.format_output(result, format, output)
181
+
182
+ if output:
183
+ console.print(f"[green]✓[/green] Model information saved to {output}")
184
+
185
+ except (ProfileNotFoundError, MissingCredentialsError) as e:
186
+ console.print(f"[red]Authentication Error: {e}[/red]")
187
+ raise typer.Exit(1)
188
+ except Exception as e:
189
+ console.print(f"[red]Error: {e}[/red]")
190
+ raise typer.Exit(1)
191
+
192
+
193
+ @version_app.command("get")
194
+ def get_version(
195
+ model_rid: str = typer.Argument(
196
+ ...,
197
+ help="Model RID (e.g., ri.foundry.main.model.xxx)",
198
+ autocompletion=complete_rid,
199
+ ),
200
+ version_rid: str = typer.Argument(
201
+ ...,
202
+ help="Version identifier (e.g., v1.0.0 or version RID)",
203
+ ),
204
+ profile: Optional[str] = typer.Option(
205
+ None,
206
+ "--profile",
207
+ "-p",
208
+ help="Profile name",
209
+ autocompletion=complete_profile,
210
+ ),
211
+ format: str = typer.Option(
212
+ "table",
213
+ "--format",
214
+ help="Output format (table, json, csv)",
215
+ autocompletion=complete_output_format,
216
+ ),
217
+ output: Optional[str] = typer.Option(
218
+ None,
219
+ "--output",
220
+ "-o",
221
+ help="Output file path (writes to file instead of stdout)",
222
+ ),
223
+ preview: bool = typer.Option(
224
+ False,
225
+ "--preview",
226
+ help="Enable preview mode",
227
+ ),
228
+ ):
229
+ """
230
+ Get information about a specific model version.
231
+
232
+ Retrieves version metadata including creation time, schema, and other properties.
233
+
234
+ Examples:
235
+
236
+ # Get specific version
237
+ pltr models version get ri.foundry.main.model.abc123 v1.0.0
238
+
239
+ # Get as JSON
240
+ pltr models version get ri.foundry.main.model.abc123 v1.0.0 \\
241
+ --format json
242
+
243
+ # Save to file
244
+ pltr models version get ri.foundry.main.model.abc123 v1.0.0 \\
245
+ --format json \\
246
+ --output version-details.json
247
+ """
248
+ try:
249
+ with SpinnerProgressTracker().track_spinner("Fetching version information"):
250
+ service = ModelsService(profile=profile)
251
+ result = service.get_model_version(
252
+ model_rid=model_rid,
253
+ model_version_rid=version_rid,
254
+ preview=preview,
255
+ )
256
+
257
+ formatter.format_output(result, format, output)
258
+
259
+ if output:
260
+ console.print(f"[green]✓[/green] Version information saved to {output}")
261
+
262
+ except (ProfileNotFoundError, MissingCredentialsError) as e:
263
+ console.print(f"[red]Authentication Error: {e}[/red]")
264
+ raise typer.Exit(1)
265
+ except Exception as e:
266
+ console.print(f"[red]Error: {e}[/red]")
267
+ raise typer.Exit(1)
268
+
269
+
270
+ @version_app.command("list")
271
+ def list_versions(
272
+ model_rid: str = typer.Argument(
273
+ ...,
274
+ help="Model RID (e.g., ri.foundry.main.model.xxx)",
275
+ autocompletion=complete_rid,
276
+ ),
277
+ page_size: Optional[int] = typer.Option(
278
+ None,
279
+ "--page-size",
280
+ help="Maximum number of versions to return per page",
281
+ ),
282
+ page_token: Optional[str] = typer.Option(
283
+ None,
284
+ "--page-token",
285
+ help="Token for fetching next page of results",
286
+ ),
287
+ profile: Optional[str] = typer.Option(
288
+ None,
289
+ "--profile",
290
+ "-p",
291
+ help="Profile name",
292
+ autocompletion=complete_profile,
293
+ ),
294
+ format: str = typer.Option(
295
+ "table",
296
+ "--format",
297
+ help="Output format (table, json, csv)",
298
+ autocompletion=complete_output_format,
299
+ ),
300
+ output: Optional[str] = typer.Option(
301
+ None,
302
+ "--output",
303
+ "-o",
304
+ help="Output file path (writes to file instead of stdout)",
305
+ ),
306
+ preview: bool = typer.Option(
307
+ False,
308
+ "--preview",
309
+ help="Enable preview mode",
310
+ ),
311
+ ):
312
+ """
313
+ List all versions of a model with pagination support.
314
+
315
+ Returns a list of model versions with their metadata.
316
+
317
+ Examples:
318
+
319
+ # List all versions
320
+ pltr models version list ri.foundry.main.model.abc123
321
+
322
+ # List with pagination
323
+ pltr models version list ri.foundry.main.model.abc123 \\
324
+ --page-size 50
325
+
326
+ # Get next page
327
+ pltr models version list ri.foundry.main.model.abc123 \\
328
+ --page-size 50 \\
329
+ --page-token <token-from-previous-response>
330
+
331
+ # Save to file
332
+ pltr models version list ri.foundry.main.model.abc123 \\
333
+ --format json \\
334
+ --output versions.json
335
+ """
336
+ try:
337
+ with SpinnerProgressTracker().track_spinner("Fetching model versions"):
338
+ service = ModelsService(profile=profile)
339
+ result = service.list_model_versions(
340
+ model_rid=model_rid,
341
+ page_size=page_size,
342
+ page_token=page_token,
343
+ preview=preview,
344
+ )
345
+
346
+ formatter.format_output(result, format, output)
347
+
348
+ # Show pagination info if available (only when outputting to console, not file)
349
+ if not output and result.get("nextPageToken"):
350
+ console.print(
351
+ f"[dim]Next page available. Use --page-token {result['nextPageToken']}[/dim]"
352
+ )
353
+
354
+ if output:
355
+ console.print(f"[green]✓[/green] Version list saved to {output}")
356
+
357
+ except (ProfileNotFoundError, MissingCredentialsError) as e:
358
+ console.print(f"[red]Authentication Error: {e}[/red]")
359
+ raise typer.Exit(1)
360
+ except Exception as e:
361
+ console.print(f"[red]Error: {e}[/red]")
362
+ raise typer.Exit(1)
pltr/commands/ontology.py CHANGED
@@ -15,6 +15,7 @@ from ..services.ontology import (
15
15
  QueryService,
16
16
  )
17
17
  from ..utils.formatting import OutputFormatter
18
+ from ..utils.pagination import PaginationConfig
18
19
  from ..utils.progress import SpinnerProgressTracker
19
20
  from ..auth.base import ProfileNotFoundError, MissingCredentialsError
20
21
 
@@ -176,36 +177,66 @@ def list_objects(
176
177
  None, "--output", "-o", help="Output file path"
177
178
  ),
178
179
  page_size: Optional[int] = typer.Option(
179
- None, "--page-size", help="Number of results per page"
180
+ None, "--page-size", help="Number of objects per page (default: from settings)"
181
+ ),
182
+ max_pages: Optional[int] = typer.Option(
183
+ 1, "--max-pages", help="Maximum number of pages to fetch (default: 1)"
184
+ ),
185
+ page_token: Optional[str] = typer.Option(
186
+ None, "--page-token", help="Page token to resume from previous response"
187
+ ),
188
+ all: bool = typer.Option(
189
+ False, "--all", help="Fetch all available pages (overrides --max-pages)"
180
190
  ),
181
191
  properties: Optional[str] = typer.Option(
182
192
  None, "--properties", help="Comma-separated list of properties to include"
183
193
  ),
184
194
  ):
185
- """List objects of a specific type."""
195
+ """
196
+ List objects of a specific type with pagination support.
197
+
198
+ By default, fetches only the first page of results. Use --all to fetch all objects,
199
+ or --max-pages to control how many pages to fetch.
200
+
201
+ Examples:
202
+ # List first page of objects (default)
203
+ pltr ontology object-list ONTOLOGY_RID ObjectType
204
+
205
+ # List all objects
206
+ pltr ontology object-list ONTOLOGY_RID ObjectType --all
207
+
208
+ # List first 3 pages
209
+ pltr ontology object-list ONTOLOGY_RID ObjectType --max-pages 3
210
+
211
+ # Resume from a specific page
212
+ pltr ontology object-list ONTOLOGY_RID ObjectType --page-token abc123
213
+ """
186
214
  try:
187
215
  service = OntologyObjectService(profile=profile)
188
216
 
189
217
  prop_list = properties.split(",") if properties else None
190
218
 
219
+ # Create pagination config
220
+ config = PaginationConfig(
221
+ page_size=page_size,
222
+ max_pages=max_pages,
223
+ page_token=page_token,
224
+ fetch_all=all,
225
+ )
226
+
191
227
  with SpinnerProgressTracker().track_spinner(
192
228
  f"Fetching {object_type} objects..."
193
229
  ):
194
- objects = service.list_objects(
195
- ontology_rid, object_type, page_size=page_size, properties=prop_list
230
+ result = service.list_objects_paginated(
231
+ ontology_rid, object_type, config, properties=prop_list
196
232
  )
197
233
 
198
- if format == "table" and objects:
199
- # Use first object's keys as columns
200
- columns = list(objects[0].keys()) if objects else []
201
- formatter.format_table(
202
- objects, columns=columns, format=format, output=output
203
- )
204
- else:
205
- formatter.format_list(objects, format=format, output=output)
206
-
234
+ # Format and display paginated results
207
235
  if output:
236
+ formatter.format_paginated_output(result, format, output)
208
237
  formatter.print_success(f"Objects saved to {output}")
238
+ else:
239
+ formatter.format_paginated_output(result, format)
209
240
 
210
241
  except (ProfileNotFoundError, MissingCredentialsError) as e:
211
242
  formatter.print_error(f"Authentication error: {e}")
@@ -9,6 +9,7 @@ from rich.console import Console
9
9
 
10
10
  from ..services.orchestration import OrchestrationService
11
11
  from ..utils.formatting import OutputFormatter
12
+ from ..utils.pagination import PaginationConfig
12
13
  from ..utils.progress import SpinnerProgressTracker
13
14
  from ..auth.base import ProfileNotFoundError, MissingCredentialsError
14
15
  from ..utils.completion import (
@@ -226,7 +227,7 @@ def get_build_jobs(
226
227
 
227
228
  if response.get("next_page_token"):
228
229
  formatter.print_info(
229
- "More results available. Use pagination token to fetch next page."
230
+ f"More results available. Use --page-token {response['next_page_token']} to fetch next page."
230
231
  )
231
232
 
232
233
  except (ProfileNotFoundError, MissingCredentialsError) as e:
@@ -241,7 +242,16 @@ def get_build_jobs(
241
242
  def search_builds(
242
243
  profile: Optional[str] = typer.Option(None, "--profile", "-p", help="Profile name"),
243
244
  page_size: Optional[int] = typer.Option(
244
- None, "--page-size", help="Number of results per page"
245
+ None, "--page-size", help="Number of builds per page (default: from settings)"
246
+ ),
247
+ max_pages: Optional[int] = typer.Option(
248
+ 1, "--max-pages", help="Maximum number of pages to fetch (default: 1)"
249
+ ),
250
+ page_token: Optional[str] = typer.Option(
251
+ None, "--page-token", help="Page token to resume from previous response"
252
+ ),
253
+ all: bool = typer.Option(
254
+ False, "--all", help="Fetch all available pages (overrides --max-pages)"
245
255
  ),
246
256
  format: str = typer.Option(
247
257
  "table", "--format", "-f", help="Output format (table, json, csv)"
@@ -250,12 +260,102 @@ def search_builds(
250
260
  None, "--output", "-o", help="Output file path"
251
261
  ),
252
262
  ):
253
- """Search for builds."""
263
+ """
264
+ Search for builds with pagination support.
265
+
266
+ By default, fetches only the first page of results. Use --all to fetch all builds,
267
+ or --max-pages to control how many pages to fetch.
268
+
269
+ Examples:
270
+ # Search first page of builds (default)
271
+ pltr orchestration builds search
272
+
273
+ # Search all builds
274
+ pltr orchestration builds search --all
275
+
276
+ # Search first 3 pages
277
+ pltr orchestration builds search --max-pages 3
278
+
279
+ # Resume from a specific page
280
+ pltr orchestration builds search --page-token abc123
281
+ """
254
282
  try:
255
283
  service = OrchestrationService(profile=profile)
256
284
 
285
+ # Create pagination config
286
+ config = PaginationConfig(
287
+ page_size=page_size,
288
+ max_pages=max_pages,
289
+ page_token=page_token,
290
+ fetch_all=all,
291
+ )
292
+
257
293
  with SpinnerProgressTracker().track_spinner("Searching builds..."):
258
- response = service.search_builds(page_size=page_size)
294
+ result = service.search_builds_paginated(config)
295
+
296
+ if not result.data:
297
+ formatter.print_warning("No builds found")
298
+ return
299
+
300
+ # Format and display paginated results
301
+ if output:
302
+ formatter.format_paginated_output(
303
+ result,
304
+ format,
305
+ output,
306
+ formatter_fn=lambda data, fmt, out: formatter.format_builds_list(
307
+ data, fmt, out
308
+ ),
309
+ )
310
+ formatter.print_success(f"Builds list saved to {output}")
311
+ else:
312
+ formatter.format_paginated_output(
313
+ result,
314
+ format,
315
+ formatter_fn=lambda data, fmt, out: formatter.format_builds_list(
316
+ data, fmt, out
317
+ ),
318
+ )
319
+
320
+ except (ProfileNotFoundError, MissingCredentialsError) as e:
321
+ formatter.print_error(f"Authentication error: {e}")
322
+ raise typer.Exit(1)
323
+ except Exception as e:
324
+ formatter.print_error(f"Failed to search builds: {e}")
325
+ raise typer.Exit(1)
326
+
327
+
328
+ @builds_app.command("get-batch")
329
+ def get_builds_batch(
330
+ build_rids: str = typer.Argument(
331
+ ..., help="Comma-separated list of Build RIDs (max 100)"
332
+ ),
333
+ profile: Optional[str] = typer.Option(None, "--profile", "-p", help="Profile name"),
334
+ format: str = typer.Option(
335
+ "table", "--format", "-f", help="Output format (table, json, csv)"
336
+ ),
337
+ output: Optional[str] = typer.Option(
338
+ None, "--output", "-o", help="Output file path"
339
+ ),
340
+ ):
341
+ """Get multiple builds in batch (max 100)."""
342
+ try:
343
+ rids_list = [rid.strip() for rid in build_rids.split(",") if rid.strip()]
344
+
345
+ if not rids_list:
346
+ formatter.print_error("No valid RIDs provided")
347
+ raise typer.Exit(1)
348
+
349
+ if len(rids_list) > 100:
350
+ formatter.print_error("Maximum batch size is 100 builds")
351
+ raise typer.Exit(1)
352
+
353
+ service = OrchestrationService(profile=profile)
354
+
355
+ with SpinnerProgressTracker().track_spinner(
356
+ f"Fetching {len(rids_list)} builds..."
357
+ ):
358
+ response = service.get_builds_batch(rids_list)
259
359
 
260
360
  builds = response.get("builds", [])
261
361
 
@@ -266,18 +366,13 @@ def search_builds(
266
366
  formatter.format_builds_list(builds, format, output)
267
367
 
268
368
  if output:
269
- formatter.print_success(f"Builds list saved to {output}")
270
-
271
- if response.get("next_page_token"):
272
- formatter.print_info(
273
- "More results available. Use pagination token to fetch next page."
274
- )
369
+ formatter.print_success(f"Builds information saved to {output}")
275
370
 
276
371
  except (ProfileNotFoundError, MissingCredentialsError) as e:
277
372
  formatter.print_error(f"Authentication error: {e}")
278
373
  raise typer.Exit(1)
279
374
  except Exception as e:
280
- formatter.print_error(f"Failed to search builds: {e}")
375
+ formatter.print_error(f"Failed to get builds batch: {e}")
281
376
  raise typer.Exit(1)
282
377
 
283
378
 
@@ -655,6 +750,67 @@ def replace_schedule(
655
750
  raise typer.Exit(1)
656
751
 
657
752
 
753
+ @schedules_app.command("runs")
754
+ def get_schedule_runs(
755
+ schedule_rid: str = typer.Argument(
756
+ ..., help="Schedule Resource Identifier", autocompletion=complete_rid
757
+ ),
758
+ profile: Optional[str] = typer.Option(
759
+ None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
760
+ ),
761
+ page_size: Optional[int] = typer.Option(
762
+ None, "--page-size", help="Number of results per page"
763
+ ),
764
+ page_token: Optional[str] = typer.Option(
765
+ None, "--page-token", help="Pagination token for next page"
766
+ ),
767
+ format: str = typer.Option(
768
+ "table",
769
+ "--format",
770
+ "-f",
771
+ help="Output format (table, json, csv)",
772
+ autocompletion=complete_output_format,
773
+ ),
774
+ output: Optional[str] = typer.Option(
775
+ None, "--output", "-o", help="Output file path"
776
+ ),
777
+ ):
778
+ """List recent execution runs for a schedule."""
779
+ try:
780
+ cache_rid(schedule_rid)
781
+ service = OrchestrationService(profile=profile)
782
+
783
+ with SpinnerProgressTracker().track_spinner(
784
+ f"Fetching runs for schedule {schedule_rid}..."
785
+ ):
786
+ response = service.get_schedule_runs(
787
+ schedule_rid, page_size=page_size, page_token=page_token
788
+ )
789
+
790
+ runs = response.get("runs", [])
791
+
792
+ if not runs:
793
+ formatter.print_warning("No runs found for this schedule")
794
+ return
795
+
796
+ formatter.format_schedule_runs_list(runs, format, output)
797
+
798
+ if output:
799
+ formatter.print_success(f"Runs list saved to {output}")
800
+
801
+ if response.get("next_page_token"):
802
+ formatter.print_info(
803
+ f"More results available. Use --page-token {response['next_page_token']} to fetch next page."
804
+ )
805
+
806
+ except (ProfileNotFoundError, MissingCredentialsError) as e:
807
+ formatter.print_error(f"Authentication error: {e}")
808
+ raise typer.Exit(1)
809
+ except Exception as e:
810
+ formatter.print_error(f"Failed to get schedule runs: {e}")
811
+ raise typer.Exit(1)
812
+
813
+
658
814
  # ============================================================================
659
815
  # Main app setup
660
816
  # ============================================================================