tetra-cli 0.2.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 (62) hide show
  1. tetra_cli/__init__.py +6 -0
  2. tetra_cli/api_client/__init__.py +10 -0
  3. tetra_cli/api_client/client.py +173 -0
  4. tetra_cli/api_client/config.py +125 -0
  5. tetra_cli/api_client/operations/__init__.py +9 -0
  6. tetra_cli/api_client/operations/accounts.py +303 -0
  7. tetra_cli/api_client/operations/ai.py +278 -0
  8. tetra_cli/api_client/operations/analysis.py +190 -0
  9. tetra_cli/api_client/operations/api_keys.py +145 -0
  10. tetra_cli/api_client/operations/archive.py +114 -0
  11. tetra_cli/api_client/operations/awards.py +123 -0
  12. tetra_cli/api_client/operations/capacity.py +84 -0
  13. tetra_cli/api_client/operations/conversations.py +447 -0
  14. tetra_cli/api_client/operations/conversations_2.py +262 -0
  15. tetra_cli/api_client/operations/cosmetics.py +148 -0
  16. tetra_cli/api_client/operations/dashboard.py +282 -0
  17. tetra_cli/api_client/operations/data.py +250 -0
  18. tetra_cli/api_client/operations/events.py +734 -0
  19. tetra_cli/api_client/operations/gamification.py +470 -0
  20. tetra_cli/api_client/operations/goals.py +1144 -0
  21. tetra_cli/api_client/operations/groups.py +647 -0
  22. tetra_cli/api_client/operations/issues.py +198 -0
  23. tetra_cli/api_client/operations/offset.py +61 -0
  24. tetra_cli/api_client/operations/onboarding.py +284 -0
  25. tetra_cli/api_client/operations/outcome_schemas.py +292 -0
  26. tetra_cli/api_client/operations/peer_connections.py +243 -0
  27. tetra_cli/api_client/operations/plaid.py +329 -0
  28. tetra_cli/api_client/operations/reminders.py +273 -0
  29. tetra_cli/api_client/operations/scratches.py +280 -0
  30. tetra_cli/api_client/operations/skill_trees.py +160 -0
  31. tetra_cli/api_client/operations/social_2.py +560 -0
  32. tetra_cli/api_client/operations/social_3.py +618 -0
  33. tetra_cli/api_client/operations/social_4.py +527 -0
  34. tetra_cli/api_client/operations/strava.py +215 -0
  35. tetra_cli/api_client/operations/stripe.py +113 -0
  36. tetra_cli/api_client/operations/tags.py +488 -0
  37. tetra_cli/api_client/operations/values.py +867 -0
  38. tetra_cli/api_client/operations/values_2.py +584 -0
  39. tetra_cli/api_client/operations/watch.py +105 -0
  40. tetra_cli/api_client/operations/webhooks.py +50 -0
  41. tetra_cli/api_client/operations/xp.py +27 -0
  42. tetra_cli/cli/__init__.py +5 -0
  43. tetra_cli/cli/__main__.py +5 -0
  44. tetra_cli/cli/app.py +86 -0
  45. tetra_cli/cli/commands/__init__.py +1 -0
  46. tetra_cli/cli/commands/auth.py +201 -0
  47. tetra_cli/cli/commands/guide.py +8 -0
  48. tetra_cli/cli/commands/messages.py +161 -0
  49. tetra_cli/cli/commands/skill.py +71 -0
  50. tetra_cli/cli/context.py +13 -0
  51. tetra_cli/cli/generate.py +282 -0
  52. tetra_cli/cli/output.py +58 -0
  53. tetra_cli/mcp_gen.py +137 -0
  54. tetra_cli/ontology.py +70 -0
  55. tetra_cli/registry.py +118 -0
  56. tetra_cli/skill/SKILL.md +69 -0
  57. tetra_cli/skill/__init__.py +1 -0
  58. tetra_cli-0.2.0.dist-info/METADATA +140 -0
  59. tetra_cli-0.2.0.dist-info/RECORD +62 -0
  60. tetra_cli-0.2.0.dist-info/WHEEL +5 -0
  61. tetra_cli-0.2.0.dist-info/entry_points.txt +2 -0
  62. tetra_cli-0.2.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,114 @@
