@reinconsole/graph 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +38 -0
- package/dist/index.d.ts +374 -0
- package/dist/index.js +910 -0
- package/dist/index.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../packages/core/src/chain.ts","../../../packages/core/src/money.ts","../../../packages/core/src/glob.ts","../../../packages/core/src/ulid.ts","../../../packages/core/src/ids.ts","../../../packages/core/src/agent.ts","../../../packages/core/src/erc8004.ts","../../../packages/core/src/intent.ts","../../../packages/core/src/decision.ts","../../../packages/core/src/canonical.ts","../../../packages/core/src/session.ts","../../../packages/core/src/payment.ts","../../../packages/core/src/receipt.ts","../../../packages/core/src/gate-receipt.ts","../../../packages/core/src/policy.ts","../../../packages/core/src/reputation.ts","../../../packages/core/src/events.ts","../src/evidence.ts","../src/intents.ts","../src/scoring.ts","../src/graph.ts","../src/server.ts"],"sourcesContent":["import { z } from 'zod';\n\n/**\n * Chains Rein observes/governs. x402 is multi-chain; Base and Solana ship\n * first, Polygon and BNB follow. The policy/ledger domain is rail-agnostic —\n * this enum is the only place chains are enumerated.\n */\nexport const Chain = z.enum(['base', 'solana', 'polygon', 'bnb']);\nexport type Chain = z.infer<typeof Chain>;\n\n/** Stablecoins settled over x402. */\nexport const Asset = z.enum(['USDC', 'USDT', 'EURC']);\nexport type Asset = z.infer<typeof Asset>;\n","import { z } from 'zod';\n\n/**\n * Monetary amounts in Rein are always non-negative **decimal strings**, never\n * floats. Float arithmetic silently loses precision on values like 0.1 + 0.2,\n * which is unacceptable for money. All comparison/aggregation goes through the\n * BigInt-backed helpers below.\n */\nexport const DecimalString = z\n .string()\n .regex(/^\\d+(\\.\\d+)?$/, 'must be a non-negative decimal string, e.g. \"5.00\"');\nexport type DecimalString = z.infer<typeof DecimalString>;\n\nconst DECIMAL_RE = /^\\d+(\\.\\d+)?$/;\n\nexport function isValidDecimal(value: string): boolean {\n return DECIMAL_RE.test(value);\n}\n\nfunction assertDecimal(value: string): void {\n if (!isValidDecimal(value)) {\n throw new TypeError(`invalid decimal string: ${JSON.stringify(value)}`);\n }\n}\n\nfunction fractionLength(value: string): number {\n const dot = value.indexOf('.');\n return dot === -1 ? 0 : value.length - dot - 1;\n}\n\n/** Scale a decimal string into an integer BigInt at a fixed number of fraction digits. */\nfunction toScaled(value: string, scale: number): bigint {\n const dot = value.indexOf('.');\n const intPart = dot === -1 ? value : value.slice(0, dot);\n const fracPart = dot === -1 ? '' : value.slice(dot + 1);\n const paddedFrac = (fracPart + '0'.repeat(scale)).slice(0, scale);\n return BigInt(intPart + paddedFrac);\n}\n\n/** Render a scaled BigInt back to a normalized decimal string (no trailing zeros). */\nfunction fromScaled(scaled: bigint, scale: number): string {\n if (scale === 0) return scaled.toString();\n const digits = scaled.toString().padStart(scale + 1, '0');\n const intPart = digits.slice(0, digits.length - scale);\n const fracPart = digits.slice(digits.length - scale).replace(/0+$/, '');\n return fracPart.length > 0 ? `${intPart}.${fracPart}` : intPart;\n}\n\n/** Compare two decimal strings. Returns -1 (a<b), 0 (a==b), or 1 (a>b). */\nexport function compareDecimal(a: string, b: string): -1 | 0 | 1 {\n assertDecimal(a);\n assertDecimal(b);\n const scale = Math.max(fractionLength(a), fractionLength(b));\n const av = toScaled(a, scale);\n const bv = toScaled(b, scale);\n return av < bv ? -1 : av > bv ? 1 : 0;\n}\n\n/** Sum a list of decimal strings without floating-point error. */\nexport function sumDecimal(values: readonly string[]): string {\n if (values.length === 0) return '0';\n let scale = 0;\n for (const v of values) {\n assertDecimal(v);\n scale = Math.max(scale, fractionLength(v));\n }\n let total = 0n;\n for (const v of values) total += toScaled(v, scale);\n return fromScaled(total, scale);\n}\n\n/** Multiply two decimal strings exactly (e.g. median * \"3\" for price-sanity). */\nexport function mulDecimal(a: string, b: string): string {\n assertDecimal(a);\n assertDecimal(b);\n const scaleA = fractionLength(a);\n const scaleB = fractionLength(b);\n const product = toScaled(a, scaleA) * toScaled(b, scaleB);\n return fromScaled(product, scaleA + scaleB);\n}\n\n/** Convenience: a > b. */\nexport function gt(a: string, b: string): boolean {\n return compareDecimal(a, b) === 1;\n}\n\n/** Convenience: a < b. */\nexport function lt(a: string, b: string): boolean {\n return compareDecimal(a, b) === -1;\n}\n","/**\n * Minimal, safe glob matcher supporting only the `*` wildcard (matches any run\n * of characters, including none). Used for vendor host allowlists\n * (e.g. \"*.trusted.io\"), agent-id targeting (e.g. \"agt_research_*\"), and\n * Gate route pricing (e.g. \"/api/reports/*\").\n *\n * Deliberately NOT a regex from user input — the pattern is escaped so a\n * malicious policy value cannot inject regex behavior (ReDoS, etc.).\n */\nexport function globMatch(pattern: string, value: string): boolean {\n const escaped = pattern.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); // escape regex metachars\n const withWildcard = escaped.replace(/\\\\\\*/g, '.*'); // re-enable only `*`\n return new RegExp(`^${withWildcard}$`).test(value);\n}\n\n/** True if `value` matches any pattern in the list. */\nexport function globMatchAny(patterns: readonly string[], value: string): boolean {\n return patterns.some((p) => globMatch(p, value));\n}\n","/**\n * Minimal ULID generation, dependency-free. ULIDs are lexicographically\n * sortable (time-prefixed) and url-safe, which is why Rein uses them for all\n * primary keys instead of UUIDs. Works in Node 22 and modern browsers/edge via\n * the WebCrypto `globalThis.crypto`.\n */\n\n// Crockford's base32 alphabet (excludes I, L, O, U to avoid ambiguity).\nconst ENCODING = '0123456789ABCDEFGHJKMNPQRSTVWXYZ';\nconst TIME_LEN = 10;\nconst RANDOM_LEN = 16;\n\nfunction randomBytes(length: number): Uint8Array {\n const bytes = new Uint8Array(length);\n globalThis.crypto.getRandomValues(bytes);\n return bytes;\n}\n\nfunction encodeTime(now: number): string {\n let time = now;\n let out = '';\n for (let i = TIME_LEN - 1; i >= 0; i--) {\n out = ENCODING.charAt(time % 32) + out;\n time = Math.floor(time / 32);\n }\n return out;\n}\n\nfunction encodeRandom(): string {\n let out = '';\n for (const byte of randomBytes(RANDOM_LEN)) {\n out += ENCODING.charAt(byte % 32);\n }\n return out;\n}\n\n/** Generate a 26-character ULID. */\nexport function ulid(seedTime: number = Date.now()): string {\n return encodeTime(seedTime) + encodeRandom();\n}\n\n/** Generate a Stripe-style prefixed id, e.g. `newId('agt')` -> `agt_01J...`. */\nexport function newId<P extends string>(prefix: P): `${P}_${string}` {\n return `${prefix}_${ulid()}`;\n}\n","import { z } from 'zod';\n\n/** Crockford base32 ULID body (26 chars), as produced by `ulid()`. */\nconst ULID_BODY = '[0-9A-HJKMNP-TV-Z]{26}';\n\n/**\n * A zod schema for a Stripe-style prefixed ULID, e.g. `agt_01J7...`.\n * Centralizing this keeps id formats consistent across DB rows, API payloads,\n * and SDK types.\n */\nexport function prefixedId(prefix: string) {\n return z\n .string()\n .regex(new RegExp(`^${prefix}_${ULID_BODY}$`), `expected a \"${prefix}_\" prefixed id`);\n}\n\nexport const OrgId = prefixedId('org');\nexport const AgentId = prefixedId('agt');\nexport const PolicyId = prefixedId('pol');\nexport const IntentId = prefixedId('int');\nexport const DecisionId = prefixedId('dec');\nexport const ReceiptId = prefixedId('rcp');\nexport const SessionId = prefixedId('ses');\nexport const GateReceiptId = prefixedId('grc');\n\nexport type OrgId = z.infer<typeof OrgId>;\nexport type AgentId = z.infer<typeof AgentId>;\nexport type PolicyId = z.infer<typeof PolicyId>;\nexport type IntentId = z.infer<typeof IntentId>;\nexport type DecisionId = z.infer<typeof DecisionId>;\nexport type ReceiptId = z.infer<typeof ReceiptId>;\nexport type SessionId = z.infer<typeof SessionId>;\nexport type GateReceiptId = z.infer<typeof GateReceiptId>;\n","import { z } from 'zod';\nimport { AgentId, OrgId } from './ids.js';\nimport { Chain } from './chain.js';\n\n/**\n * Enforcement tier of a given agent wallet:\n * - `observed` — Rein sees spend on-chain but has no control (no SDK either).\n * - `sdk` — agent uses @reinconsole/sdk; advisory + observability (bypassable).\n * - `session-key` — signer-level scope; out-of-policy txs cannot be signed.\n */\nexport const EnforcementMode = z.enum(['observed', 'sdk', 'session-key']);\nexport type EnforcementMode = z.infer<typeof EnforcementMode>;\n\nexport const AgentWallet = z.object({\n chain: Chain,\n address: z.string().min(1),\n mode: EnforcementMode,\n});\nexport type AgentWallet = z.infer<typeof AgentWallet>;\n\nexport const AgentStatus = z.enum(['active', 'frozen']);\nexport type AgentStatus = z.infer<typeof AgentStatus>;\n\nexport const Agent = z.object({\n id: AgentId,\n orgId: OrgId,\n name: z.string().min(1).max(200),\n /** On-chain ERC-8004 identity, if the agent is registered. */\n erc8004Id: z.string().optional(),\n wallets: z.array(AgentWallet).default([]),\n status: AgentStatus.default('active'),\n createdAt: z.coerce.date(),\n});\nexport type Agent = z.infer<typeof Agent>;\n","import { z } from 'zod';\n\n/**\n * The canonical string form of an ERC-8004 agent identity:\n *\n * eip155:{chainId}:{identityRegistry}/{tokenId}\n *\n * The part before the `/` is the spec's registry reference verbatim (the\n * `agentRegistry` field of a registration file, CAIP-10 account form); the\n * tokenId is the ERC-721 id the Identity Registry minted (`agentId` in the\n * spec). This exact string is what `Agent.erc8004Id` / `Vendor.erc8004Id`\n * carry, AND the reputation-subject id a registered agent's evidence keys by.\n *\n * Casing is load-bearing: reputation subject keys for agent-kind ids are\n * case-sensitive unless they start with `0x` (see @reinconsole/graph\n * `normalizeSubject`), and an eip155 string does not. `formatErc8004Id`\n * therefore always emits the registry address in lowercase, and consumers must\n * never hand-build the string — parse then re-format to normalize.\n */\n\nexport interface Erc8004Ref {\n /** EIP-155 chain id (e.g. 8453 Base, 84532 Base Sepolia). */\n chainId: number;\n /** Identity Registry contract address, lowercase 0x-hex. */\n registry: string;\n /** ERC-721 tokenId — the spec's `agentId`. bigint: token ids exceed 2^53. */\n tokenId: bigint;\n}\n\nconst REGISTRY_PATTERN = /^0x[0-9a-fA-F]{40}$/;\nconst ID_PATTERN = /^eip155:(\\d+):(0x[0-9a-fA-F]{40})\\/(\\d+)$/;\n\n/** Build the canonical id string. Throws on a malformed ref (programmer error). */\nexport function formatErc8004Id(ref: Erc8004Ref): string {\n if (!Number.isSafeInteger(ref.chainId) || ref.chainId < 1) {\n throw new RangeError(`erc8004: bad chainId ${ref.chainId}`);\n }\n if (!REGISTRY_PATTERN.test(ref.registry)) {\n throw new RangeError(`erc8004: bad registry address ${ref.registry}`);\n }\n if (typeof ref.tokenId !== 'bigint' || ref.tokenId < 0n) {\n // The typeof guard matters for plain-JS callers: 1.5 < 0n is legal JS and\n // false, and would mint the unparseable \"…/1.5\".\n throw new RangeError(`erc8004: bad tokenId ${ref.tokenId}`);\n }\n return `eip155:${ref.chainId}:${ref.registry.toLowerCase()}/${ref.tokenId}`;\n}\n\n/**\n * Parse a canonical (or hand-written) id string. Accepts any address casing\n * and returns a lowercase ref, or undefined when malformed — so\n * `formatErc8004Id(parseErc8004Id(x)!)` is the normalization step.\n */\nexport function parseErc8004Id(value: string): Erc8004Ref | undefined {\n const match = ID_PATTERN.exec(value);\n if (!match) return undefined;\n const chainId = Number(match[1]);\n if (!Number.isSafeInteger(chainId) || chainId < 1) return undefined;\n return {\n chainId,\n registry: match[2]!.toLowerCase(),\n tokenId: BigInt(match[3]!),\n };\n}\n\n/** Strict boundary schema for the id string (the fields themselves stay free-form). */\nexport const Erc8004Id = z\n .string()\n .refine((value) => parseErc8004Id(value) !== undefined, {\n message: 'expected \"eip155:{chainId}:{registry}/{tokenId}\"',\n });\nexport type Erc8004Id = z.infer<typeof Erc8004Id>;\n","import { z } from 'zod';\nimport { AgentId, IntentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\n\nexport const Vendor = z.object({\n host: z.string().min(1),\n address: z.string().min(1),\n erc8004Id: z.string().optional(),\n});\nexport type Vendor = z.infer<typeof Vendor>;\n\n/**\n * The observability gold: links every micro-payment back to the task and run\n * that caused it, so finance teams can answer \"what was this spend for?\".\n */\nexport const TaskContext = z.object({\n taskId: z.string().optional(),\n parentRunId: z.string().optional(),\n purpose: z.string().max(500).optional(),\n});\nexport type TaskContext = z.infer<typeof TaskContext>;\n\n/**\n * A request to spend, submitted to the policy engine BEFORE any signature is\n * released. The `nonce` provides replay protection on the signer path.\n */\nexport const PaymentIntent = z.object({\n id: IntentId,\n agentId: AgentId,\n vendor: Vendor,\n resource: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n nonce: z.string().min(1),\n createdAt: z.coerce.date(),\n});\nexport type PaymentIntent = z.infer<typeof PaymentIntent>;\n","import { z } from 'zod';\nimport { DecisionId, IntentId } from './ids.js';\n\nexport const DecisionOutcome = z.enum(['allow', 'deny', 'escalate']);\nexport type DecisionOutcome = z.infer<typeof DecisionOutcome>;\n\n/**\n * The signed, hash-chained record of a single policy evaluation. Written BEFORE\n * any signature is released. `prevHash` + `hash` form a tamper-evident chain;\n * `signature` is the policy service's signing key over `hash`. The eventual\n * on-chain `txHash` is attached later by the indexer (see SettledPayment).\n */\nexport const Decision = z.object({\n id: DecisionId,\n intentId: IntentId,\n /**\n * sha256 of the intent's canonical content (see canonical.ts). Binds the\n * decision to the exact transfer it judged — amount, recipient, asset,\n * chain — so a signer can verify an {intent, decision} pair offline as a\n * self-contained spend voucher, not just a reference by id.\n */\n intentHash: z.string(),\n outcome: DecisionOutcome,\n /** Ids of the rules that fired, for explainability. */\n matchedRules: z.array(z.string()).default([]),\n /** Human-readable explanation surfaced in the dashboard. */\n reason: z.string().optional(),\n policyId: z.string(),\n policyVersion: z.string(),\n /** Hash of the previous decision in the chain (tamper-evident log). */\n prevHash: z.string(),\n /** Hash of this decision's canonical content. */\n hash: z.string(),\n /** Service signing-key signature over `hash`. */\n signature: z.string(),\n latencyMs: z.number().nonnegative(),\n decidedAt: z.coerce.date(),\n});\nexport type Decision = z.infer<typeof Decision>;\n","import type { PaymentIntent } from './intent.js';\nimport type { DecisionOutcome } from './decision.js';\n\n/**\n * Canonical byte forms shared by the policy engine (which hashes and signs\n * them) and the signer (which verifies them offline). Field order is fixed,\n * dates are ISO strings, and absent optionals are explicit nulls, so the same\n * parsed object always canonicalizes to the same bytes — including after a\n * JSON round-trip over HTTP.\n *\n * These builders are pure (no node:crypto) so @reinconsole/core stays loadable in a\n * browser; services hash the strings with whatever sha256 they have.\n */\n\n/** Canonical form of an intent — what `Decision.intentHash` commits to. */\nexport function canonicalIntent(intent: PaymentIntent): string {\n return JSON.stringify({\n id: intent.id,\n agentId: intent.agentId,\n vendor: {\n host: intent.vendor.host,\n address: intent.vendor.address,\n erc8004Id: intent.vendor.erc8004Id ?? null,\n },\n resource: intent.resource,\n amount: intent.amount,\n asset: intent.asset,\n chain: intent.chain,\n taskContext: {\n taskId: intent.taskContext.taskId ?? null,\n parentRunId: intent.taskContext.parentRunId ?? null,\n purpose: intent.taskContext.purpose ?? null,\n },\n nonce: intent.nonce,\n createdAt: intent.createdAt.toISOString(),\n });\n}\n\n/** The decision fields covered by `Decision.hash` (and thus its signature). */\nexport interface DecisionContent {\n intentId: string;\n intentHash: string;\n outcome: DecisionOutcome;\n matchedRules: string[];\n policyId: string;\n policyVersion: string;\n prevHash: string;\n decidedAt: Date;\n}\n\n/** Canonical form of a decision — what `Decision.hash` is computed over. */\nexport function canonicalDecision(d: DecisionContent): string {\n return JSON.stringify({\n intentId: d.intentId,\n intentHash: d.intentHash,\n outcome: d.outcome,\n matchedRules: d.matchedRules,\n policyId: d.policyId,\n policyVersion: d.policyVersion,\n prevHash: d.prevHash,\n decidedAt: d.decidedAt.toISOString(),\n });\n}\n","import { z } from 'zod';\nimport { AgentId, SessionId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * A session-key grant: the signer tier's unit of delegated authority. The\n * agent process holds only the bearer token — the wallet key never leaves the\n * signer — and the stored record keeps a hash of the token, never the token\n * itself (it is returned exactly once, at creation).\n *\n * Caps here are the signer-side backstop UNDER whatever policy says: a\n * signature is released only when the engine allowed the intent AND the\n * session has room. Amounts are decimal strings in the asset's human units.\n */\nexport const Session = z.object({\n id: SessionId,\n agentId: AgentId,\n /** sha256 hex of the bearer token. */\n tokenHash: z.string(),\n /** Cumulative ceiling across the session's lifetime. Absent = uncapped. */\n capAmount: DecimalString.optional(),\n /** Ceiling per individual signature. Absent = uncapped. */\n maxPerPayment: DecimalString.optional(),\n expiresAt: z.coerce.date(),\n createdAt: z.coerce.date(),\n revokedAt: z.coerce.date().optional(),\n});\nexport type Session = z.infer<typeof Session>;\n","import { z } from 'zod';\nimport { IntentId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/**\n * On-chain confirmation of a settled payment, reconciled by the indexer against\n * the originating intent (amount + recipient + nonce, or facilitator webhook).\n */\nexport const SettledPayment = z.object({\n intentId: IntentId,\n txHash: z.string(),\n chain: Chain,\n blockNumber: z.coerce.bigint(),\n facilitator: z.string().optional(),\n feePaid: DecimalString.optional(),\n confirmedAt: z.coerce.date(),\n});\nexport type SettledPayment = z.infer<typeof SettledPayment>;\n","import { z } from 'zod';\nimport { ReceiptId, IntentId, DecisionId, AgentId } from './ids.js';\nimport { Chain, Asset } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { TaskContext } from './intent.js';\nimport { DecisionOutcome } from './decision.js';\n\n/**\n * What the SDK reports back after settlement: the `X-PAYMENT-RESPONSE` header\n * a vendor returns once payment clears. Mock facilitators fill this in v0.1;\n * the indexer reconciles it against on-chain truth later (see SettledPayment).\n */\nexport const ReceiptSettlement = z.object({\n txHash: z.string().optional(),\n networkId: z.string().optional(),\n /** Raw header payload, kept for forensics until the indexer confirms. */\n raw: z.string().optional(),\n});\nexport type ReceiptSettlement = z.infer<typeof ReceiptSettlement>;\n\n/**\n * The SDK-side record of one guarded payment attempt: which request triggered\n * it, what the engine decided, and (if allowed and paid) how it settled.\n * Receipts are the observability primitive — every 402 the guard touches\n * produces exactly one, whether the payment was allowed or blocked.\n */\nexport const Receipt = z.object({\n id: ReceiptId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n outcome: DecisionOutcome,\n /** The URL the agent actually fetched (the paywalled resource). */\n url: z.string(),\n method: z.string().default('GET'),\n vendorHost: z.string(),\n amount: DecimalString,\n asset: Asset,\n chain: Chain,\n taskContext: TaskContext.default({}),\n /** Human-readable explanation copied from the decision. */\n reason: z.string().optional(),\n /** Present only once a payment was made and the vendor confirmed it. */\n settlement: ReceiptSettlement.optional(),\n createdAt: z.coerce.date(),\n});\nexport type Receipt = z.infer<typeof Receipt>;\n","import { z } from 'zod';\nimport { GateReceiptId } from './ids.js';\nimport { DecimalString } from './money.js';\n\n/**\n * The vendor-side twin of `Receipt`: one settled x402 payment as the GATE saw\n * it — who paid, for which priced route, and the settlement transaction. The\n * agent-side Receipt records what an agent tried to spend; a GateReceipt\n * records what a vendor actually earned.\n */\nexport const GateReceipt = z.object({\n id: GateReceiptId,\n at: z.coerce.date(),\n /** The route pattern that priced this request, e.g. \"/api/reports/*\". */\n route: z.string().min(1),\n /** The concrete resource paid for (URL path actually requested). */\n resource: z.string().min(1),\n method: z.string().min(1),\n /** The paying wallet address, as asserted by the settled payment. */\n payer: z.string().min(1),\n payTo: z.string().min(1),\n /** Human-unit decimal amount, e.g. \"0.05\". */\n amount: DecimalString,\n /** The same amount in the asset's atomic units, e.g. \"50000\". */\n amountAtomic: z.string().regex(/^\\d+$/, 'atomic amount must be an integer string'),\n /** Token symbol or contract address, exactly as quoted in the requirement. */\n asset: z.string().min(1),\n network: z.string().min(1),\n /** Settlement transaction hash (mock ledger or on-chain). */\n transaction: z.string().min(1),\n});\nexport type GateReceipt = z.infer<typeof GateReceipt>;\n","import { z } from 'zod';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\n\n/** A rolling-window spec, e.g. \"24h\", \"1h\", \"30m\", \"7d\". */\nexport const Window = z\n .string()\n .regex(/^\\d+[smhd]$/, 'window must be like \"30s\", \"15m\", \"1h\", or \"7d\"');\nexport type Window = z.infer<typeof Window>;\n\n/** A relative multiplier, e.g. \"3x\" (used for price-sanity checks). */\nexport const Multiplier = z.string().regex(/^\\d+(\\.\\d+)?x$/, 'multiplier must be like \"3x\"');\nexport type Multiplier = z.infer<typeof Multiplier>;\n\n/**\n * The set of predicates a rule can test. Multiple predicates in one condition\n * are ANDed together. Each maps to an evaluator in the policy engine.\n */\nexport const Condition = z\n .object({\n /** Per-transaction amount exceeds this value. */\n amountGt: DecimalString.optional(),\n /** Sum of spend in a rolling window exceeds `gt`. */\n rollingSum: z.object({ window: Window, gt: DecimalString }).optional(),\n /** Transaction count in a rolling window exceeds `gt`. */\n txCount: z.object({ window: Window, gt: z.number().int().nonnegative() }).optional(),\n /** Vendor host matches one of these patterns (supports `*` globs). */\n vendorHostIn: z.array(z.string()).optional(),\n /** First time Rein has seen this vendor for the agent. */\n vendorFirstSeen: z.boolean().optional(),\n /** Vendor reputation score is below this threshold (Phase 3 hook). */\n vendorReputationLt: z.number().min(0).max(100).optional(),\n /** Amount is more than `gt`-times the observed median for this resource. */\n amountVsResourceMedian: z.object({ gt: Multiplier }).optional(),\n })\n .refine((c) => Object.values(c).some((v) => v !== undefined), {\n message: 'a condition must specify at least one predicate',\n });\nexport type Condition = z.infer<typeof Condition>;\n\n/**\n * A single rule: an id plus exactly one action (allow / deny / escalate) whose\n * value is the condition that triggers it.\n */\nexport const Rule = z\n .object({\n id: z.string().min(1),\n allow: Condition.optional(),\n deny: Condition.optional(),\n escalate: Condition.optional(),\n })\n .refine((r) => [r.allow, r.deny, r.escalate].filter((v) => v !== undefined).length === 1, {\n message: 'a rule must specify exactly one of allow / deny / escalate',\n });\nexport type Rule = z.infer<typeof Rule>;\n\nexport const PolicyDefault = z.enum(['allow', 'deny']);\nexport type PolicyDefault = z.infer<typeof PolicyDefault>;\n\nexport const AppliesTo = z.object({\n /** Agent id patterns (supports `*` globs, e.g. \"agt_research_*\"). */\n agents: z.array(z.string()).optional(),\n chains: z.array(Chain).optional(),\n});\nexport type AppliesTo = z.infer<typeof AppliesTo>;\n\nexport const Escalation = z.object({\n approvers: z.array(z.string()).default([]),\n timeoutAction: PolicyDefault.default('deny'),\n timeoutMin: z.number().int().positive().default(15),\n});\nexport type Escalation = z.infer<typeof Escalation>;\n\n/**\n * A declarative, versioned, immutable-once-active policy. Evaluation order in\n * the engine is: explicit DENY > ESCALATE > ALLOW > `default`.\n */\nexport const Policy = z.object({\n policyId: z.string().min(1),\n version: z.string().default('1'),\n appliesTo: AppliesTo.default({}),\n rules: z.array(Rule).default([]),\n default: PolicyDefault.default('deny'),\n /** Below this amount, fail-open is permitted during a policy-service outage. */\n denyFloor: DecimalString.default('0.05'),\n escalation: Escalation.optional(),\n});\nexport type Policy = z.infer<typeof Policy>;\n","import { z } from 'zod';\n\nexport const ReputationSubject = z.object({\n kind: z.enum(['agent', 'vendor']),\n id: z.string(),\n});\nexport type ReputationSubject = z.infer<typeof ReputationSubject>;\n\nexport const ReputationComponents = z.object({\n volume: z.number(),\n longevity: z.number(),\n disputeRate: z.number(),\n counterpartyQuality: z.number(),\n settlementReliability: z.number(),\n});\nexport type ReputationComponents = z.infer<typeof ReputationComponents>;\n\n/**\n * A reputation score for an agent or vendor (Phase 3 — Graph). `confidence` is\n * first-class: a thin-history subject returns LOW confidence rather than a\n * misleadingly high score, so policy can avoid both false trust and unfair\n * freezing.\n */\nexport const ReputationScore = z.object({\n subject: ReputationSubject,\n score: z.number().min(0).max(100),\n components: ReputationComponents,\n confidence: z.number().min(0).max(1),\n asOf: z.coerce.date(),\n /** Hash-anchored attestation, optionally published on-chain (ERC-8004). */\n evidenceUri: z.string().optional(),\n});\nexport type ReputationScore = z.infer<typeof ReputationScore>;\n","import { z } from 'zod';\nimport { AgentId, DecisionId, IntentId, SessionId } from './ids.js';\nimport { Chain } from './chain.js';\nimport { DecimalString } from './money.js';\nimport { PaymentIntent } from './intent.js';\nimport { Decision } from './decision.js';\nimport { SettledPayment } from './payment.js';\nimport { GateReceipt } from './gate-receipt.js';\n\n/**\n * The canonical event envelope published on the bus (NATS in production).\n * `shadow.spend` is emitted when the indexer sees on-chain spend from a managed\n * wallet with NO corresponding ALLOW decision — the bypass signal that catches\n * SDK-mode evasion and drives the upgrade to the signer tier.\n * `signature.released` / `signature.refused` are that tier's heartbeat: every\n * time the signer does or does not put a key to work, the bus knows why.\n * `gate.*` is the vendor side of the wire: every quote a Gate issues, every\n * payment it accepts, every payment it turns away.\n */\nexport const ReinEvent = z.discriminatedUnion('type', [\n z.object({ type: z.literal('intent.created'), at: z.coerce.date(), intent: PaymentIntent }),\n z.object({ type: z.literal('decision.made'), at: z.coerce.date(), decision: Decision }),\n z.object({ type: z.literal('payment.settled'), at: z.coerce.date(), payment: SettledPayment }),\n z.object({\n type: z.literal('shadow.spend'),\n at: z.coerce.date(),\n agentId: AgentId,\n txHash: z.string(),\n chain: Chain,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.released'),\n at: z.coerce.date(),\n sessionId: SessionId,\n agentId: AgentId,\n intentId: IntentId,\n decisionId: DecisionId,\n amount: DecimalString,\n }),\n z.object({\n type: z.literal('signature.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"decision_replayed\" (see @reinconsole/signer). */\n code: z.string(),\n reason: z.string(),\n sessionId: SessionId.optional(),\n agentId: AgentId.optional(),\n intentId: IntentId.optional(),\n }),\n z.object({\n type: z.literal('gate.quoted'),\n at: z.coerce.date(),\n resource: z.string(),\n method: z.string(),\n amount: DecimalString,\n asset: z.string(),\n network: z.string(),\n }),\n z.object({ type: z.literal('gate.settled'), at: z.coerce.date(), receipt: GateReceipt }),\n z.object({\n type: z.literal('gate.refused'),\n at: z.coerce.date(),\n /** Refusal code, e.g. \"payment_replayed\" (see @reinconsole/gate). */\n code: z.string(),\n reason: z.string(),\n resource: z.string(),\n /** Known only when the payment header decoded far enough to name a payer. */\n payer: z.string().optional(),\n }),\n]);\nexport type ReinEvent = z.infer<typeof ReinEvent>;\n","import { formatErc8004Id, parseErc8004Id, sumDecimal, type ReputationSubject } from '@reinconsole/core';\n\n/** A value that may be produced synchronously or awaited (durable writes). */\nexport type MaybePromise<T> = T | Promise<T>;\n\n/** One settled-money edge to a counterparty (the \"graph\" in reputation graph). */\nexport interface CounterpartyLine {\n settled: number;\n /** Settled decimal volume across this edge. */\n volume: string;\n}\n\n/**\n * Everything the graph has observed about one subject. Counters are raw and\n * append-only — scoring (scoring.ts) is a pure function over this record, so a\n * score is always re-derivable and explainable from the evidence behind it.\n */\nexport interface SubjectEvidence {\n subject: ReputationSubject;\n firstSeenMs: number;\n lastSeenMs: number;\n /** Payment attempts observed (allowed intents, presented payments). */\n attempts: number;\n /** Confirmed settlements (indexer-reconciled or gate-receipted). */\n settled: number;\n /** Settled decimal volume. */\n volume: string;\n /** Refusals by code (gate refusal codes, signer refusal codes). */\n refusals: Record<string, number>;\n /** Managed-wallet spend with no ALLOW decision behind it (bypass). */\n shadowSpends: number;\n /** Manual out-of-band reports (chargebacks, fraud complaints). */\n disputes: number;\n /** Manual out-of-band vouches. */\n endorsements: number;\n /** Who this subject has settled money with, keyed by subjectKey(). */\n counterparties: Map<string, CounterpartyLine>;\n}\n\n/**\n * Canonical subject identity. Hosts and EVM addresses are case-insensitive,\n * so they normalize to lowercase; ULID agent ids are case-sensitive and pass\n * through. ERC-8004 ids (`eip155:{chainId}:{registry}/{tokenId}`) normalize\n * via parse->format — @reinconsole/erc8004 always emits the canonical form, but this\n * is the graph's OWN boundary (remote producers hit POST /v1/links with\n * hand-built strings), and a checksummed registry or zero-padded tokenId\n * variant must not mint a split subject row. Note the two id spaces under\n * kind \"agent\": the engine names agents by ULID, a gate names them by paying\n * wallet — ERC-8004 linking (S17) folds both into the on-chain identity.\n */\nexport function normalizeSubject(subject: ReputationSubject): ReputationSubject {\n if (subject.id.startsWith('eip155:')) {\n const ref = parseErc8004Id(subject.id);\n if (ref) return { kind: subject.kind, id: formatErc8004Id(ref) };\n // Malformed eip155-ish strings fall through to the plain rules below.\n }\n const id =\n subject.kind === 'vendor' || subject.id.startsWith('0x') || subject.id.startsWith('0X')\n ? subject.id.toLowerCase()\n : subject.id;\n return { kind: subject.kind, id };\n}\n\nexport function subjectKey(subject: ReputationSubject): string {\n const normal = normalizeSubject(subject);\n return `${normal.kind}:${normal.id}`;\n}\n\n/**\n * The evidence store seam the graph depends on. Writes may be asynchronous (a\n * durable ledger persists behind them); reads are synchronous from the\n * hydrated working set so `score()` / `payerCheck()` stay sync in the gate hot\n * path. Mutations are explicit, atomic operations rather than a returned record\n * the caller mutates — that is what lets a durable implementation persist them.\n */\nexport interface EvidenceLedgerPort {\n /** A payment attempt (allowed intent / presented payment). */\n recordAttempt(subject: ReputationSubject, atMs: number): MaybePromise<void>;\n /** A confirmed settlement between two subjects (credits both sides + the edge). */\n recordSettlement(\n a: ReputationSubject,\n b: ReputationSubject,\n amount: string,\n atMs: number,\n ): MaybePromise<void>;\n /** A refusal against a subject, by code. */\n recordRefusal(subject: ReputationSubject, code: string, atMs: number): MaybePromise<void>;\n /** Managed-wallet spend with no ALLOW behind it. */\n recordShadowSpend(subject: ReputationSubject, atMs: number): MaybePromise<void>;\n /** An out-of-band dispute. */\n recordDispute(subject: ReputationSubject, atMs: number): MaybePromise<void>;\n /** An out-of-band endorsement. */\n recordEndorsement(subject: ReputationSubject, atMs: number): MaybePromise<void>;\n /**\n * Fold everything known about `alias` into `canonical` and forget the alias:\n * counters sum, volumes add, first/last seen widen, and settled-money edges\n * re-key on BOTH endpoints (peers that pointed at the alias now point at the\n * canonical subject). No-op when the alias has no record — which makes\n * re-asserting links at boot idempotent. This is the identity-linking\n * primitive (ERC-8004: one on-chain identity, many addresses/ids).\n */\n merge(canonical: ReputationSubject, alias: ReputationSubject): MaybePromise<void>;\n get(subject: ReputationSubject): SubjectEvidence | undefined;\n getByKey(key: string): SubjectEvidence | undefined;\n all(): IterableIterator<SubjectEvidence>;\n readonly size: number;\n /**\n * Await any pending durable writes (no-op in memory). Durable\n * implementations surface write failures HERE — the graph fire-and-forgets\n * its writes (a bus handler cannot await), so flush() is the error channel.\n */\n flush?(): Promise<void>;\n}\n\n/** The evidence store: one record per subject, created on first sighting. */\nexport class EvidenceLedger implements EvidenceLedgerPort {\n private readonly records = new Map<string, SubjectEvidence>();\n\n recordAttempt(subject: ReputationSubject, atMs: number): void {\n this.touch(subject, atMs).attempts += 1;\n }\n\n recordSettlement(\n a: ReputationSubject,\n b: ReputationSubject,\n amount: string,\n atMs: number,\n ): void {\n for (const [subject, other] of [\n [a, b],\n [b, a],\n ] as const) {\n const ev = this.touch(subject, atMs);\n ev.settled += 1;\n ev.volume = sumDecimal([ev.volume, amount]);\n const key = subjectKey(other);\n const line = ev.counterparties.get(key) ?? { settled: 0, volume: '0' };\n line.settled += 1;\n line.volume = sumDecimal([line.volume, amount]);\n ev.counterparties.set(key, line);\n }\n }\n\n recordRefusal(subject: ReputationSubject, code: string, atMs: number): void {\n const ev = this.touch(subject, atMs);\n ev.refusals[code] = (ev.refusals[code] ?? 0) + 1;\n }\n\n recordShadowSpend(subject: ReputationSubject, atMs: number): void {\n this.touch(subject, atMs).shadowSpends += 1;\n }\n\n recordDispute(subject: ReputationSubject, atMs: number): void {\n this.touch(subject, atMs).disputes += 1;\n }\n\n recordEndorsement(subject: ReputationSubject, atMs: number): void {\n this.touch(subject, atMs).endorsements += 1;\n }\n\n merge(canonical: ReputationSubject, alias: ReputationSubject): void {\n const aliasKey = subjectKey(alias);\n const canonicalKey = subjectKey(canonical);\n const from = this.records.get(aliasKey);\n if (!from || aliasKey === canonicalKey) return;\n // The canonical side may have no record yet — the alias's history becomes\n // its history (same create shape as touch, seeded with the alias's window).\n const into = this.records.get(canonicalKey) ?? this.touch(canonical, from.firstSeenMs);\n into.firstSeenMs = Math.min(into.firstSeenMs, from.firstSeenMs);\n into.lastSeenMs = Math.max(into.lastSeenMs, from.lastSeenMs);\n into.attempts += from.attempts;\n into.settled += from.settled;\n into.volume = sumDecimal([into.volume, from.volume]);\n for (const [code, count] of Object.entries(from.refusals)) {\n into.refusals[code] = (into.refusals[code] ?? 0) + count;\n }\n into.shadowSpends += from.shadowSpends;\n into.disputes += from.disputes;\n into.endorsements += from.endorsements;\n for (const [peerKey, line] of from.counterparties) {\n if (peerKey === canonicalKey) continue; // a self-edge would score the subject by itself\n const existing = into.counterparties.get(peerKey) ?? { settled: 0, volume: '0' };\n existing.settled += line.settled;\n existing.volume = sumDecimal([existing.volume, line.volume]);\n into.counterparties.set(peerKey, existing);\n // Re-key the peer's reverse edge: alias -> canonical.\n const peer = this.records.get(peerKey);\n const held = peer?.counterparties.get(aliasKey);\n if (peer && held) {\n peer.counterparties.delete(aliasKey);\n const reverse = peer.counterparties.get(canonicalKey) ?? { settled: 0, volume: '0' };\n reverse.settled += held.settled;\n reverse.volume = sumDecimal([reverse.volume, held.volume]);\n peer.counterparties.set(canonicalKey, reverse);\n }\n }\n into.counterparties.delete(aliasKey);\n this.records.delete(aliasKey);\n }\n\n get(subject: ReputationSubject): SubjectEvidence | undefined {\n return this.records.get(subjectKey(subject));\n }\n\n getByKey(key: string): SubjectEvidence | undefined {\n return this.records.get(key);\n }\n\n all(): IterableIterator<SubjectEvidence> {\n return this.records.values();\n }\n\n get size(): number {\n return this.records.size;\n }\n\n /**\n * Insert a fully-formed record verbatim — the hydration primitive a durable\n * store uses to rebuild the working set on open. Bypasses the live counters\n * (the record already holds its accumulated state and timestamps).\n */\n load(record: SubjectEvidence): void {\n this.records.set(subjectKey(record.subject), record);\n }\n\n /** Get-or-create the record for a subject and stamp first/last seen. */\n private touch(subject: ReputationSubject, atMs: number): SubjectEvidence {\n const key = subjectKey(subject);\n let record = this.records.get(key);\n if (!record) {\n record = {\n subject: normalizeSubject(subject),\n firstSeenMs: atMs,\n lastSeenMs: atMs,\n attempts: 0,\n settled: 0,\n volume: '0',\n refusals: {},\n shadowSpends: 0,\n disputes: 0,\n endorsements: 0,\n counterparties: new Map(),\n };\n this.records.set(key, record);\n }\n if (atMs < record.firstSeenMs) record.firstSeenMs = atMs;\n if (atMs > record.lastSeenMs) record.lastSeenMs = atMs;\n return record;\n }\n}\n","import type { MaybePromise } from './evidence.js';\n\n/**\n * What an `intent.created` event tells us, kept until the matching\n * `payment.settled` (which carries only an intentId) can be attributed.\n */\nexport interface IntentFacts {\n agentId: string;\n host: string;\n amount: string;\n}\n\nexport const DEFAULT_CORRELATION_LIMIT = 10_000;\n\n/**\n * Bridges `intent.created` -> later `payment.settled`/`decision.made`. A\n * `payment.settled` event names only an intentId, so the graph remembers every\n * undecided intent until it settles. Bounded (oldest-evicted) so undecided\n * intents that never settle cannot leak. Writes may be async (a durable store\n * persists them so an in-flight intent survives a restart); reads are sync.\n */\nexport interface IntentCorrelationPort {\n remember(intentId: string, facts: IntentFacts): MaybePromise<void>;\n /** Read the facts without consuming them (decision.made reads, doesn't burn). */\n peek(intentId: string): IntentFacts | undefined;\n /** Read and consume (payment.settled attributes once, then forgets). */\n take(intentId: string): IntentFacts | undefined;\n readonly size: number;\n /**\n * Await any pending durable writes (no-op in memory). Durable\n * implementations surface write failures HERE — the graph fire-and-forgets\n * its writes, so flush() is the error channel.\n */\n flush?(): Promise<void>;\n}\n\n/** In-memory correlation map with FIFO eviction once `limit` is reached. */\nexport class InMemoryIntentStore implements IntentCorrelationPort {\n private readonly intents = new Map<string, IntentFacts>();\n\n constructor(private readonly limit: number = DEFAULT_CORRELATION_LIMIT) {}\n\n remember(intentId: string, facts: IntentFacts): void {\n // Re-remembering an existing id is an update, not a new entry — evicting\n // for it would shrink the working set below the bound (and desync a\n // durable mirror, whose upsert adds no row). Updates keep their position,\n // matching an SQL upsert leaving seq unchanged.\n if (!this.intents.has(intentId) && this.intents.size >= this.limit) {\n const oldest = this.intents.keys().next().value;\n if (oldest !== undefined) this.intents.delete(oldest);\n }\n this.intents.set(intentId, facts);\n }\n\n peek(intentId: string): IntentFacts | undefined {\n return this.intents.get(intentId);\n }\n\n take(intentId: string): IntentFacts | undefined {\n const facts = this.intents.get(intentId);\n if (facts) this.intents.delete(intentId);\n return facts;\n }\n\n get size(): number {\n return this.intents.size;\n }\n}\n","import type { ReputationComponents } from '@reinconsole/core';\nimport type { SubjectEvidence } from './evidence.js';\n\n/**\n * Component weights, summing to 1. The blend is a deliberately transparent\n * heuristic: every component is 0–100 with higher = healthier, so a score is\n * readable straight off its explanation. Sophistication can replace this\n * later without touching the evidence model — scores are pure functions of\n * evidence, never stored.\n */\nexport interface ScoreWeights {\n volume: number;\n longevity: number;\n disputeRate: number;\n counterpartyQuality: number;\n settlementReliability: number;\n}\n\nexport const DEFAULT_WEIGHTS: ScoreWeights = {\n settlementReliability: 0.3,\n disputeRate: 0.3,\n volume: 0.15,\n counterpartyQuality: 0.15,\n longevity: 0.1,\n};\n\nconst DAY_MS = 86_400_000;\n\n/**\n * How much one bad observation hurts, relative to a plain refusal. Disputes\n * and shadow spends are deliberate misconduct; a replay means someone tried\n * to spend the same money twice; the rest is sloppiness.\n */\nconst BADNESS = { dispute: 4, shadowSpend: 4, replay: 3, refusal: 1, endorsementCredit: 2 };\n\nconst REPLAY_CODES = new Set(['payment_replayed', 'decision_replayed']);\n\nfunction clamp(value: number, lo: number, hi: number): number {\n return Math.min(hi, Math.max(lo, value));\n}\n\nfunction refusalCounts(ev: SubjectEvidence): { replays: number; others: number } {\n let replays = 0;\n let others = 0;\n for (const [code, count] of Object.entries(ev.refusals)) {\n if (REPLAY_CODES.has(code)) replays += count;\n else others += count;\n }\n return { replays, others };\n}\n\n/** Saturating settled-transaction volume: 0 at none, ~63 at 20, ~92 at 50. */\nexport function volumeComponent(ev: SubjectEvidence): number {\n return 100 * (1 - Math.exp(-ev.settled / 20));\n}\n\n/** How long the subject has been known: linear to 100 at 30 days. */\nexport function longevityComponent(ev: SubjectEvidence, nowMs: number): number {\n const knownDays = Math.max(0, nowMs - ev.firstSeenMs) / DAY_MS;\n return 100 * Math.min(1, knownDays / 30);\n}\n\n/**\n * Dispute hygiene (the core field is named `disputeRate`; the component is\n * stored INVERTED — 100 = a clean record — so all five components blend in\n * the same direction). Weighted badness over total interactions; manual\n * endorsements buy back a little slack.\n */\nexport function disputeComponent(ev: SubjectEvidence): number {\n const { replays, others } = refusalCounts(ev);\n const badness = Math.max(\n 0,\n ev.disputes * BADNESS.dispute +\n ev.shadowSpends * BADNESS.shadowSpend +\n replays * BADNESS.replay +\n others * BADNESS.refusal -\n ev.endorsements * BADNESS.endorsementCredit,\n );\n const interactions = Math.max(1, ev.attempts + ev.disputes + ev.endorsements);\n return 100 * Math.max(0, 1 - badness / interactions);\n}\n\n/** Settled / attempted. No attempts yet = neutral 50, not perfect 100. */\nexport function reliabilityComponent(ev: SubjectEvidence): number {\n if (ev.attempts === 0) return 50;\n return 100 * Math.min(1, ev.settled / ev.attempts);\n}\n\n/**\n * Confidence is first-class (see core ReputationScore): a thin or brand-new\n * history yields LOW confidence rather than a misleading score, so consumers\n * (engine sync, gate screening) can refuse to act on it. Depth of evidence\n * saturates around 10 observations; age discounts same-day evidence to 40%\n * and stops mattering after a week.\n */\nexport function confidence(ev: SubjectEvidence, nowMs: number): number {\n const { replays, others } = refusalCounts(ev);\n const observations =\n ev.attempts + ev.disputes + ev.endorsements + ev.shadowSpends + replays + others;\n const depth = 1 - Math.exp(-observations / 10);\n const knownDays = Math.max(0, nowMs - ev.firstSeenMs) / DAY_MS;\n const age = 0.4 + 0.6 * Math.min(1, knownDays / 7);\n return clamp(depth * age, 0, 1);\n}\n\n/** Blend all five components into the headline 0–100 score. */\nexport function blend(components: ReputationComponents, weights: ScoreWeights): number {\n const total =\n components.volume * weights.volume +\n components.longevity * weights.longevity +\n components.disputeRate * weights.disputeRate +\n components.counterpartyQuality * weights.counterpartyQuality +\n components.settlementReliability * weights.settlementReliability;\n return clamp(Math.round(total), 0, 100);\n}\n\n/**\n * The one-hop base score: the blend WITHOUT counterpartyQuality, with the\n * remaining weights renormalized. Counterparty quality for subject A averages\n * the base scores of A's counterparties — base, not full, so the computation\n * is a single hop and cycles (A pays B pays A) cannot recurse.\n */\nexport function blendBase(ev: SubjectEvidence, nowMs: number, weights: ScoreWeights): number {\n const remaining =\n weights.volume + weights.longevity + weights.disputeRate + weights.settlementReliability;\n if (remaining <= 0) return 50;\n const total =\n volumeComponent(ev) * weights.volume +\n longevityComponent(ev, nowMs) * weights.longevity +\n disputeComponent(ev) * weights.disputeRate +\n reliabilityComponent(ev) * weights.settlementReliability;\n return clamp(total / remaining, 0, 100);\n}\n","import {\n ReputationScore,\n type Receipt,\n type ReinEvent,\n type ReputationComponents,\n type ReputationSubject,\n} from '@reinconsole/core';\nimport {\n EvidenceLedger,\n normalizeSubject,\n subjectKey,\n type EvidenceLedgerPort,\n type MaybePromise,\n type SubjectEvidence,\n} from './evidence.js';\nimport {\n DEFAULT_CORRELATION_LIMIT,\n InMemoryIntentStore,\n type IntentCorrelationPort,\n} from './intents.js';\nimport {\n blend,\n blendBase,\n confidence,\n DEFAULT_WEIGHTS,\n disputeComponent,\n longevityComponent,\n reliabilityComponent,\n volumeComponent,\n type ScoreWeights,\n} from './scoring.js';\n\n/** Anything with a Rein event bus: engine, indexer, gate, signer. */\nexport interface EventSource {\n onEvent(handler: (event: ReinEvent) => void): void;\n}\n\n/**\n * Gate refusal codes that are the vendor's throttle or the vendor's rails\n * failing — not payer misbehavior. They must never become reputation evidence\n * (see the `gate.refused` case below). Mirrors @reinconsole/gate's no-fault classes;\n * kept as strings because the event schema deliberately carries codes as\n * strings (remote gates may run other versions).\n */\nconst NO_FAULT_GATE_CODES = new Set([\n 'rate_limited',\n 'velocity_exceeded',\n 'rails_unavailable',\n 'settle_unknown',\n]);\n\n/**\n * Where vendor scores land. `PolicyEngine.spend` satisfies this structurally,\n * so `graph.syncVendors(engine.spend)` closes the loop — durable when the\n * engine runs on @reinconsole/store.\n */\nexport interface VendorReputationSink {\n setVendorReputation(host: string, score: number): void | Promise<void>;\n}\n\nexport interface ReputationGraphOptions {\n weights?: Partial<ScoreWeights>;\n /** Injectable clock (scores are functions of evidence AND time). */\n now?: () => Date;\n /**\n * Max undecided intents remembered for settlement correlation. Ignored when\n * a custom `intents` store is injected (that store owns its own bound).\n */\n correlationLimit?: number;\n /**\n * Durable evidence ledger. Defaults to in-memory; @reinconsole/store provides a\n * PGlite-backed one so scores survive a restart.\n */\n ledger?: EvidenceLedgerPort;\n /** Durable intent correlation store. Defaults to in-memory (bounded by `correlationLimit`). */\n intents?: IntentCorrelationPort;\n}\n\nexport interface ManualReport {\n subject: ReputationSubject;\n kind: 'dispute' | 'endorsement';\n /** When the incident happened (defaults to now). */\n at?: Date;\n note?: string;\n}\n\nexport interface SyncedVendorScore {\n host: string;\n score: number;\n confidence: number;\n}\n\nexport interface SyncOptions {\n /**\n * Scores below this confidence are NOT pushed — the evaluator treats an\n * unknown reputation as indeterminate (never triggers vendorReputationLt),\n * and a thin history must stay unknown rather than condemn a newcomer.\n */\n minConfidence?: number;\n}\n\n/** A score plus the raw evidence it was derived from, render-ready. */\nexport interface ReputationExplanation {\n score: ReputationScore;\n weights: ScoreWeights;\n evidence: {\n attempts: number;\n settled: number;\n volume: string;\n refusals: Record<string, number>;\n shadowSpends: number;\n disputes: number;\n endorsements: number;\n firstSeen: Date;\n lastSeen: Date;\n counterparties: { subject: ReputationSubject; settled: number; volume: string }[];\n };\n}\n\n/**\n * The Rein reputation graph (Phase 3). Subscribes to the event buses both\n * sides already publish — the engine/indexer name vendors by host and agents\n * by id; a gate names payers by wallet — and accumulates per-subject evidence:\n * settlements, refusals, shadow spends, manual disputes, and settled-money\n * edges between counterparties. Scores are computed on demand (never stored)\n * from that evidence, so every number is explainable, and they feed back into\n * enforcement on both sides of the wire:\n *\n * graph.syncVendors(engine.spend) -> policies with vendorReputationLt fire\n * screen: { check: payerCheck(graph) } -> a gate turns away low-rep wallets\n *\n * Event mapping notes: engine-side evidence keys agents by ULID and vendors by\n * host; gate-side evidence keys payers by wallet and recipients by payTo\n * address — distinct subjects, so feeding one graph from BOTH buses (the\n * console world) never double-counts. `payment.settled` carries only an\n * intentId, so the graph keeps a bounded intent.created correlation map.\n * Denied decisions are deliberately NOT held against anyone: a deny means\n * policy worked, not that the agent or vendor misbehaved.\n */\nexport class ReputationGraph {\n private readonly ledger: EvidenceLedgerPort;\n private readonly intents: IntentCorrelationPort;\n private readonly weights: ScoreWeights;\n private readonly now: () => Date;\n /** aliasKey -> canonical subject. Links are derived state (an agent registry\n * or ERC-8004 lookup knows them) — re-assert at boot; merges are idempotent. */\n private readonly aliases = new Map<string, ReputationSubject>();\n\n constructor(options: ReputationGraphOptions = {}) {\n this.weights = { ...DEFAULT_WEIGHTS, ...options.weights };\n this.now = options.now ?? (() => new Date());\n this.ledger = options.ledger ?? new EvidenceLedger();\n this.intents =\n options.intents ??\n new InMemoryIntentStore(options.correlationLimit ?? DEFAULT_CORRELATION_LIMIT);\n }\n\n /** Subscribe to a bus. Returns `this` so construction chains. */\n observe(source: EventSource): this {\n source.onEvent((event) => this.ingest(event));\n return this;\n }\n\n /**\n * Fire-and-forget a port write: bus handlers cannot await, and a rejecting\n * durable write must never become an unhandled rejection (Node kills the\n * process). Failures are the port's to surface — flush() throws them.\n */\n private fire(write: () => MaybePromise<void>): void {\n // Thunk form (parity with the gate's fire, S19): a ledger that THROWS\n // synchronously must not turn an ingest into a crash — telemetry failures\n // are the port's to surface, and flush() throws them.\n try {\n void Promise.resolve(write()).catch(() => undefined);\n } catch {\n // swallowed by design — see above\n }\n }\n\n /**\n * Declare that `alias` is the same real-world party as `canonical` (the\n * ERC-8004 identity story: one identity, many addresses/ids — an engine\n * agent's ULID and its paying wallet, or a vendor's host and its payTo\n * address). Everything already known about the alias is folded into the\n * canonical subject, and all future evidence and lookups for the alias\n * resolve to it. Idempotent — re-asserting known links at boot is free.\n */\n link(canonical: ReputationSubject, alias: ReputationSubject): void {\n const target = normalizeSubject(this.resolve(canonical)); // flatten chains\n const aliasKey = subjectKey(alias);\n if (subjectKey(target) === aliasKey) return;\n this.aliases.set(aliasKey, target);\n // Repoint any alias that resolved THROUGH this alias (a->b then b->c).\n for (const [key, resolved] of this.aliases) {\n if (subjectKey(resolved) === aliasKey) this.aliases.set(key, target);\n }\n this.fire(() => this.ledger.merge(target, alias));\n }\n\n /** The canonical subject for a possibly-aliased one. */\n private resolve(subject: ReputationSubject): ReputationSubject {\n return this.aliases.get(subjectKey(subject)) ?? subject;\n }\n\n ingest(event: ReinEvent): void {\n const atMs = event.at.getTime();\n switch (event.type) {\n case 'intent.created': {\n this.fire(() =>\n this.intents.remember(event.intent.id, {\n agentId: event.intent.agentId,\n host: event.intent.vendor.host,\n amount: event.intent.amount,\n }),\n );\n return;\n }\n case 'decision.made': {\n if (event.decision.outcome !== 'allow') return;\n const facts = this.intents.peek(event.decision.intentId);\n if (!facts) return;\n this.fire(() => this.ledger.recordAttempt(this.resolve({ kind: 'agent', id: facts.agentId }), atMs));\n this.fire(() => this.ledger.recordAttempt(this.resolve({ kind: 'vendor', id: facts.host }), atMs));\n return;\n }\n case 'payment.settled': {\n const facts = this.intents.take(event.payment.intentId);\n if (!facts) return; // unattributable — no subject to credit\n const agent = this.resolve({ kind: 'agent', id: facts.agentId });\n const vendor = this.resolve({ kind: 'vendor', id: facts.host });\n this.fire(() => this.ledger.recordSettlement(agent, vendor, facts.amount, atMs));\n return;\n }\n case 'shadow.spend': {\n this.fire(() => this.ledger.recordShadowSpend(this.resolve({ kind: 'agent', id: event.agentId }), atMs));\n return;\n }\n case 'signature.refused': {\n const agentId = event.agentId; // hoisted: narrowing must survive the thunk\n if (!agentId) return;\n this.fire(() =>\n this.ledger.recordRefusal(this.resolve({ kind: 'agent', id: agentId }), event.code, atMs),\n );\n return;\n }\n case 'gate.settled': {\n const payer = this.resolve({ kind: 'agent', id: event.receipt.payer });\n const recipient = this.resolve({ kind: 'vendor', id: event.receipt.payTo });\n this.fire(() => this.ledger.recordAttempt(payer, atMs));\n this.fire(() => this.ledger.recordAttempt(recipient, atMs));\n this.fire(() => this.ledger.recordSettlement(payer, recipient, event.receipt.amount, atMs));\n return;\n }\n case 'gate.refused': {\n // No-fault refusals carry NO evidence — the gate-side parallel of\n // \"denied decisions count against no one\". Throttle codes are the\n // VENDOR'S cap (one gate's rate limit must not bleed into a payer's\n // global score); rails codes are the vendor's infrastructure failing\n // (a settle_unknown payment may even have gone through). Not even the\n // attempt is recorded: an attempt with no settlement would silently\n // drag settlementReliability down.\n if (!event.payer || NO_FAULT_GATE_CODES.has(event.code)) return;\n const payer = this.resolve({ kind: 'agent', id: event.payer });\n this.fire(() => this.ledger.recordAttempt(payer, atMs));\n this.fire(() => this.ledger.recordRefusal(payer, event.code, atMs));\n return;\n }\n // signature.released and gate.quoted carry no evidence the engine-side\n // events don't already: released duplicates the allow that preceded it,\n // and a quote names no payer.\n case 'signature.released':\n case 'gate.quoted':\n return;\n }\n }\n\n /**\n * Agent-side alternative to observing the engine bus: feed the SDK guard's\n * onReceipt straight in. Connect events OR receipts per side, not both —\n * a receipt restates the decision/settlement the bus already carried.\n */\n ingestReceipt(receipt: Receipt): void {\n if (receipt.outcome !== 'allow') return; // policy verdicts are not subject badness\n const atMs = receipt.createdAt.getTime();\n const agent = this.resolve({ kind: 'agent', id: receipt.agentId });\n const vendor = this.resolve({ kind: 'vendor', id: receipt.vendorHost });\n this.fire(() => this.ledger.recordAttempt(agent, atMs));\n this.fire(() => this.ledger.recordAttempt(vendor, atMs));\n if (receipt.settlement?.txHash) {\n this.fire(() => this.ledger.recordSettlement(agent, vendor, receipt.amount, atMs));\n }\n }\n\n /** Record an out-of-band dispute or endorsement against a subject. */\n report(input: ManualReport): void {\n const atMs = (input.at ?? this.now()).getTime();\n const subject = this.resolve(input.subject);\n if (input.kind === 'dispute') this.fire(() => this.ledger.recordDispute(subject, atMs));\n else this.fire(() => this.ledger.recordEndorsement(subject, atMs));\n }\n\n /** Await any pending durable writes (no-op for in-memory stores). */\n async flush(): Promise<void> {\n await this.ledger.flush?.();\n await this.intents.flush?.();\n }\n\n /** The score for one subject, or undefined when nothing is known (fairness).\n * Aliased subjects resolve to their canonical identity — a linked wallet\n * answers with the merged history, on both sides of the wire. */\n score(subject: ReputationSubject): ReputationScore | undefined {\n const ev = this.ledger.get(this.resolve(subject));\n return ev && this.scoreOf(ev);\n }\n\n /** All known scores, best first. */\n scores(kind?: ReputationSubject['kind']): ReputationScore[] {\n const out: ReputationScore[] = [];\n for (const ev of this.ledger.all()) {\n if (kind && ev.subject.kind !== kind) continue;\n out.push(this.scoreOf(ev));\n }\n return out.sort((a, b) => b.score - a.score);\n }\n\n /** The score plus the raw evidence behind it. */\n explain(subject: ReputationSubject): ReputationExplanation | undefined {\n const ev = this.ledger.get(this.resolve(subject));\n if (!ev) return undefined;\n return {\n score: this.scoreOf(ev),\n weights: this.weights,\n evidence: {\n attempts: ev.attempts,\n settled: ev.settled,\n volume: ev.volume,\n refusals: { ...ev.refusals },\n shadowSpends: ev.shadowSpends,\n disputes: ev.disputes,\n endorsements: ev.endorsements,\n firstSeen: new Date(ev.firstSeenMs),\n lastSeen: new Date(ev.lastSeenMs),\n counterparties: [...ev.counterparties.entries()].map(([key, line]) => {\n const [kind, ...id] = key.split(':');\n return {\n subject: { kind: kind as ReputationSubject['kind'], id: id.join(':') },\n settled: line.settled,\n volume: line.volume,\n };\n }),\n },\n };\n }\n\n /**\n * Push every vendor score that clears the confidence floor into the engine's\n * spend store (or any sink). Returns what was pushed. Low-confidence scores\n * are withheld so `vendorReputationLt` keeps treating thin histories as\n * unknown — the evaluator's no-data-no-trigger rule stays intact end to end.\n */\n async syncVendors(\n sink: VendorReputationSink,\n options: SyncOptions = {},\n ): Promise<SyncedVendorScore[]> {\n const minConfidence = options.minConfidence ?? 0.3;\n const pushed: SyncedVendorScore[] = [];\n for (const ev of this.ledger.all()) {\n if (ev.subject.kind !== 'vendor') continue;\n const score = this.scoreOf(ev);\n if (score.confidence < minConfidence) continue;\n await sink.setVendorReputation(ev.subject.id, score.score);\n pushed.push({ host: ev.subject.id, score: score.score, confidence: score.confidence });\n }\n return pushed;\n }\n\n /** Number of subjects with evidence. */\n subjects(): number {\n return this.ledger.size;\n }\n\n private scoreOf(ev: SubjectEvidence): ReputationScore {\n const nowMs = this.now().getTime();\n const components: ReputationComponents = {\n volume: volumeComponent(ev),\n longevity: longevityComponent(ev, nowMs),\n disputeRate: disputeComponent(ev),\n counterpartyQuality: this.counterpartyQuality(ev, nowMs),\n settlementReliability: reliabilityComponent(ev),\n };\n return ReputationScore.parse({\n subject: ev.subject,\n score: blend(components, this.weights),\n components,\n confidence: confidence(ev, nowMs),\n asOf: new Date(nowMs),\n });\n }\n\n /** One-hop mean of the counterparties' base scores; neutral 50 when alone. */\n private counterpartyQuality(ev: SubjectEvidence, nowMs: number): number {\n if (ev.counterparties.size === 0) return 50;\n let total = 0;\n for (const key of ev.counterparties.keys()) {\n const other = this.ledger.getByKey(key);\n total += other ? blendBase(other, nowMs, this.weights) : 50;\n }\n return total / ev.counterparties.size;\n }\n}\n\nexport interface PayerCheckOptions {\n /** Refuse payers scoring below this (default 40). */\n denyBelow?: number;\n /** Ignore scores below this confidence (default 0.3) — newcomers pass. */\n minConfidence?: number;\n}\n\n/**\n * Reputation-driven gate screening: plugs into @reinconsole/gate's `screen.check`.\n * Unknown wallets and thin histories pass (same fairness rule as the engine\n * sync); a confident low score is turned away at the door, before any\n * facilitator round-trip.\n */\nexport function payerCheck(\n graph: ReputationGraph,\n options: PayerCheckOptions = {},\n): (payer: string) => string | undefined {\n const denyBelow = options.denyBelow ?? 40;\n const minConfidence = options.minConfidence ?? 0.3;\n return (payer) => {\n const score = graph.score({ kind: 'agent', id: payer });\n if (!score || score.confidence < minConfidence) return undefined;\n if (score.score >= denyBelow) return undefined;\n return `payer reputation ${score.score} is below this gate's floor of ${denyBelow}`;\n };\n}\n","import { fileURLToPath } from 'node:url';\nimport { realpathSync } from 'node:fs';\nimport Fastify, { type FastifyInstance } from 'fastify';\nimport { z } from 'zod';\nimport { ReinEvent, ReputationSubject } from '@reinconsole/core';\nimport { ReputationGraph } from './graph.js';\n\nconst ReportInput = z.object({\n subject: ReputationSubject,\n kind: z.enum(['dispute', 'endorsement']),\n at: z.coerce.date().optional(),\n note: z.string().max(500).optional(),\n});\n\nconst ScoresQuery = z.object({ kind: z.enum(['agent', 'vendor']).optional() });\n\nconst LinkInput = z\n .object({\n canonical: ReputationSubject,\n alias: ReputationSubject,\n })\n // Merging across kinds would delete a vendor row into an agent identity\n // (silently dropping the host from syncVendors) — always a caller bug.\n .refine((l) => l.canonical.kind === l.alias.kind, {\n message: 'canonical and alias must be the same kind',\n });\n\n/**\n * Build the graph HTTP API. Remote producers POST their events here; anyone\n * can read scores with the evidence behind them. Pass a graph for tests, or\n * let it create a fresh in-memory one.\n */\nexport function buildGraphServer(graph: ReputationGraph = new ReputationGraph()): FastifyInstance {\n const app = Fastify({ logger: false });\n\n // Turn ZodErrors into clean 400s instead of 500s.\n app.setErrorHandler((err: unknown, _req, reply) => {\n if (err instanceof z.ZodError) {\n return reply.status(400).send({ error: 'validation_error', issues: err.issues });\n }\n const message = err instanceof Error ? err.message : String(err);\n return reply.status(500).send({ error: 'internal_error', message });\n });\n\n app.get('/health', () => ({ status: 'ok', subjects: graph.subjects() }));\n\n // --- Ingestion ---\n // The HTTP path can await durability even though the in-process bus path\n // cannot — flush the durable writes before answering so a POST that returns\n // 200 is persisted.\n app.post('/v1/events', async (req) => {\n const events = z.union([ReinEvent.transform((e) => [e]), z.array(ReinEvent)]).parse(req.body);\n for (const event of events) graph.ingest(event);\n await graph.flush();\n return { ingested: events.length };\n });\n\n app.post('/v1/reports', async (req) => {\n const input = ReportInput.parse(req.body);\n graph.report(input);\n await graph.flush();\n return graph.score(input.subject);\n });\n\n // --- Identity links ---\n // Unverified by DESIGN: this endpoint's trust level equals POST /v1/events —\n // whoever can post events can already fabricate the evidence itself. On-chain\n // verification belongs to the CALLER (@reinconsole/erc8004 derives link facts from\n // the Identity Registry, then asserts them here).\n app.post('/v1/links', async (req) => {\n const links = z.union([LinkInput.transform((l) => [l]), z.array(LinkInput)]).parse(req.body);\n for (const link of links) graph.link(link.canonical, link.alias);\n await graph.flush(); // durable merges land before the 200 (same contract as /v1/events)\n return { linked: links.length };\n });\n\n // --- Scores ---\n app.get('/v1/scores', (req) => {\n const { kind } = ScoresQuery.parse(req.query);\n return graph.scores(kind);\n });\n\n app.get('/v1/scores/:kind/:id', (req, reply) => {\n const subject = ReputationSubject.parse(req.params);\n const explanation = graph.explain(subject);\n if (!explanation) {\n return reply\n .status(404)\n .send({ error: 'not_found', message: `no evidence for ${subject.kind} ${subject.id}` });\n }\n return explanation;\n });\n\n return app;\n}\n\n// Start the server when run directly (tsx/node), not when imported.\nfunction isMainModule(): boolean {\n if (!process.argv[1]) return false;\n try {\n return realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url));\n } catch {\n return false;\n }\n}\n\nif (isMainModule()) {\n const port = Number(process.env.PORT ?? 8788);\n const host = process.env.HOST ?? '0.0.0.0';\n const app = buildGraphServer();\n app\n .listen({ port, host })\n .then(() => console.log(`[rein] graph listening on http://${host}:${port}`))\n .catch((err) => {\n console.error(err);\n process.exit(1);\n });\n}\n"],"mappings":";;AAOO,IAAM,QAAQ,EAAE,KAAK,CAAC,QAAQ,UAAU,WAAW,KAAK,CAAC;AAIzD,IAAM,QAAQ,EAAE,KAAK,CAAC,QAAQ,QAAQ,MAAM,CAAC;ACH7C,IAAM,gBAAgBA,EAC1B,OAAA,EACA,MAAM,iBAAiB,oDAAoD;AAG9E,IAAM,aAAa;AAEZ,SAAS,eAAe,OAAwB;AACrD,SAAO,WAAW,KAAK,KAAK;AAC9B;AAEA,SAAS,cAAc,OAAqB;AAC1C,MAAI,CAAC,eAAe,KAAK,GAAG;AAC1B,UAAM,IAAI,UAAU,2BAA2B,KAAK,UAAU,KAAK,CAAC,EAAE;EACxE;AACF;AAEA,SAAS,eAAe,OAAuB;AAC7C,QAAM,MAAM,MAAM,QAAQ,GAAG;AAC7B,SAAO,QAAQ,KAAK,IAAI,MAAM,SAAS,MAAM;AAC/C;AAGA,SAAS,SAAS,OAAe,OAAuB;AACtD,QAAM,MAAM,MAAM,QAAQ,GAAG;AAC7B,QAAM,UAAU,QAAQ,KAAK,QAAQ,MAAM,MAAM,GAAG,GAAG;AACvD,QAAM,WAAW,QAAQ,KAAK,KAAK,MAAM,MAAM,MAAM,CAAC;AACtD,QAAM,cAAc,WAAW,IAAI,OAAO,KAAK,GAAG,MAAM,GAAG,KAAK;AAChE,SAAO,OAAO,UAAU,UAAU;AACpC;AAGA,SAAS,WAAW,QAAgB,OAAuB;AACzD,MAAI,UAAU,EAAG,QAAO,OAAO,SAAA;AAC/B,QAAM,SAAS,OAAO,SAAA,EAAW,SAAS,QAAQ,GAAG,GAAG;AACxD,QAAM,UAAU,OAAO,MAAM,GAAG,OAAO,SAAS,KAAK;AACrD,QAAM,WAAW,OAAO,MAAM,OAAO,SAAS,KAAK,EAAE,QAAQ,OAAO,EAAE;AACtE,SAAO,SAAS,SAAS,IAAI,GAAG,OAAO,IAAI,QAAQ,KAAK;AAC1D;AAaO,SAAS,WAAW,QAAmC;AAC5D,MAAI,OAAO,WAAW,EAAG,QAAO;AAChC,MAAI,QAAQ;AACZ,aAAW,KAAK,QAAQ;AACtB,kBAAc,CAAC;AACf,YAAQ,KAAK,IAAI,OAAO,eAAe,CAAC,CAAC;EAC3C;AACA,MAAI,QAAQ;AACZ,aAAW,KAAK,OAAQ,UAAS,SAAS,GAAG,KAAK;AAClD,SAAO,WAAW,OAAO,KAAK;AAChC;AGlEA,IAAM,YAAY;AAOX,SAAS,WAAW,QAAgB;AACzC,SAAOC,EACJ,OAAA,EACA,MAAM,IAAI,OAAO,IAAI,MAAM,IAAI,SAAS,GAAG,GAAG,eAAe,MAAM,gBAAgB;AACxF;AAEO,IAAM,QAAQ,WAAW,KAAK;AAC9B,IAAM,UAAU,WAAW,KAAK;AAChC,IAAM,WAAW,WAAW,KAAK;AACjC,IAAM,WAAW,WAAW,KAAK;AACjC,IAAM,aAAa,WAAW,KAAK;AACnC,IAAM,YAAY,WAAW,KAAK;AAClC,IAAM,YAAY,WAAW,KAAK;AAClC,IAAM,gBAAgB,WAAW,KAAK;ACbtC,IAAM,kBAAkBA,EAAE,KAAK,CAAC,YAAY,OAAO,aAAa,CAAC;AAGjE,IAAM,cAAcA,EAAE,OAAO;EAClC,OAAO;EACP,SAASA,EAAE,OAAA,EAAS,IAAI,CAAC;EACzB,MAAM;AACR,CAAC;AAGM,IAAM,cAAcA,EAAE,KAAK,CAAC,UAAU,QAAQ,CAAC;AAG/C,IAAM,QAAQA,EAAE,OAAO;EAC5B,IAAI;EACJ,OAAO;EACP,MAAMA,EAAE,OAAA,EAAS,IAAI,CAAC,EAAE,IAAI,GAAG;;EAE/B,WAAWA,EAAE,OAAA,EAAS,SAAA;EACtB,SAASA,EAAE,MAAM,WAAW,EAAE,QAAQ,CAAA,CAAE;EACxC,QAAQ,YAAY,QAAQ,QAAQ;EACpC,WAAWA,EAAE,OAAO,KAAA;AACtB,CAAC;ACHD,IAAM,mBAAmB;AACzB,IAAM,aAAa;AAGZ,SAAS,gBAAgB,KAAyB;AACvD,MAAI,CAAC,OAAO,cAAc,IAAI,OAAO,KAAK,IAAI,UAAU,GAAG;AACzD,UAAM,IAAI,WAAW,wBAAwB,IAAI,OAAO,EAAE;EAC5D;AACA,MAAI,CAAC,iBAAiB,KAAK,IAAI,QAAQ,GAAG;AACxC,UAAM,IAAI,WAAW,iCAAiC,IAAI,QAAQ,EAAE;EACtE;AACA,MAAI,OAAO,IAAI,YAAY,YAAY,IAAI,UAAU,IAAI;AAGvD,UAAM,IAAI,WAAW,wBAAwB,IAAI,OAAO,EAAE;EAC5D;AACA,SAAO,UAAU,IAAI,OAAO,IAAI,IAAI,SAAS,YAAA,CAAa,IAAI,IAAI,OAAO;AAC3E;AAOO,SAAS,eAAe,OAAuC;AACpE,QAAM,QAAQ,WAAW,KAAK,KAAK;AACnC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,UAAU,OAAO,MAAM,CAAC,CAAC;AAC/B,MAAI,CAAC,OAAO,cAAc,OAAO,KAAK,UAAU,EAAG,QAAO;AAC1D,SAAO;IACL;IACA,UAAU,MAAM,CAAC,EAAG,YAAA;IACpB,SAAS,OAAO,MAAM,CAAC,CAAE;EAAA;AAE7B;AAGO,IAAM,YAAYA,EACtB,OAAA,EACA,OAAO,CAAC,UAAU,eAAe,KAAK,MAAM,QAAW;EACtD,SAAS;AACX,CAAC;ACjEI,IAAM,SAASA,EAAE,OAAO;EAC7B,MAAMA,EAAE,OAAA,EAAS,IAAI,CAAC;EACtB,SAASA,EAAE,OAAA,EAAS,IAAI,CAAC;EACzB,WAAWA,EAAE,OAAA,EAAS,SAAA;AACxB,CAAC;AAOM,IAAM,cAAcA,EAAE,OAAO;EAClC,QAAQA,EAAE,OAAA,EAAS,SAAA;EACnB,aAAaA,EAAE,OAAA,EAAS,SAAA;EACxB,SAASA,EAAE,OAAA,EAAS,IAAI,GAAG,EAAE,SAAA;AAC/B,CAAC;AAOM,IAAM,gBAAgBA,EAAE,OAAO;EACpC,IAAI;EACJ,SAAS;EACT,QAAQ;EACR,UAAUA,EAAE,OAAA;EACZ,QAAQ;EACR,OAAO;EACP,OAAO;EACP,aAAa,YAAY,QAAQ,CAAA,CAAE;EACnC,OAAOA,EAAE,OAAA,EAAS,IAAI,CAAC;EACvB,WAAWA,EAAE,OAAO,KAAA;AACtB,CAAC;ACnCM,IAAM,kBAAkBA,EAAE,KAAK,CAAC,SAAS,QAAQ,UAAU,CAAC;AAS5D,IAAM,WAAWA,EAAE,OAAO;EAC/B,IAAI;EACJ,UAAU;;;;;;;EAOV,YAAYA,EAAE,OAAA;EACd,SAAS;;EAET,cAAcA,EAAE,MAAMA,EAAE,OAAA,CAAQ,EAAE,QAAQ,CAAA,CAAE;;EAE5C,QAAQA,EAAE,OAAA,EAAS,SAAA;EACnB,UAAUA,EAAE,OAAA;EACZ,eAAeA,EAAE,OAAA;;EAEjB,UAAUA,EAAE,OAAA;;EAEZ,MAAMA,EAAE,OAAA;;EAER,WAAWA,EAAE,OAAA;EACb,WAAWA,EAAE,OAAA,EAAS,YAAA;EACtB,WAAWA,EAAE,OAAO,KAAA;AACtB,CAAC;AEvBM,IAAM,UAAUC,EAAE,OAAO;EAC9B,IAAI;EACJ,SAAS;;EAET,WAAWA,EAAE,OAAA;;EAEb,WAAW,cAAc,SAAA;;EAEzB,eAAe,cAAc,SAAA;EAC7B,WAAWA,EAAE,OAAO,KAAA;EACpB,WAAWA,EAAE,OAAO,KAAA;EACpB,WAAWA,EAAE,OAAO,KAAA,EAAO,SAAA;AAC7B,CAAC;ACjBM,IAAM,iBAAiBA,EAAE,OAAO;EACrC,UAAU;EACV,QAAQA,EAAE,OAAA;EACV,OAAO;EACP,aAAaA,EAAE,OAAO,OAAA;EACtB,aAAaA,EAAE,OAAA,EAAS,SAAA;EACxB,SAAS,cAAc,SAAA;EACvB,aAAaA,EAAE,OAAO,KAAA;AACxB,CAAC;ACLM,IAAM,oBAAoBA,EAAE,OAAO;EACxC,QAAQA,EAAE,OAAA,EAAS,SAAA;EACnB,WAAWA,EAAE,OAAA,EAAS,SAAA;;EAEtB,KAAKA,EAAE,OAAA,EAAS,SAAA;AAClB,CAAC;AASM,IAAM,UAAUA,EAAE,OAAO;EAC9B,IAAI;EACJ,SAAS;EACT,UAAU;EACV,YAAY;EACZ,SAAS;;EAET,KAAKA,EAAE,OAAA;EACP,QAAQA,EAAE,OAAA,EAAS,QAAQ,KAAK;EAChC,YAAYA,EAAE,OAAA;EACd,QAAQ;EACR,OAAO;EACP,OAAO;EACP,aAAa,YAAY,QAAQ,CAAA,CAAE;;EAEnC,QAAQA,EAAE,OAAA,EAAS,SAAA;;EAEnB,YAAY,kBAAkB,SAAA;EAC9B,WAAWA,EAAE,OAAO,KAAA;AACtB,CAAC;ACnCM,IAAM,cAAcA,EAAE,OAAO;EAClC,IAAI;EACJ,IAAIA,EAAE,OAAO,KAAA;;EAEb,OAAOA,EAAE,OAAA,EAAS,IAAI,CAAC;;EAEvB,UAAUA,EAAE,OAAA,EAAS,IAAI,CAAC;EAC1B,QAAQA,EAAE,OAAA,EAAS,IAAI,CAAC;;EAExB,OAAOA,EAAE,OAAA,EAAS,IAAI,CAAC;EACvB,OAAOA,EAAE,OAAA,EAAS,IAAI,CAAC;;EAEvB,QAAQ;;EAER,cAAcA,EAAE,OAAA,EAAS,MAAM,SAAS,yCAAyC;;EAEjF,OAAOA,EAAE,OAAA,EAAS,IAAI,CAAC;EACvB,SAASA,EAAE,OAAA,EAAS,IAAI,CAAC;;EAEzB,aAAaA,EAAE,OAAA,EAAS,IAAI,CAAC;AAC/B,CAAC;ACzBM,IAAM,SAASA,EACnB,OAAA,EACA,MAAM,eAAe,iDAAiD;AAIlE,IAAM,aAAaA,EAAE,OAAA,EAAS,MAAM,kBAAkB,8BAA8B;AAOpF,IAAM,YAAYA,EACtB,OAAO;;EAEN,UAAU,cAAc,SAAA;;EAExB,YAAYA,EAAE,OAAO,EAAE,QAAQ,QAAQ,IAAI,cAAA,CAAe,EAAE,SAAA;;EAE5D,SAASA,EAAE,OAAO,EAAE,QAAQ,QAAQ,IAAIA,EAAE,OAAA,EAAS,IAAA,EAAM,YAAA,EAAY,CAAG,EAAE,SAAA;;EAE1E,cAAcA,EAAE,MAAMA,EAAE,OAAA,CAAQ,EAAE,SAAA;;EAElC,iBAAiBA,EAAE,QAAA,EAAU,SAAA;;EAE7B,oBAAoBA,EAAE,OAAA,EAAS,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAA;;EAE/C,wBAAwBA,EAAE,OAAO,EAAE,IAAI,WAAA,CAAY,EAAE,SAAA;AACvD,CAAC,EACA,OAAO,CAAC,MAAM,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,MAAM,MAAS,GAAG;EAC5D,SAAS;AACX,CAAC;AAOI,IAAM,OAAOA,EACjB,OAAO;EACN,IAAIA,EAAE,OAAA,EAAS,IAAI,CAAC;EACpB,OAAO,UAAU,SAAA;EACjB,MAAM,UAAU,SAAA;EAChB,UAAU,UAAU,SAAA;AACtB,CAAC,EACA,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,MAAM,MAAS,EAAE,WAAW,GAAG;EACxF,SAAS;AACX,CAAC;AAGI,IAAM,gBAAgBA,EAAE,KAAK,CAAC,SAAS,MAAM,CAAC;AAG9C,IAAM,YAAYA,EAAE,OAAO;;EAEhC,QAAQA,EAAE,MAAMA,EAAE,OAAA,CAAQ,EAAE,SAAA;EAC5B,QAAQA,EAAE,MAAM,KAAK,EAAE,SAAA;AACzB,CAAC;AAGM,IAAM,aAAaA,EAAE,OAAO;EACjC,WAAWA,EAAE,MAAMA,EAAE,OAAA,CAAQ,EAAE,QAAQ,CAAA,CAAE;EACzC,eAAe,cAAc,QAAQ,MAAM;EAC3C,YAAYA,EAAE,OAAA,EAAS,IAAA,EAAM,SAAA,EAAW,QAAQ,EAAE;AACpD,CAAC;AAOM,IAAM,SAASA,EAAE,OAAO;EAC7B,UAAUA,EAAE,OAAA,EAAS,IAAI,CAAC;EAC1B,SAASA,EAAE,OAAA,EAAS,QAAQ,GAAG;EAC/B,WAAW,UAAU,QAAQ,CAAA,CAAE;EAC/B,OAAOA,EAAE,MAAM,IAAI,EAAE,QAAQ,CAAA,CAAE;EAC/B,SAAS,cAAc,QAAQ,MAAM;;EAErC,WAAW,cAAc,QAAQ,MAAM;EACvC,YAAY,WAAW,SAAA;AACzB,CAAC;ACpFM,IAAM,oBAAoBA,EAAE,OAAO;EACxC,MAAMA,EAAE,KAAK,CAAC,SAAS,QAAQ,CAAC;EAChC,IAAIA,EAAE,OAAA;AACR,CAAC;AAGM,IAAM,uBAAuBA,EAAE,OAAO;EAC3C,QAAQA,EAAE,OAAA;EACV,WAAWA,EAAE,OAAA;EACb,aAAaA,EAAE,OAAA;EACf,qBAAqBA,EAAE,OAAA;EACvB,uBAAuBA,EAAE,OAAA;AAC3B,CAAC;AASM,IAAM,kBAAkBA,EAAE,OAAO;EACtC,SAAS;EACT,OAAOA,EAAE,OAAA,EAAS,IAAI,CAAC,EAAE,IAAI,GAAG;EAChC,YAAY;EACZ,YAAYA,EAAE,OAAA,EAAS,IAAI,CAAC,EAAE,IAAI,CAAC;EACnC,MAAMA,EAAE,OAAO,KAAA;;EAEf,aAAaA,EAAE,OAAA,EAAS,SAAA;AAC1B,CAAC;ACZM,IAAM,YAAYA,EAAE,mBAAmB,QAAQ;EACpDA,EAAE,OAAO,EAAE,MAAMA,EAAE,QAAQ,gBAAgB,GAAG,IAAIA,EAAE,OAAO,KAAA,GAAQ,QAAQ,cAAA,CAAe;EAC1FA,EAAE,OAAO,EAAE,MAAMA,EAAE,QAAQ,eAAe,GAAG,IAAIA,EAAE,OAAO,KAAA,GAAQ,UAAU,SAAA,CAAU;EACtFA,EAAE,OAAO,EAAE,MAAMA,EAAE,QAAQ,iBAAiB,GAAG,IAAIA,EAAE,OAAO,KAAA,GAAQ,SAAS,eAAA,CAAgB;EAC7FA,EAAE,OAAO;IACP,MAAMA,EAAE,QAAQ,cAAc;IAC9B,IAAIA,EAAE,OAAO,KAAA;IACb,SAAS;IACT,QAAQA,EAAE,OAAA;IACV,OAAO;IACP,QAAQ;EAAA,CACT;EACDA,EAAE,OAAO;IACP,MAAMA,EAAE,QAAQ,oBAAoB;IACpC,IAAIA,EAAE,OAAO,KAAA;IACb,WAAW;IACX,SAAS;IACT,UAAU;IACV,YAAY;IACZ,QAAQ;EAAA,CACT;EACDA,EAAE,OAAO;IACP,MAAMA,EAAE,QAAQ,mBAAmB;IACnC,IAAIA,EAAE,OAAO,KAAA;;IAEb,MAAMA,EAAE,OAAA;IACR,QAAQA,EAAE,OAAA;IACV,WAAW,UAAU,SAAA;IACrB,SAAS,QAAQ,SAAA;IACjB,UAAU,SAAS,SAAA;EAAS,CAC7B;EACDA,EAAE,OAAO;IACP,MAAMA,EAAE,QAAQ,aAAa;IAC7B,IAAIA,EAAE,OAAO,KAAA;IACb,UAAUA,EAAE,OAAA;IACZ,QAAQA,EAAE,OAAA;IACV,QAAQ;IACR,OAAOA,EAAE,OAAA;IACT,SAASA,EAAE,OAAA;EAAO,CACnB;EACDA,EAAE,OAAO,EAAE,MAAMA,EAAE,QAAQ,cAAc,GAAG,IAAIA,EAAE,OAAO,KAAA,GAAQ,SAAS,YAAA,CAAa;EACvFA,EAAE,OAAO;IACP,MAAMA,EAAE,QAAQ,cAAc;IAC9B,IAAIA,EAAE,OAAO,KAAA;;IAEb,MAAMA,EAAE,OAAA;IACR,QAAQA,EAAE,OAAA;IACV,UAAUA,EAAE,OAAA;;IAEZ,OAAOA,EAAE,OAAA,EAAS,SAAA;EAAS,CAC5B;AACH,CAAC;;;ACpBM,SAAS,iBAAiB,SAA+C;AAC9E,MAAI,QAAQ,GAAG,WAAW,SAAS,GAAG;AACpC,UAAM,MAAM,eAAe,QAAQ,EAAE;AACrC,QAAI,IAAK,QAAO,EAAE,MAAM,QAAQ,MAAM,IAAI,gBAAgB,GAAG,EAAE;AAAA,EAEjE;AACA,QAAM,KACJ,QAAQ,SAAS,YAAY,QAAQ,GAAG,WAAW,IAAI,KAAK,QAAQ,GAAG,WAAW,IAAI,IAClF,QAAQ,GAAG,YAAY,IACvB,QAAQ;AACd,SAAO,EAAE,MAAM,QAAQ,MAAM,GAAG;AAClC;AAEO,SAAS,WAAW,SAAoC;AAC7D,QAAM,SAAS,iBAAiB,OAAO;AACvC,SAAO,GAAG,OAAO,IAAI,IAAI,OAAO,EAAE;AACpC;AAiDO,IAAM,iBAAN,MAAmD;AAAA,EACvC,UAAU,oBAAI,IAA6B;AAAA,EAE5D,cAAc,SAA4B,MAAoB;AAC5D,SAAK,MAAM,SAAS,IAAI,EAAE,YAAY;AAAA,EACxC;AAAA,EAEA,iBACE,GACA,GACA,QACA,MACM;AACN,eAAW,CAAC,SAAS,KAAK,KAAK;AAAA,MAC7B,CAAC,GAAG,CAAC;AAAA,MACL,CAAC,GAAG,CAAC;AAAA,IACP,GAAY;AACV,YAAM,KAAK,KAAK,MAAM,SAAS,IAAI;AACnC,SAAG,WAAW;AACd,SAAG,SAAS,WAAW,CAAC,GAAG,QAAQ,MAAM,CAAC;AAC1C,YAAM,MAAM,WAAW,KAAK;AAC5B,YAAM,OAAO,GAAG,eAAe,IAAI,GAAG,KAAK,EAAE,SAAS,GAAG,QAAQ,IAAI;AACrE,WAAK,WAAW;AAChB,WAAK,SAAS,WAAW,CAAC,KAAK,QAAQ,MAAM,CAAC;AAC9C,SAAG,eAAe,IAAI,KAAK,IAAI;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,cAAc,SAA4B,MAAc,MAAoB;AAC1E,UAAM,KAAK,KAAK,MAAM,SAAS,IAAI;AACnC,OAAG,SAAS,IAAI,KAAK,GAAG,SAAS,IAAI,KAAK,KAAK;AAAA,EACjD;AAAA,EAEA,kBAAkB,SAA4B,MAAoB;AAChE,SAAK,MAAM,SAAS,IAAI,EAAE,gBAAgB;AAAA,EAC5C;AAAA,EAEA,cAAc,SAA4B,MAAoB;AAC5D,SAAK,MAAM,SAAS,IAAI,EAAE,YAAY;AAAA,EACxC;AAAA,EAEA,kBAAkB,SAA4B,MAAoB;AAChE,SAAK,MAAM,SAAS,IAAI,EAAE,gBAAgB;AAAA,EAC5C;AAAA,EAEA,MAAM,WAA8B,OAAgC;AAClE,UAAM,WAAW,WAAW,KAAK;AACjC,UAAM,eAAe,WAAW,SAAS;AACzC,UAAM,OAAO,KAAK,QAAQ,IAAI,QAAQ;AACtC,QAAI,CAAC,QAAQ,aAAa,aAAc;AAGxC,UAAM,OAAO,KAAK,QAAQ,IAAI,YAAY,KAAK,KAAK,MAAM,WAAW,KAAK,WAAW;AACrF,SAAK,cAAc,KAAK,IAAI,KAAK,aAAa,KAAK,WAAW;AAC9D,SAAK,aAAa,KAAK,IAAI,KAAK,YAAY,KAAK,UAAU;AAC3D,SAAK,YAAY,KAAK;AACtB,SAAK,WAAW,KAAK;AACrB,SAAK,SAAS,WAAW,CAAC,KAAK,QAAQ,KAAK,MAAM,CAAC;AACnD,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,KAAK,QAAQ,GAAG;AACzD,WAAK,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK;AAAA,IACrD;AACA,SAAK,gBAAgB,KAAK;AAC1B,SAAK,YAAY,KAAK;AACtB,SAAK,gBAAgB,KAAK;AAC1B,eAAW,CAAC,SAAS,IAAI,KAAK,KAAK,gBAAgB;AACjD,UAAI,YAAY,aAAc;AAC9B,YAAM,WAAW,KAAK,eAAe,IAAI,OAAO,KAAK,EAAE,SAAS,GAAG,QAAQ,IAAI;AAC/E,eAAS,WAAW,KAAK;AACzB,eAAS,SAAS,WAAW,CAAC,SAAS,QAAQ,KAAK,MAAM,CAAC;AAC3D,WAAK,eAAe,IAAI,SAAS,QAAQ;AAEzC,YAAM,OAAO,KAAK,QAAQ,IAAI,OAAO;AACrC,YAAM,OAAO,MAAM,eAAe,IAAI,QAAQ;AAC9C,UAAI,QAAQ,MAAM;AAChB,aAAK,eAAe,OAAO,QAAQ;AACnC,cAAM,UAAU,KAAK,eAAe,IAAI,YAAY,KAAK,EAAE,SAAS,GAAG,QAAQ,IAAI;AACnF,gBAAQ,WAAW,KAAK;AACxB,gBAAQ,SAAS,WAAW,CAAC,QAAQ,QAAQ,KAAK,MAAM,CAAC;AACzD,aAAK,eAAe,IAAI,cAAc,OAAO;AAAA,MAC/C;AAAA,IACF;AACA,SAAK,eAAe,OAAO,QAAQ;AACnC,SAAK,QAAQ,OAAO,QAAQ;AAAA,EAC9B;AAAA,EAEA,IAAI,SAAyD;AAC3D,WAAO,KAAK,QAAQ,IAAI,WAAW,OAAO,CAAC;AAAA,EAC7C;AAAA,EAEA,SAAS,KAA0C;AACjD,WAAO,KAAK,QAAQ,IAAI,GAAG;AAAA,EAC7B;AAAA,EAEA,MAAyC;AACvC,WAAO,KAAK,QAAQ,OAAO;AAAA,EAC7B;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAK,QAA+B;AAClC,SAAK,QAAQ,IAAI,WAAW,OAAO,OAAO,GAAG,MAAM;AAAA,EACrD;AAAA;AAAA,EAGQ,MAAM,SAA4B,MAA+B;AACvE,UAAM,MAAM,WAAW,OAAO;AAC9B,QAAI,SAAS,KAAK,QAAQ,IAAI,GAAG;AACjC,QAAI,CAAC,QAAQ;AACX,eAAS;AAAA,QACP,SAAS,iBAAiB,OAAO;AAAA,QACjC,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,SAAS;AAAA,QACT,QAAQ;AAAA,QACR,UAAU,CAAC;AAAA,QACX,cAAc;AAAA,QACd,UAAU;AAAA,QACV,cAAc;AAAA,QACd,gBAAgB,oBAAI,IAAI;AAAA,MAC1B;AACA,WAAK,QAAQ,IAAI,KAAK,MAAM;AAAA,IAC9B;AACA,QAAI,OAAO,OAAO,YAAa,QAAO,cAAc;AACpD,QAAI,OAAO,OAAO,WAAY,QAAO,aAAa;AAClD,WAAO;AAAA,EACT;AACF;;;AC7OO,IAAM,4BAA4B;AAyBlC,IAAM,sBAAN,MAA2D;AAAA,EAGhE,YAA6B,QAAgB,2BAA2B;AAA3C;AAAA,EAA4C;AAAA,EAA5C;AAAA,EAFZ,UAAU,oBAAI,IAAyB;AAAA,EAIxD,SAAS,UAAkB,OAA0B;AAKnD,QAAI,CAAC,KAAK,QAAQ,IAAI,QAAQ,KAAK,KAAK,QAAQ,QAAQ,KAAK,OAAO;AAClE,YAAM,SAAS,KAAK,QAAQ,KAAK,EAAE,KAAK,EAAE;AAC1C,UAAI,WAAW,OAAW,MAAK,QAAQ,OAAO,MAAM;AAAA,IACtD;AACA,SAAK,QAAQ,IAAI,UAAU,KAAK;AAAA,EAClC;AAAA,EAEA,KAAK,UAA2C;AAC9C,WAAO,KAAK,QAAQ,IAAI,QAAQ;AAAA,EAClC;AAAA,EAEA,KAAK,UAA2C;AAC9C,UAAM,QAAQ,KAAK,QAAQ,IAAI,QAAQ;AACvC,QAAI,MAAO,MAAK,QAAQ,OAAO,QAAQ;AACvC,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,KAAK,QAAQ;AAAA,EACtB;AACF;;;ACjDO,IAAM,kBAAgC;AAAA,EAC3C,uBAAuB;AAAA,EACvB,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,qBAAqB;AAAA,EACrB,WAAW;AACb;AAEA,IAAM,SAAS;AAOf,IAAM,UAAU,EAAE,SAAS,GAAG,aAAa,GAAG,QAAQ,GAAG,SAAS,GAAG,mBAAmB,EAAE;AAE1F,IAAM,eAAe,oBAAI,IAAI,CAAC,oBAAoB,mBAAmB,CAAC;AAEtE,SAAS,MAAM,OAAe,IAAY,IAAoB;AAC5D,SAAO,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,CAAC;AACzC;AAEA,SAAS,cAAc,IAA0D;AAC/E,MAAI,UAAU;AACd,MAAI,SAAS;AACb,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,GAAG,QAAQ,GAAG;AACvD,QAAI,aAAa,IAAI,IAAI,EAAG,YAAW;AAAA,QAClC,WAAU;AAAA,EACjB;AACA,SAAO,EAAE,SAAS,OAAO;AAC3B;AAGO,SAAS,gBAAgB,IAA6B;AAC3D,SAAO,OAAO,IAAI,KAAK,IAAI,CAAC,GAAG,UAAU,EAAE;AAC7C;AAGO,SAAS,mBAAmB,IAAqB,OAAuB;AAC7E,QAAM,YAAY,KAAK,IAAI,GAAG,QAAQ,GAAG,WAAW,IAAI;AACxD,SAAO,MAAM,KAAK,IAAI,GAAG,YAAY,EAAE;AACzC;AAQO,SAAS,iBAAiB,IAA6B;AAC5D,QAAM,EAAE,SAAS,OAAO,IAAI,cAAc,EAAE;AAC5C,QAAM,UAAU,KAAK;AAAA,IACnB;AAAA,IACA,GAAG,WAAW,QAAQ,UACpB,GAAG,eAAe,QAAQ,cAC1B,UAAU,QAAQ,SAClB,SAAS,QAAQ,UACjB,GAAG,eAAe,QAAQ;AAAA,EAC9B;AACA,QAAM,eAAe,KAAK,IAAI,GAAG,GAAG,WAAW,GAAG,WAAW,GAAG,YAAY;AAC5E,SAAO,MAAM,KAAK,IAAI,GAAG,IAAI,UAAU,YAAY;AACrD;AAGO,SAAS,qBAAqB,IAA6B;AAChE,MAAI,GAAG,aAAa,EAAG,QAAO;AAC9B,SAAO,MAAM,KAAK,IAAI,GAAG,GAAG,UAAU,GAAG,QAAQ;AACnD;AASO,SAAS,WAAW,IAAqB,OAAuB;AACrE,QAAM,EAAE,SAAS,OAAO,IAAI,cAAc,EAAE;AAC5C,QAAM,eACJ,GAAG,WAAW,GAAG,WAAW,GAAG,eAAe,GAAG,eAAe,UAAU;AAC5E,QAAM,QAAQ,IAAI,KAAK,IAAI,CAAC,eAAe,EAAE;AAC7C,QAAM,YAAY,KAAK,IAAI,GAAG,QAAQ,GAAG,WAAW,IAAI;AACxD,QAAM,MAAM,MAAM,MAAM,KAAK,IAAI,GAAG,YAAY,CAAC;AACjD,SAAO,MAAM,QAAQ,KAAK,GAAG,CAAC;AAChC;AAGO,SAAS,MAAM,YAAkC,SAA+B;AACrF,QAAM,QACJ,WAAW,SAAS,QAAQ,SAC5B,WAAW,YAAY,QAAQ,YAC/B,WAAW,cAAc,QAAQ,cACjC,WAAW,sBAAsB,QAAQ,sBACzC,WAAW,wBAAwB,QAAQ;AAC7C,SAAO,MAAM,KAAK,MAAM,KAAK,GAAG,GAAG,GAAG;AACxC;AAQO,SAAS,UAAU,IAAqB,OAAe,SAA+B;AAC3F,QAAM,YACJ,QAAQ,SAAS,QAAQ,YAAY,QAAQ,cAAc,QAAQ;AACrE,MAAI,aAAa,EAAG,QAAO;AAC3B,QAAM,QACJ,gBAAgB,EAAE,IAAI,QAAQ,SAC9B,mBAAmB,IAAI,KAAK,IAAI,QAAQ,YACxC,iBAAiB,EAAE,IAAI,QAAQ,cAC/B,qBAAqB,EAAE,IAAI,QAAQ;AACrC,SAAO,MAAM,QAAQ,WAAW,GAAG,GAAG;AACxC;;;ACxFA,IAAM,sBAAsB,oBAAI,IAAI;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AA0FM,IAAM,kBAAN,MAAsB;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA,EAGA,UAAU,oBAAI,IAA+B;AAAA,EAE9D,YAAY,UAAkC,CAAC,GAAG;AAChD,SAAK,UAAU,EAAE,GAAG,iBAAiB,GAAG,QAAQ,QAAQ;AACxD,SAAK,MAAM,QAAQ,QAAQ,MAAM,oBAAI,KAAK;AAC1C,SAAK,SAAS,QAAQ,UAAU,IAAI,eAAe;AACnD,SAAK,UACH,QAAQ,WACR,IAAI,oBAAoB,QAAQ,oBAAoB,yBAAyB;AAAA,EACjF;AAAA;AAAA,EAGA,QAAQ,QAA2B;AACjC,WAAO,QAAQ,CAAC,UAAU,KAAK,OAAO,KAAK,CAAC;AAC5C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,KAAK,OAAuC;AAIlD,QAAI;AACF,WAAK,QAAQ,QAAQ,MAAM,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,IACrD,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,KAAK,WAA8B,OAAgC;AACjE,UAAM,SAAS,iBAAiB,KAAK,QAAQ,SAAS,CAAC;AACvD,UAAM,WAAW,WAAW,KAAK;AACjC,QAAI,WAAW,MAAM,MAAM,SAAU;AACrC,SAAK,QAAQ,IAAI,UAAU,MAAM;AAEjC,eAAW,CAAC,KAAK,QAAQ,KAAK,KAAK,SAAS;AAC1C,UAAI,WAAW,QAAQ,MAAM,SAAU,MAAK,QAAQ,IAAI,KAAK,MAAM;AAAA,IACrE;AACA,SAAK,KAAK,MAAM,KAAK,OAAO,MAAM,QAAQ,KAAK,CAAC;AAAA,EAClD;AAAA;AAAA,EAGQ,QAAQ,SAA+C;AAC7D,WAAO,KAAK,QAAQ,IAAI,WAAW,OAAO,CAAC,KAAK;AAAA,EAClD;AAAA,EAEA,OAAO,OAAwB;AAC7B,UAAM,OAAO,MAAM,GAAG,QAAQ;AAC9B,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK,kBAAkB;AACrB,aAAK;AAAA,UAAK,MACR,KAAK,QAAQ,SAAS,MAAM,OAAO,IAAI;AAAA,YACrC,SAAS,MAAM,OAAO;AAAA,YACtB,MAAM,MAAM,OAAO,OAAO;AAAA,YAC1B,QAAQ,MAAM,OAAO;AAAA,UACvB,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAAA,MACA,KAAK,iBAAiB;AACpB,YAAI,MAAM,SAAS,YAAY,QAAS;AACxC,cAAM,QAAQ,KAAK,QAAQ,KAAK,MAAM,SAAS,QAAQ;AACvD,YAAI,CAAC,MAAO;AACZ,aAAK,KAAK,MAAM,KAAK,OAAO,cAAc,KAAK,QAAQ,EAAE,MAAM,SAAS,IAAI,MAAM,QAAQ,CAAC,GAAG,IAAI,CAAC;AACnG,aAAK,KAAK,MAAM,KAAK,OAAO,cAAc,KAAK,QAAQ,EAAE,MAAM,UAAU,IAAI,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC;AACjG;AAAA,MACF;AAAA,MACA,KAAK,mBAAmB;AACtB,cAAM,QAAQ,KAAK,QAAQ,KAAK,MAAM,QAAQ,QAAQ;AACtD,YAAI,CAAC,MAAO;AACZ,cAAM,QAAQ,KAAK,QAAQ,EAAE,MAAM,SAAS,IAAI,MAAM,QAAQ,CAAC;AAC/D,cAAM,SAAS,KAAK,QAAQ,EAAE,MAAM,UAAU,IAAI,MAAM,KAAK,CAAC;AAC9D,aAAK,KAAK,MAAM,KAAK,OAAO,iBAAiB,OAAO,QAAQ,MAAM,QAAQ,IAAI,CAAC;AAC/E;AAAA,MACF;AAAA,MACA,KAAK,gBAAgB;AACnB,aAAK,KAAK,MAAM,KAAK,OAAO,kBAAkB,KAAK,QAAQ,EAAE,MAAM,SAAS,IAAI,MAAM,QAAQ,CAAC,GAAG,IAAI,CAAC;AACvG;AAAA,MACF;AAAA,MACA,KAAK,qBAAqB;AACxB,cAAM,UAAU,MAAM;AACtB,YAAI,CAAC,QAAS;AACd,aAAK;AAAA,UAAK,MACR,KAAK,OAAO,cAAc,KAAK,QAAQ,EAAE,MAAM,SAAS,IAAI,QAAQ,CAAC,GAAG,MAAM,MAAM,IAAI;AAAA,QAC1F;AACA;AAAA,MACF;AAAA,MACA,KAAK,gBAAgB;AACnB,cAAM,QAAQ,KAAK,QAAQ,EAAE,MAAM,SAAS,IAAI,MAAM,QAAQ,MAAM,CAAC;AACrE,cAAM,YAAY,KAAK,QAAQ,EAAE,MAAM,UAAU,IAAI,MAAM,QAAQ,MAAM,CAAC;AAC1E,aAAK,KAAK,MAAM,KAAK,OAAO,cAAc,OAAO,IAAI,CAAC;AACtD,aAAK,KAAK,MAAM,KAAK,OAAO,cAAc,WAAW,IAAI,CAAC;AAC1D,aAAK,KAAK,MAAM,KAAK,OAAO,iBAAiB,OAAO,WAAW,MAAM,QAAQ,QAAQ,IAAI,CAAC;AAC1F;AAAA,MACF;AAAA,MACA,KAAK,gBAAgB;AAQnB,YAAI,CAAC,MAAM,SAAS,oBAAoB,IAAI,MAAM,IAAI,EAAG;AACzD,cAAM,QAAQ,KAAK,QAAQ,EAAE,MAAM,SAAS,IAAI,MAAM,MAAM,CAAC;AAC7D,aAAK,KAAK,MAAM,KAAK,OAAO,cAAc,OAAO,IAAI,CAAC;AACtD,aAAK,KAAK,MAAM,KAAK,OAAO,cAAc,OAAO,MAAM,MAAM,IAAI,CAAC;AAClE;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAIA,KAAK;AAAA,MACL,KAAK;AACH;AAAA,IACJ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,SAAwB;AACpC,QAAI,QAAQ,YAAY,QAAS;AACjC,UAAM,OAAO,QAAQ,UAAU,QAAQ;AACvC,UAAM,QAAQ,KAAK,QAAQ,EAAE,MAAM,SAAS,IAAI,QAAQ,QAAQ,CAAC;AACjE,UAAM,SAAS,KAAK,QAAQ,EAAE,MAAM,UAAU,IAAI,QAAQ,WAAW,CAAC;AACtE,SAAK,KAAK,MAAM,KAAK,OAAO,cAAc,OAAO,IAAI,CAAC;AACtD,SAAK,KAAK,MAAM,KAAK,OAAO,cAAc,QAAQ,IAAI,CAAC;AACvD,QAAI,QAAQ,YAAY,QAAQ;AAC9B,WAAK,KAAK,MAAM,KAAK,OAAO,iBAAiB,OAAO,QAAQ,QAAQ,QAAQ,IAAI,CAAC;AAAA,IACnF;AAAA,EACF;AAAA;AAAA,EAGA,OAAO,OAA2B;AAChC,UAAM,QAAQ,MAAM,MAAM,KAAK,IAAI,GAAG,QAAQ;AAC9C,UAAM,UAAU,KAAK,QAAQ,MAAM,OAAO;AAC1C,QAAI,MAAM,SAAS,UAAW,MAAK,KAAK,MAAM,KAAK,OAAO,cAAc,SAAS,IAAI,CAAC;AAAA,QACjF,MAAK,KAAK,MAAM,KAAK,OAAO,kBAAkB,SAAS,IAAI,CAAC;AAAA,EACnE;AAAA;AAAA,EAGA,MAAM,QAAuB;AAC3B,UAAM,KAAK,OAAO,QAAQ;AAC1B,UAAM,KAAK,QAAQ,QAAQ;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAyD;AAC7D,UAAM,KAAK,KAAK,OAAO,IAAI,KAAK,QAAQ,OAAO,CAAC;AAChD,WAAO,MAAM,KAAK,QAAQ,EAAE;AAAA,EAC9B;AAAA;AAAA,EAGA,OAAO,MAAqD;AAC1D,UAAM,MAAyB,CAAC;AAChC,eAAW,MAAM,KAAK,OAAO,IAAI,GAAG;AAClC,UAAI,QAAQ,GAAG,QAAQ,SAAS,KAAM;AACtC,UAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;AAAA,IAC3B;AACA,WAAO,IAAI,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAAA,EAC7C;AAAA;AAAA,EAGA,QAAQ,SAA+D;AACrE,UAAM,KAAK,KAAK,OAAO,IAAI,KAAK,QAAQ,OAAO,CAAC;AAChD,QAAI,CAAC,GAAI,QAAO;AAChB,WAAO;AAAA,MACL,OAAO,KAAK,QAAQ,EAAE;AAAA,MACtB,SAAS,KAAK;AAAA,MACd,UAAU;AAAA,QACR,UAAU,GAAG;AAAA,QACb,SAAS,GAAG;AAAA,QACZ,QAAQ,GAAG;AAAA,QACX,UAAU,EAAE,GAAG,GAAG,SAAS;AAAA,QAC3B,cAAc,GAAG;AAAA,QACjB,UAAU,GAAG;AAAA,QACb,cAAc,GAAG;AAAA,QACjB,WAAW,IAAI,KAAK,GAAG,WAAW;AAAA,QAClC,UAAU,IAAI,KAAK,GAAG,UAAU;AAAA,QAChC,gBAAgB,CAAC,GAAG,GAAG,eAAe,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM;AACpE,gBAAM,CAAC,MAAM,GAAG,EAAE,IAAI,IAAI,MAAM,GAAG;AACnC,iBAAO;AAAA,YACL,SAAS,EAAE,MAAyC,IAAI,GAAG,KAAK,GAAG,EAAE;AAAA,YACrE,SAAS,KAAK;AAAA,YACd,QAAQ,KAAK;AAAA,UACf;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,YACJ,MACA,UAAuB,CAAC,GACM;AAC9B,UAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,UAAM,SAA8B,CAAC;AACrC,eAAW,MAAM,KAAK,OAAO,IAAI,GAAG;AAClC,UAAI,GAAG,QAAQ,SAAS,SAAU;AAClC,YAAM,QAAQ,KAAK,QAAQ,EAAE;AAC7B,UAAI,MAAM,aAAa,cAAe;AACtC,YAAM,KAAK,oBAAoB,GAAG,QAAQ,IAAI,MAAM,KAAK;AACzD,aAAO,KAAK,EAAE,MAAM,GAAG,QAAQ,IAAI,OAAO,MAAM,OAAO,YAAY,MAAM,WAAW,CAAC;AAAA,IACvF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,WAAmB;AACjB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEQ,QAAQ,IAAsC;AACpD,UAAM,QAAQ,KAAK,IAAI,EAAE,QAAQ;AACjC,UAAM,aAAmC;AAAA,MACvC,QAAQ,gBAAgB,EAAE;AAAA,MAC1B,WAAW,mBAAmB,IAAI,KAAK;AAAA,MACvC,aAAa,iBAAiB,EAAE;AAAA,MAChC,qBAAqB,KAAK,oBAAoB,IAAI,KAAK;AAAA,MACvD,uBAAuB,qBAAqB,EAAE;AAAA,IAChD;AACA,WAAO,gBAAgB,MAAM;AAAA,MAC3B,SAAS,GAAG;AAAA,MACZ,OAAO,MAAM,YAAY,KAAK,OAAO;AAAA,MACrC;AAAA,MACA,YAAY,WAAW,IAAI,KAAK;AAAA,MAChC,MAAM,IAAI,KAAK,KAAK;AAAA,IACtB,CAAC;AAAA,EACH;AAAA;AAAA,EAGQ,oBAAoB,IAAqB,OAAuB;AACtE,QAAI,GAAG,eAAe,SAAS,EAAG,QAAO;AACzC,QAAI,QAAQ;AACZ,eAAW,OAAO,GAAG,eAAe,KAAK,GAAG;AAC1C,YAAM,QAAQ,KAAK,OAAO,SAAS,GAAG;AACtC,eAAS,QAAQ,UAAU,OAAO,OAAO,KAAK,OAAO,IAAI;AAAA,IAC3D;AACA,WAAO,QAAQ,GAAG,eAAe;AAAA,EACnC;AACF;AAeO,SAAS,WACd,OACA,UAA6B,CAAC,GACS;AACvC,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,SAAO,CAAC,UAAU;AAChB,UAAM,QAAQ,MAAM,MAAM,EAAE,MAAM,SAAS,IAAI,MAAM,CAAC;AACtD,QAAI,CAAC,SAAS,MAAM,aAAa,cAAe,QAAO;AACvD,QAAI,MAAM,SAAS,UAAW,QAAO;AACrC,WAAO,oBAAoB,MAAM,KAAK,kCAAkC,SAAS;AAAA,EACnF;AACF;;;ACpbA,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAC7B,OAAO,aAAuC;AAC9C,SAAS,KAAAC,UAAS;AAIlB,IAAM,cAAcC,GAAE,OAAO;AAAA,EAC3B,SAAS;AAAA,EACT,MAAMA,GAAE,KAAK,CAAC,WAAW,aAAa,CAAC;AAAA,EACvC,IAAIA,GAAE,OAAO,KAAK,EAAE,SAAS;AAAA,EAC7B,MAAMA,GAAE,OAAO,EAAE,IAAI,GAAG,EAAE,SAAS;AACrC,CAAC;AAED,IAAM,cAAcA,GAAE,OAAO,EAAE,MAAMA,GAAE,KAAK,CAAC,SAAS,QAAQ,CAAC,EAAE,SAAS,EAAE,CAAC;AAE7E,IAAM,YAAYA,GACf,OAAO;AAAA,EACN,WAAW;AAAA,EACX,OAAO;AACT,CAAC,EAGA,OAAO,CAAC,MAAM,EAAE,UAAU,SAAS,EAAE,MAAM,MAAM;AAAA,EAChD,SAAS;AACX,CAAC;AAOI,SAAS,iBAAiB,QAAyB,IAAI,gBAAgB,GAAoB;AAChG,QAAM,MAAM,QAAQ,EAAE,QAAQ,MAAM,CAAC;AAGrC,MAAI,gBAAgB,CAAC,KAAc,MAAM,UAAU;AACjD,QAAI,eAAeA,GAAE,UAAU;AAC7B,aAAO,MAAM,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,oBAAoB,QAAQ,IAAI,OAAO,CAAC;AAAA,IACjF;AACA,UAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,WAAO,MAAM,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,kBAAkB,QAAQ,CAAC;AAAA,EACpE,CAAC;AAED,MAAI,IAAI,WAAW,OAAO,EAAE,QAAQ,MAAM,UAAU,MAAM,SAAS,EAAE,EAAE;AAMvE,MAAI,KAAK,cAAc,OAAO,QAAQ;AACpC,UAAM,SAASA,GAAE,MAAM,CAAC,UAAU,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,GAAGA,GAAE,MAAM,SAAS,CAAC,CAAC,EAAE,MAAM,IAAI,IAAI;AAC5F,eAAW,SAAS,OAAQ,OAAM,OAAO,KAAK;AAC9C,UAAM,MAAM,MAAM;AAClB,WAAO,EAAE,UAAU,OAAO,OAAO;AAAA,EACnC,CAAC;AAED,MAAI,KAAK,eAAe,OAAO,QAAQ;AACrC,UAAM,QAAQ,YAAY,MAAM,IAAI,IAAI;AACxC,UAAM,OAAO,KAAK;AAClB,UAAM,MAAM,MAAM;AAClB,WAAO,MAAM,MAAM,MAAM,OAAO;AAAA,EAClC,CAAC;AAOD,MAAI,KAAK,aAAa,OAAO,QAAQ;AACnC,UAAM,QAAQA,GAAE,MAAM,CAAC,UAAU,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,GAAGA,GAAE,MAAM,SAAS,CAAC,CAAC,EAAE,MAAM,IAAI,IAAI;AAC3F,eAAW,QAAQ,MAAO,OAAM,KAAK,KAAK,WAAW,KAAK,KAAK;AAC/D,UAAM,MAAM,MAAM;AAClB,WAAO,EAAE,QAAQ,MAAM,OAAO;AAAA,EAChC,CAAC;AAGD,MAAI,IAAI,cAAc,CAAC,QAAQ;AAC7B,UAAM,EAAE,KAAK,IAAI,YAAY,MAAM,IAAI,KAAK;AAC5C,WAAO,MAAM,OAAO,IAAI;AAAA,EAC1B,CAAC;AAED,MAAI,IAAI,wBAAwB,CAAC,KAAK,UAAU;AAC9C,UAAM,UAAU,kBAAkB,MAAM,IAAI,MAAM;AAClD,UAAM,cAAc,MAAM,QAAQ,OAAO;AACzC,QAAI,CAAC,aAAa;AAChB,aAAO,MACJ,OAAO,GAAG,EACV,KAAK,EAAE,OAAO,aAAa,SAAS,mBAAmB,QAAQ,IAAI,IAAI,QAAQ,EAAE,GAAG,CAAC;AAAA,IAC1F;AACA,WAAO;AAAA,EACT,CAAC;AAED,SAAO;AACT;AAGA,SAAS,eAAwB;AAC/B,MAAI,CAAC,QAAQ,KAAK,CAAC,EAAG,QAAO;AAC7B,MAAI;AACF,WAAO,aAAa,QAAQ,KAAK,CAAC,CAAC,MAAM,aAAa,cAAc,YAAY,GAAG,CAAC;AAAA,EACtF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,IAAI,aAAa,GAAG;AAClB,QAAM,OAAO,OAAO,QAAQ,IAAI,QAAQ,IAAI;AAC5C,QAAM,OAAO,QAAQ,IAAI,QAAQ;AACjC,QAAM,MAAM,iBAAiB;AAC7B,MACG,OAAO,EAAE,MAAM,KAAK,CAAC,EACrB,KAAK,MAAM,QAAQ,IAAI,oCAAoC,IAAI,IAAI,IAAI,EAAE,CAAC,EAC1E,MAAM,CAAC,QAAQ;AACd,YAAQ,MAAM,GAAG;AACjB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACL;","names":["z","z","z","z","z"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@reinconsole/graph",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Rein's reputation graph (Phase 3) — turns guard receipts and gate receipts into explainable reputation scores, and feeds them back into policy (vendorReputationLt) and gate screening.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"homepage": "https://github.com/bugiiiii11/rein#readme",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/bugiiiii11/rein.git",
|
|
10
|
+
"directory": "services/graph"
|
|
11
|
+
},
|
|
12
|
+
"bugs": "https://github.com/bugiiiii11/rein/issues",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"rein",
|
|
15
|
+
"reputation",
|
|
16
|
+
"trust",
|
|
17
|
+
"x402",
|
|
18
|
+
"erc-8004",
|
|
19
|
+
"ai-agents",
|
|
20
|
+
"agent-payments"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=22"
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"type": "module",
|
|
29
|
+
"sideEffects": false,
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"import": "./dist/index.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"main": "./dist/index.js",
|
|
37
|
+
"types": "./dist/index.d.ts",
|
|
38
|
+
"files": [
|
|
39
|
+
"dist"
|
|
40
|
+
],
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"fastify": "^5.2.0",
|
|
43
|
+
"zod": "^3.24.1",
|
|
44
|
+
"@reinconsole/core": "^0.1.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^22.10.0",
|
|
48
|
+
"tsup": "^8.3.5",
|
|
49
|
+
"typescript": "^5.7.2",
|
|
50
|
+
"vitest": "^2.1.8",
|
|
51
|
+
"@reinconsole/gate": "0.1.0",
|
|
52
|
+
"@reinconsole/policy-engine": "0.1.0"
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "tsup",
|
|
56
|
+
"typecheck": "tsc --noEmit",
|
|
57
|
+
"test": "vitest run",
|
|
58
|
+
"test:watch": "vitest",
|
|
59
|
+
"clean": "rimraf dist .turbo"
|
|
60
|
+
}
|
|
61
|
+
}
|