pipefy-cli 0.3.0a1__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 (40) hide show
  1. pipefy_cli/__init__.py +7 -0
  2. pipefy_cli/_docs.py +3 -0
  3. pipefy_cli/auth.py +225 -0
  4. pipefy_cli/commands/__init__.py +5 -0
  5. pipefy_cli/commands/_common.py +359 -0
  6. pipefy_cli/commands/agent.py +358 -0
  7. pipefy_cli/commands/ai_automation.py +318 -0
  8. pipefy_cli/commands/attachment.py +122 -0
  9. pipefy_cli/commands/audit.py +63 -0
  10. pipefy_cli/commands/auth.py +519 -0
  11. pipefy_cli/commands/automation.py +529 -0
  12. pipefy_cli/commands/card.py +439 -0
  13. pipefy_cli/commands/email.py +169 -0
  14. pipefy_cli/commands/export.py +61 -0
  15. pipefy_cli/commands/field.py +113 -0
  16. pipefy_cli/commands/field_condition.py +201 -0
  17. pipefy_cli/commands/graphql.py +110 -0
  18. pipefy_cli/commands/introspect.py +110 -0
  19. pipefy_cli/commands/label.py +109 -0
  20. pipefy_cli/commands/member.py +126 -0
  21. pipefy_cli/commands/org.py +60 -0
  22. pipefy_cli/commands/phase.py +264 -0
  23. pipefy_cli/commands/pipe.py +167 -0
  24. pipefy_cli/commands/portal.py +871 -0
  25. pipefy_cli/commands/record.py +219 -0
  26. pipefy_cli/commands/relation.py +173 -0
  27. pipefy_cli/commands/report_org.py +241 -0
  28. pipefy_cli/commands/report_pipe.py +290 -0
  29. pipefy_cli/commands/table.py +151 -0
  30. pipefy_cli/commands/usage.py +100 -0
  31. pipefy_cli/commands/webhook.py +141 -0
  32. pipefy_cli/main.py +132 -0
  33. pipefy_cli/output/__init__.py +8 -0
  34. pipefy_cli/output/json_renderer.py +24 -0
  35. pipefy_cli/output/rich_renderer.py +81 -0
  36. pipefy_cli/settings.py +66 -0
  37. pipefy_cli-0.3.0a1.dist-info/METADATA +104 -0
  38. pipefy_cli-0.3.0a1.dist-info/RECORD +40 -0
  39. pipefy_cli-0.3.0a1.dist-info/WHEEL +4 -0
  40. pipefy_cli-0.3.0a1.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,529 @@