1
+ """Pure async operations for the archive API.
2
+
3
+ The archive surface lets an agent inspect and recover entities (values,
4
+ goals, events) that were soft-deleted. Listing and inspecting are reads;
5
+ restore recreates the entity from its archived snapshot, while permanent
6
+ delete removes the archived row for good (irreversible).
7
+ """
8
+ from typing import Any
9
+
10
+ from tetra_cli.api_client import TetraClient
11
+ from tetra_cli.registry import arg, operation, opt
12
+
13
+
14
+ @operation(
15
+ cli="archive list",
16
+ summary="List archived (soft-deleted) entities, newest first.",
17
+ covers=[("GET", "/api/v1/archive/")],
18
+ params={
19
+ "entity_type": opt(
20
+ "--entity-type",
21
+ choices=["value", "goal", "event"],
22
+ help="Filter by entity type (value | goal | event).",
23
+ ),
24
+ },
25
+ )
26
+ async def list_archived(
27
+ client: TetraClient,
28
+ *,
29
+ entity_type: str | None = None,
30
+ ) -> list[dict[str, Any]]:
31
+ """List all archived entities for the current user.
32
+
33
+ Optionally filter by entity type. Results come back sorted by deletion
34
+ date, most recent first.
35
+
36
+ Args:
37
+ client: Authenticated TetraClient
38
+ entity_type: Optional filter — one of 'value', 'goal', or 'event'.
39
+ When None, all archived entities are returned.
40
+
41
+ Returns:
42
+ List of archived-entity dicts (uid, original_uid, entity_type,
43
+ entity_name, deleted_at, deleted_reason, cascade_from_uid).
44
+ """
45
+ params: dict[str, Any] = {}
46
+ if entity_type is not None:
47
+ params["entity_type"] = entity_type
48
+ return await client.get("/api/v1/archive/", params=params or None)
49
+
50
+
51
+ @operation(
52
+ cli="archive get",
53
+ summary="Get a single archived entity by its archive UID.",
54
+ covers=[("GET", "/api/v1/archive/{uid}")],
55
+ params={"uid": arg(help="Archive entry UID")},
56
+ )
57
+ async def get_archived(client: TetraClient, uid: str) -> dict[str, Any]:
58
+ """Get a single archived entity by UID.
59
+
60
+ Args:
61
+ client: Authenticated TetraClient
62
+ uid: The archive entry's UID (not the original entity UID).
63
+
64
+ Returns:
65
+ Archived-entity dict.
66
+ """
67
+ return await client.get(f"/api/v1/archive/{uid}")
68
+
69
+
70
+ @operation(
71
+ cli="archive restore",
72
+ summary="Restore an archived entity, recreating it with its original data.",
73
+ covers=[("POST", "/api/v1/archive/{uid}/restore")],
74
+ params={"uid": arg(help="Archive entry UID to restore")},
75
+ )
76
+ async def restore_archived(client: TetraClient, uid: str) -> dict[str, Any]:
77
+ """Restore an archived entity.
78
+
79
+ The entity is recreated from its archived snapshot. Restoration fails
80
+ (the API returns an error) if an active entity with the same name
81
+ already exists, or if restoring a goal/value would exceed the account's
82
+ active-entity capacity.
83
+
84
+ Args:
85
+ client: Authenticated TetraClient
86
+ uid: The archive entry's UID to restore.
87
+
88
+ Returns:
89
+ Restore result dict with 'restored' (bool) and the recreated
90
+ entity 'uid' on success.
91
+ """
92
+ return await client.post(f"/api/v1/archive/{uid}/restore")
93
+
94
+
95
+ @operation(
96
+ cli="archive delete",
97
+ summary="Permanently delete an archived entity (irreversible).",
98
+ covers=[("DELETE", "/api/v1/archive/{uid}")],
99
+ params={"uid": arg(help="Archive entry UID to permanently delete")},
100
+ )
101
+ async def delete_archived(client: TetraClient, uid: str) -> dict[str, Any]:
102
+ """Permanently delete an archived entity.
103
+
104
+ This action cannot be undone — the archived row is removed entirely and
105
+ the entity can no longer be restored.
106
+
107
+ Args:
108
+ client: Authenticated TetraClient
109
+ uid: The archive entry's UID to permanently delete.
110
+
111
+ Returns:
112
+ Deletion confirmation dict ({'deleted': True} on 204).
113
+ """
114
+ return await client.delete(f"/api/v1/archive/{uid}")
@@ -0,0 +1,123 @@
1
+ """Pure async operations for the awards API.
2
+
3
+ Awards are the gamification catalog: definitions describe possible
4
+ achievements, progress tracks a user toward each one, evaluation scans data to
5
+ grant missing awards, and seeding installs the predefined definitions. These
6
+ ops mirror the backend ``/api/v1/awards`` routes one-to-one.
7
+ """
8
+ from typing import Any
9
+
10
+ from tetra_cli.api_client import TetraClient
11
+ from tetra_cli.registry import arg, operation, opt
12
+
13
+
14
+ @operation(
15
+ cli="awards definitions",
16
+ summary="List all award definitions in the catalog.",
17
+ covers=[("GET", "/api/v1/awards/definitions")],
18
+ )
19
+ async def list_award_definitions(client: TetraClient) -> dict[str, Any]:
20
+ """List the catalog of all possible awards with criteria and rewards.
21
+
22
+ Args:
23
+ client: Authenticated TetraClient
24
+
25
+ Returns:
26
+ Dict with a 'definitions' list.
27
+ """
28
+ return await client.get("/api/v1/awards/definitions")
29
+
30
+
31
+ @operation(
32
+ cli="awards progress",
33
+ summary="Show progress toward all awards.",
34
+ covers=[("GET", "/api/v1/awards/progress")],
35
+ )
36
+ async def get_award_progress(client: TetraClient) -> dict[str, Any]:
37
+ """Get progress (level, triggers, credits) toward every award.
38
+
39
+ Args:
40
+ client: Authenticated TetraClient
41
+
42
+ Returns:
43
+ Dict with an 'awards' list and a 'summary'.
44
+ """
45
+ return await client.get("/api/v1/awards/progress")
46
+
47
+
48
+ @operation(
49
+ cli="awards progress-for",
50
+ summary="Show progress toward a single award.",
51
+ covers=[("GET", "/api/v1/awards/progress/{award_id}")],
52
+ params={"award_id": arg(help="Award definition id")},
53
+ )
54
+ async def get_award_progress_for(
55
+ client: TetraClient, award_id: str
56
+ ) -> dict[str, Any]:
57
+ """Get progress toward one specific award.
58
+
59
+ Args:
60
+ client: Authenticated TetraClient
61
+ award_id: The award definition id to look up.
62
+
63
+ Returns:
64
+ Award progress dict for the given award.
65
+ """
66
+ return await client.get(f"/api/v1/awards/progress/{award_id}")
67
+
68
+
69
+ @operation(
70
+ cli="awards evaluate",
71
+ summary="Scan data and grant any missing awards.",
72
+ covers=[("POST", "/api/v1/awards/evaluate")],
73
+ params={
74
+ "start_date": opt("--start-date", help="Only consider data from this date (YYYY-MM-DD)"),
75
+ "end_date": opt("--end-date", help="Only consider data until this date (YYYY-MM-DD)"),
76
+ },
77
+ )
78
+ async def evaluate_awards(
79
+ client: TetraClient,
80
+ *,
81
+ dry_run: bool = False,
82
+ start_date: str | None = None,
83
+ end_date: str | None = None,
84
+ as_regular: bool = False,
85
+ ) -> dict[str, Any]:
86
+ """Evaluate all data and grant awards that should have been earned.
87
+
88
+ Useful after a data import. ``dry_run`` calculates without granting.
89
+ ``as_regular`` is superuser-only and grants full (non-retroactive) credits.
90
+
91
+ Args:
92
+ client: Authenticated TetraClient
93
+ dry_run: If True, calculate but do not grant awards.
94
+ start_date: Optional lower bound date filter (YYYY-MM-DD).
95
+ end_date: Optional upper bound date filter (YYYY-MM-DD).
96
+ as_regular: Superuser only — grant as regular awards with full credits.
97
+
98
+ Returns:
99
+ Dict with 'results', 'total_credits', 'total_xp', and 'dry_run'.
100
+ """
101
+ body: dict[str, Any] = {"dry_run": dry_run, "as_regular": as_regular}
102
+ if start_date is not None:
103
+ body["start_date"] = start_date
104
+ if end_date is not None:
105
+ body["end_date"] = end_date
106
+ return await client.post("/api/v1/awards/evaluate", json=body)
107
+
108
+
109
+ @operation(
110
+ cli="awards seed",
111
+ summary="Seed predefined award definitions into the database.",
112
+ covers=[("POST", "/api/v1/awards/seed")],
113
+ )
114
+ async def seed_award_definitions(client: TetraClient) -> dict[str, Any]:
115
+ """Create any predefined award definitions that don't already exist.
116
+
117
+ Args:
118
+ client: Authenticated TetraClient
119
+
120
+ Returns:
121
+ Dict with 'created' count and a 'message'.
122
+ """
123
+ return await client.post("/api/v1/awards/seed")
@@ -0,0 +1,84 @@
1
+ """Pure async operations for the capacity API.
2
+
3
+ Capacity tracks how many *active* entities the caller (or a group) may hold.
4
+ Personal scope exposes the effective cap, current usage, credit-purchased
5
+ slots, and the escalating cost of the next slot; group scope exposes the
6
+ shared-pool cap. Slots are bought with credits via ``purchase-slot``.
7
+
8
+ These ops are the single source of truth for both the CLI and MCP surfaces —
9
+ each is a thin async wrapper over :class:`TetraClient`.
10
+ """
11
+ from typing import Any
12
+
13
+ from tetra_cli.api_client import TetraClient
14
+ from tetra_cli.registry import arg, operation
15
+
16
+
17
+ @operation(
18
+ cli="capacity status",
19
+ summary="Show the caller's active/archive capacity usage and next-slot cost.",
20
+ covers=[("GET", "/api/v1/capacity/")],
21
+ )
22
+ async def get_capacity(client: TetraClient) -> dict[str, Any]:
23
+ """Show active-entity capacity status for the caller's personal scope.
24
+
25
+ Args:
26
+ client: Authenticated TetraClient
27
+
28
+ Returns:
29
+ Dict with ``effective_cap`` (null == unlimited for Pro),
30
+ ``active_count``, ``archive_cap``, ``archive_count``, ``is_pro``,
31
+ ``at_capacity``, ``purchased_slots`` (credit-bought cap slots), and
32
+ ``next_slot_cost`` (credit price of the next slot; null for Pro/comp).
33
+ """
34
+ return await client.get("/api/v1/capacity/")
35
+
36
+
37
+ @operation(
38
+ cli="capacity group",
39
+ summary="Show shared-pool capacity for a group the caller can see.",
40
+ covers=[("GET", "/api/v1/capacity/group/{group_uid}")],
41
+ params={"group_uid": arg(help="Group UID")},
42
+ )
43
+ async def get_group_capacity(
44
+ client: TetraClient, group_uid: str,
45
+ ) -> dict[str, Any]:
46
+ """Show shared-pool capacity for a group the caller can see.
47
+
48
+ Non-members of a private group get a 404 (surfaced as a ``Not found``
49
+ error) so the endpoint never discloses the group's existence.
50
+
51
+ Args:
52
+ client: Authenticated TetraClient
53
+ group_uid: Group UID
54
+
55
+ Returns:
56
+ Dict with the group's ``effective_cap`` (null == unlimited),
57
+ ``active_count``, ``is_unlimited``, and ``at_capacity``.
58
+ """
59
+ return await client.get(f"/api/v1/capacity/group/{group_uid}")
60
+
61
+
62
+ @operation(
63
+ cli="capacity purchase-slot",
64
+ summary="Buy the next credit-purchased active capacity slot.",
65
+ covers=[("POST", "/api/v1/capacity/purchase-slot")],
66
+ )
67
+ async def purchase_capacity_slot(client: TetraClient) -> dict[str, Any]:
68
+ """Buy the next credit-purchased active slot (escalating credit cost).
69
+
70
+ The endpoint takes no body — the next slot's cost and the caller's
71
+ eligibility are derived server-side from the account state.
72
+
73
+ Args:
74
+ client: Authenticated TetraClient
75
+
76
+ Returns:
77
+ Updated capacity dict reflecting the new ``purchased_slots`` and
78
+ ``next_slot_cost``.
79
+
80
+ Raises:
81
+ TetraClientError: 400 ``insufficient_credits`` if the balance is too
82
+ low; 400 ``unlimited_capacity`` for Pro/comped accounts.
83
+ """
84
+ return await client.post("/api/v1/capacity/purchase-slot")