dero-mcp-server 0.1.2 → 0.4.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.
Files changed (77) hide show
  1. package/POSITIONING.md +94 -0
  2. package/README.md +132 -31
  3. package/SKILL.md +264 -0
  4. package/data/docs-index.json +276 -264
  5. package/dist/bn254.d.ts +74 -0
  6. package/dist/bn254.d.ts.map +1 -0
  7. package/dist/bn254.js +205 -0
  8. package/dist/bn254.js.map +1 -0
  9. package/dist/citations.d.ts +140 -0
  10. package/dist/citations.d.ts.map +1 -0
  11. package/dist/citations.js +322 -0
  12. package/dist/citations.js.map +1 -0
  13. package/dist/composites/_shared.d.ts +119 -0
  14. package/dist/composites/_shared.d.ts.map +1 -0
  15. package/dist/composites/_shared.js +152 -0
  16. package/dist/composites/_shared.js.map +1 -0
  17. package/dist/composites/audit-chain-artifact-claim.d.ts +128 -0
  18. package/dist/composites/audit-chain-artifact-claim.d.ts.map +1 -0
  19. package/dist/composites/audit-chain-artifact-claim.js +305 -0
  20. package/dist/composites/audit-chain-artifact-claim.js.map +1 -0
  21. package/dist/composites/diagnose-chain-health.d.ts +64 -0
  22. package/dist/composites/diagnose-chain-health.d.ts.map +1 -0
  23. package/dist/composites/diagnose-chain-health.js +144 -0
  24. package/dist/composites/diagnose-chain-health.js.map +1 -0
  25. package/dist/composites/estimate-deploy-cost.d.ts +83 -0
  26. package/dist/composites/estimate-deploy-cost.d.ts.map +1 -0
  27. package/dist/composites/estimate-deploy-cost.js +116 -0
  28. package/dist/composites/estimate-deploy-cost.js.map +1 -0
  29. package/dist/composites/explain-smart-contract.d.ts +64 -0
  30. package/dist/composites/explain-smart-contract.d.ts.map +1 -0
  31. package/dist/composites/explain-smart-contract.js +149 -0
  32. package/dist/composites/explain-smart-contract.js.map +1 -0
  33. package/dist/composites/forge-demo-proof.d.ts +81 -0
  34. package/dist/composites/forge-demo-proof.d.ts.map +1 -0
  35. package/dist/composites/forge-demo-proof.js +204 -0
  36. package/dist/composites/forge-demo-proof.js.map +1 -0
  37. package/dist/composites/recommend-docs-path.d.ts +97 -0
  38. package/dist/composites/recommend-docs-path.d.ts.map +1 -0
  39. package/dist/composites/recommend-docs-path.js +149 -0
  40. package/dist/composites/recommend-docs-path.js.map +1 -0
  41. package/dist/composites/trace-transaction-with-context.d.ts +107 -0
  42. package/dist/composites/trace-transaction-with-context.d.ts.map +1 -0
  43. package/dist/composites/trace-transaction-with-context.js +217 -0
  44. package/dist/composites/trace-transaction-with-context.js.map +1 -0
  45. package/dist/daemon-base.d.ts +28 -0
  46. package/dist/daemon-base.d.ts.map +1 -0
  47. package/dist/daemon-base.js +62 -0
  48. package/dist/daemon-base.js.map +1 -0
  49. package/dist/dero-curve.d.ts +79 -0
  50. package/dist/dero-curve.d.ts.map +1 -0
  51. package/dist/dero-curve.js +79 -0
  52. package/dist/dero-curve.js.map +1 -0
  53. package/dist/docs-parse.d.ts.map +1 -1
  54. package/dist/docs-parse.js +18 -2
  55. package/dist/docs-parse.js.map +1 -1
  56. package/dist/http-server.d.ts +37 -0
  57. package/dist/http-server.d.ts.map +1 -0
  58. package/dist/http-server.js +132 -0
  59. package/dist/http-server.js.map +1 -0
  60. package/dist/index.js +18 -11
  61. package/dist/index.js.map +1 -1
  62. package/dist/proof-decode.d.ts +125 -0
  63. package/dist/proof-decode.d.ts.map +1 -0
  64. package/dist/proof-decode.js +619 -0
  65. package/dist/proof-decode.js.map +1 -0
  66. package/dist/server.d.ts.map +1 -1
  67. package/dist/server.js +414 -114
  68. package/dist/server.js.map +1 -1
  69. package/dist/tool-descriptions.d.ts +53 -0
  70. package/dist/tool-descriptions.d.ts.map +1 -0
  71. package/dist/tool-descriptions.js +285 -0
  72. package/dist/tool-descriptions.js.map +1 -0
  73. package/dist/tx-parse.d.ts +63 -0
  74. package/dist/tx-parse.d.ts.map +1 -0
  75. package/dist/tx-parse.js +183 -0
  76. package/dist/tx-parse.js.map +1 -0
  77. package/package.json +27 -2
