patchr 0.1.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 (116) hide show
  1. apps/__init__.py +2 -0
  2. apps/api/__init__.py +2 -0
  3. apps/api/main.py +652 -0
  4. apps/benchmarks/__init__.py +1 -0
  5. apps/benchmarks/main.py +20 -0
  6. apps/sandbox/__init__.py +1 -0
  7. apps/sandbox/main.py +20 -0
  8. apps/worker/__init__.py +2 -0
  9. apps/worker/main.py +15 -0
  10. apps/worker/verify.py +14 -0
  11. patchr/__init__.py +12 -0
  12. patchr/sdk/__init__.py +20 -0
  13. patchr/sdk/client.py +12 -0
  14. patchr-0.1.0.dist-info/METADATA +137 -0
  15. patchr-0.1.0.dist-info/RECORD +116 -0
  16. patchr-0.1.0.dist-info/WHEEL +5 -0
  17. patchr-0.1.0.dist-info/entry_points.txt +5 -0
  18. patchr-0.1.0.dist-info/licenses/LICENSE +17 -0
  19. patchr-0.1.0.dist-info/top_level.txt +3 -0
  20. picux/__init__.py +6 -0
  21. picux/agents/__init__.py +5 -0
  22. picux/agents/registry.py +204 -0
  23. picux/api/__init__.py +5 -0
  24. picux/api/service.py +5075 -0
  25. picux/audit/__init__.py +31 -0
  26. picux/audit/activity.py +97 -0
  27. picux/audit/observability.py +55 -0
  28. picux/audit/verification/__init__.py +21 -0
  29. picux/audit/verification/ledger.py +633 -0
  30. picux/benchmarks/__init__.py +5 -0
  31. picux/benchmarks/local.py +286 -0
  32. picux/config.py +140 -0
  33. picux/contracts/__init__.py +22 -0
  34. picux/contracts/handshake.py +122 -0
  35. picux/contracts/integration.py +385 -0
  36. picux/contracts/openapi.py +187 -0
  37. picux/contracts/protocol_map.py +152 -0
  38. picux/contracts/routes.py +980 -0
  39. picux/contracts/schema_catalog.py +125 -0
  40. picux/core/__init__.py +17 -0
  41. picux/core/models.py +148 -0
  42. picux/core/router.py +131 -0
  43. picux/core/runtime.py +42 -0
  44. picux/core/state_machine.py +38 -0
  45. picux/domains/__init__.py +2 -0
  46. picux/domains/bridge/HostRun.py +1104 -0
  47. picux/domains/bridge/__init__.py +6 -0
  48. picux/domains/bridge/engine.py +345 -0
  49. picux/domains/hunt/__init__.py +6 -0
  50. picux/domains/hunt/engine.py +307 -0
  51. picux/domains/hunt/models.py +88 -0
  52. picux/domains/pay/__init__.py +16 -0
  53. picux/domains/pay/adapters.py +607 -0
  54. picux/domains/pay/engine.py +950 -0
  55. picux/domains/pay/models.py +95 -0
  56. picux/domains/proxy/__init__.py +5 -0
  57. picux/domains/proxy/engine.py +466 -0
  58. picux/domains/resolve/__init__.py +5 -0
  59. picux/domains/resolve/engine.py +546 -0
  60. picux/orchestrator/__init__.py +3 -0
  61. picux/orchestrator/engine.py +2840 -0
  62. picux/portals/__init__.py +17 -0
  63. picux/portals/templates.py +272 -0
  64. picux/protocols/__init__.py +1 -0
  65. picux/protocols/a2a/__init__.py +6 -0
  66. picux/protocols/a2a/client.py +51 -0
  67. picux/protocols/a2a/envelope.py +132 -0
  68. picux/protocols/mcp/__init__.py +7 -0
  69. picux/protocols/mcp/client.py +69 -0
  70. picux/protocols/mcp/contract.py +67 -0
  71. picux/protocols/mcp/server.py +76 -0
  72. picux/sandbox/__init__.py +6 -0
  73. picux/sandbox/midnight_arbitrage.py +215 -0
  74. picux/sandbox/models.py +90 -0
  75. picux/sdk/__init__.py +13 -0
  76. picux/sdk/client.py +768 -0
  77. picux/sdk/external.py +245 -0
  78. picux/security/__init__.py +18 -0
  79. picux/security/auth.py +86 -0
  80. picux/security/config_validator.py +58 -0
  81. picux/security/policy.py +158 -0
  82. picux/security/secrets.py +144 -0
  83. picux/signals/__init__.py +1 -0
  84. picux/signals/community/__init__.py +24 -0
  85. picux/signals/community/adapters/__init__.py +7 -0
  86. picux/signals/community/adapters/reddit.py +37 -0
  87. picux/signals/community/adapters/shopify.py +23 -0
  88. picux/signals/community/adapters/web.py +23 -0
  89. picux/signals/community/disambiguation.py +51 -0
  90. picux/signals/community/intake.py +227 -0
  91. picux/signals/community/models.py +102 -0
  92. picux/signals/community/rules.py +91 -0
  93. picux/signals/community/scoring.py +64 -0
  94. picux/storage/__init__.py +41 -0
  95. picux/storage/agents.py +50 -0
  96. picux/storage/cases.py +440 -0
  97. picux/storage/channels.py +476 -0
  98. picux/storage/connectors.py +411 -0
  99. picux/storage/envelopes.py +137 -0
  100. picux/storage/escrows.py +168 -0
  101. picux/storage/events.py +989 -0
  102. picux/storage/keyspace.py +60 -0
  103. picux/storage/mandates.py +107 -0
  104. picux/storage/portals.py +222 -0
  105. picux/storage/postgres.py +2049 -0
  106. picux/storage/providers.py +148 -0
  107. picux/storage/proxy.py +231 -0
  108. picux/storage/receipts.py +131 -0
  109. picux/storage/signals.py +147 -0
  110. picux/storage/tasks.py +179 -0
  111. picux/tools/__init__.py +11 -0
  112. picux/tools/shared.py +2048 -0
  113. picux/verification/__init__.py +5 -0
  114. picux/verification/rollout.py +183 -0
  115. picux/workflows/__init__.py +5 -0
  116. picux/workflows/templates.py +74 -0
