reactifact 0.6.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 (103) hide show
  1. reactifact/__init__.py +96 -0
  2. reactifact/__main__.py +10 -0
  3. reactifact/_extras.py +36 -0
  4. reactifact/agents.py +173 -0
  5. reactifact/artifacts.py +130 -0
  6. reactifact/branching.py +255 -0
  7. reactifact/budget.py +41 -0
  8. reactifact/chat.py +373 -0
  9. reactifact/checkpoints.py +329 -0
  10. reactifact/cli/__init__.py +73 -0
  11. reactifact/cli/branch.py +77 -0
  12. reactifact/cli/common.py +67 -0
  13. reactifact/cli/context.py +53 -0
  14. reactifact/cli/graph.py +21 -0
  15. reactifact/cli/replay.py +69 -0
  16. reactifact/cli/scenario.py +94 -0
  17. reactifact/cli/trace.py +45 -0
  18. reactifact/commit.py +97 -0
  19. reactifact/commit_log.py +235 -0
  20. reactifact/consume.py +96 -0
  21. reactifact/context.py +599 -0
  22. reactifact/effects.py +232 -0
  23. reactifact/eval.py +319 -0
  24. reactifact/events.py +34 -0
  25. reactifact/interrupt.py +22 -0
  26. reactifact/llm_agent.py +172 -0
  27. reactifact/operations.py +192 -0
  28. reactifact/patches.py +112 -0
  29. reactifact/produce.py +226 -0
  30. reactifact/prompts.py +111 -0
  31. reactifact/providers/__init__.py +153 -0
  32. reactifact/providers/_retry.py +61 -0
  33. reactifact/providers/anthropic.py +182 -0
  34. reactifact/providers/azure.py +31 -0
  35. reactifact/providers/cerebras.py +11 -0
  36. reactifact/providers/chat.py +417 -0
  37. reactifact/providers/contracts.py +105 -0
  38. reactifact/providers/deepseek.py +11 -0
  39. reactifact/providers/fake.py +40 -0
  40. reactifact/providers/fireworks.py +17 -0
  41. reactifact/providers/gemini.py +284 -0
  42. reactifact/providers/github_models.py +13 -0
  43. reactifact/providers/groq.py +18 -0
  44. reactifact/providers/image.py +157 -0
  45. reactifact/providers/mistral.py +17 -0
  46. reactifact/providers/nvidia.py +18 -0
  47. reactifact/providers/ollama.py +18 -0
  48. reactifact/providers/openai.py +44 -0
  49. reactifact/providers/openrouter.py +70 -0
  50. reactifact/providers/perplexity.py +11 -0
  51. reactifact/providers/qwen.py +17 -0
  52. reactifact/providers/speech.py +347 -0
  53. reactifact/providers/together.py +17 -0
  54. reactifact/providers/video.py +407 -0
  55. reactifact/providers/xai.py +11 -0
  56. reactifact/providers/zai.py +11 -0
  57. reactifact/py.typed +0 -0
  58. reactifact/recipes/__init__.py +63 -0
  59. reactifact/recipes/inputs.py +34 -0
  60. reactifact/recipes/memory.py +166 -0
  61. reactifact/recipes/resolve.py +51 -0
  62. reactifact/recipes/rollback.py +87 -0
  63. reactifact/recipes/search.py +81 -0
  64. reactifact/recipes/skills.py +108 -0
  65. reactifact/recipes/status.py +79 -0
  66. reactifact/recipes/text.py +202 -0
  67. reactifact/relations.py +104 -0
  68. reactifact/replay.py +187 -0
  69. reactifact/resources.py +45 -0
  70. reactifact/runtime.py +498 -0
  71. reactifact/scheduler.py +188 -0
  72. reactifact/session.py +75 -0
  73. reactifact/sources.py +498 -0
  74. reactifact/streaming.py +58 -0
  75. reactifact/structured.py +245 -0
  76. reactifact/testing/__init__.py +48 -0
  77. reactifact/testing/assertions.py +326 -0
  78. reactifact/testing/exceptions.py +27 -0
  79. reactifact/testing/fault.py +164 -0
  80. reactifact/testing/lab.py +350 -0
  81. reactifact/testing/mock.py +166 -0
  82. reactifact/testing/record.py +50 -0
  83. reactifact/testing/registry.py +87 -0
  84. reactifact/tool_use.py +528 -0
  85. reactifact/tools.py +111 -0
  86. reactifact/tracing/__init__.py +29 -0
  87. reactifact/tracing/langfuse.py +125 -0
  88. reactifact/tracing/models.py +93 -0
  89. reactifact/tracing/postgres.py +220 -0
  90. reactifact/tracing/store.py +254 -0
  91. reactifact/tracing/templates/ui.html +196 -0
  92. reactifact/tracing/templates/ui_run.html +264 -0
  93. reactifact/tracing/tracer.py +370 -0
  94. reactifact/tracing/web.py +117 -0
  95. reactifact/triggers.py +41 -0
  96. reactifact/viz.py +248 -0
  97. reactifact/web.py +117 -0
  98. reactifact-0.6.0.dist-info/METADATA +226 -0
  99. reactifact-0.6.0.dist-info/RECORD +103 -0
  100. reactifact-0.6.0.dist-info/WHEEL +5 -0
  101. reactifact-0.6.0.dist-info/entry_points.txt +2 -0
  102. reactifact-0.6.0.dist-info/licenses/LICENSE +21 -0
  103. reactifact-0.6.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,226 @@