@@ -0,0 +1,204 @@
1
+ /**
2
+ * `dero_forge_demo_proof` — composite #7.
3
+ *
4
+ * Builds a `deroproof…` display object for a chosen transaction, ring slot,
5
+ * and amount. The string is constructed locally from public chain data — no
6
+ * wallet, no keys, no broadcast. On an unpatched explorer it shows
7
+ * **Verified ✓** for the chosen amount; on the chain, nothing changes.
8
+ *
9
+ * Purpose: defensive demonstration of the integrity-page Part 3 forge math
10
+ * (`docs/integrity/inflation-claim`, Part 3). When an AI agent is asked
11
+ * "does this deroproof string prove the chain minted coins?", the agent can
12
+ * forge an equivalent string here and show, on real chain inputs, that
13
+ * **Verified** is a display-layer fact about the pasted object — not a
14
+ * consensus statement about coins moving.
15
+ *
16
+ * Math (same equation `proof.Prove()` checks at `proof/proof.go:88-95`):
17
+ *
18
+ * blinder = C[slot] − amount × G
19
+ * forged_string = bech32("deroproof", version || blinder_compressed || CBOR({HH: 0…0, VU: amount}))
20
+ *
21
+ * Self-check: amount × G + blinder == C[slot]. If this fails, the encoded
22
+ * string would not verify and we never return it.
23
+ *
24
+ * Read-only invariant: this tool computes a string and returns it. It does
25
+ * NOT touch a wallet, broadcast a transaction, or mutate any chain state.
26
+ * Annotation `readOnlyHint: true` is preserved.
27
+ */
28
+ import { z } from 'zod';
29
+ import { G, add, deroCompressHex, negate, pointsEqual, scalarMult, uint64ToSignedScalar, } from '../bn254.js';
30
+ import { enrichWithFlaggedArtifacts, relatedDocsFor, } from '../citations.js';
31
+ import { encodeForgeProofString } from '../proof-decode.js';
32
+ import { getRingCommitment, parseTransaction } from '../tx-parse.js';
33
+ import { runChain, stepLatencies, stepValue, } from './_shared.js';
34
+ const ATOMIC = 100000n;
35
+ const UINT64_MOD = 1n << 64n;
36
+ export const forgeDemoProofInputSchema = {
37
+ tx_hash: z
38
+ .string()
39
+ .regex(/^[0-9a-fA-F]{64}$/, 'tx_hash must be 64 hex characters')
40
+ .optional()
41
+ .describe('TX hash to forge against. Daemon fetches the TX hex + ring members. Mutually exclusive with tx_hex.'),
42
+ tx_hex: z
43
+ .string()
44
+ .min(2)
45
+ .optional()
46
+ .describe('Raw TX bytes as hex (skip the daemon round-trip). Mutually exclusive with tx_hash. When provided, ring_receiver_address is omitted from the response (the hex carries publickey pointers, not full addresses).'),
47
+ ring_slot: z
48
+ .number()
49
+ .int()
50
+ .nonnegative()
51
+ .default(0)
52
+ .describe('Which ring slot 0..ring_size-1 the forged proof should resolve to. Defaults to 0.'),
53
+ amount_dero: z
54
+ .string()
55
+ .regex(/^-?\d+(\.\d{1,5})?$/, 'amount_dero must be a signed decimal with at most 5 fractional digits (e.g. "-1", "1000000", "-2200000.00181")')
56
+ .default('-1')
57
+ .describe('Target display amount in signed DERO (5 fractional digits = atomic precision). Negative values demonstrate the uint64 wraparound. Default "-1".'),
58
+ };
59
+ /**
60
+ * Parse a signed-decimal DERO string (e.g. "-2200000.00181") into:
61
+ * - signed atoms (bigint, may be negative)
62
+ * - uint64 (atoms mod 2^64)
63
+ */
64
+ function parseAmount(amountDero) {
65
+ const negative = amountDero.startsWith('-');
66
+ const unsigned = negative ? amountDero.slice(1) : amountDero;
67
+ const dot = unsigned.indexOf('.');
68
+ const wholeStr = dot === -1 ? unsigned : unsigned.slice(0, dot);
69
+ const fracStr = dot === -1 ? '' : unsigned.slice(dot + 1);
70
+ const fracPadded = (fracStr + '00000').slice(0, 5);
71
+ const whole = BigInt(wholeStr.length === 0 ? '0' : wholeStr);
72
+ const frac = BigInt(fracPadded);
73
+ const absAtoms = whole * ATOMIC + frac;
74
+ const signedAtoms = negative ? -absAtoms : absAtoms;
75
+ const uint64 = ((signedAtoms % UINT64_MOD) + UINT64_MOD) % UINT64_MOD;
76
+ // Normalize the input echo so callers see the canonical form (5 fractional digits).
77
+ const normalized = `${negative && absAtoms > 0n ? '-' : ''}${whole.toString()}.${fracPadded}`;
78
+ return { signedAtoms, uint64, signedDeroNormalized: normalized };
79
+ }
80
+ /** Format a uint64 as the unpatched-explorer display amount (whole.fractional with 5 digits). */
81
+ function formatExplorerDisplay(uint64) {
82
+ const whole = uint64 / ATOMIC;
83
+ const frac = uint64 % ATOMIC;
84
+ // Group thousands in the whole-part for readability.
85
+ const wholeStr = whole.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
86
+ return `${wholeStr}.${frac.toString().padStart(5, '0')} DERO`;
87
+ }
88
+ /**
89
+ * Execute the forge. Composes:
90
+ * 1. (optional) daemon fetch of TX hex + ring members
91
+ * 2. parse TX → extract C[ring_slot]
92
+ * 3. compute blinder = C[slot] − amount × G
93
+ * 4. self-check: amount × G + blinder == C[slot]
94
+ * 5. encode forged proof string + assemble narrative + citations
95
+ */
96
+ export async function forgeDemoProof(rpc, input) {
97
+ if (input.tx_hash && input.tx_hex) {
98
+ throw new Error('INVALID_INPUT: provide exactly one of tx_hash or tx_hex (not both)');
99
+ }
100
+ if (!input.tx_hash && !input.tx_hex) {
101
+ throw new Error('INVALID_INPUT: provide either tx_hash or tx_hex');
102
+ }
103
+ const ringSlot = input.ring_slot ?? 0;
104
+ const amountDero = input.amount_dero ?? '-1';
105
+ // ─── 1. Fetch TX (optional daemon round-trip) ─────────────────────────────
106
+ let txHex;
107
+ let receiverAddress = null;
108
+ const txSource = input.tx_hash ? 'tx_hash' : 'tx_hex';
109
+ const steps = [];
110
+ if (input.tx_hash) {
111
+ const hash = input.tx_hash;
112
+ steps.push({
113
+ name: 'get_transaction',
114
+ required: true,
115
+ fn: () => rpc('DERO.GetTransaction', {
116
+ txs_hashes: [hash],
117
+ decode_as_json: 1,
118
+ }),
119
+ });
120
+ }
121
+ const chain = await runChain(steps);
122
+ if (input.tx_hash) {
123
+ const txResult = stepValue(chain, 'get_transaction');
124
+ if (!txResult || !txResult.txs_as_hex || txResult.txs_as_hex.length === 0) {
125
+ throw new Error(`daemon did not return TX hex for ${input.tx_hash} (chain halted at ${chain.haltedAt ?? '?'})`);
126
+ }
127
+ txHex = txResult.txs_as_hex[0];
128
+ const ring = txResult.txs?.[0]?.ring?.[0];
129
+ if (ring && ringSlot >= 0 && ringSlot < ring.length) {
130
+ receiverAddress = ring[ringSlot];
131
+ }
132
+ }
133
+ else {
134
+ txHex = input.tx_hex;
135
+ }
136
+ // ─── 2. Parse TX → extract C[ring_slot] ──────────────────────────────────
137
+ let tx;
138
+ try {
139
+ tx = parseTransaction(txHex);
140
+ }
141
+ catch (err) {
142
+ throw new Error(`tx-parse failed: ${err instanceof Error ? err.message : String(err)}`);
143
+ }
144
+ const stmt = tx.payloads[0].statement;
145
+ if (ringSlot >= stmt.ring_size) {
146
+ throw new Error(`INVALID_INPUT: ring_slot ${ringSlot} >= ring_size ${stmt.ring_size}`);
147
+ }
148
+ const Cslot = getRingCommitment(tx, ringSlot);
149
+ // ─── 3. Forge math ────────────────────────────────────────────────────────
150
+ const { signedAtoms, uint64, signedDeroNormalized } = parseAmount(amountDero);
151
+ const amountG = scalarMult(G, uint64ToSignedScalar(uint64));
152
+ const blinder = add(Cslot, negate(amountG));
153
+ // ─── 4. Self-check (mirror of proof.Prove() inner loop) ──────────────────
154
+ const reconstructed = add(amountG, blinder);
155
+ const verified = pointsEqual(reconstructed, Cslot);
156
+ if (!verified) {
157
+ // Should be impossible by construction — bail loud rather than emit a string
158
+ // that would fail an explorer check.
159
+ throw new Error('self-check FAILED: amount × G + blinder != C[slot] — bn254 math regression');
160
+ }
161
+ // ─── 5. Encode forged proof string ────────────────────────────────────────
162
+ const blinderHex = deroCompressHex(blinder);
163
+ const blinderBytes = new Uint8Array(33);
164
+ for (let i = 0; i < 33; i++)
165
+ blinderBytes[i] = parseInt(blinderHex.slice(i * 2, i * 2 + 2), 16);
166
+ const forgedString = encodeForgeProofString(blinderBytes, uint64);
167
+ // ─── 6. Citations + context_note enrichment ───────────────────────────────
168
+ const enrichment = enrichWithFlaggedArtifacts({
169
+ ...(input.tx_hash ? { tx_hash: input.tx_hash } : {}),
170
+ }, relatedDocsFor('dero_forge_demo_proof'));
171
+ const related_docs = enrichment?.related_docs ?? relatedDocsFor('dero_forge_demo_proof') ?? [];
172
+ const context_note = enrichment?.context_note ??
173
+ 'This is a forged display object built locally from public chain data — no wallet, no keys, no broadcast. On unpatched explorers it shows Verified ✓ for the chosen amount; on the chain, nothing changed. See related_docs for the technical rebuttal.';
174
+ return {
175
+ forged_proof_string: forgedString,
176
+ target_amount: {
177
+ dero: signedDeroNormalized,
178
+ atoms_signed: signedAtoms.toString(),
179
+ atoms_uint64: uint64.toString(),
180
+ },
181
+ ring_slot: ringSlot,
182
+ ring_size: stmt.ring_size,
183
+ ring_receiver_address: receiverAddress,
184
+ math: {
185
+ C_slot_hex: stmt.C_hex[ringSlot],
186
+ amount_x_G_hex: deroCompressHex(amountG),
187
+ blinder_hex: blinderHex,
188
+ },
189
+ self_check: {
190
+ verified: true,
191
+ method: 'Reconstructed amount × G + blinder and confirmed equal to C[slot] — same equation proof.Prove() uses (proof/proof.go:88-95).',
192
+ },
193
+ explorer_display_amount: formatExplorerDisplay(uint64),
194
+ context_note,
195
+ related_docs,
196
+ _diagnostics: {
197
+ step_latencies: stepLatencies(chain),
198
+ halted_at: chain.haltedAt,
199
+ total_ms: chain.totalMs,
200
+ tx_source: txSource,
201
+ },
202
+ };
203
+ }
204
+ //# sourceMappingURL=forge-demo-proof.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forge-demo-proof.js","sourceRoot":"","sources":["../../src/composites/forge-demo-proof.ts"],"names":[],"mappings":"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"}
@@ -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 § 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 § 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 § 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"}