activegraph 1.0.0rc2__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 (82) hide show
  1. activegraph/__init__.py +222 -0
  2. activegraph/__main__.py +5 -0
  3. activegraph/behaviors/__init__.py +1 -0
  4. activegraph/behaviors/base.py +153 -0
  5. activegraph/behaviors/decorators.py +218 -0
  6. activegraph/cli/__init__.py +17 -0
  7. activegraph/cli/main.py +793 -0
  8. activegraph/cli/quickstart.py +556 -0
  9. activegraph/core/__init__.py +1 -0
  10. activegraph/core/clock.py +46 -0
  11. activegraph/core/event.py +33 -0
  12. activegraph/core/graph.py +846 -0
  13. activegraph/core/ids.py +135 -0
  14. activegraph/core/patch.py +47 -0
  15. activegraph/core/view.py +59 -0
  16. activegraph/errors.py +342 -0
  17. activegraph/frame.py +15 -0
  18. activegraph/llm/__init__.py +51 -0
  19. activegraph/llm/anthropic.py +339 -0
  20. activegraph/llm/cache.py +180 -0
  21. activegraph/llm/errors.py +257 -0
  22. activegraph/llm/prompt.py +420 -0
  23. activegraph/llm/provider.py +66 -0
  24. activegraph/llm/recorded.py +270 -0
  25. activegraph/llm/types.py +130 -0
  26. activegraph/observability/__init__.py +61 -0
  27. activegraph/observability/logging.py +205 -0
  28. activegraph/observability/metrics.py +219 -0
  29. activegraph/observability/migration.py +404 -0
  30. activegraph/observability/prometheus.py +101 -0
  31. activegraph/observability/status.py +83 -0
  32. activegraph/packs/__init__.py +999 -0
  33. activegraph/packs/diligence/__init__.py +86 -0
  34. activegraph/packs/diligence/behaviors.py +447 -0
  35. activegraph/packs/diligence/fixtures/__init__.py +364 -0
  36. activegraph/packs/diligence/fixtures/companies.py +511 -0
  37. activegraph/packs/diligence/object_types.py +163 -0
  38. activegraph/packs/diligence/settings.py +60 -0
  39. activegraph/packs/diligence/tools.py +124 -0
  40. activegraph/packs/loader.py +709 -0
  41. activegraph/packs/scaffold.py +317 -0
  42. activegraph/policy.py +20 -0
  43. activegraph/runtime/__init__.py +1 -0
  44. activegraph/runtime/behavior_graph.py +151 -0
  45. activegraph/runtime/budget.py +120 -0
  46. activegraph/runtime/config_errors.py +124 -0
  47. activegraph/runtime/diff.py +145 -0
  48. activegraph/runtime/errors.py +216 -0
  49. activegraph/runtime/exec_errors.py +232 -0
  50. activegraph/runtime/patterns.py +946 -0
  51. activegraph/runtime/queue.py +27 -0
  52. activegraph/runtime/registration_errors.py +291 -0
  53. activegraph/runtime/registry.py +111 -0
  54. activegraph/runtime/runtime.py +2441 -0
  55. activegraph/runtime/scheduler.py +206 -0
  56. activegraph/runtime/view_builder.py +65 -0
  57. activegraph/store/__init__.py +41 -0
  58. activegraph/store/base.py +66 -0
  59. activegraph/store/conformance.py +161 -0
  60. activegraph/store/errors.py +84 -0
  61. activegraph/store/memory.py +118 -0
  62. activegraph/store/postgres.py +609 -0
  63. activegraph/store/serde.py +202 -0
  64. activegraph/store/sqlite.py +446 -0
  65. activegraph/store/url.py +230 -0
  66. activegraph/tools/__init__.py +64 -0
  67. activegraph/tools/base.py +57 -0
  68. activegraph/tools/cache.py +157 -0
  69. activegraph/tools/context.py +48 -0
  70. activegraph/tools/decorators.py +70 -0
  71. activegraph/tools/errors.py +320 -0
  72. activegraph/tools/graph_query.py +94 -0
  73. activegraph/tools/recorded.py +205 -0
  74. activegraph/tools/web_fetch.py +80 -0
  75. activegraph/trace/__init__.py +1 -0
  76. activegraph/trace/causal.py +123 -0
  77. activegraph/trace/printer.py +495 -0
  78. activegraph-1.0.0rc2.dist-info/METADATA +228 -0
  79. activegraph-1.0.0rc2.dist-info/RECORD +82 -0
  80. activegraph-1.0.0rc2.dist-info/WHEEL +5 -0
  81. activegraph-1.0.0rc2.dist-info/entry_points.txt +5 -0
  82. activegraph-1.0.0rc2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,232 @@