1
+ """Traditional Pipefy automations (rules, logs, exports, usage)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import typer
6
+ from pipefy_sdk import CreateSendTaskAutomationInput, PipefyClient
7
+ from pydantic import ValidationError
8
+
9
+ from pipefy_cli.commands._common import (
10
+ ID_POSITIONAL_CONTEXT_SETTINGS,
11
+ confirm_destructive,
12
+ parse_json_object,
13
+ parse_json_value,
14
+ resource_id_argument,
15
+ run_cli_command,
16
+ )
17
+
18
+ automation_app = typer.Typer(
19
+ help="Traditional automations and related exports.", no_args_is_help=True
20
+ )
21
+ export_app = typer.Typer(help="Automation jobs export (async).", no_args_is_help=True)
22
+ send_task_app = typer.Typer(help="Send-a-task automation helper.", no_args_is_help=True)
23
+ events_app = typer.Typer(help="Automation trigger catalog.", no_args_is_help=True)
24
+ actions_app = typer.Typer(help="Automation action catalog.", no_args_is_help=True)
25
+
26
+
27
+ @automation_app.command("list")
28
+ def automation_list(
29
+ ctx: typer.Context,
30
+ organization: str | None = typer.Option(
31
+ None,
32
+ "--organization",
33
+ "--org",
34
+ help="Optional organization id filter.",
35
+ ),
36
+ pipe: str | None = typer.Option(None, "--pipe", help="Optional pipe id filter."),
37
+ json_out: bool = typer.Option(
38
+ False,
39
+ "--json",
40
+ "-j",
41
+ help="Print machine-readable JSON to stdout.",
42
+ ),
43
+ ) -> None:
44
+ """List automation rules (``get_automations``)."""
45
+
46
+ async def factory(client: PipefyClient):
47
+ return await client.get_automations(
48
+ organization_id=organization,
49
+ pipe_id=pipe,
50
+ )
51
+
52
+ run_cli_command(ctx, json_out, factory)
53
+
54
+
55
+ @automation_app.command("get", context_settings=ID_POSITIONAL_CONTEXT_SETTINGS)
56
+ def automation_get(
57
+ ctx: typer.Context,
58
+ automation_id: str = resource_id_argument(help="Automation rule id."),
59
+ json_out: bool = typer.Option(
60
+ False,
61
+ "--json",
62
+ "-j",
63
+ help="Print machine-readable JSON to stdout.",
64
+ ),
65
+ ) -> None:
66
+ """Load one automation (``get_automation``)."""
67
+
68
+ async def factory(client: PipefyClient):
69
+ row = await client.get_automation(automation_id)
70
+ if row is None:
71
+ return {
72
+ "success": False,
73
+ "message": "No automation found for the given ID.",
74
+ }
75
+ return {"success": True, "message": "Automation retrieved.", "data": row}
76
+
77
+ run_cli_command(ctx, json_out, factory)
78
+
79
+
80
+ @automation_app.command("create")
81
+ def automation_create(
82
+ ctx: typer.Context,
83
+ pipe: str = typer.Option(..., "--pipe", help="Source pipe id (trigger context)."),
84
+ name: str = typer.Option(..., "--name", "-n", help="Rule name."),
85
+ trigger_id: str = typer.Option(
86
+ ...,
87
+ "--event-id",
88
+ "--trigger-id",
89
+ help="Trigger event id from ``automation events list`` (``--trigger-id`` retained as alias).",
90
+ ),
91
+ action_id: str = typer.Option(
92
+ ...,
93
+ "--action-id",
94
+ help="Action id from ``automation actions list``.",
95
+ ),
96
+ active: bool = typer.Option(
97
+ True, "--active/--no-active", help="Create enabled or disabled."
98
+ ),
99
+ action_repo: str | None = typer.Option(
100
+ None,
101
+ "--action-repo",
102
+ help="Destination pipe id for cross-pipe actions (defaults to --pipe).",
103
+ ),
104
+ extra: str | None = typer.Option(
105
+ None,
106
+ "--extra",
107
+ help="Optional JSON object: extra CreateAutomationInput fields (camelCase).",
108
+ ),
109
+ json_out: bool = typer.Option(
110
+ False,
111
+ "--json",
112
+ "-j",
113
+ help="Print machine-readable JSON to stdout.",
114
+ ),
115
+ ) -> None:
116
+ """Create an automation rule (``create_automation``)."""
117
+ extra_obj = parse_json_object(extra, "--extra")
118
+
119
+ async def factory(client: PipefyClient):
120
+ return await client.create_automation(
121
+ pipe,
122
+ name.strip(),
123
+ trigger_id,
124
+ action_id,
125
+ active=active,
126
+ action_repo_id=action_repo,
127
+ extra_input=extra_obj,
128
+ )
129
+
130
+ run_cli_command(ctx, json_out, factory)
131
+
132
+
133
+ @automation_app.command("update", context_settings=ID_POSITIONAL_CONTEXT_SETTINGS)
134
+ def automation_update(
135
+ ctx: typer.Context,
136
+ automation_id: str = resource_id_argument(help="Automation rule id."),
137
+ extra: str = typer.Option(
138
+ ...,
139
+ "--extra",
140
+ help="JSON object: fields to patch (UpdateAutomationInput, camelCase).",
141
+ ),
142
+ json_out: bool = typer.Option(
143
+ False,
144
+ "--json",
145
+ "-j",
146
+ help="Print machine-readable JSON to stdout.",
147
+ ),
148
+ ) -> None:
149
+ """Update an automation (``update_automation``)."""
150
+ extra_obj = parse_json_value(extra, "--extra")
151
+ if not isinstance(extra_obj, dict):
152
+ raise typer.BadParameter("--extra must be a JSON object")
153
+
154
+ async def factory(client: PipefyClient):
155
+ return await client.update_automation(automation_id, extra_input=extra_obj)
156
+
157
+ run_cli_command(ctx, json_out, factory)
158
+
159
+
160
+ @automation_app.command("delete", context_settings=ID_POSITIONAL_CONTEXT_SETTINGS)
161
+ def automation_delete(
162
+ ctx: typer.Context,
163
+ automation_id: str = resource_id_argument(help="Automation rule id."),
164
+ yes: bool = typer.Option(
165
+ False, "--yes", "-y", help="Skip interactive confirmation."
166
+ ),
167
+ json_out: bool = typer.Option(
168
+ False,
169
+ "--json",
170
+ "-j",
171
+ help="Print machine-readable JSON to stdout.",
172
+ ),
173
+ ) -> None:
174
+ """Delete an automation rule (``delete_automation``)."""
175
+ confirm_destructive(
176
+ yes=yes, description=f"automation {automation_id}", verb="delete"
177
+ )
178
+
179
+ async def factory(client: PipefyClient):
180
+ return await client.delete_automation(automation_id)
181
+
182
+ run_cli_command(ctx, json_out, factory)
183
+
184
+
185
+ @automation_app.command("simulate")
186
+ def automation_simulate(
187
+ ctx: typer.Context,
188
+ pipe: str = typer.Option(
189
+ ..., "--pipe", help="Pipe id (event/action repo defaults)."
190
+ ),
191
+ action_id: str = typer.Option(
192
+ ..., "--action-id", help="Simulation action id (e.g. generate_with_ai)."
193
+ ),
194
+ sample_card: str = typer.Option(
195
+ ..., "--sample-card", help="Card id for the dry-run."
196
+ ),
197
+ event_id: str | None = typer.Option(
198
+ None, "--event-id", help="Optional trigger event id."
199
+ ),
200
+ event_params: str | None = typer.Option(
201
+ None, "--event-params", help="Optional JSON object."
202
+ ),
203
+ action_params: str | None = typer.Option(
204
+ None, "--action-params", help="Optional JSON object."
205
+ ),
206
+ condition: str | None = typer.Option(
207
+ None, "--condition", help="Optional JSON object."
208
+ ),
209
+ name: str | None = typer.Option(None, "--name", help="Optional simulation name."),
210
+ extra: str | None = typer.Option(
211
+ None,
212
+ "--extra",
213
+ help="Optional JSON object merged into simulation input.",
214
+ ),
215
+ json_out: bool = typer.Option(
216
+ False,
217
+ "--json",
218
+ "-j",
219
+ help="Print machine-readable JSON to stdout.",
220
+ ),
221
+ ) -> None:
222
+ """Dry-run an automation against a card (``simulate_automation``)."""
223
+ ep = parse_json_object(event_params, "--event-params")
224
+ ap = parse_json_object(action_params, "--action-params")
225
+ cond = parse_json_object(condition, "--condition")
226
+ ex = parse_json_object(extra, "--extra")
227
+
228
+ async def factory(client: PipefyClient):
229
+ return await client.simulate_automation(
230
+ pipe_id=pipe,
231
+ action_id=action_id,
232
+ sample_card_id=sample_card,
233
+ event_id=event_id,
234
+ event_params=ep,
235
+ action_params=ap,
236
+ condition=cond,
237
+ name=name,
238
+ extra_input=ex,
239
+ )
240
+
241
+ run_cli_command(ctx, json_out, factory)
242
+
243
+
244
+ @send_task_app.command("create")
245
+ def automation_send_task_create(
246
+ ctx: typer.Context,
247
+ pipe: str = typer.Option(..., "--pipe", help="Pipe id."),
248
+ name: str = typer.Option(..., "--name", "-n", help="Rule name."),
249
+ event_id: str = typer.Option(..., "--event-id", help="Trigger event id."),
250
+ task_title: str = typer.Option(..., "--task-title", help="Task title."),
251
+ recipients: str = typer.Option(
252
+ ...,
253
+ "--recipients",
254
+ help="Recipient emails (comma-separated).",
255
+ ),
256
+ active: bool = typer.Option(
257
+ True, "--active/--no-active", help="Create enabled or disabled."
258
+ ),
259
+ event_params: str | None = typer.Option(
260
+ None, "--event-params", help="Optional JSON object."
261
+ ),
262
+ condition: str | None = typer.Option(
263
+ None, "--condition", help="Optional JSON object."
264
+ ),
265
+ json_out: bool = typer.Option(
266
+ False,
267
+ "--json",
268
+ "-j",
269
+ help="Print machine-readable JSON to stdout.",
270
+ ),
271
+ ) -> None:
272
+ """Create a send-a-task automation (``create_send_task_automation``)."""
273
+ ep = parse_json_object(event_params, "--event-params")
274
+ cond = parse_json_object(condition, "--condition")
275
+ try:
276
+ validated = CreateSendTaskAutomationInput(
277
+ pipe_id=pipe,
278
+ name=name,
279
+ event_id=event_id,
280
+ task_title=task_title,
281
+ recipients=recipients,
282
+ event_params=ep,
283
+ condition=cond,
284
+ )
285
+ except ValidationError as exc:
286
+ raise typer.BadParameter(str(exc)) from exc
287
+
288
+ async def factory(client: PipefyClient):
289
+ return await client.create_send_task_automation(
290
+ validated.pipe_id,
291
+ validated.name,
292
+ validated.event_id,
293
+ validated.task_title,
294
+ validated.recipients,
295
+ active=active,
296
+ event_params=validated.event_params,
297
+ condition=validated.condition,
298
+ )
299
+
300
+ run_cli_command(ctx, json_out, factory)
301
+
302
+
303
+ @automation_app.command("logs")
304
+ def automation_logs(
305
+ ctx: typer.Context,
306
+ automation: str | None = typer.Option(
307
+ None,
308
+ "--automation",
309
+ help="Automation id (use this or --repo, not both).",
310
+ ),
311
+ repo: str | None = typer.Option(
312
+ None,
313
+ "--repo",
314
+ help="Pipe id: list logs for all automations in the repo (``get_automation_logs_by_repo``).",
315
+ ),
316
+ first: int = typer.Option(30, "--first", help="Page size."),
317
+ after: str | None = typer.Option(None, "--after", help="Pagination cursor."),
318
+ status: str | None = typer.Option(None, "--status", help="Log status filter."),
319
+ search: str | None = typer.Option(None, "--search", help="Free-text search."),
320
+ json_out: bool = typer.Option(
321
+ False,
322
+ "--json",
323
+ "-j",
324
+ help="Print machine-readable JSON to stdout.",
325
+ ),
326
+ ) -> None:
327
+ """List automation execution logs (``get_automation_logs`` or ``get_automation_logs_by_repo``)."""
328
+ if (automation is None) == (repo is None):
329
+ raise typer.BadParameter("Provide exactly one of --automation or --repo.")
330
+
331
+ async def factory(client: PipefyClient):
332
+ if automation is not None:
333
+ return await client.get_automation_logs(
334
+ automation,
335
+ first=first,
336
+ after=after,
337
+ status=status,
338
+ search_term=search,
339
+ )
340
+ return await client.get_automation_logs_by_repo(
341
+ repo or "",
342
+ first=first,
343
+ after=after,
344
+ status=status,
345
+ search_term=search,
346
+ )
347
+
348
+ run_cli_command(ctx, json_out, factory)
349
+
350
+
351
+ @events_app.command("list")
352
+ def automation_events_list(
353
+ ctx: typer.Context,
354
+ pipe: str = typer.Option(..., "--pipe", help="Pipe id (context for catalog)."),
355
+ json_out: bool = typer.Option(
356
+ False,
357
+ "--json",
358
+ "-j",
359
+ help="Print machine-readable JSON to stdout.",
360
+ ),
361
+ ) -> None:
362
+ """List trigger events (``get_automation_events``)."""
363
+
364
+ async def factory(client: PipefyClient):
365
+ return await client.get_automation_events(pipe)
366
+
367
+ run_cli_command(ctx, json_out, factory)
368
+
369
+
370
+ @automation_app.command("event-attributes")
371
+ def automation_event_attributes(
372
+ ctx: typer.Context,
373
+ json_out: bool = typer.Option(
374
+ False,
375
+ "--json",
376
+ "-j",
377
+ help="Print machine-readable JSON to stdout.",
378
+ ),
379
+ ) -> None:
380
+ """List official event-attribute tokens (``get_automation_event_attributes``)."""
381
+
382
+ async def factory(client: PipefyClient):
383
+ return await client.get_automation_event_attributes()
384
+
385
+ run_cli_command(ctx, json_out, factory)
386
+
387
+
388
+ @actions_app.command("list")
389
+ def automation_actions_list(
390
+ ctx: typer.Context,
391
+ pipe: str = typer.Option(..., "--pipe", help="Pipe id."),
392
+ json_out: bool = typer.Option(
393
+ False,
394
+ "--json",
395
+ "-j",
396
+ help="Print machine-readable JSON to stdout.",
397
+ ),
398
+ ) -> None:
399
+ """List action types for a pipe (``get_automation_actions``)."""
400
+
401
+ async def factory(client: PipefyClient):
402
+ return await client.get_automation_actions(pipe)
403
+
404
+ run_cli_command(ctx, json_out, factory)
405
+
406
+
407
+ @automation_app.command("usage")
408
+ def automation_usage(
409
+ ctx: typer.Context,
410
+ organization: str = typer.Option(
411
+ ...,
412
+ "--organization",
413
+ "--org",
414
+ help="Organization UUID or numeric id (resolved like MCP).",
415
+ ),
416
+ date_from: str = typer.Option(
417
+ ...,
418
+ "--from",
419
+ help="Range start (ISO8601), maps to filter_date.from.",
420
+ ),
421
+ date_to: str = typer.Option(
422
+ ...,
423
+ "--to",
424
+ help="Range end (ISO8601), maps to filter_date.to.",
425
+ ),
426
+ filters: str | None = typer.Option(
427
+ None, "--filters", help="Optional JSON object (FilterParams)."
428
+ ),
429
+ search: str | None = typer.Option(
430
+ None, "--search", help="Optional free-text search."
431
+ ),
432
+ sort: str | None = typer.Option(
433
+ None, "--sort", help="Optional JSON object (SortCriteria)."
434
+ ),
435
+ json_out: bool = typer.Option(
436
+ False,
437
+ "--json",
438
+ "-j",
439
+ help="Print machine-readable JSON to stdout.",
440
+ ),
441
+ ) -> None:
442
+ """Automation usage for an org in a date range (``get_automations_usage``)."""
443
+ filter_date = {"from": date_from, "to": date_to}
444
+ filters_obj = parse_json_object(filters, "--filters")
445
+ sort_obj = parse_json_object(sort, "--sort")
446
+
447
+ async def factory(client: PipefyClient):
448
+ return await client.get_automations_usage(
449
+ organization,
450
+ filter_date,
451
+ filters=filters_obj,
452
+ search=search,
453
+ sort=sort_obj,
454
+ )
455
+
456
+ run_cli_command(ctx, json_out, factory)
457
+
458
+
459
+ @export_app.command("jobs")
460
+ def automation_export_jobs(
461
+ ctx: typer.Context,
462
+ organization: str = typer.Option(
463
+ ...,
464
+ "--organization",
465
+ "--org",
466
+ help="Organization id.",
467
+ ),
468
+ period: str = typer.Option(
469
+ ...,
470
+ "--period",
471
+ help="Period filter: current_month, last_month, or last_3_months.",
472
+ ),
473
+ json_out: bool = typer.Option(
474
+ False,
475
+ "--json",
476
+ "-j",
477
+ help="Print machine-readable JSON to stdout.",
478
+ ),
479
+ ) -> None:
480
+ """Start automation jobs export (``export_automation_jobs``)."""
481
+
482
+ async def factory(client: PipefyClient):
483
+ return await client.export_automation_jobs(organization, period)
484
+
485
+ run_cli_command(ctx, json_out, factory)
486
+
487
+
488
+ @export_app.command("status", context_settings=ID_POSITIONAL_CONTEXT_SETTINGS)
489
+ def automation_export_status(
490
+ ctx: typer.Context,
491
+ export_id: str = resource_id_argument(help="Export id from ``export jobs``."),
492
+ json_out: bool = typer.Option(
493
+ False,
494
+ "--json",
495
+ "-j",
496
+ help="Print machine-readable JSON to stdout.",
497
+ ),
498
+ ) -> None:
499
+ """Poll export status / signed URL (``get_automation_jobs_export``)."""
500
+
501
+ async def factory(client: PipefyClient):
502
+ return await client.get_automation_jobs_export(export_id)
503
+
504
+ run_cli_command(ctx, json_out, factory)
505
+
506
+
507
+ @export_app.command("csv", context_settings=ID_POSITIONAL_CONTEXT_SETTINGS)
508
+ def automation_export_csv(
509
+ ctx: typer.Context,
510
+ export_id: str = resource_id_argument(help="Finished export id."),
511
+ json_out: bool = typer.Option(
512
+ False,
513
+ "--json",
514
+ "-j",
515
+ help="Print machine-readable JSON to stdout.",
516
+ ),
517
+ ) -> None:
518
+ """Download finished export as CSV text (``get_automation_jobs_export_csv``)."""
519
+
520
+ async def factory(client: PipefyClient):
521
+ return await client.get_automation_jobs_export_csv(export_id)
522
+
523
+ run_cli_command(ctx, json_out, factory)
524
+
525
+
526
+ automation_app.add_typer(send_task_app, name="send-task")
527
+ automation_app.add_typer(export_app, name="export")
528
+ automation_app.add_typer(events_app, name="events")
529
+ automation_app.add_typer(actions_app, name="actions")