codemie-sdk-python 0.1.691__tar.gz → 0.1.693__tar.gz

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 (82) hide show
  1. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/PKG-INFO +1 -1
  2. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/pyproject.toml +1 -1
  3. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/__init__.py +14 -0
  4. codemie_sdk_python-0.1.693/src/codemie_sdk/models/analytics.py +338 -0
  5. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/analytics.py +97 -0
  6. codemie_sdk_python-0.1.691/src/codemie_sdk/models/analytics.py +0 -148
  7. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/README.md +0 -0
  8. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/auth/__init__.py +0 -0
  9. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/auth/credentials.py +0 -0
  10. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/builders/__init__.py +0 -0
  11. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/builders/workflow/__init__.py +0 -0
  12. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/builders/workflow/builder.py +0 -0
  13. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/builders/workflow/definition.py +0 -0
  14. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/builders/workflow/publish.py +0 -0
  15. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/client/__init__.py +0 -0
  16. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/client/client.py +0 -0
  17. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/exceptions.py +0 -0
  18. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/__init__.py +0 -0
  19. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/a2a.py +0 -0
  20. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/activity_event.py +0 -0
  21. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/admin.py +0 -0
  22. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/assistant.py +0 -0
  23. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/categories.py +0 -0
  24. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/common.py +0 -0
  25. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/conversation.py +0 -0
  26. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/cost_center.py +0 -0
  27. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/datasource.py +0 -0
  28. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/errors.py +0 -0
  29. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/file_operation.py +0 -0
  30. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/guardrails.py +0 -0
  31. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/integration.py +0 -0
  32. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/llm.py +0 -0
  33. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/mcp_config.py +0 -0
  34. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/mermaid.py +0 -0
  35. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/project.py +0 -0
  36. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/skill.py +0 -0
  37. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/task.py +0 -0
  38. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/user.py +0 -0
  39. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/vendor_assistant.py +0 -0
  40. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/vendor_guardrail.py +0 -0
  41. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/vendor_knowledgebase.py +0 -0
  42. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/vendor_runtime.py +0 -0
  43. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/vendor_workflow.py +0 -0
  44. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/workflow.py +0 -0
  45. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/workflow_execution_payload.py +0 -0
  46. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/workflow_state.py +0 -0
  47. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/workflow_thoughts.py +0 -0
  48. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/workflow_transition.py +0 -0
  49. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/models/workspace.py +0 -0
  50. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/a2a.py +0 -0
  51. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/activity_event.py +0 -0
  52. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/admin.py +0 -0
  53. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/assistant.py +0 -0
  54. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/categories.py +0 -0
  55. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/codemie_guardrails.py +0 -0
  56. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/conversation.py +0 -0
  57. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/cost_center.py +0 -0
  58. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/customer_config_service.py +0 -0
  59. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/datasource.py +0 -0
  60. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/dynamic_config.py +0 -0
  61. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/files.py +0 -0
  62. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/integration.py +0 -0
  63. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/llm.py +0 -0
  64. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/mcp_configs.py +0 -0
  65. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/mermaid.py +0 -0
  66. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/project.py +0 -0
  67. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/project_budget_groups.py +0 -0
  68. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/skill.py +0 -0
  69. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/task.py +0 -0
  70. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/user.py +0 -0
  71. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/vendor_assistant.py +0 -0
  72. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/vendor_guardrail.py +0 -0
  73. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/vendor_knowledgebase.py +0 -0
  74. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/vendor_runtime.py +0 -0
  75. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/vendor_workflow.py +0 -0
  76. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/webhook.py +0 -0
  77. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/workflow.py +0 -0
  78. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/workflow_execution.py +0 -0
  79. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/workflow_execution_state.py +0 -0
  80. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/services/workspace.py +0 -0
  81. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/utils/__init__.py +0 -0
  82. {codemie_sdk_python-0.1.691 → codemie_sdk_python-0.1.693}/src/codemie_sdk/utils/http.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codemie-sdk-python
3
- Version: 0.1.691
3
+ Version: 0.1.693
4
4
  Summary: CodeMie SDK for Python
5
5
  Author: Vadym Vlasenko