1
+ """Execution-layer error leaves. v1.0 PR-D — ExecutionError category.
2
+
3
+ The two carrier leaves (:class:`LLMBehaviorError`,
4
+ :class:`ToolError`) live in their topic modules (``activegraph/llm/errors.py``
5
+ and ``activegraph/tools/errors.py``) because the per-reason prose
6
+ tables are co-located with the modules that raise them. This module
7
+ holds the runtime-internal execution-layer leaves that don't fit
8
+ cleanly into either topic.
9
+
10
+ PR-D adds:
11
+
12
+ - :class:`ApprovalNotFoundError` — pending-approval lookup miss.
13
+
14
+ PR-F adds (cross-category audit findings — sites that looked like
15
+ ConfigurationError on the PR-E hand-off list but classified as
16
+ ExecutionError on closer reading):
17
+
18
+ - :class:`RuntimeContextRequiredError` — ``ctx.propose_object`` was
19
+ called from a behavior whose context wasn't bound to a runtime.
20
+ Fires inside a running behavior, not at construction time.
21
+ - :class:`InvalidPatchLifecycleState` — ``graph.apply_patch`` was
22
+ called on a patch that isn't in ``"proposed"`` state. Fires during
23
+ the patch lifecycle, mid-execution.
24
+
25
+ PR-G adds:
26
+
27
+ - :class:`InternalEvaluatorError` — for the view-filter evaluator in
28
+ ``graph.py``. Sibling to the two pattern-evaluator internal-bug
29
+ raises in ``activegraph/runtime/patterns.py``; uses the shared
30
+ :func:`activegraph.errors.internal_bug_fields` helper so the
31
+ framework-bug prose is uniform across all three sites.
32
+ """
33
+
34
+ from __future__ import annotations
35
+
36
+ from typing import Any, Optional
37
+
38
+ from activegraph.errors import DOCS_BASE_URL, ExecutionError
39
+
40
+
41
+ class ApprovalNotFoundError(ExecutionError, LookupError):
42
+ """Pending-approval lookup miss.
43
+
44
+ Fires from ``runtime.approve(approval_id)`` when the id doesn't
45
+ refer to any currently-pending approval. Multi-inherits
46
+ :class:`LookupError` so user code that does ``except LookupError``
47
+ around the approval API continues to work.
48
+ """
49
+
50
+ _doc_slug = "approval-not-found-error"
51
+
52
+ def __init__(
53
+ self,
54
+ approval_id: str,
55
+ *,
56
+ pending_count: Optional[int] = None,
57
+ ) -> None:
58
+ self.approval_id = approval_id
59
+ self.pending_count = pending_count
60
+ ctx: dict[str, Any] = {"approval_id": approval_id}
61
+ if pending_count is not None:
62
+ ctx["pending_count"] = pending_count
63
+ pending_hint = (
64
+ f"There are currently {pending_count} pending approvals; "
65
+ f"none of them match {approval_id!r}."
66
+ if pending_count is not None
67
+ else "There are no pending approvals in this runtime."
68
+ )
69
+ ExecutionError.__init__(
70
+ self,
71
+ f"no pending approval named {approval_id!r}",
72
+ what_failed=(
73
+ f"runtime.approve({approval_id!r}) could not find a pending "
74
+ f"approval with that id.\n {pending_hint}"
75
+ ),
76
+ why=(
77
+ "Approval ids are generated by the runtime when a behavior "
78
+ "calls ctx.propose_object under a gating policy "
79
+ "(memo_approval, risk_approval, etc.). Each id is unique "
80
+ "to its runtime instance and is consumed when approve() "
81
+ "succeeds. A miss means either the id is stale (already "
82
+ "approved or denied), the runtime instance is fresh "
83
+ "(approvals don't carry across Runtime.load), or the id is "
84
+ "a typo. The framework refuses to no-op an unknown id "
85
+ "because that would silently corrupt the approval audit "
86
+ "trail."
87
+ ),
88
+ how_to_fix=(
89
+ "List the currently-pending approvals:\n"
90
+ " rt.pending_approvals()\n"
91
+ "to confirm what's actually pending. The diligence demo's\n"
92
+ "step_2_approval_demo (examples/diligence_real_run.py)\n"
93
+ "shows the canonical pattern: enumerate, then approve by id."
94
+ ),
95
+ context=ctx,
96
+ )
97
+
98
+
99
+ class RuntimeContextRequiredError(ExecutionError, RuntimeError):
100
+ """``ctx.propose_object`` (or another ctx method that requires the
101
+ runtime) was called from a behavior whose context isn't bound to a
102
+ runtime.
103
+
104
+ Fires at execution time, inside a running behavior — the caller is
105
+ the behavior body that invoked the ctx method, not the framework's
106
+ construction code. Multi-inherits :class:`RuntimeError` for
107
+ back-compat.
108
+ """
109
+
110
+ _doc_slug = "runtime-context-required-error"
111
+
112
+ def __init__(self, *, method: str = "ctx.propose_object") -> None:
113
+ self.method = method
114
+ ExecutionError.__init__(
115
+ self,
116
+ f"{method} requires a runtime-bound context",
117
+ what_failed=(
118
+ f"A behavior called {method} on a BehaviorGraph context that "
119
+ f"was constructed without a Runtime — likely a test fixture "
120
+ f"that stubbed the graph without going through Runtime."
121
+ ),
122
+ why=(
123
+ "ctx.propose_object writes to the runtime's pending-approvals "
124
+ "queue and emits a `approval.proposed` event. Without a "
125
+ "runtime, neither side effect can happen, and a no-op would "
126
+ "silently break the policy gate the behavior depends on — "
127
+ "the audit trail would show no proposal and the operator "
128
+ "would have no record to approve.\n"
129
+ "\n"
130
+ f"See {DOCS_BASE_URL}/concepts/failure-model "
131
+ f"for when the framework prefers exceptions over silent no-ops."
132
+ ),
133
+ how_to_fix=(
134
+ "Construct the BehaviorGraph through a Runtime:\n"
135
+ " rt = Runtime(graph, ...)\n"
136
+ " rt.run_goal('...') # behaviors see ctx bound to rt\n"
137
+ "\n"
138
+ "In a test, drive the behavior through a real Runtime — the "
139
+ "ctx is built from the runtime's context factory and bound "
140
+ "automatically. Mocking the ctx directly bypasses this; if "
141
+ "the test really needs to bypass the runtime, mock the "
142
+ "policy gate as well so propose_object isn't reached."
143
+ ),
144
+ context={"method": method},
145
+ )
146
+
147
+
148
+ class InvalidPatchLifecycleState(ExecutionError, ValueError):
149
+ """``graph.apply_patch(patch_id)`` was called on a patch that isn't
150
+ in ``"proposed"`` state.
151
+
152
+ Patches go through ``proposed → applied`` (success) or ``proposed →
153
+ rejected`` (policy or behavior rejection). Calling ``apply_patch``
154
+ on an already-applied or already-rejected patch is a programmer
155
+ error in the calling code path; the framework refuses rather than
156
+ re-apply or silently no-op. Multi-inherits :class:`ValueError`.
157
+ """
158
+
159
+ _doc_slug = "invalid-patch-lifecycle-state"
160
+
161
+ def __init__(self, *, patch_id: str, current_status: str) -> None:
162
+ self.patch_id = patch_id
163
+ self.current_status = current_status
164
+ ExecutionError.__init__(
165
+ self,
166
+ f"patch {patch_id} is {current_status!r}, not 'proposed'",
167
+ what_failed=(
168
+ f"graph.apply_patch({patch_id!r}) was called, but the patch's "
169
+ f"current status is {current_status!r}. Only patches in the "
170
+ f"'proposed' state can be applied."
171
+ ),
172
+ why=(
173
+ "Patches are one-shot: a 'proposed' patch becomes 'applied' "
174
+ "(success) or 'rejected' (refusal) exactly once. Re-applying "
175
+ "an already-applied patch would emit a duplicate "
176
+ "`patch.applied` event, which would break the replay "
177
+ "contract — replay would produce a different event stream "
178
+ "than the original run. The framework refuses re-application "
179
+ "rather than emit the duplicate.\n"
180
+ "\n"
181
+ f"See {DOCS_BASE_URL}/concepts/failure-model "
182
+ f"for the patch-lifecycle invariants."
183
+ ),
184
+ how_to_fix=(
185
+ f"Check the patch's current status before applying:\n"
186
+ f" patch = graph.get_patch({patch_id!r})\n"
187
+ f" if patch.status == 'proposed':\n"
188
+ f" graph.apply_patch({patch_id!r})\n"
189
+ f"\n"
190
+ f"If the patch is already applied and the caller wants a "
191
+ f"new mutation, propose a new patch — patches don't get "
192
+ f"re-used."
193
+ ),
194
+ context={"patch_id": patch_id, "current_status": current_status},
195
+ )
196
+
197
+
198
+ class InternalEvaluatorError(ExecutionError, ValueError):
199
+ """A framework-internal evaluator received input it does not
200
+ recognize. Should not fire in normal use — the framework's parsers
201
+ produce a closed set of operators / AST nodes, and an unrecognized
202
+ one means either drift between parser and evaluator or external
203
+ AST construction that bypassed the parser.
204
+
205
+ Multi-inherits :class:`ValueError` so user code that catches the
206
+ builtin around view operations continues to work. Used by
207
+ ``activegraph/core/graph.py`` for the view-filter evaluator; the
208
+ pattern-subscription evaluator's two internal-bug raises stay as
209
+ :class:`UnsupportedPatternError` (the natural category) but use
210
+ the same :func:`activegraph.errors.internal_bug_fields` helper so
211
+ the prose is uniform across all three sites.
212
+ """
213
+
214
+ _doc_slug = "internal-evaluator-error"
215
+
216
+ def __init__(
217
+ self,
218
+ summary: str,
219
+ *,
220
+ what_failed: str,
221
+ why: str,
222
+ how_to_fix: str,
223
+ context: Optional[dict[str, Any]] = None,
224
+ ) -> None:
225
+ ExecutionError.__init__(
226
+ self,
227
+ summary,
228
+ what_failed=what_failed,
229
+ why=why,
230
+ how_to_fix=how_to_fix,
231
+ context=context,
232
+ )