@@ -0,0 +1,168 @@
1
+ from __future__ import annotations
2
+
3
+ import copy
4
+ import time
5
+ from typing import Any
6
+
7
+
8
+ ESCROW_STATUSES = {
9
+ "pending",
10
+ "created",
11
+ "funded",
12
+ "awaitingProof",
13
+ "settled",
14
+ "rejected",
15
+ "refunded",
16
+ "disputed",
17
+ "slashed",
18
+ "frozen",
19
+ "canceled",
20
+ }
21
+
22
+
23
+ class EscrowBook:
24
+ """Escrow record storage with optional durable backing."""
25
+
26
+ def __init__(self, *, backing: Any | None = None) -> None:
27
+ self.backing = backing
28
+ self._records: dict[str, dict[str, Any]] = {}
29
+
30
+ def saveEscrow(self, payload: dict[str, Any], *, status: str = "pending") -> dict[str, Any]:
31
+ escrowId = str(payload.get("escrowId", "") or "")
32
+ if not escrowId:
33
+ return {"ok": False, "error": "missing:escrowId"}
34
+ current = self.getEscrow(escrowId)
35
+ now = int(time.time())
36
+ createdAt = current.get("escrow", {}).get("createdAt", now) if current.get("ok") else now
37
+ record = _recordFromPayload(payload, status=status, createdAt=createdAt, updatedAt=now)
38
+ self._saveRecord(record)
39
+ return {"ok": True, "escrow": copy.deepcopy(record)}
40
+
41
+ def getEscrow(self, escrowId: str) -> dict[str, Any]:
42
+ escrowId = str(escrowId or "")
43
+ record = self._records.get(escrowId)
44
+ if record is None and self._backingEnabled() and hasattr(self.backing, "fetchEscrow"):
45
+ record = self.backing.fetchEscrow(escrowId)
46
+ if record:
47
+ self._records[escrowId] = copy.deepcopy(record)
48
+ if not record:
49
+ return {"ok": False, "error": "escrowNotFound", "escrowId": escrowId}
50
+ return {"ok": True, "escrow": copy.deepcopy(record)}
51
+
52
+ def listEscrows(self, filters: dict[str, Any] | None = None) -> dict[str, Any]:
53
+ self._loadBacking()
54
+ filters = filters or {}
55
+ status = str(filters.get("status", "") or "")
56
+ mandateId = str(filters.get("mandateId", "") or "")
57
+ taskId = str(filters.get("taskId", "") or "")
58
+ records = list(self._records.values())
59
+ if status:
60
+ records = [record for record in records if record.get("status") == status]
61
+ if mandateId:
62
+ records = [record for record in records if record.get("mandateId") == mandateId]
63
+ if taskId:
64
+ records = [record for record in records if record.get("taskId") == taskId]
65
+ records.sort(
66
+ key=lambda item: (int(item.get("createdAt", 0) or 0), str(item.get("escrowId", ""))),
67
+ reverse=True,
68
+ )
69
+ limit = _limit(filters.get("limit", 100))
70
+ return {
71
+ "ok": True,
72
+ "escrows": [copy.deepcopy(record) for record in records[:limit]],
73
+ "count": min(len(records), limit),
74
+ }
75
+
76
+ def updateEscrow(self, escrowId: str, updates: dict[str, Any]) -> dict[str, Any]:
77
+ current = self.getEscrow(escrowId)
78
+ if not current.get("ok"):
79
+ return current
80
+ record = current["escrow"]
81
+ status = _status(updates.get("status", record.get("status", "pending")))
82
+ payload = record.get("payload", {}) if isinstance(record.get("payload"), dict) else {}
83
+ if isinstance(updates.get("payload"), dict):
84
+ payload = copy.deepcopy(updates["payload"])
85
+ decision = record.get("decision", {}) if isinstance(record.get("decision"), dict) else {}
86
+ if isinstance(updates.get("decision"), dict):
87
+ decision = copy.deepcopy(updates["decision"])
88
+ merged = {
89
+ **record,
90
+ "status": status,
91
+ "mandateId": str(updates.get("mandateId", record.get("mandateId", "")) or ""),
92
+ "taskId": str(updates.get("taskId", record.get("taskId", "")) or ""),
93
+ "amount": _amount(updates.get("amount", record.get("amount", {}))),
94
+ "povRef": str(updates.get("povRef", record.get("povRef", "")) or ""),
95
+ "receiptId": str(updates.get("receiptId", record.get("receiptId", "")) or ""),
96
+ "payload": payload,
97
+ "decision": decision,
98
+ "updatedAt": int(updates.get("updatedAt", int(time.time())) or int(time.time())),
99
+ }
100
+ self._saveRecord(merged)
101
+ return {"ok": True, "escrow": copy.deepcopy(merged)}
102
+
103
+ def _saveRecord(self, record: dict[str, Any]) -> None:
104
+ escrowId = str(record.get("escrowId", "") or "")
105
+ if not escrowId:
106
+ return
107
+ self._records[escrowId] = copy.deepcopy(record)
108
+ if self._backingEnabled() and hasattr(self.backing, "upsertEscrow"):
109
+ self.backing.upsertEscrow(record)
110
+
111
+ def _loadBacking(self) -> None:
112
+ if self.backing is None or not self._backingEnabled() or not hasattr(self.backing, "listEscrows"):
113
+ return
114
+ for record in self.backing.listEscrows():
115
+ escrowId = str(record.get("escrowId", "") or "")
116
+ if escrowId:
117
+ self._records[escrowId] = copy.deepcopy(record)
118
+
119
+ def _backingEnabled(self) -> bool:
120
+ if self.backing is None:
121
+ return False
122
+ return bool(getattr(self.backing, "enabled", True))
123
+
124
+
125
+ def _recordFromPayload(payload: dict[str, Any], *, status: str, createdAt: int, updatedAt: int) -> dict[str, Any]:
126
+ request = payload.get("request", {}) if isinstance(payload.get("request"), dict) else payload
127
+ mandate = payload.get("paymentMandate", {}) if isinstance(payload.get("paymentMandate"), dict) else {}
128
+ if not mandate:
129
+ mandate = payload.get("mandate", {}) if isinstance(payload.get("mandate"), dict) else {}
130
+ pov = request.get("pov", {}) if isinstance(request.get("pov"), dict) else {}
131
+ return {
132
+ "escrowId": str(payload.get("escrowId", "") or ""),
133
+ "status": _status(payload.get("status", status)),
134
+ "mandateId": str(payload.get("mandateId", mandate.get("mandateId", request.get("mandateId", ""))) or ""),
135
+ "taskId": str(payload.get("taskId", request.get("taskId", "")) or ""),
136
+ "amount": _amount(payload.get("amount", request.get("amount", {}))),
137
+ "povRef": str(payload.get("povRef", pov.get("povId", "")) or ""),
138
+ "receiptId": str(payload.get("receiptId", "") or ""),
139
+ "payload": copy.deepcopy(payload),
140
+ "decision": payload.get("decision", {}) if isinstance(payload.get("decision"), dict) else {},
141
+ "createdAt": int(createdAt or updatedAt),
142
+ "updatedAt": int(updatedAt or createdAt),
143
+ }
144
+
145
+
146
+ def _amount(value: Any) -> dict[str, Any]:
147
+ amount = value if isinstance(value, dict) else {}
148
+ try:
149
+ parsed = float(amount.get("amount", 0.0) or 0.0)
150
+ except (TypeError, ValueError):
151
+ parsed = 0.0
152
+ return {
153
+ "amount": round(max(0.0, parsed), 2),
154
+ "currency": str(amount.get("currency", "USD") or "USD").upper(),
155
+ }
156
+
157
+
158
+ def _status(value: Any) -> str:
159
+ status = str(value or "pending")
160
+ return status if status in ESCROW_STATUSES else "pending"
161
+
162
+
163
+ def _limit(value: Any) -> int:
164
+ try:
165
+ parsed = int(value)
166
+ except (TypeError, ValueError):
167
+ return 100
168
+ return max(1, min(parsed, 500))