kranth 0.2.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.
@@ -0,0 +1,72 @@
1
+ # ── Rust ───────────────────────────────────────
2
+ target/
3
+ *.rs.bk
4
+ Cargo.lock
5
+
6
+ # ── Go ─────────────────────────────────────────
7
+ *.out
8
+ vendor/
9
+
10
+ # ── Python ─────────────────────────────────────
11
+ __pycache__/
12
+ *.py[cod]
13
+ *.egg-info/
14
+ .venv/
15
+ .uv/
16
+ .python-version
17
+ dist/
18
+ build/
19
+ .ruff_cache/
20
+ .mypy_cache/
21
+
22
+ # ── Node / web ────────────────────────────────
23
+ node_modules/
24
+ .vite/
25
+ dist/
26
+ .next/
27
+ .turbo/
28
+ *.tsbuildinfo
29
+
30
+ # ── Env & secrets ──────────────────────────────
31
+ .env
32
+ .env.*
33
+ !.env.example
34
+ *.pem
35
+ *.key
36
+ secrets/
37
+
38
+ # ── IDE / OS ───────────────────────────────────
39
+ .vscode/
40
+ .idea/
41
+ .DS_Store
42
+ Thumbs.db
43
+ *.swp
44
+ *.swo
45
+
46
+ # ── Logs & coverage ────────────────────────────
47
+ *.log
48
+ coverage/
49
+ .pytest_cache/
50
+
51
+ # ── Generated proto stubs (regenerated at build) ──
52
+ **/proto/*.pb.go
53
+ **/proto/*_pb2.py
54
+ **/proto/*_pb2_grpc.py
55
+ **/proto/*.pyi
56
+ **/proto/*.rs
57
+
58
+ # ── Playwright / test artifacts ────────────────
59
+ test-results/
60
+ playwright-report/
61
+ .playwright-mcp/
62
+
63
+ # ── Local data / runtime ───────────────────────
64
+ data/
65
+ volumes/
66
+ postgres-data/
67
+ neo4j-data/
68
+ redis-data/
69
+
70
+ # ── Tooling caches ─────────────────────────────
71
+ .cache/
72
+ .parcel-cache/
kranth-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,152 @@
1
+ Metadata-Version: 2.4
2
+ Name: kranth
3
+ Version: 0.2.0
4
+ Summary: Stress-test ideas with hundreds of AI personas. Adversarial multi-bias debate. API-first.
5
+ Project-URL: Homepage, https://kranth.com
6
+ Project-URL: Source, https://github.com/VYLTH/kranth-python
7
+ Project-URL: Issues, https://github.com/VYLTH/kranth-python/issues
8
+ Author-email: Kranth <support@kranth.com>
9
+ License: Apache-2.0
10
+ Keywords: ai,kranth,personas,simulation,synthetic-audience
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: httpx-sse>=0.4.0
21
+ Requires-Dist: httpx>=0.27.0
22
+ Description-Content-Type: text/markdown
23
+
24
+ # Kranth — Python SDK
25
+
26
+ ```bash
27
+ pip install kranth
28
+ ```
29
+
30
+ ```python
31
+ from kranth import Kranth
32
+
33
+ client = Kranth(api_key="kr_live_…")
34
+
35
+ sim = client.sims.create(
36
+ idea_text="We're launching a paid Rust devtool. $29/mo, hosted, no self-host.",
37
+ persona_count=50,
38
+ model_id="claude-sonnet-4-6",
39
+ )
40
+
41
+ for ev in client.sims.stream(sim.sim_id):
42
+ if ev.kind == "persona.ready":
43
+ print(f"persona {ev.data['persona_id']} ready")
44
+ elif ev.kind == "reaction.complete":
45
+ print(f" → {ev.data['sentiment']:+.2f} {ev.data['persona_id']}")
46
+ elif ev.kind == "sim.complete":
47
+ report = ev.data.get("report") or {}
48
+ print("verdict:", report.get("sentiment_score"))
49
+ print("objections:")
50
+ for o in report.get("top_objections", []):
51
+ print(" ·", o)
52
+ break
53
+ ```
54
+
55
+ ## Async
56
+
57
+ ```python
58
+ import asyncio
59
+ from kranth import AsyncKranth
60
+
61
+ async def main():
62
+ async with AsyncKranth(api_key="kr_live_…") as client:
63
+ models = await client.models.list()
64
+ sim = await client.sims.create(
65
+ idea_text="…",
66
+ persona_count=50,
67
+ model_id=models[0].id,
68
+ )
69
+ async for ev in client.sims.stream(sim.sim_id):
70
+ print(ev.kind)
71
+
72
+ asyncio.run(main())
73
+ ```
74
+
75
+ ## Recon — web-grounded research
76
+
77
+ A swarm of agents researches your idea on the live web and returns a cited, scored verdict.
78
+
79
+ ```python
80
+ recon = client.recon.create(idea_text="Paid Rust devtool, $29/mo", tier="scout")
81
+ for ev in client.recon.stream(recon.recon_id):
82
+ if ev.kind == "recon.complete":
83
+ break
84
+ detail = client.recon.get(recon.recon_id)
85
+ print(detail.run.score, "·", len(detail.findings), "findings", len(detail.sources), "sources")
86
+ ```
87
+
88
+ ## Debates — adversarial panel
89
+
90
+ ```python
91
+ debate = client.debates.create(topic="Should we kill the free tier?", mode="panel")
92
+ for ev in client.debates.stream(debate.id):
93
+ if ev.kind == "debate.complete":
94
+ break
95
+ d = client.debates.get(debate.id)
96
+ print(d.synthesis.score, d.synthesis.summary)
97
+ ```
98
+
99
+ ## Resources
100
+
101
+ - `client.sims.create(...)` — submit a sim
102
+ - `client.sims.get(sim_id)` — single sim with status + verdict
103
+ - `client.sims.list(status=..., cursor=..., limit=...)` — paginated
104
+ - `client.sims.stream(sim_id)` — SSE event stream
105
+ - `client.sims.cancel(sim_id)` — abort + refund unspent credits
106
+ - `client.sims.export(sim_id)` — full report incl. reactions + clusters
107
+ - `client.recon.create(idea_text, tier, ...)` / `get` / `list` / `tiers` / `export` / `stream` — web-grounded research
108
+ - `client.debates.create(topic, mode, ...)` / `get` / `list` / `turns` / `set_public` / `cancel` / `export` / `stream` — adversarial panel
109
+ - `client.api_keys.create(name, env="live"|"test")` — mint
110
+ - `client.api_keys.list()` / `client.api_keys.revoke(id)`
111
+ - `client.models.list()` — registry (id, tier, credits/100p, plan_min)
112
+ - `client.billing.usage()` — credits consumed + remaining
113
+ - `client.billing.checkout_url(plan="pro", billing_period="monthly")` — Stripe Checkout URL
114
+ - `client.billing.portal_url()` — Stripe Customer Portal URL
115
+
116
+ ## Errors
117
+
118
+ ```python
119
+ from kranth import KranthPaymentRequired, KranthRateLimited
120
+
121
+ try:
122
+ client.sims.create(...)
123
+ except KranthPaymentRequired:
124
+ # out of credits — top up via client.billing.checkout_url("pro")
125
+ ...
126
+ except KranthRateLimited as e:
127
+ # over RPM — back off for e.retry_after seconds
128
+ ...
129
+ ```
130
+
131
+ Full exception tree: `KranthError → KranthAPIError → {KranthAuthError, KranthValidationError, KranthPaymentRequired, KranthRateLimited}`.
132
+
133
+ ## Configuration
134
+
135
+ ```python
136
+ client = Kranth(
137
+ api_key="kr_live_…",
138
+ base_url="https://api.kranth.ai", # default
139
+ timeout=30.0,
140
+ )
141
+ ```
142
+
143
+ Bring your own `httpx.Client` if you need custom transport (proxies, mTLS, retries):
144
+
145
+ ```python
146
+ import httpx
147
+ client = Kranth(api_key="…", client=httpx.Client(transport=httpx.HTTPTransport(retries=3)))
148
+ ```
149
+
150
+ ## License
151
+
152
+ Apache-2.0
kranth-0.2.0/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # Kranth — Python SDK
2
+
3
+ ```bash
4
+ pip install kranth
5
+ ```
6
+
7
+ ```python
8
+ from kranth import Kranth
9
+
10
+ client = Kranth(api_key="kr_live_…")
11
+
12
+ sim = client.sims.create(
13
+ idea_text="We're launching a paid Rust devtool. $29/mo, hosted, no self-host.",
14
+ persona_count=50,
15
+ model_id="claude-sonnet-4-6",
16
+ )
17
+
18
+ for ev in client.sims.stream(sim.sim_id):
19
+ if ev.kind == "persona.ready":
20
+ print(f"persona {ev.data['persona_id']} ready")
21
+ elif ev.kind == "reaction.complete":
22
+ print(f" → {ev.data['sentiment']:+.2f} {ev.data['persona_id']}")
23
+ elif ev.kind == "sim.complete":
24
+ report = ev.data.get("report") or {}
25
+ print("verdict:", report.get("sentiment_score"))
26
+ print("objections:")
27
+ for o in report.get("top_objections", []):
28
+ print(" ·", o)
29
+ break
30
+ ```
31
+
32
+ ## Async
33
+
34
+ ```python
35
+ import asyncio
36
+ from kranth import AsyncKranth
37
+
38
+ async def main():
39
+ async with AsyncKranth(api_key="kr_live_…") as client:
40
+ models = await client.models.list()
41
+ sim = await client.sims.create(
42
+ idea_text="…",
43
+ persona_count=50,
44
+ model_id=models[0].id,
45
+ )
46
+ async for ev in client.sims.stream(sim.sim_id):
47
+ print(ev.kind)
48
+
49
+ asyncio.run(main())
50
+ ```
51
+
52
+ ## Recon — web-grounded research
53
+
54
+ A swarm of agents researches your idea on the live web and returns a cited, scored verdict.
55
+
56
+ ```python
57
+ recon = client.recon.create(idea_text="Paid Rust devtool, $29/mo", tier="scout")
58
+ for ev in client.recon.stream(recon.recon_id):
59
+ if ev.kind == "recon.complete":
60
+ break
61
+ detail = client.recon.get(recon.recon_id)
62
+ print(detail.run.score, "·", len(detail.findings), "findings", len(detail.sources), "sources")
63
+ ```
64
+
65
+ ## Debates — adversarial panel
66
+
67
+ ```python
68
+ debate = client.debates.create(topic="Should we kill the free tier?", mode="panel")
69
+ for ev in client.debates.stream(debate.id):
70
+ if ev.kind == "debate.complete":
71
+ break
72
+ d = client.debates.get(debate.id)
73
+ print(d.synthesis.score, d.synthesis.summary)
74
+ ```
75
+
76
+ ## Resources
77
+
78
+ - `client.sims.create(...)` — submit a sim
79
+ - `client.sims.get(sim_id)` — single sim with status + verdict
80
+ - `client.sims.list(status=..., cursor=..., limit=...)` — paginated
81
+ - `client.sims.stream(sim_id)` — SSE event stream
82
+ - `client.sims.cancel(sim_id)` — abort + refund unspent credits
83
+ - `client.sims.export(sim_id)` — full report incl. reactions + clusters
84
+ - `client.recon.create(idea_text, tier, ...)` / `get` / `list` / `tiers` / `export` / `stream` — web-grounded research
85
+ - `client.debates.create(topic, mode, ...)` / `get` / `list` / `turns` / `set_public` / `cancel` / `export` / `stream` — adversarial panel
86
+ - `client.api_keys.create(name, env="live"|"test")` — mint
87
+ - `client.api_keys.list()` / `client.api_keys.revoke(id)`
88
+ - `client.models.list()` — registry (id, tier, credits/100p, plan_min)
89
+ - `client.billing.usage()` — credits consumed + remaining
90
+ - `client.billing.checkout_url(plan="pro", billing_period="monthly")` — Stripe Checkout URL
91
+ - `client.billing.portal_url()` — Stripe Customer Portal URL
92
+
93
+ ## Errors
94
+
95
+ ```python
96
+ from kranth import KranthPaymentRequired, KranthRateLimited
97
+
98
+ try:
99
+ client.sims.create(...)
100
+ except KranthPaymentRequired:
101
+ # out of credits — top up via client.billing.checkout_url("pro")
102
+ ...
103
+ except KranthRateLimited as e:
104
+ # over RPM — back off for e.retry_after seconds
105
+ ...
106
+ ```
107
+
108
+ Full exception tree: `KranthError → KranthAPIError → {KranthAuthError, KranthValidationError, KranthPaymentRequired, KranthRateLimited}`.
109
+
110
+ ## Configuration
111
+
112
+ ```python
113
+ client = Kranth(
114
+ api_key="kr_live_…",
115
+ base_url="https://api.kranth.ai", # default
116
+ timeout=30.0,
117
+ )
118
+ ```
119
+
120
+ Bring your own `httpx.Client` if you need custom transport (proxies, mTLS, retries):
121
+
122
+ ```python
123
+ import httpx
124
+ client = Kranth(api_key="…", client=httpx.Client(transport=httpx.HTTPTransport(retries=3)))
125
+ ```
126
+
127
+ ## License
128
+
129
+ Apache-2.0
@@ -0,0 +1,42 @@
1
+ [project]
2
+ name = "kranth"
3
+ version = "0.2.0"
4
+ description = "Stress-test ideas with hundreds of AI personas. Adversarial multi-bias debate. API-first."
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ license = { text = "Apache-2.0" }
8
+ authors = [{ name = "Kranth", email = "support@kranth.com" }]
9
+ keywords = ["kranth", "personas", "ai", "synthetic-audience", "simulation"]
10
+ classifiers = [
11
+ "Development Status :: 3 - Alpha",
12
+ "Intended Audience :: Developers",
13
+ "License :: OSI Approved :: Apache Software License",
14
+ "Programming Language :: Python :: 3.10",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Topic :: Software Development :: Libraries :: Python Modules",
19
+ ]
20
+ dependencies = [
21
+ "httpx>=0.27.0",
22
+ "httpx-sse>=0.4.0",
23
+ ]
24
+
25
+ [project.urls]
26
+ Homepage = "https://kranth.com"
27
+ Source = "https://github.com/VYLTH/kranth-python"
28
+ Issues = "https://github.com/VYLTH/kranth-python/issues"
29
+
30
+ [build-system]
31
+ requires = ["hatchling"]
32
+ build-backend = "hatchling.build"
33
+
34
+ [tool.hatch.build.targets.wheel]
35
+ packages = ["src/kranth"]
36
+
37
+ [tool.hatch.build.targets.sdist]
38
+ include = ["src/", "README.md", "LICENSE"]
39
+
40
+ [tool.ruff]
41
+ line-length = 100
42
+ target-version = "py310"
@@ -0,0 +1,98 @@
1
+ """Kranth — stress-test ideas with hundreds of AI personas.
2
+
3
+ The whole surface is two clients:
4
+
5
+ >>> from kranth import Kranth
6
+ >>> client = Kranth(api_key="kr_live_…")
7
+ >>> sim = client.sims.create(
8
+ ... idea_text="Launch a paid Rust newsletter.",
9
+ ... persona_count=50,
10
+ ... model_id="claude-sonnet-4-6",
11
+ ... )
12
+ >>> for event in client.sims.stream(sim.sim_id):
13
+ ... print(event.kind, event.data)
14
+
15
+ >>> from kranth import AsyncKranth
16
+ >>> async with AsyncKranth(api_key="kr_live_…") as client:
17
+ ... models = await client.models.list()
18
+ """
19
+
20
+ from kranth._async import AsyncKranth
21
+ from kranth._client import Kranth
22
+ from kranth._errors import (
23
+ KranthAPIError,
24
+ KranthAuthError,
25
+ KranthError,
26
+ KranthPaymentRequired,
27
+ KranthRateLimited,
28
+ KranthValidationError,
29
+ )
30
+ from kranth._models import (
31
+ ApiKey,
32
+ AudienceReaction,
33
+ CreateApiKeyResponse,
34
+ CreateReconResponse,
35
+ CreateSimResponse,
36
+ Debate,
37
+ DebateDetail,
38
+ DebateEvent,
39
+ DebateSynthesis,
40
+ DebateTurn,
41
+ ListDebatesResponse,
42
+ ListSimsResponse,
43
+ Me,
44
+ ModelInfo,
45
+ ReconDetail,
46
+ ReconEvent,
47
+ ReconFinding,
48
+ ReconRun,
49
+ ReconSource,
50
+ ReconSummary,
51
+ ReconTier,
52
+ SimEvent,
53
+ SimSummary,
54
+ SpeakerPreview,
55
+ Usage,
56
+ VerdictReport,
57
+ )
58
+
59
+ __all__ = [
60
+ "Kranth",
61
+ "AsyncKranth",
62
+ "KranthError",
63
+ "KranthAPIError",
64
+ "KranthAuthError",
65
+ "KranthValidationError",
66
+ "KranthPaymentRequired",
67
+ "KranthRateLimited",
68
+ "ApiKey",
69
+ "CreateApiKeyResponse",
70
+ "CreateSimResponse",
71
+ "ListSimsResponse",
72
+ "Me",
73
+ "ModelInfo",
74
+ "SimEvent",
75
+ "SimSummary",
76
+ "Usage",
77
+ "VerdictReport",
78
+ # Recon
79
+ "CreateReconResponse",
80
+ "ReconSummary",
81
+ "ReconDetail",
82
+ "ReconRun",
83
+ "ReconFinding",
84
+ "ReconSource",
85
+ "ReconTier",
86
+ "ReconEvent",
87
+ # Debate
88
+ "Debate",
89
+ "DebateDetail",
90
+ "DebateTurn",
91
+ "DebateSynthesis",
92
+ "AudienceReaction",
93
+ "SpeakerPreview",
94
+ "ListDebatesResponse",
95
+ "DebateEvent",
96
+ ]
97
+
98
+ __version__ = "0.2.0"