dero-mcp-server 0.1.1 → 0.2.2
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/README.md +79 -6
- package/data/docs-index.json +5702 -0
- package/dist/citations.d.ts +70 -0
- package/dist/citations.d.ts.map +1 -0
- package/dist/citations.js +162 -0
- package/dist/citations.js.map +1 -0
- package/dist/composites/_shared.d.ts +119 -0
- package/dist/composites/_shared.d.ts.map +1 -0
- package/dist/composites/_shared.js +152 -0
- package/dist/composites/_shared.js.map +1 -0
- package/dist/composites/diagnose-chain-health.d.ts +64 -0
- package/dist/composites/diagnose-chain-health.d.ts.map +1 -0
- package/dist/composites/diagnose-chain-health.js +144 -0
- package/dist/composites/diagnose-chain-health.js.map +1 -0
- package/dist/composites/estimate-deploy-cost.d.ts +83 -0
- package/dist/composites/estimate-deploy-cost.d.ts.map +1 -0
- package/dist/composites/estimate-deploy-cost.js +116 -0
- package/dist/composites/estimate-deploy-cost.js.map +1 -0
- package/dist/composites/explain-smart-contract.d.ts +64 -0
- package/dist/composites/explain-smart-contract.d.ts.map +1 -0
- package/dist/composites/explain-smart-contract.js +149 -0
- package/dist/composites/explain-smart-contract.js.map +1 -0
- package/dist/composites/recommend-docs-path.d.ts +97 -0
- package/dist/composites/recommend-docs-path.d.ts.map +1 -0
- package/dist/composites/recommend-docs-path.js +149 -0
- package/dist/composites/recommend-docs-path.js.map +1 -0
- package/dist/composites/trace-transaction-with-context.d.ts +107 -0
- package/dist/composites/trace-transaction-with-context.d.ts.map +1 -0
- package/dist/composites/trace-transaction-with-context.js +217 -0
- package/dist/composites/trace-transaction-with-context.js.map +1 -0
- package/dist/docs-parse.d.ts +30 -0
- package/dist/docs-parse.d.ts.map +1 -0
- package/dist/docs-parse.js +147 -0
- package/dist/docs-parse.js.map +1 -0
- package/dist/docs.d.ts +101 -0
- package/dist/docs.d.ts.map +1 -0
- package/dist/docs.js +172 -0
- package/dist/docs.js.map +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +417 -100
- package/dist/server.js.map +1 -1
- package/dist/tool-descriptions.d.ts +50 -0
- package/dist/tool-descriptions.d.ts.map +1 -0
- package/dist/tool-descriptions.js +246 -0
- package/dist/tool-descriptions.js.map +1 -0
- package/package.json +15 -3
- package/.github/workflows/ci.yml +0 -62
- package/docs/example-agent-flows.md +0 -236
- package/docs/mcp-agent-ready-evidence.md +0 -108
- package/glama.json +0 -6
- package/scripts/doctor.sh +0 -85
- package/scripts/flow-test.ts +0 -257
- package/scripts/mcp-smoke-probes.ts +0 -168
- package/server.json +0 -23
- package/src/index.ts +0 -30
- package/src/rpc.ts +0 -60
- package/src/server.ts +0 -636
- package/tsconfig.json +0 -16
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `recommend_docs_path` — Phase C composite #3.
|
|
3
|
+
*
|
|
4
|
+
* Docs-only composite. Takes a natural-language intent, runs scoped
|
|
5
|
+
* searches across ALL four products in parallel, boosts
|
|
6
|
+
* hint-matching scores by 1.5× (when `product_hint` is provided),
|
|
7
|
+
* groups results by product, and returns a ranked path with
|
|
8
|
+
* per-result rationale and ready-to-cite citations.
|
|
9
|
+
*
|
|
10
|
+
* Wedge: agents currently have to guess which docs product to search
|
|
11
|
+
* (derod for daemon RPC, tela for on-chain apps, hologram for the
|
|
12
|
+
* simulator, deropay for the merchant flow). This composite removes
|
|
13
|
+
* that guess: one call, one ranked answer, with citations the agent
|
|
14
|
+
* can drop straight into a response.
|
|
15
|
+
*
|
|
16
|
+
* Design contract: `docs/composites.md` § 3. Sequencing rule: SHIP
|
|
17
|
+
* THIRD. Pure docs composition — no chain reads. Proves the
|
|
18
|
+
* "docs-only composite" pattern that future docs-heavy tools can
|
|
19
|
+
* reuse.
|
|
20
|
+
*
|
|
21
|
+
* Design clarification: the spec text "for each product (or just
|
|
22
|
+
* `product_hint` if provided)" reads like a filter, but the spec's
|
|
23
|
+
* scoring rule ("score by `score * productHintBoost` for hint
|
|
24
|
+
* matches") only makes sense if all four products are always
|
|
25
|
+
* searched and the hint is treated as a BIAS, not a FILTER. Treating
|
|
26
|
+
* the hint as a filter would make the boost a uniform no-op. This
|
|
27
|
+
* implementation searches all four products on every call so the
|
|
28
|
+
* hint scoring carries real weight and the agent still sees relevant
|
|
29
|
+
* cross-product docs (e.g. derod RPC pages that touch TELA).
|
|
30
|
+
*
|
|
31
|
+
* Failure model:
|
|
32
|
+
* - Zero matches across every product → throw
|
|
33
|
+
* `'No DERO docs matched intent: "..."'`. The `withStructuredErrors`
|
|
34
|
+
* wrapper classifies this as `NO_DOCS_MATCH` and emits a hint
|
|
35
|
+
* telling the agent to rephrase (or change the `product_hint`).
|
|
36
|
+
* - The bundled docs index missing → propagates the existing
|
|
37
|
+
* `DOCS_UNAVAILABLE` classification from `searchDeroDocs`.
|
|
38
|
+
*/
|
|
39
|
+
import { z } from 'zod';
|
|
40
|
+
import { type DeroDocProduct } from '../docs.js';
|
|
41
|
+
import { type DeroCitation } from '../citations.js';
|
|
42
|
+
export declare const recommendDocsPathInputSchema: {
|
|
43
|
+
readonly intent: z.ZodString;
|
|
44
|
+
readonly product_hint: z.ZodOptional<z.ZodEnum<["derod", "tela", "hologram", "deropay"]>>;
|
|
45
|
+
readonly limit_per_product: z.ZodOptional<z.ZodNumber>;
|
|
46
|
+
};
|
|
47
|
+
type RecommendInput = {
|
|
48
|
+
intent: string;
|
|
49
|
+
product_hint?: DeroDocProduct;
|
|
50
|
+
limit_per_product?: number;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Per-result shape returned by `searchDeroDocs`. Re-declared here as the
|
|
54
|
+
* minimum surface the composite touches so this module stays decoupled
|
|
55
|
+
* from internal changes to the docs search response.
|
|
56
|
+
*/
|
|
57
|
+
type SearchHit = {
|
|
58
|
+
product: DeroDocProduct;
|
|
59
|
+
slug: string;
|
|
60
|
+
title: string;
|
|
61
|
+
description?: string;
|
|
62
|
+
canonical_url: string;
|
|
63
|
+
headings: string[];
|
|
64
|
+
excerpt: string;
|
|
65
|
+
score: number;
|
|
66
|
+
};
|
|
67
|
+
type Recommendation = {
|
|
68
|
+
product: DeroDocProduct;
|
|
69
|
+
slug: string;
|
|
70
|
+
title: string;
|
|
71
|
+
canonical_url: string;
|
|
72
|
+
score: number;
|
|
73
|
+
boosted_score: number;
|
|
74
|
+
rationale: string;
|
|
75
|
+
};
|
|
76
|
+
type ByProductSummary = Record<DeroDocProduct, {
|
|
77
|
+
count: number;
|
|
78
|
+
top_slug: string | null;
|
|
79
|
+
top_score: number | null;
|
|
80
|
+
}>;
|
|
81
|
+
/**
|
|
82
|
+
* Pure helper: turn raw per-product hits into a ranked, deduplicated
|
|
83
|
+
* list with boosted scores and rationale strings. Exported so flow
|
|
84
|
+
* tests / future unit tests can call it without spinning up an MCP
|
|
85
|
+
* client.
|
|
86
|
+
*/
|
|
87
|
+
export declare function rankRecommendations(intent: string, productHint: DeroDocProduct | undefined, hitsByProduct: ReadonlyMap<DeroDocProduct, readonly SearchHit[]>): Recommendation[];
|
|
88
|
+
export declare function recommendDocsPath(args: RecommendInput): Promise<{
|
|
89
|
+
intent: string;
|
|
90
|
+
product_hint: "derod" | "tela" | "hologram" | "deropay" | null;
|
|
91
|
+
limit_per_product: number;
|
|
92
|
+
recommended: Recommendation[];
|
|
93
|
+
by_product: ByProductSummary;
|
|
94
|
+
related_docs: DeroCitation[];
|
|
95
|
+
}>;
|
|
96
|
+
export {};
|
|
97
|
+
//# sourceMappingURL=recommend-docs-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommend-docs-path.d.ts","sourceRoot":"","sources":["../../src/composites/recommend-docs-path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,YAAY,CAAA;AACnB,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAItE,eAAO,MAAM,4BAA4B;;;;CAkB/B,CAAA;AAEV,KAAK,cAAc,GAAG;IACpB,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,cAAc,CAAA;IAC7B,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED;;;;GAIG;AACH,KAAK,SAAS,GAAG;IACf,OAAO,EAAE,cAAc,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,cAAc,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,MAAM,CAAA;IACrB,KAAK,EAAE,MAAM,CAAA;IACb,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,KAAK,gBAAgB,GAAG,MAAM,CAC5B,cAAc,EACd;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CACrE,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,cAAc,GAAG,SAAS,EACvC,aAAa,EAAE,WAAW,CAAC,cAAc,EAAE,SAAS,SAAS,EAAE,CAAC,GAC/D,cAAc,EAAE,CA2BlB;AA4CD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,cAAc;;;;;;;GAsC3D"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `recommend_docs_path` — Phase C composite #3.
|
|
3
|
+
*
|
|
4
|
+
* Docs-only composite. Takes a natural-language intent, runs scoped
|
|
5
|
+
* searches across ALL four products in parallel, boosts
|
|
6
|
+
* hint-matching scores by 1.5× (when `product_hint` is provided),
|
|
7
|
+
* groups results by product, and returns a ranked path with
|
|
8
|
+
* per-result rationale and ready-to-cite citations.
|
|
9
|
+
*
|
|
10
|
+
* Wedge: agents currently have to guess which docs product to search
|
|
11
|
+
* (derod for daemon RPC, tela for on-chain apps, hologram for the
|
|
12
|
+
* simulator, deropay for the merchant flow). This composite removes
|
|
13
|
+
* that guess: one call, one ranked answer, with citations the agent
|
|
14
|
+
* can drop straight into a response.
|
|
15
|
+
*
|
|
16
|
+
* Design contract: `docs/composites.md` § 3. Sequencing rule: SHIP
|
|
17
|
+
* THIRD. Pure docs composition — no chain reads. Proves the
|
|
18
|
+
* "docs-only composite" pattern that future docs-heavy tools can
|
|
19
|
+
* reuse.
|
|
20
|
+
*
|
|
21
|
+
* Design clarification: the spec text "for each product (or just
|
|
22
|
+
* `product_hint` if provided)" reads like a filter, but the spec's
|
|
23
|
+
* scoring rule ("score by `score * productHintBoost` for hint
|
|
24
|
+
* matches") only makes sense if all four products are always
|
|
25
|
+
* searched and the hint is treated as a BIAS, not a FILTER. Treating
|
|
26
|
+
* the hint as a filter would make the boost a uniform no-op. This
|
|
27
|
+
* implementation searches all four products on every call so the
|
|
28
|
+
* hint scoring carries real weight and the agent still sees relevant
|
|
29
|
+
* cross-product docs (e.g. derod RPC pages that touch TELA).
|
|
30
|
+
*
|
|
31
|
+
* Failure model:
|
|
32
|
+
* - Zero matches across every product → throw
|
|
33
|
+
* `'No DERO docs matched intent: "..."'`. The `withStructuredErrors`
|
|
34
|
+
* wrapper classifies this as `NO_DOCS_MATCH` and emits a hint
|
|
35
|
+
* telling the agent to rephrase (or change the `product_hint`).
|
|
36
|
+
* - The bundled docs index missing → propagates the existing
|
|
37
|
+
* `DOCS_UNAVAILABLE` classification from `searchDeroDocs`.
|
|
38
|
+
*/
|
|
39
|
+
import { z } from 'zod';
|
|
40
|
+
import { DERO_DOC_PRODUCTS, searchDeroDocs, } from '../docs.js';
|
|
41
|
+
import { buildDeroCitation } from '../citations.js';
|
|
42
|
+
const PRODUCT_HINT_BOOST = 1.5;
|
|
43
|
+
export const recommendDocsPathInputSchema = {
|
|
44
|
+
intent: z
|
|
45
|
+
.string()
|
|
46
|
+
.min(8)
|
|
47
|
+
.describe('Natural-language description of what the user wants to do (e.g. "deploy a TELA app", "trace a transaction by hash", "verify a webhook signature").'),
|
|
48
|
+
product_hint: z
|
|
49
|
+
.enum(DERO_DOC_PRODUCTS)
|
|
50
|
+
.optional()
|
|
51
|
+
.describe('Optional bias toward one product (derod | tela | hologram | deropay) when known.'),
|
|
52
|
+
limit_per_product: z
|
|
53
|
+
.number()
|
|
54
|
+
.int()
|
|
55
|
+
.min(1)
|
|
56
|
+
.max(5)
|
|
57
|
+
.optional()
|
|
58
|
+
.describe('Cap per-product search results before merging. Default 2.'),
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Pure helper: turn raw per-product hits into a ranked, deduplicated
|
|
62
|
+
* list with boosted scores and rationale strings. Exported so flow
|
|
63
|
+
* tests / future unit tests can call it without spinning up an MCP
|
|
64
|
+
* client.
|
|
65
|
+
*/
|
|
66
|
+
export function rankRecommendations(intent, productHint, hitsByProduct) {
|
|
67
|
+
const out = [];
|
|
68
|
+
const seen = new Set();
|
|
69
|
+
for (const [product, hits] of hitsByProduct) {
|
|
70
|
+
for (const hit of hits) {
|
|
71
|
+
const key = `${product}::${hit.slug}`;
|
|
72
|
+
if (seen.has(key))
|
|
73
|
+
continue;
|
|
74
|
+
seen.add(key);
|
|
75
|
+
const boost = product === productHint ? PRODUCT_HINT_BOOST : 1;
|
|
76
|
+
const boostedScore = Math.round(hit.score * boost * 100) / 100;
|
|
77
|
+
const topHeading = hit.headings[0];
|
|
78
|
+
const rationale = buildRationale(intent, product, hit.score, boost, topHeading);
|
|
79
|
+
out.push({
|
|
80
|
+
product,
|
|
81
|
+
slug: hit.slug,
|
|
82
|
+
title: hit.title,
|
|
83
|
+
canonical_url: hit.canonical_url,
|
|
84
|
+
score: hit.score,
|
|
85
|
+
boosted_score: boostedScore,
|
|
86
|
+
rationale,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
out.sort((a, b) => b.boosted_score - a.boosted_score);
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
function buildRationale(intent, product, rawScore, boost, topHeading) {
|
|
94
|
+
const boostNote = boost > 1 ? ` (×${boost} product_hint boost applied)` : '';
|
|
95
|
+
const headingPart = topHeading ? ` Top heading: "${topHeading.slice(0, 80)}".` : '';
|
|
96
|
+
return `Match for "${intent.slice(0, 60)}" under product=${product} (raw score ${rawScore}${boostNote}).${headingPart}`;
|
|
97
|
+
}
|
|
98
|
+
function summarizeByProduct(recs) {
|
|
99
|
+
const out = Object.create(null);
|
|
100
|
+
for (const product of DERO_DOC_PRODUCTS) {
|
|
101
|
+
out[product] = { count: 0, top_slug: null, top_score: null };
|
|
102
|
+
}
|
|
103
|
+
for (const rec of recs) {
|
|
104
|
+
const bucket = out[rec.product];
|
|
105
|
+
bucket.count += 1;
|
|
106
|
+
if (bucket.top_score === null || rec.boosted_score > bucket.top_score) {
|
|
107
|
+
bucket.top_score = rec.boosted_score;
|
|
108
|
+
bucket.top_slug = rec.slug;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return out;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Build top-N citations from the ranked recommendations. Always
|
|
115
|
+
* deduplicated by `product::slug` (which `rankRecommendations` also
|
|
116
|
+
* enforces) so the citation list never lists the same page twice.
|
|
117
|
+
*/
|
|
118
|
+
function citationsFromRecommendations(recs, topN) {
|
|
119
|
+
return recs
|
|
120
|
+
.slice(0, topN)
|
|
121
|
+
.map((rec) => buildDeroCitation(rec.product, rec.slug, rec.title));
|
|
122
|
+
}
|
|
123
|
+
export async function recommendDocsPath(args) {
|
|
124
|
+
const intent = args.intent.trim();
|
|
125
|
+
const limitPerProduct = args.limit_per_product ?? 2;
|
|
126
|
+
const productHint = args.product_hint;
|
|
127
|
+
// Always fan out to all four products. `searchDeroDocs` shares an
|
|
128
|
+
// in-process page cache (15s TTL) so the second+ calls in the batch
|
|
129
|
+
// resolve from memory; the network/disk cost is paid once per cache
|
|
130
|
+
// window. See the module header for why we don't filter to
|
|
131
|
+
// product_hint.
|
|
132
|
+
const searches = await Promise.all(DERO_DOC_PRODUCTS.map((product) => searchDeroDocs({ query: intent, product, limit: limitPerProduct }).then((res) => [product, res.results])));
|
|
133
|
+
const hitsByProduct = new Map(searches);
|
|
134
|
+
const recommended = rankRecommendations(intent, productHint, hitsByProduct);
|
|
135
|
+
if (recommended.length === 0) {
|
|
136
|
+
throw new Error(`No DERO docs matched intent: "${intent}" across products: ${DERO_DOC_PRODUCTS.join(', ')}. Try rephrasing with product-specific nouns (e.g. "TELA INDEX-1 contract", "DeroPay webhook").`);
|
|
137
|
+
}
|
|
138
|
+
const by_product = summarizeByProduct(recommended);
|
|
139
|
+
const related_docs = citationsFromRecommendations(recommended, 2);
|
|
140
|
+
return {
|
|
141
|
+
intent,
|
|
142
|
+
product_hint: productHint ?? null,
|
|
143
|
+
limit_per_product: limitPerProduct,
|
|
144
|
+
recommended,
|
|
145
|
+
by_product,
|
|
146
|
+
related_docs,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=recommend-docs-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recommend-docs-path.js","sourceRoot":"","sources":["../../src/composites/recommend-docs-path.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `trace_transaction_with_context` — Phase C composite #5 (final).
|
|
3
|
+
*
|
|
4
|
+
* Wedge: `dero_get_transaction` returns the raw tx record (block,
|
|
5
|
+
* ring, signer, code, balances) but leaves the agent to figure out
|
|
6
|
+
* confirmation state, classify the tx kind, and separately fetch
|
|
7
|
+
* any SC context. This composite combines all of that in one call
|
|
8
|
+
* and stitches the right docs page as a citation.
|
|
9
|
+
*
|
|
10
|
+
* Design contract: `docs/composites.md` § 5. Sequencing rule: SHIP
|
|
11
|
+
* LAST — highest fan-out + failure-mode count of all Phase C
|
|
12
|
+
* composites.
|
|
13
|
+
*
|
|
14
|
+
* Implementation notes (recorded honestly so the design doc and
|
|
15
|
+
* shipped surface stay in sync):
|
|
16
|
+
*
|
|
17
|
+
* - SC INSTALL detection works directly off the tx record: when
|
|
18
|
+
* `tx.code` is non-empty the tx_hash itself IS the resulting
|
|
19
|
+
* SCID and the embedded code is the deployed source. We run
|
|
20
|
+
* `extractScSurface` on `tx.code` directly — no second
|
|
21
|
+
* `DERO.GetSC` call is needed for installs.
|
|
22
|
+
* - SC INVOCATION arg/entrypoint decoding requires walking the
|
|
23
|
+
* binary tx blob (`txs_as_hex`) with DERO's tx codec. That
|
|
24
|
+
* codec is not yet bundled in this MCP, so the composite does
|
|
25
|
+
* NOT fabricate decoded args. It surfaces `raw_tx_hex_length`
|
|
26
|
+
* so the agent knows the binary is available via
|
|
27
|
+
* `dero_get_transaction` if a downstream wallet wants to
|
|
28
|
+
* decode it.
|
|
29
|
+
* - TX_NOT_FOUND is signalled by the daemon as an EMPTY record
|
|
30
|
+
* (`block_height: 0, in_pool: false, code: ''`) — it does
|
|
31
|
+
* not throw. The composite detects this and throws a
|
|
32
|
+
* classifier-friendly message so `withStructuredErrors`
|
|
33
|
+
* surfaces `_meta.error.code = TX_NOT_FOUND`.
|
|
34
|
+
*
|
|
35
|
+
* Failure model:
|
|
36
|
+
* - `DERO.GetTransaction` throws → propagates via
|
|
37
|
+
* `withStructuredErrors` (RPC_UNREACHABLE / RPC_INVALID_PARAMS
|
|
38
|
+
* classifier branches handle the daemon-side cases).
|
|
39
|
+
* - Daemon returns empty record for the hash → composite throws
|
|
40
|
+
* `'DERO transaction not found: ...'` → classifier returns
|
|
41
|
+
* `TX_NOT_FOUND` with a retry hint.
|
|
42
|
+
* - Tx found but SC surface extraction degraded for the install
|
|
43
|
+
* case → record the surface as-is (`has_code: false`,
|
|
44
|
+
* `functions: []`) and let the narrative explain. Never abort.
|
|
45
|
+
*/
|
|
46
|
+
import { z } from 'zod';
|
|
47
|
+
import { type DeroDaemonRpc } from './_shared.js';
|
|
48
|
+
export declare const traceTransactionWithContextInputSchema: {
|
|
49
|
+
readonly tx_hash: z.ZodString;
|
|
50
|
+
readonly decode: z.ZodOptional<z.ZodBoolean>;
|
|
51
|
+
readonly include_sc_context: z.ZodOptional<z.ZodBoolean>;
|
|
52
|
+
};
|
|
53
|
+
type TraceInput = {
|
|
54
|
+
tx_hash: string;
|
|
55
|
+
decode?: boolean;
|
|
56
|
+
include_sc_context?: boolean;
|
|
57
|
+
};
|
|
58
|
+
type ConfirmationStatus = 'confirmed' | 'mempool' | 'unknown';
|
|
59
|
+
type TxKind = 'sc_install' | 'transfer_or_invocation' | 'coinbase' | 'unknown';
|
|
60
|
+
export declare function traceTransactionWithContext(rpc: DeroDaemonRpc, args: TraceInput): Promise<{
|
|
61
|
+
tx_hash: string;
|
|
62
|
+
confirmation: {
|
|
63
|
+
status: ConfirmationStatus;
|
|
64
|
+
block_height: number | null;
|
|
65
|
+
valid_block: string | null;
|
|
66
|
+
invalid_blocks: string[];
|
|
67
|
+
in_pool: boolean;
|
|
68
|
+
};
|
|
69
|
+
kind: TxKind;
|
|
70
|
+
ring: {
|
|
71
|
+
groups: number | null;
|
|
72
|
+
first_group_size: number | null;
|
|
73
|
+
};
|
|
74
|
+
reward: number | null;
|
|
75
|
+
signer_visible: boolean;
|
|
76
|
+
native_balance: {
|
|
77
|
+
scid: string;
|
|
78
|
+
at_tx: number | null;
|
|
79
|
+
current: number | null;
|
|
80
|
+
};
|
|
81
|
+
sc_install: {
|
|
82
|
+
scid: string;
|
|
83
|
+
surface: {
|
|
84
|
+
functions: import("./_shared.js").DvmFunctionSignature[];
|
|
85
|
+
stringkeys: string[];
|
|
86
|
+
uint64keys: string[];
|
|
87
|
+
balances: Record<string, string | number>;
|
|
88
|
+
};
|
|
89
|
+
raw_code_length: number;
|
|
90
|
+
has_code: boolean;
|
|
91
|
+
} | null;
|
|
92
|
+
raw_tx_hex_length: number;
|
|
93
|
+
narrative: string;
|
|
94
|
+
_diagnostics: {
|
|
95
|
+
step_latency_ms: Record<string, number>;
|
|
96
|
+
total_ms: number;
|
|
97
|
+
halted_at: string | null;
|
|
98
|
+
decode_as_json: boolean;
|
|
99
|
+
include_sc_context: boolean;
|
|
100
|
+
sc_install_surface_attempted: boolean;
|
|
101
|
+
sc_install_surface_failed: boolean;
|
|
102
|
+
};
|
|
103
|
+
} & {
|
|
104
|
+
related_docs?: import("../citations.js").DeroCitation[];
|
|
105
|
+
}>;
|
|
106
|
+
export {};
|
|
107
|
+
//# sourceMappingURL=trace-transaction-with-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-transaction-with-context.d.ts","sourceRoot":"","sources":["../../src/composites/trace-transaction-with-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAOL,KAAK,aAAa,EAEnB,MAAM,cAAc,CAAA;AAKrB,eAAO,MAAM,sCAAsC;;;;CAezC,CAAA;AAEV,KAAK,UAAU,GAAG;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,kBAAkB,CAAC,EAAE,OAAO,CAAA;CAC7B,CAAA;AA6BD,KAAK,kBAAkB,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAA;AAC7D,KAAK,MAAM,GAAG,YAAY,GAAG,wBAAwB,GAAG,UAAU,GAAG,SAAS,CAAA;AAgF9E,wBAAsB,2BAA2B,CAAC,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0GrF"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `trace_transaction_with_context` — Phase C composite #5 (final).
|
|
3
|
+
*
|
|
4
|
+
* Wedge: `dero_get_transaction` returns the raw tx record (block,
|
|
5
|
+
* ring, signer, code, balances) but leaves the agent to figure out
|
|
6
|
+
* confirmation state, classify the tx kind, and separately fetch
|
|
7
|
+
* any SC context. This composite combines all of that in one call
|
|
8
|
+
* and stitches the right docs page as a citation.
|
|
9
|
+
*
|
|
10
|
+
* Design contract: `docs/composites.md` § 5. Sequencing rule: SHIP
|
|
11
|
+
* LAST — highest fan-out + failure-mode count of all Phase C
|
|
12
|
+
* composites.
|
|
13
|
+
*
|
|
14
|
+
* Implementation notes (recorded honestly so the design doc and
|
|
15
|
+
* shipped surface stay in sync):
|
|
16
|
+
*
|
|
17
|
+
* - SC INSTALL detection works directly off the tx record: when
|
|
18
|
+
* `tx.code` is non-empty the tx_hash itself IS the resulting
|
|
19
|
+
* SCID and the embedded code is the deployed source. We run
|
|
20
|
+
* `extractScSurface` on `tx.code` directly — no second
|
|
21
|
+
* `DERO.GetSC` call is needed for installs.
|
|
22
|
+
* - SC INVOCATION arg/entrypoint decoding requires walking the
|
|
23
|
+
* binary tx blob (`txs_as_hex`) with DERO's tx codec. That
|
|
24
|
+
* codec is not yet bundled in this MCP, so the composite does
|
|
25
|
+
* NOT fabricate decoded args. It surfaces `raw_tx_hex_length`
|
|
26
|
+
* so the agent knows the binary is available via
|
|
27
|
+
* `dero_get_transaction` if a downstream wallet wants to
|
|
28
|
+
* decode it.
|
|
29
|
+
* - TX_NOT_FOUND is signalled by the daemon as an EMPTY record
|
|
30
|
+
* (`block_height: 0, in_pool: false, code: ''`) — it does
|
|
31
|
+
* not throw. The composite detects this and throws a
|
|
32
|
+
* classifier-friendly message so `withStructuredErrors`
|
|
33
|
+
* surfaces `_meta.error.code = TX_NOT_FOUND`.
|
|
34
|
+
*
|
|
35
|
+
* Failure model:
|
|
36
|
+
* - `DERO.GetTransaction` throws → propagates via
|
|
37
|
+
* `withStructuredErrors` (RPC_UNREACHABLE / RPC_INVALID_PARAMS
|
|
38
|
+
* classifier branches handle the daemon-side cases).
|
|
39
|
+
* - Daemon returns empty record for the hash → composite throws
|
|
40
|
+
* `'DERO transaction not found: ...'` → classifier returns
|
|
41
|
+
* `TX_NOT_FOUND` with a retry hint.
|
|
42
|
+
* - Tx found but SC surface extraction degraded for the install
|
|
43
|
+
* case → record the surface as-is (`has_code: false`,
|
|
44
|
+
* `functions: []`) and let the narrative explain. Never abort.
|
|
45
|
+
*/
|
|
46
|
+
import { z } from 'zod';
|
|
47
|
+
import { attachCitations, extractScSurface, runChain, stepLatencies, stepValue, } from './_shared.js';
|
|
48
|
+
const HEX64_REGEX = /^[0-9a-fA-F]{64}$/;
|
|
49
|
+
const NATIVE_DERO_SCID = '0000000000000000000000000000000000000000000000000000000000000000';
|
|
50
|
+
export const traceTransactionWithContextInputSchema = {
|
|
51
|
+
tx_hash: z
|
|
52
|
+
.string()
|
|
53
|
+
.regex(HEX64_REGEX, 'Expected 64-character hex transaction hash')
|
|
54
|
+
.describe('64-char hex transaction hash'),
|
|
55
|
+
decode: z
|
|
56
|
+
.boolean()
|
|
57
|
+
.optional()
|
|
58
|
+
.describe('Pass decode_as_json=1 to the daemon. Default true. Decoded JSON view is informational; the raw hex always comes back.'),
|
|
59
|
+
include_sc_context: z
|
|
60
|
+
.boolean()
|
|
61
|
+
.optional()
|
|
62
|
+
.describe('When true (default), runs the SC-install surface extraction inline when the tx contains contract code. SC invocation arg decoding is NOT performed in either mode; see module docs.'),
|
|
63
|
+
};
|
|
64
|
+
function classifyConfirmation(tx) {
|
|
65
|
+
if (tx.in_pool === true)
|
|
66
|
+
return 'mempool';
|
|
67
|
+
if (typeof tx.block_height === 'number' && tx.block_height > 0)
|
|
68
|
+
return 'confirmed';
|
|
69
|
+
return 'unknown';
|
|
70
|
+
}
|
|
71
|
+
function classifyKind(tx) {
|
|
72
|
+
if (typeof tx.code === 'string' && tx.code.length > 0)
|
|
73
|
+
return 'sc_install';
|
|
74
|
+
if (typeof tx.reward === 'number' && tx.reward > 0 && (!tx.ring || tx.ring.length === 0)) {
|
|
75
|
+
return 'coinbase';
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(tx.ring) && tx.ring.length > 0)
|
|
78
|
+
return 'transfer_or_invocation';
|
|
79
|
+
return 'unknown';
|
|
80
|
+
}
|
|
81
|
+
function ringStats(tx) {
|
|
82
|
+
if (!Array.isArray(tx.ring) || tx.ring.length === 0) {
|
|
83
|
+
return { groups: null, first_group_size: null };
|
|
84
|
+
}
|
|
85
|
+
const groups = tx.ring.length;
|
|
86
|
+
const first = tx.ring[0];
|
|
87
|
+
const firstSize = Array.isArray(first) ? first.length : null;
|
|
88
|
+
return { groups, first_group_size: firstSize };
|
|
89
|
+
}
|
|
90
|
+
function isEmptyTxRecord(tx) {
|
|
91
|
+
if (!tx)
|
|
92
|
+
return true;
|
|
93
|
+
const noBlock = !tx.block_height || tx.block_height === 0;
|
|
94
|
+
const noPool = tx.in_pool !== true;
|
|
95
|
+
const noCode = !tx.code || tx.code.length === 0;
|
|
96
|
+
const noRing = !Array.isArray(tx.ring) || tx.ring.length === 0;
|
|
97
|
+
return noBlock && noPool && noCode && noRing;
|
|
98
|
+
}
|
|
99
|
+
function buildNarrative(txHash, confirmation, kind, blockHeight, scInstallSurface, ringGroups, rawHexLen, scLookupFailed) {
|
|
100
|
+
const parts = [];
|
|
101
|
+
if (confirmation === 'mempool') {
|
|
102
|
+
parts.push(`Tx ${txHash} is in the mempool (not yet confirmed). It may still be reorganized or dropped; treat the result as provisional.`);
|
|
103
|
+
}
|
|
104
|
+
else if (confirmation === 'confirmed') {
|
|
105
|
+
parts.push(`Tx ${txHash} is confirmed at block height ${blockHeight ?? 'unknown'}.`);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
parts.push(`Tx ${txHash} confirmation status is unknown — the daemon returned a record but did not mark it confirmed or in mempool.`);
|
|
109
|
+
}
|
|
110
|
+
if (kind === 'sc_install') {
|
|
111
|
+
if (scInstallSurface && scInstallSurface.has_code) {
|
|
112
|
+
const fnCount = scInstallSurface.functions.length;
|
|
113
|
+
const sampleFns = scInstallSurface.functions
|
|
114
|
+
.slice(0, 4)
|
|
115
|
+
.map((f) => f.name)
|
|
116
|
+
.join(', ');
|
|
117
|
+
parts.push(`Tx is a smart-contract INSTALL: the tx_hash is the resulting SCID. The deployed source carries ${fnCount} function${fnCount === 1 ? '' : 's'}${sampleFns ? ` (${sampleFns}${fnCount > 4 ? ', …' : ''})` : ''}. The composite parsed the surface inline from the embedded code; no second dero_get_sc call was needed.`);
|
|
118
|
+
}
|
|
119
|
+
else if (scLookupFailed) {
|
|
120
|
+
parts.push('Tx is a smart-contract INSTALL but the surface extractor failed to parse the embedded code. Fall back to dero_get_sc with the tx_hash as SCID for the raw payload.');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else if (kind === 'coinbase') {
|
|
124
|
+
parts.push('Tx is a coinbase (mining reward) — no ring members, signer is the miner address.');
|
|
125
|
+
}
|
|
126
|
+
else if (kind === 'transfer_or_invocation') {
|
|
127
|
+
parts.push(`Tx is a transfer or SC invocation. ${ringGroups ? `${ringGroups} input ring group${ringGroups === 1 ? '' : 's'} present.` : ''} SC invocation arg decoding is not surfaced by the daemon's JSON response; the ${rawHexLen}-char raw hex blob is available via dero_get_transaction if a wallet-side decoder is needed.`);
|
|
128
|
+
}
|
|
129
|
+
return parts.join(' ');
|
|
130
|
+
}
|
|
131
|
+
export async function traceTransactionWithContext(rpc, args) {
|
|
132
|
+
const decode = args.decode !== false;
|
|
133
|
+
const includeScContext = args.include_sc_context !== false;
|
|
134
|
+
const params = {
|
|
135
|
+
txs_hashes: [args.tx_hash],
|
|
136
|
+
decode_as_json: decode ? 1 : 0,
|
|
137
|
+
};
|
|
138
|
+
const steps = [
|
|
139
|
+
{
|
|
140
|
+
name: 'get_transaction',
|
|
141
|
+
required: true,
|
|
142
|
+
fn: () => rpc('DERO.GetTransaction', params),
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
const chain = await runChain(steps);
|
|
146
|
+
const txResult = stepValue(chain, 'get_transaction');
|
|
147
|
+
const tx = txResult?.txs?.[0];
|
|
148
|
+
const rawHexLen = (txResult?.txs_as_hex?.[0] ?? '').length;
|
|
149
|
+
if (!tx || isEmptyTxRecord(tx)) {
|
|
150
|
+
// Daemon does not error on unknown hashes — it returns an empty record.
|
|
151
|
+
// Throw a classifier-friendly message so withStructuredErrors emits
|
|
152
|
+
// TX_NOT_FOUND.
|
|
153
|
+
throw new Error(`DERO transaction not found: ${args.tx_hash}. The daemon returned an empty record (no block_height, no mempool entry, no code, no ring).`);
|
|
154
|
+
}
|
|
155
|
+
const confirmation = classifyConfirmation(tx);
|
|
156
|
+
const kind = classifyKind(tx);
|
|
157
|
+
const { groups: ringGroups, first_group_size: firstRingSize } = ringStats(tx);
|
|
158
|
+
let scInstallSurface = null;
|
|
159
|
+
let scLookupFailed = false;
|
|
160
|
+
if (includeScContext && kind === 'sc_install') {
|
|
161
|
+
try {
|
|
162
|
+
scInstallSurface = extractScSurface({ code: tx.code });
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
scLookupFailed = true;
|
|
166
|
+
scInstallSurface = null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const narrative = buildNarrative(args.tx_hash, confirmation, kind, typeof tx.block_height === 'number' ? tx.block_height : null, scInstallSurface, ringGroups, rawHexLen, scLookupFailed);
|
|
170
|
+
return attachCitations({
|
|
171
|
+
tx_hash: args.tx_hash,
|
|
172
|
+
confirmation: {
|
|
173
|
+
status: confirmation,
|
|
174
|
+
block_height: typeof tx.block_height === 'number' ? tx.block_height : null,
|
|
175
|
+
valid_block: typeof tx.valid_block === 'string' && tx.valid_block.length > 0 ? tx.valid_block : null,
|
|
176
|
+
invalid_blocks: Array.isArray(tx.invalid_block) ? tx.invalid_block : [],
|
|
177
|
+
in_pool: tx.in_pool === true,
|
|
178
|
+
},
|
|
179
|
+
kind,
|
|
180
|
+
ring: {
|
|
181
|
+
groups: ringGroups,
|
|
182
|
+
first_group_size: firstRingSize,
|
|
183
|
+
},
|
|
184
|
+
reward: typeof tx.reward === 'number' ? tx.reward : null,
|
|
185
|
+
signer_visible: typeof tx.signer === 'string' && tx.signer.length > 0,
|
|
186
|
+
native_balance: {
|
|
187
|
+
scid: NATIVE_DERO_SCID,
|
|
188
|
+
at_tx: typeof tx.balance === 'number' ? tx.balance : null,
|
|
189
|
+
current: typeof tx.balancenow === 'number' ? tx.balancenow : null,
|
|
190
|
+
},
|
|
191
|
+
sc_install: scInstallSurface
|
|
192
|
+
? {
|
|
193
|
+
scid: args.tx_hash,
|
|
194
|
+
surface: {
|
|
195
|
+
functions: scInstallSurface.functions,
|
|
196
|
+
stringkeys: scInstallSurface.stringkeys,
|
|
197
|
+
uint64keys: scInstallSurface.uint64keys,
|
|
198
|
+
balances: scInstallSurface.balances,
|
|
199
|
+
},
|
|
200
|
+
raw_code_length: scInstallSurface.raw_code_length,
|
|
201
|
+
has_code: scInstallSurface.has_code,
|
|
202
|
+
}
|
|
203
|
+
: null,
|
|
204
|
+
raw_tx_hex_length: rawHexLen,
|
|
205
|
+
narrative,
|
|
206
|
+
_diagnostics: {
|
|
207
|
+
step_latency_ms: stepLatencies(chain),
|
|
208
|
+
total_ms: chain.totalMs,
|
|
209
|
+
halted_at: chain.haltedAt,
|
|
210
|
+
decode_as_json: decode,
|
|
211
|
+
include_sc_context: includeScContext,
|
|
212
|
+
sc_install_surface_attempted: includeScContext && kind === 'sc_install',
|
|
213
|
+
sc_install_surface_failed: scLookupFailed,
|
|
214
|
+
},
|
|
215
|
+
}, 'trace_transaction_with_context');
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=trace-transaction-with-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-transaction-with-context.js","sourceRoot":"","sources":["../../src/composites/trace-transaction-with-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export declare const DERO_DOC_PRODUCTS: readonly ["derod", "tela", "hologram", "deropay"];
|
|
2
|
+
export type DeroDocProduct = (typeof DERO_DOC_PRODUCTS)[number];
|
|
3
|
+
export declare const DOC_SITE_DIRS: Record<DeroDocProduct, string>;
|
|
4
|
+
export declare const DOC_BASE_URLS: Record<DeroDocProduct, string>;
|
|
5
|
+
export type DeroDocsPage = {
|
|
6
|
+
product: DeroDocProduct;
|
|
7
|
+
slug: string;
|
|
8
|
+
title: string;
|
|
9
|
+
description: string | null;
|
|
10
|
+
canonicalUrl: string;
|
|
11
|
+
sourcePath: string;
|
|
12
|
+
headings: string[];
|
|
13
|
+
plainText: string;
|
|
14
|
+
lastUpdated: string | null;
|
|
15
|
+
};
|
|
16
|
+
export type DocsIndexFile = {
|
|
17
|
+
version: 1;
|
|
18
|
+
generated_at: string;
|
|
19
|
+
page_count: number;
|
|
20
|
+
pages: DeroDocsPage[];
|
|
21
|
+
};
|
|
22
|
+
export declare function normalizeSlug(input: string): string;
|
|
23
|
+
export declare function pathExists(targetPath: string): Promise<boolean>;
|
|
24
|
+
export declare function parseFrontmatter(raw: string): Record<string, string>;
|
|
25
|
+
export declare function stripFrontmatter(raw: string): string;
|
|
26
|
+
export declare function extractHeadings(markdown: string): string[];
|
|
27
|
+
export declare function mdxToPlainText(raw: string): string;
|
|
28
|
+
export declare function indexDocsFromRoot(root: string): Promise<DeroDocsPage[]>;
|
|
29
|
+
export declare function resolveDeroDocsRoot(customRoot?: string): Promise<string | null>;
|
|
30
|
+
//# sourceMappingURL=docs-parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs-parse.d.ts","sourceRoot":"","sources":["../src/docs-parse.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,mDAAoD,CAAA;AAClF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE/D,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAKxD,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAKxD,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,cAAc,CAAA;IACvB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,CAAC,CAAA;IACV,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,YAAY,EAAE,CAAA;CACtB,CAAA;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEnD;AAYD,wBAAsB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOrE;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWpE;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ1D;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWlD;AAyBD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAqC7E;AAED,wBAAsB,mBAAmB,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAkBrF"}
|