1
+ Metadata-Version: 2.4
2
+ Name: reactifact
3
+ Version: 0.6.0
4
+ Summary: Reactive, artifact-driven agent runtime: agents transform versioned, typed, provenance-aware artifacts inside an evolving context
5
+ Project-URL: Homepage, https://github.com/bzdvdn/reactifact
6
+ Project-URL: Repository, https://github.com/bzdvdn/reactifact
7
+ Project-URL: Documentation, https://github.com/bzdvdn/reactifact/tree/master/docs
8
+ Requires-Python: >=3.11
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: pydantic>=2.13.4
12
+ Requires-Dist: httpx>=0.27
13
+ Requires-Dist: python-dotenv>=1.0
14
+ Provides-Extra: dev
15
+ Requires-Dist: ruff>=0.8; extra == "dev"
16
+ Requires-Dist: mypy>=1.11; extra == "dev"
17
+ Requires-Dist: pytest>=9.1.1; extra == "dev"
18
+ Requires-Dist: pytest-cov>=7.1.0; extra == "dev"
19
+ Provides-Extra: web
20
+ Requires-Dist: fastapi>=0.115; extra == "web"
21
+ Requires-Dist: uvicorn[standard]>=0.30; extra == "web"
22
+ Provides-Extra: pg
23
+ Requires-Dist: psycopg[binary]>=3.2; extra == "pg"
24
+ Dynamic: license-file
25
+
26
+ # reactifact
27
+
28
+ **Stop drawing the graph. Build agents as reactions to versioned, provable artifacts.**
29
+
30
+ [![CI](https://github.com/bzdvdn/reactifact/actions/workflows/ci.yml/badge.svg)](https://github.com/bzdvdn/reactifact/actions/workflows/ci.yml)
31
+ [![Python](https://img.shields.io/badge/python-3.11%20%7C%203.12-blue)](https://github.com/bzdvdn/reactifact)
32
+ [![PyPI version](https://img.shields.io/pypi/v/reactifact)](https://pypi.org/project/reactifact/)
33
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
34
+
35
+ Most agent frameworks make you **draw the graph**: connect nodes, wire memory,
36
+ declare control flow. But a knowledge question — *"why did infra costs jump in
37
+ Q2?"* — needs Confluence + GitLab + CSV + calculations + verification, and the
38
+ *next* question needs a different path. There is no universal graph to draw.
39
+
40
+ reactifact flips the model. You describe **what artifacts exist and what agents can
41
+ do with them**; the runtime derives what runs next from **state changes**. Agents
42
+ react to events — there is no graph, no node pipeline.
43
+
44
+ ```bash
45
+ pip install reactifact
46
+ ```
47
+
48
+ Runs offline, no API key needed — paste this straight into a `.py` file. Two
49
+ agents, no graph edge declared between them — the second reacts because the
50
+ first one's output exists, and the answer carries *proof* of where it came
51
+ from:
52
+
53
+ ```python
54
+ from pydantic import BaseModel
55
+
56
+ from reactifact import Budget, Consume, Context, Runtime, RuntimeResources, create_agent, produce
57
+
58
+
59
+ class Question(BaseModel):
60
+ text: str
61
+
62
+
63
+ class Evidence(BaseModel):
64
+ text: str
65
+
66
+
67
+ class Answer(BaseModel):
68
+ text: str
69
+
70
+
71
+ DOCS = {
72
+ "refund": "Refunds are available within 14 days of purchase.",
73
+ "pricing": "The Pro plan is $49/month, billed annually.",
74
+ }
75
+
76
+
77
+ @produce(Evidence)
78
+ async def find_evidence(context, inputs, event, effects):
79
+ question = next((a for a in inputs if isinstance(a.data, Question)), None)
80
+ if question is None:
81
+ return None
82
+ hit = next((v for k, v in DOCS.items() if k in question.data.text.lower()), None)
83
+ if hit is not None:
84
+ effects.create(Evidence(text=hit))
85
+
86
+
87
+ @produce(Answer)
88
+ async def answer_from_evidence(context, inputs, event, effects):
89
+ evidence = next((a for a in inputs if isinstance(a.data, Evidence)), None)
90
+ if evidence is None:
91
+ return None
92
+ effects.create(Answer(text=evidence.data.text)).link("supported_by", evidence)
93
+
94
+
95
+ search_agent = create_agent("search", consumes=[Consume(Question)], produces=[find_evidence])
96
+ answer_agent = create_agent("answer", consumes=[Consume(Evidence)], produces=[answer_from_evidence])
97
+
98
+ ctx = Context(resources=RuntimeResources())
99
+ runtime = Runtime(ctx, agents=[search_agent, answer_agent], budget=Budget(max_runs=10))
100
+
101
+ ctx.create(Question(text="what's your refund policy?"))
102
+ runtime.run() # search_agent and answer_agent both react — nobody wired them together
103
+
104
+ answer = ctx.latest(Answer)
105
+ evidence = ctx.related(answer.id, "supported_by")[0]
106
+ print(answer.data.text) # "Refunds are available within 14 days of purchase."
107
+ print("supported_by:", evidence.data.text) # provenance you can trace, not just a string in a log
108
+ ```
109
+
110
+ ## How it works
111
+
112
+ ```text
113
+ ARTIFACT CREATED / UPDATED
114
+
115
+
116
+ AGENTS REACT ──self.effects──► Effects ──compile──► Patch
117
+ ▲ │
118
+ └──────────────────────────────────────────────────────┘
119
+ Context v+1
120
+ ```
121
+
122
+ A produce writes what should change (`self.effects.create/update/link/ask`) and
123
+ returns `None`; the runtime compiles the effect set into one **atomic** `Patch`
124
+ and moves the context to the next version. The `event` that wakes an agent is
125
+ *derived* from that same change — the causal chain can never drift from the
126
+ actual state.
127
+
128
+ ## What makes it different
129
+
130
+ | Traditional agent (LangGraph / CrewAI / LangChain) | reactifact |
131
+ | --- | --- |
132
+ | A program follows a graph / plan | Agents **react** to state changes |
133
+ | Messages are strings | **Typed, versioned artifacts** (`Claim`, `Evidence`, `Answer`) |
134
+ | Orchestration is explicit wiring | Orchestration **falls out of the state** |
135
+ | A unit of work *returns* a change | An agent **writes effects**; the runtime compiles them |
136
+ | Retries/rollback are manual | Context is **git-like versioned** (diff, rollback, branch, merge) |
137
+ | "Who produced this?" is lost | **Provenance** links every derived artifact to its inputs |
138
+ | The model guesses the numbers | **Calculations are calculated** — the LLM is a reasoning component, not the source of truth |
139
+
140
+ Reactive. Deterministic. Accountable.
141
+
142
+ Full breakdown, including where reactifact is *not* the right choice:
143
+ [docs/en/comparison.md](docs/en/comparison.md).
144
+
145
+ ## Core primitives
146
+
147
+ - **Context** — versioned working state, git-like commits, `diff`/`rollback`/`merge`.
148
+ - **Artifact** — a first-class typed object (`Claim`, `Evidence`, `Answer`), not a string blob.
149
+ - **Effects** — an agent states its change via `self.effects.create/update/link/ask`; the runtime compiles it.
150
+ - **Patch** — the compiled, validated change-set applied as one atomic commit.
151
+ - **Agent** — a thin container declaring `consumes`/`produces`; logic lives in a `Produce`.
152
+ - **Source** — retrieval is a capability: vector search is *one* strategy; direct API, keyword, SQL, filesystem are equally first-class.
153
+ - **Provenance** — every derived artifact links to what produced it
154
+ (`Answer —supported_by→ Claim —derived_from→ Evidence —extracted_from→ Doc`).
155
+ - **HITL** — humans as `effects.ask(...)` → `PendingQuestion`, answered via `effects.resume(...)` like any agent.
156
+
157
+ ## In the box
158
+
159
+ - **Deterministic by design** — calculations over structured data, honest `None`
160
+ fallbacks instead of hallucinated answers; the model reasons, never "knows".
161
+ - **Observability** — every run traces agent spans, reads/writes, LLM calls,
162
+ tokens: SQLite store + web dashboard, exportable to Langfuse/Postgres (async sinks).
163
+ - **Budgets & replanning** — cap by runs/time/iterations/tool-calls, replan on decline.
164
+ - **Branching & replay** — `context.branch()`, three-way `merge()`, deterministic
165
+ `ReplayLLM`, all for audit and safe alternative states.
166
+ - **Sessions** — `SessionStore` over `FileKVBackend`/`SQLiteKVBackend`
167
+ (and `PostgreSQLKVBackend`) for durable chat memory.
168
+ - **Web layer** — `ChatAssistant` + `create_chat_router` mount a canonical SSE
169
+ chat on *your* FastAPI app; errors degrade to a logged fallback, never a 500.
170
+ - **Recipes** — `find`/`find_all` (typed lookup in `inputs`), `fan_out_sources`,
171
+ `materialize_doc`, `StatusMachine`, `WindowSummarizer`/`WindowPruner`
172
+ (bounded conversation memory), change→rebuild rollback helpers,
173
+ `Skill`/`match_skills` (Claude-Skills-shaped instructions, keyword-triggered)
174
+ — pure and LLM-free, except the summarizer, which takes your callback.
175
+ - **Viz & CLI** — Mermaid `blueprint`/`context_to_mermaid`/`trace_to_mermaid`;
176
+ `reactifact` with `graph`/`context`/`trace`/`replay`/`branch`.
177
+
178
+ ## Run a demo
179
+
180
+ Offline-capable, no API keys required (deterministic fallbacks):
181
+
182
+ ```bash
183
+ uv run python ./examples/llm_ladder/level1.py # the simplest LLM turn (offline too)
184
+ uv run python ./examples/repair/web.py # room renovation: plan, estimate, CSV export
185
+ uv run python ./examples/devops/web.py # HITL ops assistant + trace dashboard
186
+ ```
187
+
188
+ Classic-pattern ports run as one-liners too:
189
+ `python -m examples.{reflection,map_reduce,supervisor,summarize,time_travel,adaptive,ledger}.main`.
190
+
191
+ ## Examples (in-repo, not shipped)
192
+
193
+ - `knowledge` — multi-source chat: search → evidence → claim verification → answer, with CSV calculation.
194
+ - `research` — goes to the web (`WebSource`): lazy page fetch → evidence → verified claims → answer with URL provenance.
195
+ - `medic-lab` — hypothesis laboratory: competing hypotheses scored, HITL steering, honest report.
196
+ - `devops` — HITL tool agents + LLM tool router + trace dashboard.
197
+ - `repair` — budget-aware replanning (chat/data in Russian by design).
198
+ - `forklab` — deterministic branch & merge: two strategies on their own forks, three-way merge.
199
+ - `ledger` — offline proof of reactive recompute: edit one fact, only its real `Consume`rs re-run.
200
+ - `llm_ladder` — the workflow from one LLM call to state-changing patches (3 levels).
201
+ - `adaptive` — hybrid scheduler: rule filters + deterministic rank + LLM tie-break + `rank_limit`.
202
+ - `{reflection,map_reduce,supervisor,summarize,time_travel}` — canonical ports (see [port-matrix](docs/en/port-matrix.md)).
203
+
204
+ ## Documentation
205
+
206
+ - [English](docs/en/index.md) · [Русский](docs/ru/index.md) — concepts, sources,
207
+ providers, recipes, patterns, observability, eval, branching, replay, viz/CLI, API.
208
+ - [Quickstart](docs/en/quickstart.md) — three runnable snippets: tool-calling
209
+ agent, retrieval over your docs, session-persisted chat bot.
210
+ - [Why reactifact](docs/en/why-reactifact.md) — the *design argument*: why effects, why no graph, why determinism.
211
+ - [Comparison](docs/en/comparison.md) — reactifact vs LangGraph/CrewAI, feature by feature, and when *not* to use reactifact.
212
+ - [Tutorial · llm-ladder](docs/en/examples.md#tutorial-ladder) — learn the workflow.
213
+ - [docs/constitution.md](docs/constitution.md) — the full design rationale and invariants.
214
+
215
+ ## Development
216
+
217
+ ```bash
218
+ uv sync --extra dev --extra web
219
+ .venv/bin/python -m pytest
220
+ .venv/bin/mypy
221
+ .venv/bin/ruff check
222
+ ```
223
+
224
+ ## License
225
+
226
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,103 @@
1
+ reactifact/__init__.py,sha256=KG7xOerXVAWyGlga-2k4x3Mrk87HlQQhP7UnvFrDoPs,2588
2
+ reactifact/__main__.py,sha256=M1HDJjMBbsLW09lZYH0yJnrrSe028Kg819dRj8ORQd8,204
3
+ reactifact/_extras.py,sha256=OqDRte6kikZoMWQd-dQZqaKec5SMZa-qQc2A1UCu6UE,1315
4
+ reactifact/agents.py,sha256=RPLMG41giiyXzP8AWP-iXU9g2Jh2fnRqSmX0NXKqHC4,6520
5
+ reactifact/artifacts.py,sha256=31RgBFgl195nEvZgTzP8AKrla36YOQR0NKUAtza1hSM,5358
6
+ reactifact/branching.py,sha256=DFddTIwSjEctPGi1EJj6_eucrXoh_ZlvTCOrtoXLyIw,9989
7
+ reactifact/budget.py,sha256=QN876r-z69GXahX0WdmN4yPZ7MgAV-BtpUujK7slrOY,1268
8
+ reactifact/chat.py,sha256=xuvY02e2D_1tndqxIViqmb7ZpWoSdKrPtrnn-KYzlxY,15013
9
+ reactifact/checkpoints.py,sha256=URiCIwa_dFXHyYKXg-gUgynKTtx0vKdckcSauCNfMKk,12360
10
+ reactifact/commit.py,sha256=FT-Qc3E8EJrrpI1KQbmJtUYBElTNUkYM9lsGTt0Ch5I,2950
11
+ reactifact/commit_log.py,sha256=1NwIbDx5grRzSWOP-M77AOA856y1IRjv667rUzH0EmY,9515
12
+ reactifact/consume.py,sha256=BYnD4cHItD3_Xs98xXmKQPHBe-VixWHJRlFAF-FnHHw,3025
13
+ reactifact/context.py,sha256=o4SpYy0dMjLRvhXCU7RvIKnhqaVfwroojOuhC7oosZk,23785
14
+ reactifact/effects.py,sha256=7JdESutabQ2MpjdwSz1WC3Dzdms8brZ_UmRWvL10KUg,8237
15
+ reactifact/eval.py,sha256=9iyQnXHHTpmJeamX7DGlLelgKjs2RhA2h4SKD7decA0,10477
16
+ reactifact/events.py,sha256=Fn7IzGAamAKjC9KdVfThILIv3hxPaaG5y-HF4JZkvD4,919
17
+ reactifact/interrupt.py,sha256=z3o-cSECGeoSxPhjObDwyiqX-8YR_4_t6aTlVJ5SyAI,679
18
+ reactifact/llm_agent.py,sha256=NZskmgF4dsAcIXAwNzsfWP_1-y9YgnCQpvIeuIeqBKQ,5976
19
+ reactifact/operations.py,sha256=Pj-S3MSfeK7T-0SLXpujw2HwgYK5YKdBeZkzhmG9fl4,5537
20
+ reactifact/patches.py,sha256=8-2GmQMGk9vN-psPxCRA4E_u7pJJBg5PlQ6oIX1E8RU,3363
21
+ reactifact/produce.py,sha256=gUDjwJoZ_eIcCViASoWQrncq-QAeBoTRicDyl47akvo,9223
22
+ reactifact/prompts.py,sha256=1sYqI_Zhjeh9ZA51Vt0h1Qy8ylaM_Bd-9qd8-mX-xMM,4017
23
+ reactifact/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ reactifact/relations.py,sha256=nV_ADbVD4mv-WpLcv0QRzX0tD2IaErDT-9oPCS2-wYs,3446
25
+ reactifact/replay.py,sha256=cN54liyFOwtu3XeJ93T7dZ-llPqiG74fpi8w192kEeg,6848
26
+ reactifact/resources.py,sha256=sscRyj7JphjgkWIfzhfRDPpizm1YRLXjFpQct_oPLlw,1592
27
+ reactifact/runtime.py,sha256=sONkTZITXrS2SB0C8mvf8wI39QaXJXGSIs1yymH1JL8,21080
28
+ reactifact/scheduler.py,sha256=i-1VgeV1-w3I1yiIjtfbYrztpJ1EJo77JwJzra1MDJ8,6519
29
+ reactifact/session.py,sha256=vDp_Pv2w92QCrGTq3htSVMpp5LVSOAcKcrRUtk-PzYg,2425
30
+ reactifact/sources.py,sha256=uUn9dswPVPYec2O-7G37I5tmBaq-eQFnG90D1ino_oc,18997
31
+ reactifact/streaming.py,sha256=VWT_YU_2LdUGJvsS86SvFs336d-Vhu90F9nOvJ2agdQ,1650
32
+ reactifact/structured.py,sha256=m3S48d_v_ry8WqjCjtNM42F4fKcmyaxa6MKCXACU_hY,8177
33
+ reactifact/tool_use.py,sha256=sAu-kFZpOFtYh_OvGkQxN4lqWa40kUcWHvHX43E92-8,20654
34
+ reactifact/tools.py,sha256=bj063_C7sa6RGde9tTBPEESM6mPbAwyTmMrY74z3Rh4,3741
35
+ reactifact/triggers.py,sha256=KlzHehjy4cd1c_9fRITM6_apKP4ImZ4yHChAnWPlG-g,1466
36
+ reactifact/viz.py,sha256=e9cwmE0Uv0w1V04d_d_XqomgrMXVX57IsPFIqTJCwe8,9109
37
+ reactifact/web.py,sha256=9bpecfXxJCBmChsyYl7TO6QHeuEtYMvH5A94H-B8_nY,4007
38
+ reactifact/cli/__init__.py,sha256=zN2kjlbSN7zYhhwHnJV2HPYN_x8dt-gw2JXg-I-oo2g,2664
39
+ reactifact/cli/branch.py,sha256=q6MB3R38i6wJFrELZMbB_DQZJlvQLUw_orjaK67CpGM,2766
40
+ reactifact/cli/common.py,sha256=jVLZ8k5vmAazm5Ak4L48clCVbOn1wzarK_brJG8qjEc,2456
41
+ reactifact/cli/context.py,sha256=n2Tae683A7rcoM8gytKHx-ebJid40bmwceU0dlEzxHw,1628
42
+ reactifact/cli/graph.py,sha256=fIYKBdYeJrZnijrdtLnBnFlrOOeiKe7beVMthwF-hSs,685
43
+ reactifact/cli/replay.py,sha256=bumL5Z557t7PxDBPokT9vaAfFB4npDegCEXz4nyLZ44,2224
44
+ reactifact/cli/scenario.py,sha256=nj2gsPR96yrRtd41ofb7xP5mHjT1liswEoMUNiUr4Ys,3207
45
+ reactifact/cli/trace.py,sha256=WTVxk2EyAp_Fy8gj5DwsfDBhydjlxUJ3VwJnfXpevtw,1368
46
+ reactifact/providers/__init__.py,sha256=-VCcu7aU5CJBnG4SJV0Q9r4kRtN8tjh4Xx93a3qX8TQ,4041
47
+ reactifact/providers/_retry.py,sha256=w97Hs5i7c0BOnX1bc0uh8Ab2svS40uETGZApMC8lihY,2236
48
+ reactifact/providers/anthropic.py,sha256=4kOnj8ljK_bZY1PM1TuVs8aNJdGJCIXAANe4SRZYhtA,6531
49
+ reactifact/providers/azure.py,sha256=si_zqBQGOC6d5gqQkVyQzJU1WnN2AHjgGTKNy80xWNg,948
50
+ reactifact/providers/cerebras.py,sha256=1ESDYmZnjJ8O1tSciT_cqisJbObGeE-643pBi_y6Qcs,286
51
+ reactifact/providers/chat.py,sha256=t5XXeHgZzEJ00JoK75CznVjNlObxRnp7oDiWk73z9tA,15292
52
+ reactifact/providers/contracts.py,sha256=dgKziVrxEATSnbj-r_wfNdU28GA9OR9A21gpgRHvYog,3293
53
+ reactifact/providers/deepseek.py,sha256=rtBDgG0bHI2ttX5FXhuJqZpo71t1Q6qWpkdzhQsCnSk,290
54
+ reactifact/providers/fake.py,sha256=CHvzi7MkjVW1CyhH8inUTTDv2wVPwMonE2DrvWPZv8g,1149
55
+ reactifact/providers/fireworks.py,sha256=1-7o6tQTChNewWqsmYmO3TEsBHL3pAJ5RSE3ihO_XCw,572
56
+ reactifact/providers/gemini.py,sha256=_LIwOPTtXiNaEPXZA_eyuHWPO1FKS-_o7FX3HFfz5EM,9915
57
+ reactifact/providers/github_models.py,sha256=eflhy7HHXHVWQf67JPECKC1ICBqqJd4MaIgTZPjV_aE,391
58
+ reactifact/providers/groq.py,sha256=FDvAk9lAnzeSiq8bppgvgI4wTGomntsCWS9bPU_TTQA,529
59
+ reactifact/providers/image.py,sha256=BuQs2FzB0CVaYd_F_6C3QnEy0qWNr0ZfMvvhKdOkTSU,5141
60
+ reactifact/providers/mistral.py,sha256=lDywFWh_45mHZl9JkNL6I45W0vlctQqbiAN5FeU9hWU,480
61
+ reactifact/providers/nvidia.py,sha256=FrqW3WbryAgzAE76GHkC9bgX2q0Klj9j4LCIZbCTydc,564
62
+ reactifact/providers/ollama.py,sha256=E2eRs2IYhsFltsl9TT-ykR5WTgvGKlAF2KM4znEoWUc,422
63
+ reactifact/providers/openai.py,sha256=RmZ04Eld0KnM_VSVERyOqbfNyVa5svc6RKkBys1cpvs,1223
64
+ reactifact/providers/openrouter.py,sha256=nj-KpJBD1-BJHzZQG0_sFIS_-3VmfXkJspbNnD_a5a8,2405
65
+ reactifact/providers/perplexity.py,sha256=5kDRnWu52GYqJXVOog443ePVkv8fGWlY_zbBtj16it4,304
66
+ reactifact/providers/qwen.py,sha256=FRfDq7JOHari9zAD5YShZc8kPNmraOFHbG139ygXNP4,519
67
+ reactifact/providers/speech.py,sha256=oE3df1893uoQruBC_kLVLEDnMcTmqfq9tYXAGxXAwxc,11683
68
+ reactifact/providers/together.py,sha256=UmkHskh8YCw9JK6-DL7uOTTH5Ss6olI7xte5WKJ2dcY,527
69
+ reactifact/providers/video.py,sha256=ss8TvbOlgpQOiYtwIquXJYO6Gx1ud01FYm-kKBIFwT4,14561
70
+ reactifact/providers/xai.py,sha256=oVh3SIug9fQPgMTs4HtEAgL-HhGcEYenpcmYpfjwPlA,248
71
+ reactifact/providers/zai.py,sha256=B55GgBOWcu3RV1OtnMLzWEBhuKKlVuBcG_b_sKC_Lbk,264
72
+ reactifact/recipes/__init__.py,sha256=ZGJl7QGnlAoqB9woanpESLOIZwyRF2zIXdbP2GZ4lBo,2700
73
+ reactifact/recipes/inputs.py,sha256=vuf10INr9TB3FJlccEEeRKRArKQ3bKnGCeND8cci7nA,1189
74
+ reactifact/recipes/memory.py,sha256=KiGS9nL7RJGyVomnjF0SKh1jCUMdemwe93jqU385GG8,5842
75
+ reactifact/recipes/resolve.py,sha256=oNxW0I_gJ9M-ZFik5_Pw6U-EFKlvm-bXsBBrvSz-Kg0,1710
76
+ reactifact/recipes/rollback.py,sha256=f7RcJ-rifoxUdUXQQgyHQNtrM6LquWjChYdvDfF2EYY,2736
77
+ reactifact/recipes/search.py,sha256=7rQ1EgWbHhFQ8pojmT7f4dPPQ_otOdwXv7QqMyf1w_g,2784
78
+ reactifact/recipes/skills.py,sha256=0NeBPGInre95G5YWdCFayJtHNxb6C_FTL2ubyANL8JY,3888
79
+ reactifact/recipes/status.py,sha256=SWtMcLwxaWpusgM1cfST1aJ4wVA1upw4ZU88Pojrv7Y,2798
80
+ reactifact/recipes/text.py,sha256=PsT70wF7JbS5lED1113HJza2xwUFcqAYVVdfHFKifeo,4309
81
+ reactifact/testing/__init__.py,sha256=cQ9FIvPkyC6Nkw_4wfctYFkdshPSKHnSH-9PX27eLXs,1370
82
+ reactifact/testing/assertions.py,sha256=tuJmrsa4PUV-5ETGaZ143UneWhdvyT8AyOTMg-mOnZ4,11962
83
+ reactifact/testing/exceptions.py,sha256=TroDaCQhcx1wjfmB3tYm1R7Mqc5CpLFdMDDgbwi7kBY,870
84
+ reactifact/testing/fault.py,sha256=K3_8xceG4b-036rcoUJih--hClyHiBsiVfQJgrcG-OQ,5873
85
+ reactifact/testing/lab.py,sha256=rFbXi6xpJhSSUYjw4EF8qu0kt5an34SaqPyFA6ygkD4,12824
86
+ reactifact/testing/mock.py,sha256=BvVpMl2G-bayLK6-DegD5mRfISLGuFUJSXSyD6de57A,6362
87
+ reactifact/testing/record.py,sha256=FnXqhDhk1eYt-devw--E8QlnAfGsgxJEzXW6Hmk-_yg,1712
88
+ reactifact/testing/registry.py,sha256=g-8C-5EJD2RFu_rGy1AhxTThbs08ZofZpNjbU7stn4w,3514
89
+ reactifact/tracing/__init__.py,sha256=jIEmBC8a8MqIH7iQO1UYyKTiEcOTgtVgyiF7HNut7zQ,810
90
+ reactifact/tracing/langfuse.py,sha256=eQSLmwQgIcUciYz6HAGHpVM8JJpEUvSQYrkPcQMceYw,4738
91
+ reactifact/tracing/models.py,sha256=2YYn0yz-Ra97P3RbxxXJoNbfgMA9Chft3AB1XBT8IFI,2599
92
+ reactifact/tracing/postgres.py,sha256=BCeJ2ll4gAOs8pNntRgWkGJpDdk-i0JaG7NOnbnpIaU,8240
93
+ reactifact/tracing/store.py,sha256=PcXQXtNJGMglD8Moemc6zebXbWEvRFsb28JqOydaXpw,9005
94
+ reactifact/tracing/tracer.py,sha256=3A0K3EendTywtAZCMY6mgX4rdPVbkKIAvyIsHzFhwuM,12858
95
+ reactifact/tracing/web.py,sha256=iW7X6p3n7GpTFUxfQipW-lAmWhFTS_xQMfqQShE5UM8,4116
96
+ reactifact/tracing/templates/ui.html,sha256=qrLX8kqlSLv8_JFcKUM9-NvwIKSQNvH9hEQPfSQg2M0,11853
97
+ reactifact/tracing/templates/ui_run.html,sha256=hZmHAWJ5zCollpALTaF6uQMWIRYSMZpSSq8xZeJcwGI,18372
98
+ reactifact-0.6.0.dist-info/licenses/LICENSE,sha256=BEtQBC6oL254Psz9A6XEltJbizRY88n908YDtwKZk4U,1060
99
+ reactifact-0.6.0.dist-info/METADATA,sha256=vSw5VDI1uG4cguxgkFMYZjGg_lvgz_z7x9ji143zXcg,10667
100
+ reactifact-0.6.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
101
+ reactifact-0.6.0.dist-info/entry_points.txt,sha256=3Lj31b7Wkqj9ipyBMPta8GTsI9gV7zQYb23WRoPAxhY,56
102
+ reactifact-0.6.0.dist-info/top_level.txt,sha256=HZDniEB1fk5Ox2bGIDMMSxMM32x7bWKoL_H2zkGGX04,11
103
+ reactifact-0.6.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ reactifact = reactifact.__main__:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 bzdv
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ reactifact