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,385 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any
5
+
6
+ from picux import __version__
7
+ from picux.contracts.routes import CONTRACT_ENDPOINTS
8
+ from picux.contracts.schema_catalog import SCHEMA_ENTRIES
9
+
10
+
11
+ @dataclass(frozen=True)
12
+ class IntegrationSurface:
13
+ id: str
14
+ kind: str
15
+ url: str
16
+ auth: str
17
+ contract: str = ""
18
+
19
+ def toMap(self) -> dict[str, Any]:
20
+ return {
21
+ "id": self.id,
22
+ "kind": self.kind,
23
+ "url": self.url,
24
+ "auth": self.auth,
25
+ "contract": self.contract,
26
+ }
27
+
28
+
29
+ @dataclass(frozen=True)
30
+ class EnvKey:
31
+ key: str
32
+ scope: str
33
+ requiredProd: bool
34
+ desc: str
35
+
36
+ def toMap(self) -> dict[str, Any]:
37
+ return {
38
+ "key": self.key,
39
+ "scope": self.scope,
40
+ "requiredProd": self.requiredProd,
41
+ "desc": self.desc,
42
+ }
43
+
44
+
45
+ @dataclass(frozen=True)
46
+ class DomainCapability:
47
+ id: str
48
+ desc: str
49
+ schemas: tuple[str, ...]
50
+ sdkHelpers: tuple[str, ...]
51
+ guide: str
52
+ policyActions: tuple[str, ...] = ()
53
+ policyResource: str = ""
54
+ policyRequired: bool = False
55
+ painPoints: tuple[str, ...] = ()
56
+ outcomes: tuple[str, ...] = ()
57
+ adoptionBlockers: tuple[str, ...] = ()
58
+ enhancements: tuple[str, ...] = ()
59
+ proofPack: str = ""
60
+ reviewProtocol: str = ""
61
+
62
+ def toMap(self, *, routes: list[dict[str, Any]], mcpTools: list[str]) -> dict[str, Any]:
63
+ return {
64
+ "id": self.id,
65
+ "desc": self.desc,
66
+ "routes": routes,
67
+ "schemas": list(self.schemas),
68
+ "mcpTools": mcpTools,
69
+ "sdkHelpers": list(self.sdkHelpers),
70
+ "guide": self.guide,
71
+ "policy": {
72
+ "required": self.policyRequired,
73
+ "actions": list(self.policyActions),
74
+ "resource": self.policyResource,
75
+ },
76
+ "painPoints": list(self.painPoints),
77
+ "outcomes": list(self.outcomes),
78
+ "adoptionBlockers": list(self.adoptionBlockers),
79
+ "enhancements": list(self.enhancements),
80
+ "proofPack": self.proofPack,
81
+ "reviewProtocol": self.reviewProtocol,
82
+ }
83
+
84
+
85
+ SURFACES: tuple[IntegrationSurface, ...] = (
86
+ IntegrationSurface("api", "http", "/openapi.json", "api", "/v1/contract"),
87
+ IntegrationSurface("sdk", "python", "picux.sdk.PicuxClient", "api", "/v1/manifest"),
88
+ IntegrationSurface("mcp", "jsonRpc", "/mcp", "mcp", "/v1/contract"),
89
+ IntegrationSurface("a2a", "http", "/v1/a2a/envelopes", "a2a", "/v1/a2a/contract"),
90
+ IntegrationSurface("schemas", "jsonSchema", "/v1/schemas", "public", "/v1/schemas"),
91
+ IntegrationSurface("protocolMap", "jsonLd", "/v1/protocol-map", "public", "/v1/protocol-map"),
92
+ IntegrationSurface("workflows", "http", "/v1/workflows/templates", "api", "/v1/workflows/templates"),
93
+ IntegrationSurface("payAdapter", "contract", "/v1/pay/adapters/contract", "public", "/v1/pay/adapters/contract"),
94
+ IntegrationSurface("payRails", "http", "/v1/pay/rails", "api", "/v1/pay/rails"),
95
+ IntegrationSurface("payChallenges", "http", "/v1/pay/challenges", "api", "/v1/pay/challenges"),
96
+ )
97
+
98
+
99
+ DOMAIN_CAPABILITIES: tuple[DomainCapability, ...] = (
100
+ DomainCapability(
101
+ "hunt",
102
+ "Signal discovery, source attribution, monitoring, and launchable public signals.",
103
+ ("communitySignal", "communitySignalRecord", "proofPack", "proofCard", "workflowTemplate"),
104
+ ("PicuxClient.huntDiscover", "ExternalAppClient.publishSignal", "PicuxClient.createProofPack", "PicuxClient.runWorkflowTemplate"),
105
+ "docs/developers/domain-reference.md#hunt",
106
+ painPoints=(
107
+ "Fragmented discovery across markets, people, leads, opportunities, and evidence sources.",
108
+ "Continuous scam-pattern monitoring across public discussion channels and web signals.",
109
+ "Public-signal entity collisions and misinformation risk before launch.",
110
+ ),
111
+ outcomes=("Ranked discoveries with source attribution.", "Human-review queue for low-confidence claims."),
112
+ adoptionBlockers=("Opaque multi-agent discovery outputs.",),
113
+ enhancements=("Misinformation escalation protocol routes low-confidence claims to PROXY review.",),
114
+ proofPack="Completed HUNT monitoring runs can emit source snapshots and decision logs as a portable case file.",
115
+ reviewProtocol="Claims below the confidence threshold are routed to PROXY instead of surfaced as answers.",
116
+ ),
117
+ DomainCapability(
118
+ "resolve",
119
+ "Dispute, audit, chronology, evidence integrity, and deterministic decision support.",
120
+ ("proofValue", "evidenceArtifact", "vaultEvidence", "fraudSourceTaxonomy", "proofPack", "proofCard", "workflowTemplate"),
121
+ ("ExternalAppClient.requestResolve", "PicuxClient.resolveTask", "PicuxClient.resolveScamTriage", "PicuxClient.createProofPack", "PicuxClient.runWorkflowTemplate"),
122
+ "docs/developers/domain-reference.md#resolve",
123
+ painPoints=(
124
+ "Disputes, audits, and contested claims where chronology and evidence integrity matter.",
125
+ "Agent complaints or document inconsistencies that need defensible outcomes.",
126
+ "Trust-sensitive decisions where automation must remain auditable and human-readable.",
127
+ ),
128
+ outcomes=("Chronology-aware claim drafts and decisions.", "Portable proof pack for defending outcomes later."),
129
+ adoptionBlockers=("Multi-agent systems can feel opaque unless outputs are tightly audited.",),
130
+ enhancements=("Auto-Audit Vault stores source snapshots, decision logs, complaint evidence, source classes, and fraud indicators.",),
131
+ proofPack="RESOLVE outcomes should close with a shareable proof pack: from opaque workflow to portable case file.",
132
+ reviewProtocol="Low-confidence or regulated-life-decision claims can suspend into PROXY for human review.",
133
+ ),
134
+ DomainCapability(
135
+ "bridge",
136
+ "External connector registry, scoped credentials, preflight, MCP, and A2A handoffs.",
137
+ (
138
+ "bridgeConnector",
139
+ "bridgeConnectionSession",
140
+ "bridgePreflight",
141
+ "credentialScope",
142
+ "providerAction",
143
+ "providerCallback",
144
+ "portalSession",
145
+ "portalSessionPreflight",
146
+ "portalAction",
147
+ "portalActionTemplate",
148
+ "portalPlaybook",
149
+ "portalStep",
150
+ "portalProof",
151
+ "a2aEnvelope",
152
+ "a2aEnvelopeRecord",
153
+ ),
154
+ (
155
+ "PicuxClient.registerConnector",
156
+ "PicuxClient.createBridgeConnectionSession",
157
+ "PicuxClient.matchConnectors",
158
+ "PicuxClient.preflightConnector",
159
+ "PicuxClient.preflightConnectorPaid",
160
+ "PicuxClient.createBridgeAction",
161
+ "PicuxClient.runBridgeAction",
162
+ "PicuxClient.updateBridgeAction",
163
+ "PicuxClient.createPortalSession",
164
+ "PicuxClient.preflightPortalSession",
165
+ "PicuxClient.listPortalActionTemplates",
166
+ "PicuxClient.getPortalActionTemplate",
167
+ "PicuxClient.listPortalPlaybooks",
168
+ "PicuxClient.getPortalPlaybook",
169
+ "PicuxClient.instantiatePortalPlaybook",
170
+ "PicuxClient.runPortalAction",
171
+ ),
172
+ "docs/developers/bridge-connectors.md",
173
+ ("bridge.<action>",),
174
+ "payload.resource or connector scope resource",
175
+ True,
176
+ ),
177
+ DomainCapability(
178
+ "channels",
179
+ "Durable conversation state across email, chat, messaging apps, telephony, CRM callbacks, and adapter actions.",
180
+ ("channelThread", "channelTimeline", "touchpoint", "providerAction", "providerCallback", "providerCaseSync", "channelState"),
181
+ (
182
+ "PicuxClient.createChannelThread",
183
+ "PicuxClient.channelThreadTimeline",
184
+ "PicuxClient.recordTouchpoint",
185
+ "PicuxClient.ingestProviderCallback",
186
+ "PicuxClient.listTouchpoints",
187
+ ),
188
+ "docs/developers/channelGuide.md",
189
+ painPoints=(
190
+ "Conversation state fragmented across email, chat, calls, CRM records, and webhooks.",
191
+ "Provider callbacks need to resume the correct Picux conversation and case.",
192
+ "Developers need inspectable inbound/outbound traces for every channel touchpoint.",
193
+ ),
194
+ outcomes=("Provider callbacks reconcile into one channel thread.", "Touchpoints can be exported into case evidence bundles."),
195
+ adoptionBlockers=("Deep integrations become hard to trust when provider IDs are not source-bound.",),
196
+ enhancements=("Channel threads bind provider thread IDs, Picux conversation IDs, case IDs, and proof artifacts."),
197
+ proofPack="Touchpoints become evidence-ready source records for Resolve and Proxy case workspaces.",
198
+ ),
199
+ DomainCapability(
200
+ "cases",
201
+ "Formal dispute and audit workspaces with stakeholders, deadlines, timelines, evidence refs, collaboration, and portable bundle exports.",
202
+ ("caseWorkspace", "caseStakeholder", "caseDeadline", "caseAction", "caseEvent", "caseNote", "caseBundleDocument", "evidenceBundle", "proofPack", "touchpoint"),
203
+ (
204
+ "PicuxClient.createCase",
205
+ "PicuxClient.addCaseStakeholder",
206
+ "PicuxClient.addCaseDeadline",
207
+ "PicuxClient.reviewCaseDeadlines",
208
+ "PicuxClient.addCaseAction",
209
+ "PicuxClient.listCaseActions",
210
+ "PicuxClient.updateCaseAction",
211
+ "PicuxClient.addCaseNote",
212
+ "PicuxClient.listCaseNotes",
213
+ "PicuxClient.addCaseEvidence",
214
+ "PicuxClient.exportCaseBundle",
215
+ ),
216
+ "docs/developers/caseGuide.md",
217
+ painPoints=(
218
+ "Complex disputes scatter evidence across documents, calls, chats, and provider portals.",
219
+ "Deadlines and stakeholder accountability are easy to lose in automation-only logs.",
220
+ "Operators need a shareable record that can defend the outcome later.",
221
+ ),
222
+ outcomes=("Portable case file.", "Deadline-aware status timeline.", "Stakeholder collaboration record."),
223
+ adoptionBlockers=("Evidence-rich users need exportable proof, not just internal logs.",),
224
+ enhancements=("Every Resolve or Proxy workflow can attach to a case workspace and export an evidence bundle."),
225
+ proofPack="Case exports turn touchpoints, proof packs, deadlines, and decisions into a portable case file.",
226
+ ),
227
+ DomainCapability(
228
+ "pay",
229
+ "Payment-as-auth challenges, bounded sessions, mandates, escrow records, receipts, and adapter contracts.",
230
+ (
231
+ "payRail",
232
+ "paymentChallenge",
233
+ "paymentCredential",
234
+ "paymentSession",
235
+ "usageMandate",
236
+ "procurementMandate",
237
+ "paymentMandate",
238
+ "mandateRecord",
239
+ "escrowMission",
240
+ "disputeCase",
241
+ "reputationCard",
242
+ "settlementAdapter",
243
+ "settlementInstruction",
244
+ "escrowRecord",
245
+ "settlementReceipt",
246
+ ),
247
+ (
248
+ "PicuxClient.listPayRails",
249
+ "PicuxClient.listPayAdapters",
250
+ "PicuxClient.getPayAdapter",
251
+ "PicuxClient.invokePayAdapter",
252
+ "PicuxClient.initEscrowMission",
253
+ "PicuxClient.settleEscrowMission",
254
+ "PicuxClient.abortEscrowMission",
255
+ "PicuxClient.listReputationCards",
256
+ "PicuxClient.updateReputationCard",
257
+ "PicuxClient.createPaymentChallenge",
258
+ "PicuxClient.verifyPaymentChallenge",
259
+ "PicuxClient.createPaymentSession",
260
+ "PicuxClient.consumePaymentSession",
261
+ "PicuxClient.localPaymentCredential",
262
+ "PicuxClient.payFetch",
263
+ "PicuxClient.createMandate",
264
+ "PicuxClient.fundEscrow",
265
+ "PicuxClient.submitEscrowProof",
266
+ "PicuxClient.settleEscrow",
267
+ "PicuxClient.refundEscrow",
268
+ "PicuxClient.disputeEscrow",
269
+ "PicuxClient.prepareSettlement",
270
+ "PicuxClient.settle",
271
+ ),
272
+ "docs/developers/pay-guide.md",
273
+ ("pay.challenge", "pay.session", "pay.adapter", "pay.prepare", "pay.settle"),
274
+ "escrow:<escrowId> or mandate:<mandateId>",
275
+ True,
276
+ painPoints=(
277
+ "API-key and account setup friction for machine-to-machine resource use.",
278
+ "High-frequency microtransactions that are too small for human-centric billing.",
279
+ "Irreversible autonomous purchases that need proof-gated settlement and dispute paths.",
280
+ ),
281
+ outcomes=("Payment-authenticated resource access.", "Bounded spending sessions.", "Proof-backed receipts and escrow gates."),
282
+ adoptionBlockers=("Agent spending needs clear limits before developers and users trust it.",),
283
+ enhancements=("PAY v2 adds 402 challenges, usage mandates, MPP sessions, escrow missions, and reputation cards.",),
284
+ proofPack="PAY receipts and escrow outcomes link payment, mandate, proof artifact, and settlement status.",
285
+ reviewProtocol="Tier 3 spending and disputed settlements suspend into PROXY for explicit human arbitration.",
286
+ ),
287
+ DomainCapability(
288
+ "proxy",
289
+ "Human intervention for oversight, physical logistics, subjective judgment, proof, and Resolve resume.",
290
+ ("proxyMission", "proxyBrief", "proxyOutcome", "proxyProof", "proxyRoute", "channelMsg", "voiceCall", "caseOpsTimeline", "proofPack", "proofCard", "workflowTemplate"),
291
+ (
292
+ "ExternalAppClient.requestProxy",
293
+ "ExternalAppClient.submitProxy",
294
+ "PicuxClient.createProxyMission",
295
+ "PicuxClient.submitProxyOutcomeByRef",
296
+ "PicuxClient.createProofPack",
297
+ "PicuxClient.runWorkflowTemplate",
298
+ ),
299
+ "docs/developers/proxy-guide.md",
300
+ ("proxy.request", "proxy.submit"),
301
+ "explicit resource, proxy:<proxyId>, task:<taskId>, or proxy:missions",
302
+ True,
303
+ painPoints=(
304
+ "Human logistics coordination across multiple actors, documents, and status changes.",
305
+ "Escalations to consultants, legal review, or document verification.",
306
+ "Voice, chat, and physical proof collection before Resolve or PAY can continue.",
307
+ ),
308
+ outcomes=("Suspend/resume mission state.", "Verified human outcome proof.", "Shareable workflow proof pack."),
309
+ adoptionBlockers=("Trust-sensitive users may worry about automation making the wrong call.",),
310
+ enhancements=("Human review routes make low-confidence claims explicit instead of hidden in agent output.",),
311
+ proofPack="Every completed PROXY workflow can emit a shareable proof pack for operators and reviewers.",
312
+ reviewProtocol="PROXY is the default misinformationEscalation route for human review and mission-critical ambiguity.",
313
+ ),
314
+ )
315
+
316
+
317
+ ENV_KEYS: tuple[EnvKey, ...] = (
318
+ EnvKey("PICUX_API_BASE_URL", "api", True, "Base URL for HTTP API and SDK clients."),
319
+ EnvKey("PICUX_API_TOKEN", "api", True, "Bearer token for protected API routes."),
320
+ EnvKey("PICUX_MCP_BASE_URL", "mcp", True, "Base URL for MCP JSON-RPC clients."),
321
+ EnvKey("PICUX_MCP_TOKEN", "mcp", True, "Bearer token for MCP JSON-RPC calls."),
322
+ EnvKey("PICUX_A2A_BASE_URL", "a2a", True, "Base URL for A2A envelope transport."),
323
+ EnvKey("PICUX_A2A_TOKEN", "a2a", True, "Bearer token for A2A envelope transport."),
324
+ EnvKey("PICUX_POSTGRES_DSN", "storage", True, "Postgres DSN for durable protocol state."),
325
+ EnvKey("PICUX_REDIS_URL", "cache", True, "Redis URL for runtime coordination."),
326
+ EnvKey("PICUX_ENV", "runtime", False, "Runtime environment label."),
327
+ EnvKey("PICUX_PRODUCTION_MODE", "runtime", False, "Fail-closed production-mode switch."),
328
+ )
329
+
330
+
331
+ def integrationManifest() -> dict[str, Any]:
332
+ """Return the compact integration contract for external builders."""
333
+
334
+ tools = [endpoint.mcpTool for endpoint in CONTRACT_ENDPOINTS if endpoint.mcpTool]
335
+ routes = [endpoint.toMap() for endpoint in CONTRACT_ENDPOINTS]
336
+ schemaIds = [entry.schemaId for entry in SCHEMA_ENTRIES]
337
+ domains = _domainMap()
338
+ return {
339
+ "ok": True,
340
+ "name": "picux",
341
+ "version": __version__,
342
+ "kind": "agenticEconomyInfra",
343
+ "surfaces": [surface.toMap() for surface in SURFACES],
344
+ "auth": {
345
+ "api": {"type": "bearer", "env": "PICUX_API_TOKEN"},
346
+ "mcp": {"type": "bearer", "env": "PICUX_MCP_TOKEN", "fallback": "PICUX_API_TOKEN"},
347
+ "a2a": {"type": "bearer", "env": "PICUX_A2A_TOKEN", "fallback": "PICUX_API_TOKEN"},
348
+ "public": {"type": "none"},
349
+ },
350
+ "env": [item.toMap() for item in ENV_KEYS],
351
+ "sdk": {
352
+ "python": {
353
+ "client": "picux.sdk.PicuxClient",
354
+ "transport": "picux.sdk.HttpTransport",
355
+ "env": ["PICUX_API_BASE_URL", "PICUX_API_TOKEN"],
356
+ }
357
+ },
358
+ "contracts": {
359
+ "api": "/openapi.json",
360
+ "summary": "/v1/contract",
361
+ "manifest": "/v1/manifest",
362
+ "protocolMap": "/v1/protocol-map",
363
+ "mcp": "/mcp",
364
+ "a2a": "/v1/a2a/contract",
365
+ "schemas": "/v1/schemas",
366
+ },
367
+ "schemas": {
368
+ "catalog": "/v1/schemas",
369
+ "ids": schemaIds,
370
+ },
371
+ "domains": domains,
372
+ "mcpTools": tools,
373
+ "routes": routes,
374
+ }
375
+
376
+
377
+ def _domainMap() -> dict[str, Any]:
378
+ out: dict[str, Any] = {}
379
+ for capability in DOMAIN_CAPABILITIES:
380
+ endpoints = [endpoint for endpoint in CONTRACT_ENDPOINTS if endpoint.tag == capability.id]
381
+ out[capability.id] = capability.toMap(
382
+ routes=[endpoint.toMap() for endpoint in endpoints],
383
+ mcpTools=[str(endpoint.mcpTool) for endpoint in endpoints if endpoint.mcpTool],
384
+ )
385
+ return out
@@ -0,0 +1,187 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from picux import __version__
6
+ from picux.contracts.routes import CONTRACT_ENDPOINTS, ContractEndpoint
7
+
8
+
9
+ def openapiSpec() -> dict[str, Any]:
10
+ paths: dict[str, Any] = {}
11
+ for endpoint in CONTRACT_ENDPOINTS:
12
+ paths.setdefault(endpoint.path, {})[endpoint.method.lower()] = _operation(endpoint)
13
+ return {
14
+ "openapi": "3.1.0",
15
+ "info": {
16
+ "title": "Picux Protocol API",
17
+ "version": __version__,
18
+ "summary": "Agentic economy infrastructure contract for external apps, services, and agents.",
19
+ },
20
+ "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
21
+ "servers": [{"url": "http://127.0.0.1:8088", "description": "Local development"}],
22
+ "tags": _tags(),
23
+ "paths": paths,
24
+ "components": {
25
+ "schemas": {
26
+ "AnyObject": {"type": "object", "additionalProperties": True},
27
+ "Ok": {
28
+ "type": "object",
29
+ "required": ["ok"],
30
+ "properties": {"ok": {"type": "boolean"}},
31
+ "additionalProperties": True,
32
+ },
33
+ "Error": {
34
+ "type": "object",
35
+ "required": ["ok", "error"],
36
+ "properties": {"ok": {"const": False}, "error": {"type": "string"}},
37
+ "additionalProperties": True,
38
+ },
39
+ },
40
+ "securitySchemes": {
41
+ "bearerAuth": {
42
+ "type": "http",
43
+ "scheme": "bearer",
44
+ }
45
+ },
46
+ },
47
+ "security": [{"bearerAuth": []}],
48
+ }
49
+
50
+
51
+ def contractSummary() -> dict[str, Any]:
52
+ return {
53
+ "ok": True,
54
+ "name": "picux",
55
+ "version": __version__,
56
+ "contracts": {
57
+ "api": "/openapi.json",
58
+ "manifest": "/v1/manifest",
59
+ "protocolMap": "/v1/protocol-map",
60
+ "mcp": "/v1/contract",
61
+ },
62
+ "endpoints": [endpoint.toMap() for endpoint in CONTRACT_ENDPOINTS],
63
+ "mcpTools": mcpTools(),
64
+ }
65
+
66
+
67
+ def mcpTools() -> list[dict[str, Any]]:
68
+ tools = []
69
+ for endpoint in CONTRACT_ENDPOINTS:
70
+ if not endpoint.mcpTool:
71
+ continue
72
+ tools.append(
73
+ {
74
+ "name": endpoint.mcpTool,
75
+ "description": endpoint.desc,
76
+ "inputSchema": {
77
+ "type": "object",
78
+ "additionalProperties": True,
79
+ },
80
+ }
81
+ )
82
+ return tools
83
+
84
+
85
+ def _operation(endpoint: ContractEndpoint) -> dict[str, Any]:
86
+ operation: dict[str, Any] = {
87
+ "operationId": endpoint.opId,
88
+ "summary": endpoint.desc,
89
+ "tags": [endpoint.tag],
90
+ "responses": {
91
+ "200": {
92
+ "description": "Picux response",
93
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Ok"}}},
94
+ },
95
+ "404": {
96
+ "description": "Not found",
97
+ "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}},
98
+ },
99
+ },
100
+ }
101
+ params = _pathParams(endpoint.path)
102
+ if params:
103
+ operation["parameters"] = params
104
+ if endpoint.method == "POST":
105
+ operation["requestBody"] = {
106
+ "required": False,
107
+ "content": {
108
+ "application/json": {
109
+ "schema": {"$ref": "#/components/schemas/AnyObject"},
110
+ }
111
+ },
112
+ }
113
+ return operation
114
+
115
+
116
+ def _pathParams(path: str) -> list[dict[str, Any]]:
117
+ params: list[dict[str, Any]] = []
118
+ for name in (
119
+ "taskId",
120
+ "mandateId",
121
+ "receiptId",
122
+ "artifactId",
123
+ "povId",
124
+ "packId",
125
+ "agentId",
126
+ "connectorId",
127
+ "proxyId",
128
+ "escrowId",
129
+ "railId",
130
+ "challengeId",
131
+ "resourceId",
132
+ "adapterId",
133
+ "cardId",
134
+ "schemaId",
135
+ "msgId",
136
+ "signalId",
137
+ "eventId",
138
+ "subId",
139
+ "deliveryId",
140
+ "templateId",
141
+ "sessionId",
142
+ "threadId",
143
+ "touchpointId",
144
+ "actionId",
145
+ "caseId",
146
+ "portalSessionId",
147
+ "portalActionId",
148
+ ):
149
+ if "{" + name + "}" in path:
150
+ params.append(
151
+ {
152
+ "name": name,
153
+ "in": "path",
154
+ "required": True,
155
+ "schema": {"type": "string"},
156
+ }
157
+ )
158
+ return params
159
+
160
+
161
+ def _tags() -> list[dict[str, str]]:
162
+ labels = {
163
+ "runtime": "Runtime health and configuration.",
164
+ "contract": "Machine-readable Picux contracts.",
165
+ "mcp": "MCP JSON-RPC transport for external agents.",
166
+ "a2a": "Agent-to-agent envelope contracts.",
167
+ "security": "Policy evaluation for mandate sessions and capability grants.",
168
+ "sandbox": "Deterministic benchmark traces for developer playgrounds.",
169
+ "orchestrator": "Live developer orchestration across Picux domains.",
170
+ "benchmarks": "Local benchmark evidence and claim labels.",
171
+ "agents": "Agent lifecycle and capability discovery.",
172
+ "tasks": "Task lifecycle.",
173
+ "cases": "Formal case workspaces, deadlines, stakeholders, timelines, and evidence bundle exports.",
174
+ "workflows": "Use-case-first workflow templates.",
175
+ "hunt": "Discovery and telemetry ranking.",
176
+ "resolve": "Resolve decisions and evidence.",
177
+ "bridge": "External connector registry, scope, and preflight contracts.",
178
+ "channels": "Persistent conversation state across provider touchpoints.",
179
+ "proxy": "Human-in-the-loop suspend and resume contracts.",
180
+ "mandates": "Mandate registration and verification.",
181
+ "pay": "PAY settlement and receipts.",
182
+ "audit": "Evidence, proof-of-value, and receipt verification.",
183
+ "signals": "Community signal ingestion and task launch.",
184
+ "events": "External integration event outbox, subscriptions, and delivery attempts.",
185
+ }
186
+ used = dict.fromkeys(endpoint.tag for endpoint in CONTRACT_ENDPOINTS)
187
+ return [{"name": tag, "description": labels.get(tag, "")} for tag in used]