codespar 0.1.0__tar.gz → 0.3.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codespar
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: Python SDK for CodeSpar — commerce infrastructure for AI agents in Latin America.
5
5
  Project-URL: Homepage, https://codespar.dev
6
6
  Project-URL: Documentation, https://docs.codespar.dev
@@ -179,6 +179,10 @@ This package mirrors [`@codespar/sdk`](https://www.npmjs.com/package/@codespar/s
179
179
  method-for-method. Same backend, same payloads, same preset names — pick
180
180
  the language that fits your stack without giving anything up.
181
181
 
182
+ ## Need more?
183
+
184
+ Need governance, budget limits, and audit trails for agent payments? **[CodeSpar Enterprise](https://codespar.dev/enterprise)** adds policy engine, payment routing, and compliance templates on top of these MCP servers.
185
+
182
186
  ## Links
183
187
 
184
188
  - [Documentation](https://docs.codespar.dev)
@@ -148,6 +148,10 @@ This package mirrors [`@codespar/sdk`](https://www.npmjs.com/package/@codespar/s
148
148
  method-for-method. Same backend, same payloads, same preset names — pick
149
149
  the language that fits your stack without giving anything up.
150
150
 
151
+ ## Need more?
152
+
153
+ Need governance, budget limits, and audit trails for agent payments? **[CodeSpar Enterprise](https://codespar.dev/enterprise)** adds policy engine, payment routing, and compliance templates on top of these MCP servers.
154
+
151
155
  ## Links
152
156
 
153
157
  - [Documentation](https://docs.codespar.dev)
@@ -0,0 +1,37 @@
1
+ # codespar Python SDK — examples
2
+
3
+ Runnable scripts demonstrating the CodeSpar Python SDK end-to-end.
4
+ Each file is standalone — just `pip install codespar`, set
5
+ `CODESPAR_API_KEY`, and run.
6
+
7
+ ## Setup
8
+
9
+ ```bash
10
+ pip install codespar
11
+ export CODESPAR_API_KEY="csk_live_..." # get one at dashboard.codespar.dev
12
+ ```
13
+
14
+ Optionally pin a specific project (staging, prod, etc.):
15
+
16
+ ```bash
17
+ export CODESPAR_PROJECT_ID="prj_a1b2c3d4e5f6g7h8"
18
+ ```
19
+
20
+ ## Examples
21
+
22
+ | File | What it does | SDK surface |
23
+ |------|--------------|-------------|
24
+ | [`ecommerce_checkout.py`](./ecommerce_checkout.py) | Full Complete Loop: checkout → NF-e → ship → notify via WhatsApp | `send_stream`, typed events |
25
+ | [`pix_payment.py`](./pix_payment.py) | Create a Pix charge and notify the customer | `send`, `tool_calls` |
26
+ | [`proxy_execute.py`](./proxy_execute.py) | Raw HTTP proxy to a provider API with server-side auth injection | `proxy_execute` |
27
+ | [`connect_link.py`](./connect_link.py) | Generate an OAuth Connect Link for an end user | `authorize` |
28
+ | [`async_basic.py`](./async_basic.py) | Same flow using `AsyncCodeSpar` for FastAPI / asyncio stacks | `AsyncCodeSpar` |
29
+
30
+ ## Running
31
+
32
+ ```bash
33
+ python examples/ecommerce_checkout.py
34
+ ```
35
+
36
+ All examples use `preset="brazilian"` by default. Change to
37
+ `mexican` / `argentinian` / `colombian` to run the LatAm-wide stack.
@@ -0,0 +1,46 @@
1
+ """
2
+ Same Pix flow as ``pix_payment.py``, but with ``AsyncCodeSpar`` —
3
+ the canonical shape for FastAPI, LangChain, or anything already on
4
+ asyncio. The SDK's async client is the primary implementation; the
5
+ sync ``CodeSpar`` is a thin wrapper on top.
6
+
7
+ Usage:
8
+ export CODESPAR_API_KEY="csk_live_..."
9
+ python examples/async_basic.py
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import asyncio
15
+ import os
16
+ import sys
17
+
18
+ from codespar import AsyncCodeSpar
19
+
20
+ PROMPT = "Crie um Pix de R$200 e envie o QR code para +5511999887766."
21
+
22
+
23
+ async def run() -> int:
24
+ api_key = os.environ.get("CODESPAR_API_KEY")
25
+ if not api_key:
26
+ print("error: set CODESPAR_API_KEY first", file=sys.stderr)
27
+ return 1
28
+
29
+ async with AsyncCodeSpar(api_key=api_key) as cs:
30
+ session = await cs.create("demo_user", preset="brazilian")
31
+ try:
32
+ async for event in session.send_stream(PROMPT):
33
+ if event.type == "assistant_text":
34
+ print(event.content, end="", flush=True)
35
+ elif event.type == "tool_use":
36
+ print(f"\n→ {event.name}")
37
+ elif event.type == "done":
38
+ print(f"\n✓ done · {event.result.iterations} iterations")
39
+ finally:
40
+ await session.close()
41
+
42
+ return 0
43
+
44
+
45
+ if __name__ == "__main__":
46
+ raise SystemExit(asyncio.run(run()))
@@ -0,0 +1,46 @@
1
+ """
2
+ Connect Links example — generate the OAuth URL your end user opens
3
+ to grant provider access. CodeSpar stores the tokens in the
4
+ per-project vault once the user completes the flow, then forwards
5
+ them back to ``redirect_uri`` with ``?status=connected`` appended.
6
+
7
+ Usage:
8
+ export CODESPAR_API_KEY="csk_live_..."
9
+ python examples/connect_link.py
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import os
15
+ import sys
16
+
17
+ from codespar import AuthConfig, CodeSpar
18
+
19
+
20
+ def main() -> int:
21
+ api_key = os.environ.get("CODESPAR_API_KEY")
22
+ if not api_key:
23
+ print("error: set CODESPAR_API_KEY first", file=sys.stderr)
24
+ return 1
25
+
26
+ with CodeSpar(api_key=api_key) as cs:
27
+ session = cs.create("demo_user", servers=["stripe-acp"])
28
+ try:
29
+ link = session.authorize(
30
+ "stripe-acp",
31
+ AuthConfig(
32
+ redirect_uri="https://your-app.example/connected",
33
+ ),
34
+ )
35
+ print("Open this URL to connect Stripe:")
36
+ print(f" {link.authorize_url}")
37
+ print(f"\nLink token: {link.link_token}")
38
+ print(f"Expires at: {link.expires_at}")
39
+ finally:
40
+ session.close()
41
+
42
+ return 0
43
+
44
+
45
+ if __name__ == "__main__":
46
+ raise SystemExit(main())
@@ -0,0 +1,73 @@
1
+ """
2
+ End-to-end e-commerce checkout — the canonical Complete Loop demo.
3
+
4
+ Drives a single natural-language turn through four tools:
5
+ codespar_checkout → codespar_invoice → codespar_ship → codespar_notify
6
+
7
+ Exactly what the dashboard's Sandbox / E-Commerce Checkout runs, just
8
+ from Python instead of the browser. Streams events so you can watch
9
+ the agent progress through each step in real time.
10
+
11
+ Usage:
12
+ export CODESPAR_API_KEY="csk_live_..."
13
+ python examples/ecommerce_checkout.py
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import os
19
+ import sys
20
+
21
+ from codespar import CodeSpar
22
+
23
+ PROMPT = (
24
+ "Quero comprar o Starter Kit por R$149,00. "
25
+ "Meu CEP é 01310-100. Pode processar tudo: "
26
+ "checkout via Stripe, NF-e via Nuvem Fiscal, "
27
+ "frete via Correios, e me avise pelo WhatsApp."
28
+ )
29
+
30
+
31
+ def main() -> int:
32
+ api_key = os.environ.get("CODESPAR_API_KEY")
33
+ if not api_key:
34
+ print("error: set CODESPAR_API_KEY first — see dashboard.codespar.dev", file=sys.stderr)
35
+ return 1
36
+
37
+ with CodeSpar(
38
+ api_key=api_key,
39
+ project_id=os.environ.get("CODESPAR_PROJECT_ID"),
40
+ ) as cs:
41
+ session = cs.create("demo_user", preset="brazilian")
42
+ try:
43
+ print(f"→ session {session.id}")
44
+ print(f"→ servers: {', '.join(session.servers)}\n")
45
+
46
+ for event in session.send_stream(PROMPT):
47
+ # Stream type is a discriminated union — pattern match
48
+ # on the event.type literal so mypy can narrow the
49
+ # attributes each branch touches.
50
+ if event.type == "assistant_text":
51
+ print(event.content, end="", flush=True)
52
+ elif event.type == "tool_use":
53
+ print(f"\n\n → calling {event.name}")
54
+ elif event.type == "tool_result":
55
+ tc = event.tool_call
56
+ status = "ok" if tc.status == "success" else f"error ({tc.error_code})"
57
+ print(f" {status} · {tc.duration_ms}ms")
58
+ elif event.type == "done":
59
+ tool_count = len(event.result.tool_calls)
60
+ iterations = event.result.iterations
61
+ print("\n\n✓ complete")
62
+ print(f" {tool_count} tools · {iterations} iterations")
63
+ elif event.type == "error":
64
+ print(f"\n✗ error: {event.error}", file=sys.stderr)
65
+ return 2
66
+ finally:
67
+ session.close()
68
+
69
+ return 0
70
+
71
+
72
+ if __name__ == "__main__":
73
+ raise SystemExit(main())
@@ -0,0 +1,48 @@
1
+ """
2
+ Minimal Pix example — create a charge, send the QR code via WhatsApp.
3
+
4
+ Uses ``send`` (blocking) instead of ``send_stream`` because this flow
5
+ is short enough that streaming would be overkill; you get the full
6
+ transcript back in one call.
7
+
8
+ Usage:
9
+ export CODESPAR_API_KEY="csk_live_..."
10
+ python examples/pix_payment.py
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import os
16
+ import sys
17
+
18
+ from codespar import CodeSpar
19
+
20
+ PROMPT = (
21
+ "Crie uma cobrança Pix de R$500,00 e envie o QR code "
22
+ "pelo WhatsApp para +5511999887766."
23
+ )
24
+
25
+
26
+ def main() -> int:
27
+ api_key = os.environ.get("CODESPAR_API_KEY")
28
+ if not api_key:
29
+ print("error: set CODESPAR_API_KEY first", file=sys.stderr)
30
+ return 1
31
+
32
+ with CodeSpar(api_key=api_key) as cs:
33
+ session = cs.create("demo_user", preset="brazilian")
34
+ try:
35
+ result = session.send(PROMPT)
36
+ print(result.message)
37
+ print(f"\n{len(result.tool_calls)} tools called over {result.iterations} iterations:")
38
+ for tc in result.tool_calls:
39
+ marker = "✓" if tc.status == "success" else "✗"
40
+ print(f" {marker} {tc.tool_name} · {tc.server_id} · {tc.duration_ms}ms")
41
+ finally:
42
+ session.close()
43
+
44
+ return 0
45
+
46
+
47
+ if __name__ == "__main__":
48
+ raise SystemExit(main())
@@ -0,0 +1,53 @@
1
+ """
2
+ Raw HTTP proxy example — bypass the agent loop and call a provider
3
+ endpoint directly through CodeSpar's credential vault.
4
+
5
+ CodeSpar injects the Stripe API key server-side; your code never
6
+ sees it. Same pattern works for every connected server — swap
7
+ ``server="stripe-acp"`` for ``"asaas"``, ``"nuvem-fiscal"``, etc.
8
+
9
+ Usage:
10
+ export CODESPAR_API_KEY="csk_live_..."
11
+ python examples/proxy_execute.py
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import json
17
+ import os
18
+ import sys
19
+
20
+ from codespar import CodeSpar, ProxyRequest
21
+
22
+
23
+ def main() -> int:
24
+ api_key = os.environ.get("CODESPAR_API_KEY")
25
+ if not api_key:
26
+ print("error: set CODESPAR_API_KEY first", file=sys.stderr)
27
+ return 1
28
+
29
+ with CodeSpar(api_key=api_key) as cs:
30
+ session = cs.create("demo_user", servers=["stripe-acp"])
31
+ try:
32
+ response = session.proxy_execute(
33
+ ProxyRequest(
34
+ server="stripe-acp",
35
+ endpoint="/v1/charges",
36
+ method="POST",
37
+ body={
38
+ "amount": 14900, # R$149.00 in cents
39
+ "currency": "brl",
40
+ "description": "Starter Kit",
41
+ },
42
+ )
43
+ )
44
+ print(f"HTTP {response.status} · {response.duration}ms")
45
+ print(json.dumps(response.data, indent=2, ensure_ascii=False))
46
+ finally:
47
+ session.close()
48
+
49
+ return 0
50
+
51
+
52
+ if __name__ == "__main__":
53
+ raise SystemExit(main())
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "codespar"
7
- version = "0.1.0"
7
+ version = "0.3.0"
8
8
  description = "Python SDK for CodeSpar — commerce infrastructure for AI agents in Latin America."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -47,6 +47,13 @@ Issues = "https://github.com/codespar/codespar/issues"
47
47
  [tool.hatch.build.targets.wheel]
48
48
  packages = ["src/codespar"]
49
49
 
50
+ # PEP 561 — the empty `py.typed` marker signals to mypy / pyright /
51
+ # pyrefly that this package ships inline type hints. Without it,
52
+ # downstream projects lose type info even though every public fn
53
+ # is annotated.
54
+ [tool.hatch.build.targets.wheel.force-include]
55
+ "src/codespar/py.typed" = "codespar/py.typed"
56
+
50
57
  [tool.pytest.ini_options]
51
58
  testpaths = ["tests"]
52
59
  asyncio_mode = "auto"
@@ -61,7 +61,7 @@ from .types import (
61
61
  UserMessageEvent,
62
62
  )
63
63
 
64
- __version__ = "0.1.0"
64
+ __version__ = "0.3.0"
65
65
 
66
66
  __all__ = [
67
67
  "ApiError",
@@ -28,7 +28,7 @@ def build_headers(
28
28
  headers = {
29
29
  "Content-Type": "application/json",
30
30
  "Authorization": f"Bearer {api_key}",
31
- "User-Agent": "codespar-python/0.1.0",
31
+ "User-Agent": "codespar-python/0.1.1",
32
32
  }
33
33
  if project_id:
34
34
  headers["x-codespar-project"] = project_id
File without changes
File without changes
File without changes
File without changes
File without changes