enprompta 1.0.0__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.

Potentially problematic release.


This version of enprompta might be problematic. Click here for more details.

@@ -0,0 +1,61 @@
1
+ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
+
3
+ # dependencies
4
+ /node_modules
5
+ /.pnp
6
+ .pnp.*
7
+ .yarn/*
8
+ !.yarn/patches
9
+ !.yarn/plugins
10
+ !.yarn/releases
11
+ !.yarn/versions
12
+
13
+ # testing
14
+ /coverage
15
+
16
+ # next.js
17
+ /.next/
18
+ /out/
19
+
20
+ # production
21
+ /build
22
+
23
+ # misc
24
+ .DS_Store
25
+ *.pem
26
+ nul
27
+
28
+ # debug
29
+ npm-debug.log*
30
+ yarn-debug.log*
31
+ yarn-error.log*
32
+ .pnpm-debug.log*
33
+
34
+ # env files (can opt-in for committing if needed)
35
+ .env*
36
+
37
+ # vercel
38
+ .vercel
39
+
40
+ # typescript
41
+ *.tsbuildinfo
42
+ next-env.d.ts
43
+
44
+ /src/generated/prisma
45
+
46
+ .vercel
47
+ .env*.local
48
+
49
+ .vercel
50
+ node_modules/
51
+ dist/
52
+ .next/
53
+ playwright-report/
54
+ test-results/
55
+ # Visual-regression baselines are tracked — they ARE the test contract.
56
+ # Only the captured-actual screenshots from a failed run live in test-results/.
57
+ *.zip
58
+ __pycache__/
59
+ *.pyc
60
+ temp_ext/
61
+ temp_extension/
@@ -0,0 +1,388 @@
1
+ Metadata-Version: 2.4
2
+ Name: enprompta
3
+ Version: 1.0.0
4
+ Summary: Official Python SDK for the Enprompta API
5
+ Project-URL: Homepage, https://enprompta.com
6
+ Project-URL: Documentation, https://enprompta.com/docs/sdk/python
7
+ Project-URL: Repository, https://github.com/igwebupower/enprompta
8
+ Project-URL: Issues, https://github.com/igwebupower/enprompta/issues
9
+ Author-email: Enprompta <support@enprompta.com>
10
+ License-Expression: MIT
11
+ Keywords: ai,api,enprompta,llm,prompts,sdk
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.8
25
+ Requires-Dist: httpx>=0.25.0
26
+ Requires-Dist: pydantic>=2.0.0
27
+ Provides-Extra: dev
28
+ Requires-Dist: mypy>=1.0.0; extra == 'dev'
29
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
30
+ Requires-Dist: pytest-httpx>=0.21.0; extra == 'dev'
31
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
32
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
33
+ Description-Content-Type: text/markdown
34
+
35
+ # enprompta
36
+
37
+ Official Python SDK for the Enprompta API.
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ pip install enprompta
43
+ # or
44
+ poetry add enprompta
45
+ # or
46
+ pipenv install enprompta
47
+ ```
48
+
49
+ ## Requirements
50
+
51
+ - Python 3.8+
52
+ - httpx 0.25+
53
+ - pydantic 2.0+
54
+
55
+ ## Quick Start
56
+
57
+ ```python
58
+ import asyncio
59
+ from enprompta import Enprompta
60
+
61
+ async def main():
62
+ # Initialize with API key
63
+ client = Enprompta(api_key="ep_your_api_key")
64
+
65
+ # List prompts
66
+ prompts = await client.prompts.list()
67
+ for prompt in prompts.data:
68
+ print(prompt.title)
69
+
70
+ # Create a prompt
71
+ prompt = await client.prompts.create(
72
+ title="Email Writer",
73
+ content="Write a professional email about {{topic}}",
74
+ visibility="PRIVATE"
75
+ )
76
+
77
+ # Execute a prompt
78
+ result = await client.prompts.execute(
79
+ prompt.id,
80
+ variables={"topic": "project update"},
81
+ provider="openai",
82
+ model="gpt-4"
83
+ )
84
+
85
+ print(result.output)
86
+
87
+ asyncio.run(main())
88
+ ```
89
+
90
+ ## Authentication
91
+
92
+ ### API Key
93
+
94
+ ```python
95
+ from enprompta import Enprompta
96
+
97
+ client = Enprompta(api_key="ep_your_api_key")
98
+ ```
99
+
100
+ ### OAuth2 Client Credentials
101
+
102
+ ```python
103
+ client = Enprompta(
104
+ client_id="your_client_id",
105
+ client_secret="your_client_secret",
106
+ scopes=["prompts:read", "prompts:write"]
107
+ )
108
+ ```
109
+
110
+ ### Environment Variables
111
+
112
+ ```python
113
+ # Set these environment variables:
114
+ # ENPROMPTA_API_KEY
115
+ # ENPROMPTA_CLIENT_ID
116
+ # ENPROMPTA_CLIENT_SECRET
117
+
118
+ client = Enprompta() # Auto-reads from environment
119
+ ```
120
+
121
+ ## Features
122
+
123
+ ### Prompts
124
+
125
+ ```python
126
+ # List with pagination
127
+ response = await client.prompts.list(limit=20, visibility="PRIVATE")
128
+ for prompt in response.data:
129
+ print(prompt.title)
130
+
131
+ # Auto-pagination
132
+ async for prompt in client.prompts.list_all():
133
+ print(prompt.title)
134
+
135
+ # Create
136
+ prompt = await client.prompts.create(
137
+ title="My Prompt",
138
+ content="Hello {{name}}",
139
+ variables=[{"name": "name", "type": "text", "required": True}]
140
+ )
141
+
142
+ # Get
143
+ prompt = await client.prompts.get("prompt_id")
144
+
145
+ # Update
146
+ await client.prompts.update("prompt_id", title="New Title")
147
+
148
+ # Delete
149
+ await client.prompts.delete("prompt_id")
150
+
151
+ # Execute
152
+ result = await client.prompts.execute(
153
+ "prompt_id",
154
+ variables={"name": "World"},
155
+ provider="openai",
156
+ model="gpt-4"
157
+ )
158
+ ```
159
+
160
+ ### Executions
161
+
162
+ ```python
163
+ # List executions
164
+ response = await client.executions.list(
165
+ prompt_id="prompt_id",
166
+ start_date="2024-01-01"
167
+ )
168
+
169
+ # Get statistics
170
+ stats = await client.executions.get_stats(group_by="day")
171
+ ```
172
+
173
+ ### Teams
174
+
175
+ ```python
176
+ teams = await client.teams.list()
177
+ team = await client.teams.create(name="Engineering")
178
+ await client.teams.update("team_id", name="New Name")
179
+ ```
180
+
181
+ ### Webhooks
182
+
183
+ ```python
184
+ webhook = await client.webhooks.create(
185
+ name="My Webhook",
186
+ url="https://example.com/webhook",
187
+ events=["prompt.created", "execution.completed"]
188
+ )
189
+ ```
190
+
191
+ ## Synchronous Client
192
+
193
+ For non-async code:
194
+
195
+ ```python
196
+ from enprompta import EnpromptaSync
197
+
198
+ client = EnpromptaSync(api_key="ep_your_api_key")
199
+
200
+ # All methods work without await
201
+ prompts = client.prompts.list()
202
+ prompt = client.prompts.create(title="My Prompt", content="Hello")
203
+ ```
204
+
205
+ ## Context Manager
206
+
207
+ ```python
208
+ # Async
209
+ async with Enprompta(api_key="ep_your_api_key") as client:
210
+ prompts = await client.prompts.list()
211
+
212
+ # Sync
213
+ with EnpromptaSync(api_key="ep_your_api_key") as client:
214
+ prompts = client.prompts.list()
215
+ ```
216
+
217
+ ## Error Handling
218
+
219
+ ```python
220
+ from enprompta.exceptions import (
221
+ EnpromptaError,
222
+ AuthenticationError,
223
+ RateLimitError,
224
+ ValidationError,
225
+ NotFoundError
226
+ )
227
+
228
+ try:
229
+ await client.prompts.get("invalid_id")
230
+ except NotFoundError:
231
+ print("Prompt not found")
232
+ except RateLimitError as e:
233
+ print(f"Retry after {e.retry_after}s")
234
+ except EnpromptaError as e:
235
+ print(f"Error {e.code}: {e.message}")
236
+ ```
237
+
238
+ ## LLM Observability & Tracing
239
+
240
+ ### @trace Decorator
241
+
242
+ Automatically trace any LLM function with the `@trace` decorator:
243
+
244
+ ```python
245
+ from enprompta import Enprompta, trace
246
+ import openai
247
+
248
+ client = Enprompta(api_key="ep_your_api_key")
249
+
250
+ @trace(client, provider="openai", model="gpt-4")
251
+ def generate_response(prompt: str) -> str:
252
+ response = openai.chat.completions.create(
253
+ model="gpt-4",
254
+ messages=[{"role": "user", "content": prompt}]
255
+ )
256
+ return response.choices[0].message.content
257
+
258
+ # Traces are automatically recorded with timing, tokens, and cost
259
+ result = generate_response("Explain quantum computing")
260
+ ```
261
+
262
+ ### Async Support
263
+
264
+ ```python
265
+ @trace(client, provider="anthropic", model="claude-3-sonnet", session_id="user-123")
266
+ async def async_chat(prompt: str) -> str:
267
+ response = await anthropic.messages.create(
268
+ model="claude-3-sonnet-20240229",
269
+ messages=[{"role": "user", "content": prompt}]
270
+ )
271
+ return response.content[0].text
272
+ ```
273
+
274
+ ### Auto-traced OpenAI Client
275
+
276
+ Wrap your OpenAI client for zero-code tracing:
277
+
278
+ ```python
279
+ from enprompta import Enprompta, traced_openai
280
+ from openai import OpenAI
281
+
282
+ enprompta = Enprompta(api_key="ep_...")
283
+ openai = traced_openai(enprompta, OpenAI())
284
+
285
+ # All calls are now automatically traced!
286
+ response = openai.chat.completions.create(
287
+ model="gpt-4",
288
+ messages=[{"role": "user", "content": "Hello"}]
289
+ )
290
+ ```
291
+
292
+ ### Context Manager (Manual Tracing)
293
+
294
+ For more control, use the context manager:
295
+
296
+ ```python
297
+ with client.traces.wrap(
298
+ provider="openai",
299
+ model="gpt-4",
300
+ input="Hello"
301
+ ) as ctx:
302
+ response = openai.chat.completions.create(
303
+ model="gpt-4",
304
+ messages=[{"role": "user", "content": "Hello"}]
305
+ )
306
+ ctx.set_output(
307
+ output=response.choices[0].message.content,
308
+ input_tokens=response.usage.prompt_tokens,
309
+ output_tokens=response.usage.completion_tokens
310
+ )
311
+
312
+ print(f"Trace ID: {ctx.trace_id}")
313
+ ```
314
+
315
+ ### Nested Spans for Complex Pipelines
316
+
317
+ Track multi-step operations like RAG:
318
+
319
+ ```python
320
+ # Record the main trace
321
+ result = client.traces.record(
322
+ provider="openai",
323
+ model="gpt-4",
324
+ input="What are our refund policies?",
325
+ output="Based on our documentation...",
326
+ latency_ms=2500
327
+ )
328
+
329
+ # Add spans for each step
330
+ client.traces.create_span(
331
+ result["trace_id"],
332
+ name="vector_search",
333
+ span_type=SpanType.RETRIEVAL,
334
+ input={"query": "refund policies", "top_k": 5},
335
+ output={"document_ids": ["doc1", "doc2"]},
336
+ duration_ms=150
337
+ )
338
+
339
+ client.traces.create_span(
340
+ result["trace_id"],
341
+ name="embedding",
342
+ span_type=SpanType.EMBEDDING,
343
+ tokens=8,
344
+ duration_ms=50
345
+ )
346
+ ```
347
+
348
+ ## Webhook Signature Verification
349
+
350
+ ```python
351
+ from enprompta.webhooks import verify_signature
352
+
353
+ # In your webhook handler (FastAPI example)
354
+ @app.post("/webhooks/enprompta")
355
+ async def handle_webhook(request: Request):
356
+ payload = await request.body()
357
+ signature = request.headers.get("X-Enprompta-Signature")
358
+
359
+ if not verify_signature(payload, signature, webhook_secret):
360
+ raise HTTPException(status_code=401)
361
+
362
+ event = json.loads(payload)
363
+ print(f"Received: {event['event']}")
364
+ return {"status": "ok"}
365
+ ```
366
+
367
+ ## Type Hints
368
+
369
+ Full type hint support:
370
+
371
+ ```python
372
+ from enprompta.types import (
373
+ Prompt,
374
+ Execution,
375
+ Team,
376
+ Webhook,
377
+ CreatePromptParams,
378
+ ExecutePromptParams
379
+ )
380
+ ```
381
+
382
+ ## Documentation
383
+
384
+ Full documentation: https://enprompta.com/docs/sdk/python
385
+
386
+ ## License
387
+
388
+ MIT