6
6
  Author-email: vadym_vlasenko@epam.com
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "codemie-sdk-python"
3
- version = "0.1.691"
3
+ version = "0.1.693"
4
4
  description = "CodeMie SDK for Python"
5
5
  authors = [
6
6
  "Vadym Vlasenko <vadym_vlasenko@epam.com>",
@@ -93,6 +93,13 @@ from .models.analytics import (
93
93
  UsersListResponse,
94
94
  AnalyticsQueryParams,
95
95
  PaginatedAnalyticsQueryParams,
96
+ CliAnalyticsQueryParams,
97
+ CliAnalyticsSessionsQueryParams,
98
+ CliAnalyticsCostResponse,
99
+ CliAnalyticsUsersResponse,
100
+ CliAnalyticsSessionsResponse,
101
+ CliAnalyticsSessionDetailResponse,
102
+ CliAnalyticsRepositoriesResponse,
96
103
  )
97
104
  from .services.customer_config_service import CustomerConfigService
98
105
  from .services.vendor_assistant import VendorAssistantService
@@ -253,6 +260,13 @@ __all__ = [
253
260
  "UsersListResponse",
254
261
  "AnalyticsQueryParams",
255
262
  "PaginatedAnalyticsQueryParams",
263
+ "CliAnalyticsQueryParams",
264
+ "CliAnalyticsSessionsQueryParams",
265
+ "CliAnalyticsCostResponse",
266
+ "CliAnalyticsUsersResponse",
267
+ "CliAnalyticsSessionsResponse",
268
+ "CliAnalyticsSessionDetailResponse",
269
+ "CliAnalyticsRepositoriesResponse",
256
270
  "AnalyticsService",
257
271
  "CustomerConfigService",
258
272
  "MermaidDiagramRequest",
@@ -0,0 +1,338 @@
1
+ """Models for analytics-related data structures."""
2
+
3
+ from typing import Any
4
+
5
+ from pydantic import BaseModel, ConfigDict, Field
6
+
7
+
8
+ class ResponseMetadata(BaseModel):
9
+ """Metadata for analytics responses."""
10
+
11
+ model_config = ConfigDict(extra="ignore")
12
+
13
+ timestamp: str = Field(description="ISO 8601 timestamp when response generated")
14
+ data_as_of: str = Field(description="ISO 8601 timestamp of data freshness")
15
+ filters_applied: dict[str, Any] = Field(description="Applied filters")
16
+ execution_time_ms: float = Field(description="Query execution time in milliseconds")
17
+
18
+
19
+ class PaginationMetadata(BaseModel):
20
+ """Pagination metadata for tabular responses."""
21
+
22
+ model_config = ConfigDict(extra="ignore")
23
+
24
+ page: int = Field(description="Zero-indexed page number")
25
+ per_page: int = Field(description="Items per page")
26
+ total_count: int = Field(description="Total items available")
27
+ has_more: bool = Field(description="Whether more pages exist")
28
+
29
+
30
+ class ColumnDefinition(BaseModel):
31
+ """Column metadata for tabular data."""
32
+
33
+ model_config = ConfigDict(extra="ignore")
34
+
35
+ id: str = Field(description="Column identifier")
36
+ label: str = Field(description="Human-readable label")
37
+ type: str = Field(description='Data type: "string", "number", "date"')
38
+ format: str | None = Field(
39
+ None, description='Format hint: "currency", "percentage", "timestamp"'
40
+ )
41
+ description: str | None = Field(None, description="Column description")
42
+
43
+
44
+ class Metric(BaseModel):
45
+ """Individual metric in summary responses."""
46
+
47
+ model_config = ConfigDict(extra="ignore")
48
+
49
+ id: str = Field(description="Metric identifier")
50
+ label: str = Field(description="Human-readable label")
51
+ type: str = Field(description="Data type")
52
+ value: Any = Field(description="Metric value (int, float, str, etc.)")
53
+ format: str | None = Field(
54
+ None, description='Format hint: "currency", "percentage", "number"'
55
+ )
56
+ description: str | None = Field(None, description="Metric description")
57
+
58
+
59
+ class SummariesData(BaseModel):
60
+ """Container for summary metrics."""
61
+
62
+ model_config = ConfigDict(extra="ignore")
63
+
64
+ metrics: list[Metric] = Field(description="Array of metrics")
65
+
66
+
67
+ class TabularData(BaseModel):
68
+ """Container for tabular data with dynamic columns."""
69
+
70
+ model_config = ConfigDict(extra="ignore")
71
+
72
+ columns: list[ColumnDefinition] = Field(description="Column definitions")
73
+ rows: list[dict[str, Any]] = Field(description="Data rows (dict per row)")
74
+ totals: dict[str, Any] | None = Field(None, description="Optional totals row")
75
+
76
+
77
+ class UserListItem(BaseModel):
78
+ """Individual user item."""
79
+
80
+ model_config = ConfigDict(extra="ignore")
81
+
82
+ id: str = Field(description="User ID")
83
+ name: str = Field(description="User name")
84
+
85
+
86
+ class UsersListData(BaseModel):
87
+ """Container for users list."""
88
+
89
+ model_config = ConfigDict(extra="ignore")
90
+
91
+ users: list[UserListItem] = Field(description="List of users")
92
+ total_count: int = Field(description="Total number of users")
93
+
94
+
95
+ class SummariesResponse(BaseModel):
96
+ """Response for summary endpoints (summaries, cli-summary)."""
97
+
98
+ model_config = ConfigDict(extra="ignore")
99
+
100
+ data: SummariesData = Field(description="Summary data")
101
+ metadata: ResponseMetadata = Field(description="Response metadata")
102
+
103
+
104
+ class TabularResponse(BaseModel):
105
+ """Response for tabular endpoints (19 endpoints)."""
106
+
107
+ model_config = ConfigDict(extra="ignore")
108
+
109
+ data: TabularData = Field(description="Tabular data")
110
+ metadata: ResponseMetadata = Field(description="Response metadata")
111
+ pagination: PaginationMetadata | None = Field(
112
+ None, description="Optional pagination metadata"
113
+ )
114
+
115
+
116
+ class UsersListResponse(BaseModel):
117
+ """Response for users list endpoint."""
118
+
119
+ model_config = ConfigDict(extra="ignore")
120
+
121
+ data: UsersListData = Field(description="Users list data")
122
+ metadata: ResponseMetadata = Field(description="Response metadata")
123
+
124
+
125
+ class AnalyticsQueryParams(BaseModel):
126
+ """Query parameters for analytics endpoints."""
127
+
128
+ model_config = ConfigDict(extra="ignore")
129
+
130
+ time_period: str | None = Field(
131
+ None,
132
+ description='Time period: "last_hour", "last_6_hours", "last_24_hours", "last_7_days", "last_30_days", "last_90_days", "last_year"',
133
+ )
134
+ start_date: str | None = Field(
135
+ None, description="ISO 8601 format start date (use with end_date)"
136
+ )
137
+ end_date: str | None = Field(
138
+ None, description="ISO 8601 format end date (use with start_date)"
139
+ )
140
+ users: str | None = Field(None, description="Comma-separated user IDs")
141
+ projects: str | None = Field(None, description="Comma-separated project names")
142
+
143
+
144
+ class PaginatedAnalyticsQueryParams(AnalyticsQueryParams):
145
+ """Query parameters with pagination."""
146
+
147
+ page: int = Field(0, description="Zero-indexed page number")
148
+ per_page: int = Field(20, description="Items per page")
149
+
150
+
151
+ # ── CLI Analytics: /v1/analytics/cli-analytics/* ─────────────────────────────
152
+
153
+
154
+ class CliAnalyticsQueryParams(AnalyticsQueryParams):
155
+ """Filters shared by the /v1/analytics/cli-analytics/* read endpoints."""
156
+
157
+ repositories: str | None = Field(
158
+ None, description="Comma-separated repository names"
159
+ )
160
+
161
+
162
+ class CliAnalyticsSessionsQueryParams(CliAnalyticsQueryParams):
163
+ """Query parameters of the CLI Analytics session list."""
164
+
165
+ page: int | None = Field(None, description="Zero-indexed page number")
166
+ per_page: int | None = Field(None, description="Items per page")
167
+ is_unattributed: bool | None = Field(
168
+ None, description="Only sessions with no attributed repository"
169
+ )
170
+
171
+
172
+ class CliAnalyticsMetadata(BaseModel):
173
+ """Metadata of CLI Analytics responses."""
174
+
175
+ model_config = ConfigDict(extra="ignore")
176
+
177
+ timestamp: str = Field(description="ISO 8601 timestamp when response generated")
178
+ data_as_of: str = Field(description="ISO 8601 date/datetime of the newest data")
179
+ execution_time_ms: float = Field(description="Query execution time in milliseconds")
180
+
181
+
182
+ class CliAnalyticsCostKpis(BaseModel):
183
+ """Totals of the CLI Analytics cost breakdown."""
184
+
185
+ model_config = ConfigDict(extra="ignore")
186
+
187
+ total_sessions: int
188
+ total_cost_usd: float
189
+ total_tokens: int
190
+ avg_cost_per_session: float
191
+
192
+
193
+ class CliAnalyticsCostByUser(BaseModel):
194
+ """Cost of one user."""
195
+
196
+ model_config = ConfigDict(extra="ignore")
197
+
198
+ developer_name: str
199
+ cost_usd: float
200
+
201
+
202
+ class CliAnalyticsCostByModel(BaseModel):
203
+ """Cost of one model."""
204
+
205
+ model_config = ConfigDict(extra="ignore")
206
+
207
+ model_name: str
208
+ cost_usd: float
209
+
210
+
211
+ class CliAnalyticsCostData(BaseModel):
212
+ """Cost breakdown data."""
213
+
214
+ model_config = ConfigDict(extra="ignore")
215
+
216
+ kpis: CliAnalyticsCostKpis
217
+ cost_by_user: list[CliAnalyticsCostByUser] = Field(default_factory=list)
218
+ cost_by_model: list[CliAnalyticsCostByModel] = Field(default_factory=list)
219
+
220
+
221
+ class CliAnalyticsCostResponse(BaseModel):
222
+ """Response of GET /v1/analytics/cli-analytics/cost."""
223
+
224
+ model_config = ConfigDict(extra="ignore")
225
+
226
+ data: CliAnalyticsCostData
227
+ metadata: CliAnalyticsMetadata
228
+
229
+
230
+ class CliAnalyticsUserRow(BaseModel):
231
+ """One user of the CLI Analytics user leaderboard."""
232
+
233
+ model_config = ConfigDict(extra="ignore")
234
+
235
+ developer_name: str = Field(description="Resolved user email")
236
+ session_count: int
237
+ input_tokens: int
238
+ output_tokens: int
239
+ cache_read_tokens: int
240
+ cache_creation_tokens: int
241
+ cost_usd: float
242
+
243
+
244
+ class CliAnalyticsUsersData(BaseModel):
245
+ """User leaderboard data."""
246
+
247
+ model_config = ConfigDict(extra="ignore")
248
+
249
+ rows: list[CliAnalyticsUserRow]
250
+ avg_session_duration_ms: int | None = None
251
+ total_count: int | None = None
252
+
253
+
254
+ class CliAnalyticsUsersResponse(BaseModel):
255
+ """Response of GET /v1/analytics/cli-analytics/users."""
256
+
257
+ model_config = ConfigDict(extra="ignore")
258
+
259
+ data: CliAnalyticsUsersData
260
+ metadata: CliAnalyticsMetadata
261
+
262
+
263
+ class CliAnalyticsSessionRow(BaseModel):
264
+ """One CLI session."""
265
+
266
+ model_config = ConfigDict(extra="ignore")
267
+
268
+ trace_id: str = Field(description="Session id")
269
+ developer_name: str = Field(description="Resolved user email")
270
+ repository: str | None = Field(None, description="None when unattributed")
271
+ branch: str | None = None
272
+ start_time: str = Field(description="ISO 8601 session start")
273
+ duration_ms: int = Field(description="Session start to its last event")
274
+ model_name: str
275
+ input_tokens: int
276
+ output_tokens: int
277
+ cache_read_tokens: int = 0
278
+ cache_creation_tokens: int = 0
279
+ cost_usd: float
280
+
281
+
282
+ class CliAnalyticsSessionsData(BaseModel):
283
+ """Session list data."""
284
+
285
+ model_config = ConfigDict(extra="ignore")
286
+
287
+ sessions: list[CliAnalyticsSessionRow]
288
+ page: int
289
+ per_page: int
290
+ total: int
291
+
292
+
293
+ class CliAnalyticsSessionsResponse(BaseModel):
294
+ """Response of GET /v1/analytics/cli-analytics/sessions."""
295
+
296
+ model_config = ConfigDict(extra="ignore")
297
+
298
+ data: CliAnalyticsSessionsData
299
+ metadata: CliAnalyticsMetadata
300
+
301
+
302
+ class CliAnalyticsSessionDetailResponse(BaseModel):
303
+ """Response of GET /v1/analytics/cli-analytics/sessions/{trace_id}."""
304
+
305
+ model_config = ConfigDict(extra="ignore")
306
+
307
+ data: CliAnalyticsSessionRow
308
+ metadata: CliAnalyticsMetadata
309
+
310
+
311
+ class CliAnalyticsRepositoryRow(BaseModel):
312
+ """One repository (or repository branch) of the CLI Analytics breakdown."""
313
+
314
+ model_config = ConfigDict(extra="ignore")
315
+
316
+ repository: str | None = Field(None, description="None for unattributed sessions")
317
+ branch: str | None = None
318
+ session_count: int
319
+ cost_usd: float
320
+ project_name: str | None = None
321
+
322
+
323
+ class CliAnalyticsRepositoriesData(BaseModel):
324
+ """Repository breakdown data."""
325
+
326
+ model_config = ConfigDict(extra="ignore")
327
+
328
+ rows: list[CliAnalyticsRepositoryRow]
329
+ pagination: PaginationMetadata
330
+
331
+
332
+ class CliAnalyticsRepositoriesResponse(BaseModel):
333
+ """Response of GET /v1/analytics/cli-analytics/repositories."""
334
+
335
+ model_config = ConfigDict(extra="ignore")
336
+
337
+ data: CliAnalyticsRepositoriesData
338
+ metadata: CliAnalyticsMetadata
@@ -4,6 +4,13 @@ import json
4
4
 
5
5
  from ..models.analytics import (
6
6
  AnalyticsQueryParams,
7
+ CliAnalyticsCostResponse,
8
+ CliAnalyticsQueryParams,
9
+ CliAnalyticsRepositoriesResponse,
10
+ CliAnalyticsSessionDetailResponse,
11
+ CliAnalyticsSessionsQueryParams,
12
+ CliAnalyticsSessionsResponse,
13
+ CliAnalyticsUsersResponse,
7
14
  PaginatedAnalyticsQueryParams,
8
15
  SummariesResponse,
9
16
  TabularResponse,
@@ -581,3 +588,93 @@ class AnalyticsService:
581
588
  params=kwargs if kwargs else None,
582
589
  wrap_response=False,
583
590
  )
591
+
592
+ # ── CLI Analytics: /v1/analytics/cli-analytics/* ─────────────────────────
593
+
594
+ def ingest_cli_analytics_event_hooks(self, events: list[dict]) -> None:
595
+ """POST /v1/analytics/cli-analytics/event-hooks — send CLI hook events.
596
+
597
+ The endpoint takes NDJSON (one event per line); each event is posted as
598
+ its own single-line body.
599
+
600
+ Args:
601
+ events: Hook events, e.g. ``agent.session.start``, ``agent.usage.request``
602
+ """
603
+ for event in events:
604
+ self._api.post(
605
+ "/v1/analytics/cli-analytics/event-hooks",
606
+ dict,
607
+ json_data=event,
608
+ wrap_response=False,
609
+ extra_headers={"Content-Type": "application/x-ndjson"},
610
+ )
611
+
612
+ def ingest_cli_analytics_logs(self, payload: dict) -> None:
613
+ """POST /v1/analytics/cli-analytics/logs — send OTLP logs as JSON.
614
+
615
+ Args:
616
+ payload: An OTLP ``ExportLogsServiceRequest`` in its JSON form
617
+ """
618
+ self._api.post(
619
+ "/v1/analytics/cli-analytics/logs",
620
+ dict,
621
+ json_data=payload,
622
+ wrap_response=False,
623
+ )
624
+
625
+ def get_cli_analytics_cost(
626
+ self, params: CliAnalyticsQueryParams | None = None
627
+ ) -> CliAnalyticsCostResponse:
628
+ """GET /v1/analytics/cli-analytics/cost — session, token and cost totals."""
629
+ return self._api.get(
630
+ "/v1/analytics/cli-analytics/cost",
631
+ CliAnalyticsCostResponse,
632
+ params=params.model_dump(exclude_none=True) if params else {},
633
+ wrap_response=False,
634
+ )
635
+
636
+ def get_cli_analytics_users(
637
+ self, params: CliAnalyticsQueryParams | None = None
638
+ ) -> CliAnalyticsUsersResponse:
639
+ """GET /v1/analytics/cli-analytics/users — per-user sessions and tokens."""
640
+ return self._api.get(
641
+ "/v1/analytics/cli-analytics/users",
642
+ CliAnalyticsUsersResponse,
643
+ params=params.model_dump(exclude_none=True) if params else {},
644
+ wrap_response=False,
645
+ )
646
+
647
+ def get_cli_analytics_sessions(
648
+ self, params: CliAnalyticsSessionsQueryParams | None = None
649
+ ) -> CliAnalyticsSessionsResponse:
650
+ """GET /v1/analytics/cli-analytics/sessions — paginated session list."""
651
+ return self._api.get(
652
+ "/v1/analytics/cli-analytics/sessions",
653
+ CliAnalyticsSessionsResponse,
654
+ params=params.model_dump(exclude_none=True) if params else {},
655
+ wrap_response=False,
656
+ )
657
+
658
+ def get_cli_analytics_session(
659
+ self, trace_id: str
660
+ ) -> CliAnalyticsSessionDetailResponse:
661
+ """GET /v1/analytics/cli-analytics/sessions/{trace_id} — session detail."""
662
+ return self._api.get(
663
+ f"/v1/analytics/cli-analytics/sessions/{trace_id}",
664
+ CliAnalyticsSessionDetailResponse,
665
+ wrap_response=False,
666
+ )
667
+
668
+ def get_cli_analytics_repositories(
669
+ self, params: CliAnalyticsQueryParams | None = None
670
+ ) -> CliAnalyticsRepositoriesResponse:
671
+ """GET /v1/analytics/cli-analytics/repositories — per-repository breakdown.
672
+
673
+ Without pagination parameters the endpoint returns every repository branch.
674
+ """
675
+ return self._api.get(
676
+ "/v1/analytics/cli-analytics/repositories",
677
+ CliAnalyticsRepositoriesResponse,
678
+ params=params.model_dump(exclude_none=True) if params else {},
679
+ wrap_response=False,
680
+ )
@@ -1,148 +0,0 @@
1
- """Models for analytics-related data structures."""
2
-
3
- from typing import Any
4
-
5
- from pydantic import BaseModel, ConfigDict, Field
6
-
7
-
8
- class ResponseMetadata(BaseModel):
9
- """Metadata for analytics responses."""
10
-
11
- model_config = ConfigDict(extra="ignore")
12
-
13
- timestamp: str = Field(description="ISO 8601 timestamp when response generated")
14
- data_as_of: str = Field(description="ISO 8601 timestamp of data freshness")
15
- filters_applied: dict[str, Any] = Field(description="Applied filters")
16
- execution_time_ms: float = Field(description="Query execution time in milliseconds")
17
-
18
-
19
- class PaginationMetadata(BaseModel):
20
- """Pagination metadata for tabular responses."""
21
-
22
- model_config = ConfigDict(extra="ignore")
23
-
24
- page: int = Field(description="Zero-indexed page number")
25
- per_page: int = Field(description="Items per page")
26
- total_count: int = Field(description="Total items available")
27
- has_more: bool = Field(description="Whether more pages exist")
28
-
29
-
30
- class ColumnDefinition(BaseModel):
31
- """Column metadata for tabular data."""
32
-
33
- model_config = ConfigDict(extra="ignore")
34
-
35
- id: str = Field(description="Column identifier")
36
- label: str = Field(description="Human-readable label")
37
- type: str = Field(description='Data type: "string", "number", "date"')
38
- format: str | None = Field(
39
- None, description='Format hint: "currency", "percentage", "timestamp"'
40
- )
41
- description: str | None = Field(None, description="Column description")
42
-
43
-
44
- class Metric(BaseModel):
45
- """Individual metric in summary responses."""
46
-
47
- model_config = ConfigDict(extra="ignore")
48
-
49
- id: str = Field(description="Metric identifier")
50
- label: str = Field(description="Human-readable label")
51
- type: str = Field(description="Data type")
52
- value: Any = Field(description="Metric value (int, float, str, etc.)")
53
- format: str | None = Field(
54
- None, description='Format hint: "currency", "percentage", "number"'
55
- )
56
- description: str | None = Field(None, description="Metric description")
57
-
58
-
59
- class SummariesData(BaseModel):
60
- """Container for summary metrics."""
61
-
62
- model_config = ConfigDict(extra="ignore")
63
-
64
- metrics: list[Metric] = Field(description="Array of metrics")
65
-
66
-
67
- class TabularData(BaseModel):
68
- """Container for tabular data with dynamic columns."""
69
-
70
- model_config = ConfigDict(extra="ignore")
71
-
72
- columns: list[ColumnDefinition] = Field(description="Column definitions")
73
- rows: list[dict[str, Any]] = Field(description="Data rows (dict per row)")
74
- totals: dict[str, Any] | None = Field(None, description="Optional totals row")
75
-
76
-
77
- class UserListItem(BaseModel):
78
- """Individual user item."""
79
-
80
- model_config = ConfigDict(extra="ignore")
81
-
82
- id: str = Field(description="User ID")
83
- name: str = Field(description="User name")
84
-
85
-
86
- class UsersListData(BaseModel):
87
- """Container for users list."""
88
-
89
- model_config = ConfigDict(extra="ignore")
90
-
91
- users: list[UserListItem] = Field(description="List of users")
92
- total_count: int = Field(description="Total number of users")
93
-
94
-
95
- class SummariesResponse(BaseModel):
96
- """Response for summary endpoints (summaries, cli-summary)."""
97
-
98
- model_config = ConfigDict(extra="ignore")
99
-
100
- data: SummariesData = Field(description="Summary data")
101
- metadata: ResponseMetadata = Field(description="Response metadata")
102
-
103
-
104
- class TabularResponse(BaseModel):
105
- """Response for tabular endpoints (19 endpoints)."""
106
-
107
- model_config = ConfigDict(extra="ignore")
108
-
109
- data: TabularData = Field(description="Tabular data")
110
- metadata: ResponseMetadata = Field(description="Response metadata")
111
- pagination: PaginationMetadata | None = Field(
112
- None, description="Optional pagination metadata"
113
- )
114
-
115
-
116
- class UsersListResponse(BaseModel):
117
- """Response for users list endpoint."""
118
-
119
- model_config = ConfigDict(extra="ignore")
120
-
121
- data: UsersListData = Field(description="Users list data")
122
- metadata: ResponseMetadata = Field(description="Response metadata")
123
-
124
-
125
- class AnalyticsQueryParams(BaseModel):
126
- """Query parameters for analytics endpoints."""
127
-
128
- model_config = ConfigDict(extra="ignore")
129
-
130
- time_period: str | None = Field(
131
- None,
132
- description='Time period: "last_hour", "last_6_hours", "last_24_hours", "last_7_days", "last_30_days", "last_90_days", "last_year"',
133
- )
134
- start_date: str | None = Field(
135
- None, description="ISO 8601 format start date (use with end_date)"
136
- )
137
- end_date: str | None = Field(
138
- None, description="ISO 8601 format end date (use with start_date)"
139
- )
140
- users: str | None = Field(None, description="Comma-separated user IDs")
141
- projects: str | None = Field(None, description="Comma-separated project names")
142
-
143
-
144
- class PaginatedAnalyticsQueryParams(AnalyticsQueryParams):
145
- """Query parameters with pagination."""
146
-
147
- page: int = Field(0, description="Zero-indexed page number")
148
- per_page: int = Field(20, description="Items per page")