@relayburn/sdk 1.9.0 → 2.0.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/CHANGELOG.md +27 -29
- package/README.md +27 -34
- package/package.json +46 -17
- package/src/binding.cjs +91 -0
- package/src/binding.d.ts +21 -0
- package/src/index.cjs +68 -0
- package/src/index.d.ts +422 -0
- package/src/index.js +144 -0
- package/index.d.ts +0 -234
- package/index.js +0 -630
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
// Type surface for `@relayburn/sdk@2.x`.
|
|
2
|
+
//
|
|
3
|
+
// Mirrors `packages/sdk/index.d.ts` (the TS 1.x SDK) byte-for-byte modulo:
|
|
4
|
+
// - `bigint` is allowed alongside `number` for u64-typed token counts (the
|
|
5
|
+
// napi-rs binding emits `BigInt` for `u64`; the TS shape is widened so
|
|
6
|
+
// existing callers that pass through `number` keep type-checking once
|
|
7
|
+
// bound to the Rust impl).
|
|
8
|
+
// - Async fns return `Promise<T>` — the napi-rs binding uses `async fn`
|
|
9
|
+
// where the Rust SDK does, which is everywhere except the `Ledger.open`
|
|
10
|
+
// constructor.
|
|
11
|
+
//
|
|
12
|
+
// Source-of-truth comment: track `packages/sdk/index.d.ts`. Whenever a verb
|
|
13
|
+
// shape changes in TS, mirror it here AND in the Rust napi-rs binding (#247-a).
|
|
14
|
+
|
|
15
|
+
export interface LedgerOpenOptions { home?: string; contentHome?: string }
|
|
16
|
+
/**
|
|
17
|
+
* Stateful ledger handle. The 1.x TS class only exposes the static
|
|
18
|
+
* `open()` constructor; instances are placeholders today, with `home`
|
|
19
|
+
* exposed for callers that want to confirm which ledger they attached
|
|
20
|
+
* to. Verb methods are a future PR.
|
|
21
|
+
*/
|
|
22
|
+
export declare class Ledger {
|
|
23
|
+
readonly home: string;
|
|
24
|
+
static open(opts?: LedgerOpenOptions): Promise<Ledger>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface IngestOptions { sessionId?: string; harness?: 'claude-code'|'codex'|'opencode'; ledgerHome?: string }
|
|
28
|
+
export interface IngestReport {
|
|
29
|
+
scannedSessions: number | bigint;
|
|
30
|
+
ingestedSessions: number | bigint;
|
|
31
|
+
appendedTurns: number | bigint;
|
|
32
|
+
}
|
|
33
|
+
export declare function ingest(opts?: IngestOptions): Promise<IngestReport>
|
|
34
|
+
|
|
35
|
+
export interface SummaryOptions {
|
|
36
|
+
session?: string;
|
|
37
|
+
project?: string;
|
|
38
|
+
/** ISO timestamp (e.g. `2026-04-01T00:00:00Z`) or relative range (`24h`, `7d`, `4w`, `2m`). */
|
|
39
|
+
since?: string;
|
|
40
|
+
ledgerHome?: string;
|
|
41
|
+
/** Optional logger invoked when the SQLite archive read fails and the SDK falls back to a full ledger walk. */
|
|
42
|
+
onLog?: (msg: string) => void;
|
|
43
|
+
}
|
|
44
|
+
export declare function summary(opts?: SummaryOptions): Promise<{
|
|
45
|
+
totalTokens: number | bigint;
|
|
46
|
+
totalCost: number;
|
|
47
|
+
turnCount: number;
|
|
48
|
+
byTool: Array<{ tool: string; tokens: number | bigint; cost: number; count: number }>;
|
|
49
|
+
byModel: Array<{ model: string; tokens: number | bigint; cost: number }>;
|
|
50
|
+
}>
|
|
51
|
+
|
|
52
|
+
export interface SessionCostOptions {
|
|
53
|
+
/** Session id to total. Omit for `{ note: 'no session id provided' }`. */
|
|
54
|
+
session?: string;
|
|
55
|
+
ledgerHome?: string;
|
|
56
|
+
onLog?: (msg: string) => void;
|
|
57
|
+
}
|
|
58
|
+
export interface SessionCostResult {
|
|
59
|
+
sessionId: string | null;
|
|
60
|
+
totalUSD: number;
|
|
61
|
+
totalTokens: number | bigint;
|
|
62
|
+
turnCount: number;
|
|
63
|
+
models: string[];
|
|
64
|
+
note?: string;
|
|
65
|
+
}
|
|
66
|
+
/** Compact session-scoped cost shape; powers the MCP `burn__sessionCost` tool. */
|
|
67
|
+
export declare function sessionCost(opts?: SessionCostOptions): Promise<SessionCostResult>
|
|
68
|
+
|
|
69
|
+
export type OverheadFileKind = 'claude-md' | 'agents-md';
|
|
70
|
+
export type OverheadHarness = 'claude-code' | 'codex' | 'opencode';
|
|
71
|
+
|
|
72
|
+
export interface OverheadOptions {
|
|
73
|
+
project?: string;
|
|
74
|
+
since?: string;
|
|
75
|
+
kind?: OverheadFileKind;
|
|
76
|
+
ledgerHome?: string;
|
|
77
|
+
onLog?: (msg: string) => void;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface OverheadSection {
|
|
81
|
+
heading: string;
|
|
82
|
+
startLine: number;
|
|
83
|
+
endLine: number;
|
|
84
|
+
tokens: number | bigint;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface OverheadSectionCost {
|
|
88
|
+
filePath: string;
|
|
89
|
+
section: OverheadSection;
|
|
90
|
+
tokenShare: number;
|
|
91
|
+
costPerSession: number;
|
|
92
|
+
totalCost: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface OverheadAttributionDetail {
|
|
96
|
+
sessionCount: number;
|
|
97
|
+
perSessionAvg: number;
|
|
98
|
+
perSessionP95: number;
|
|
99
|
+
totalCost: number;
|
|
100
|
+
sectionCosts: OverheadSectionCost[];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface OverheadFileSummary {
|
|
104
|
+
kind: OverheadFileKind;
|
|
105
|
+
path: string;
|
|
106
|
+
appliesTo: OverheadHarness[];
|
|
107
|
+
totalLines: number;
|
|
108
|
+
bytes: number | bigint;
|
|
109
|
+
tokens: number | bigint;
|
|
110
|
+
sections: OverheadSection[];
|
|
111
|
+
groupingLevel: number;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface OverheadPerFileEntry {
|
|
115
|
+
path: string;
|
|
116
|
+
kind: OverheadFileKind;
|
|
117
|
+
appliesTo: OverheadHarness[];
|
|
118
|
+
attribution: OverheadAttributionDetail;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface OverheadResult {
|
|
122
|
+
project: string;
|
|
123
|
+
files: OverheadFileSummary[];
|
|
124
|
+
perFile: OverheadPerFileEntry[];
|
|
125
|
+
grandTotal: number;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Per-file + per-section overhead cost attribution. Powers `burn overhead`. */
|
|
129
|
+
export declare function overhead(opts?: OverheadOptions): Promise<OverheadResult>
|
|
130
|
+
|
|
131
|
+
export interface OverheadTrimOptions extends OverheadOptions {
|
|
132
|
+
top?: number;
|
|
133
|
+
includeDiff?: boolean;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface OverheadTrimRecommendation {
|
|
137
|
+
file: string;
|
|
138
|
+
kind: OverheadFileKind;
|
|
139
|
+
appliesTo: OverheadHarness[];
|
|
140
|
+
section: { heading: string; startLine: number; endLine: number; tokens: number | bigint };
|
|
141
|
+
projectedSavings: {
|
|
142
|
+
perSessionUsd: number;
|
|
143
|
+
acrossWindowUsd: number;
|
|
144
|
+
tokens: number | bigint;
|
|
145
|
+
tokenShare: number;
|
|
146
|
+
};
|
|
147
|
+
diff?: string;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export interface OverheadTrimResult {
|
|
151
|
+
project: string;
|
|
152
|
+
since: string;
|
|
153
|
+
recommendations: OverheadTrimRecommendation[];
|
|
154
|
+
summary: {
|
|
155
|
+
filesAnalyzed: number;
|
|
156
|
+
filesWithRecommendations: number;
|
|
157
|
+
totalRecommendations: number;
|
|
158
|
+
totalProjectedSavingsPerSession: number;
|
|
159
|
+
totalProjectedSavingsAcrossWindow: number;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Trim recommendations for high-cost overhead-file sections. Powers `burn overhead trim`. */
|
|
164
|
+
export declare function overheadTrim(opts?: OverheadTrimOptions): Promise<OverheadTrimResult>
|
|
165
|
+
|
|
166
|
+
export type HotspotsGroupBy = 'attribution' | 'bash' | 'bash-verb' | 'file' | 'subagent';
|
|
167
|
+
|
|
168
|
+
export interface HotspotsOptions {
|
|
169
|
+
session?: string;
|
|
170
|
+
project?: string;
|
|
171
|
+
since?: string;
|
|
172
|
+
groupBy?: HotspotsGroupBy;
|
|
173
|
+
patterns?: string[];
|
|
174
|
+
ledgerHome?: string;
|
|
175
|
+
onLog?: (msg: string) => void;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export interface HotspotsFileRow {
|
|
179
|
+
path: string;
|
|
180
|
+
firstEmitTurnIndex: number;
|
|
181
|
+
initialTokens: number | bigint;
|
|
182
|
+
persistenceTokens: number | bigint;
|
|
183
|
+
ridingTurns: number;
|
|
184
|
+
totalCost: number;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export interface HotspotsBashRow {
|
|
188
|
+
command: string | undefined;
|
|
189
|
+
argsHash: string;
|
|
190
|
+
callCount: number;
|
|
191
|
+
initialTokens: number | bigint;
|
|
192
|
+
persistenceTokens: number | bigint;
|
|
193
|
+
totalCost: number;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export interface HotspotsBashVerbRow {
|
|
197
|
+
verb: string;
|
|
198
|
+
callCount: number;
|
|
199
|
+
distinctCommands: number;
|
|
200
|
+
initialTokens: number | bigint;
|
|
201
|
+
persistenceTokens: number | bigint;
|
|
202
|
+
avgPersistenceTurns: number;
|
|
203
|
+
totalCost: number;
|
|
204
|
+
topExamples: string[];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface HotspotsSubagentRow {
|
|
208
|
+
subagentType: string;
|
|
209
|
+
callCount: number;
|
|
210
|
+
initialTokens: number | bigint;
|
|
211
|
+
persistenceTokens: number | bigint;
|
|
212
|
+
totalCost: number;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export interface HotspotsSessionTotal {
|
|
216
|
+
sessionId: string;
|
|
217
|
+
grandCost: number;
|
|
218
|
+
attributedCost: number;
|
|
219
|
+
unattributedCost: number;
|
|
220
|
+
attributionMethod: 'sized' | 'even-split';
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export interface HotspotsFidelityBlock {
|
|
224
|
+
analyzed: number;
|
|
225
|
+
excluded: number;
|
|
226
|
+
summary: unknown;
|
|
227
|
+
refused: boolean;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export interface HotspotsAttributionResult {
|
|
231
|
+
kind: 'attribution';
|
|
232
|
+
turnsAnalyzed: number;
|
|
233
|
+
grandTotal: number;
|
|
234
|
+
attributedTotal: number;
|
|
235
|
+
unattributedTotal: number;
|
|
236
|
+
attributionDegraded: boolean;
|
|
237
|
+
sessions: HotspotsSessionTotal[];
|
|
238
|
+
files: HotspotsFileRow[];
|
|
239
|
+
bashVerbs: HotspotsBashVerbRow[];
|
|
240
|
+
bash: HotspotsBashRow[];
|
|
241
|
+
subagents: HotspotsSubagentRow[];
|
|
242
|
+
fidelity: HotspotsFidelityBlock;
|
|
243
|
+
refused?: boolean;
|
|
244
|
+
refusalReason?: string;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export interface HotspotsBashResult { kind: 'bash'; rows: HotspotsBashRow[]; refused?: boolean; refusalReason?: string }
|
|
248
|
+
export interface HotspotsBashVerbResult { kind: 'bash-verb'; rows: HotspotsBashVerbRow[]; refused?: boolean; refusalReason?: string }
|
|
249
|
+
export interface HotspotsFileResult { kind: 'file'; rows: HotspotsFileRow[]; refused?: boolean; refusalReason?: string }
|
|
250
|
+
export interface HotspotsSubagentResult { kind: 'subagent'; rows: HotspotsSubagentRow[]; refused?: boolean; refusalReason?: string }
|
|
251
|
+
|
|
252
|
+
export interface HotspotsFinding {
|
|
253
|
+
kind: string;
|
|
254
|
+
severity: string;
|
|
255
|
+
sessionId: string;
|
|
256
|
+
title: string;
|
|
257
|
+
estimatedSavings: { usdPerSession?: number; [k: string]: unknown };
|
|
258
|
+
[k: string]: unknown;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export interface HotspotsFindingsResult {
|
|
262
|
+
kind: 'findings';
|
|
263
|
+
findings: HotspotsFinding[];
|
|
264
|
+
summary: unknown;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export type HotspotsResult =
|
|
268
|
+
| HotspotsAttributionResult
|
|
269
|
+
| HotspotsBashResult
|
|
270
|
+
| HotspotsBashVerbResult
|
|
271
|
+
| HotspotsFileResult
|
|
272
|
+
| HotspotsSubagentResult
|
|
273
|
+
| HotspotsFindingsResult;
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Per-axis hotspot attribution + pattern-finding queries. Returns a
|
|
277
|
+
* discriminated union — see `HotspotsResult`.
|
|
278
|
+
*/
|
|
279
|
+
export declare function hotspots(opts?: HotspotsOptions): Promise<HotspotsResult>
|
|
280
|
+
|
|
281
|
+
export type FidelityClass = 'full' | 'usage-only' | 'aggregate-only' | 'cost-only' | 'partial';
|
|
282
|
+
|
|
283
|
+
export interface FidelitySummaryShape {
|
|
284
|
+
total: number;
|
|
285
|
+
byClass: Record<FidelityClass, number>;
|
|
286
|
+
unknown: number;
|
|
287
|
+
missingCoverage: Record<string, number>;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
export interface CompareExcludedBreakdown {
|
|
291
|
+
total: number;
|
|
292
|
+
aggregateOnly: number;
|
|
293
|
+
costOnly: number;
|
|
294
|
+
partial: number;
|
|
295
|
+
usageOnly: number;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export interface CompareCellResult {
|
|
299
|
+
model: string;
|
|
300
|
+
category: string;
|
|
301
|
+
turns: number;
|
|
302
|
+
editTurns: number;
|
|
303
|
+
oneShotTurns: number;
|
|
304
|
+
pricedTurns: number;
|
|
305
|
+
totalCost: number;
|
|
306
|
+
costPerTurn: number | null;
|
|
307
|
+
oneShotRate: number | null;
|
|
308
|
+
cacheHitRate: number | null;
|
|
309
|
+
medianRetries: number | null;
|
|
310
|
+
noData: boolean;
|
|
311
|
+
insufficientSample: boolean;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export interface CompareOptions {
|
|
315
|
+
models: string[];
|
|
316
|
+
session?: string;
|
|
317
|
+
project?: string;
|
|
318
|
+
since?: string;
|
|
319
|
+
workflow?: string;
|
|
320
|
+
agent?: string;
|
|
321
|
+
provider?: string[];
|
|
322
|
+
minSample?: number;
|
|
323
|
+
minFidelity?: FidelityClass;
|
|
324
|
+
ledgerHome?: string;
|
|
325
|
+
onLog?: (msg: string) => void;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export interface CompareResult {
|
|
329
|
+
analyzedTurns: number;
|
|
330
|
+
minSample: number;
|
|
331
|
+
models: string[];
|
|
332
|
+
categories: string[];
|
|
333
|
+
totals: Record<string, { turns: number; totalCost: number }>;
|
|
334
|
+
cells: CompareCellResult[];
|
|
335
|
+
fidelity: {
|
|
336
|
+
minimum: FidelityClass;
|
|
337
|
+
excluded: CompareExcludedBreakdown;
|
|
338
|
+
summary: FidelitySummaryShape;
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** Per-(model, activity) comparison shape. Powers `burn compare`. */
|
|
343
|
+
export declare function compare(opts: CompareOptions): Promise<CompareResult>
|
|
344
|
+
|
|
345
|
+
// ---------------------------------------------------------------------------
|
|
346
|
+
// 2.x extensions — surfaces present in `relayburn-sdk` (the Rust crate)
|
|
347
|
+
// but not in the TS 1.x `packages/sdk/index.d.ts`. Pre-1.0 widening per
|
|
348
|
+
// the SDK shape rule; embedders that pinned to 1.x won't see these names
|
|
349
|
+
// (the missing `onLog` etc. plus the absence of these is the only TS-vs-
|
|
350
|
+
// napi gap the conformance gate measures).
|
|
351
|
+
// ---------------------------------------------------------------------------
|
|
352
|
+
|
|
353
|
+
export interface SearchQueryOptions {
|
|
354
|
+
/** FTS5 query string. Phrase, boolean, and prefix syntax supported. */
|
|
355
|
+
query: string;
|
|
356
|
+
/** Hit cap. Defaults to 25 when omitted. */
|
|
357
|
+
limit?: number | bigint;
|
|
358
|
+
/** Restrict to a single session_id. Omit to search all sessions. */
|
|
359
|
+
sessionId?: string;
|
|
360
|
+
ledgerHome?: string;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
export interface SearchHit {
|
|
364
|
+
sessionId: string;
|
|
365
|
+
messageId: string;
|
|
366
|
+
source: string;
|
|
367
|
+
/** FTS5 BM25 rank (lower = better match). */
|
|
368
|
+
rank: number;
|
|
369
|
+
/** `<b>…</b>`-highlighted snippet around the matching tokens. */
|
|
370
|
+
snippet: string;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export interface SearchResult {
|
|
374
|
+
query: string;
|
|
375
|
+
hits: SearchHit[];
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/** FTS5-backed message-content search. 2.x extension over the TS surface. */
|
|
379
|
+
export declare function search(opts: SearchQueryOptions): Promise<SearchResult>
|
|
380
|
+
|
|
381
|
+
export interface ExportLedgerOptions { ledgerHome?: string }
|
|
382
|
+
export interface ExportStampsOptions { ledgerHome?: string }
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Stream every event row as a JSONL-shaped JSON object. Each value has
|
|
386
|
+
* the form `{ v: 1, kind: '<kind>', record: <json> }`. 2.x extension.
|
|
387
|
+
*/
|
|
388
|
+
export declare function exportLedger(opts?: ExportLedgerOptions): Promise<unknown[]>
|
|
389
|
+
|
|
390
|
+
/** Stream every stamp row as a JSONL-shaped JSON object. 2.x extension. */
|
|
391
|
+
export declare function exportStamps(opts?: ExportStampsOptions): Promise<unknown[]>
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Tagged error code surfaced on the thrown JS `Error.code` property.
|
|
395
|
+
* Sync verbs reject with one of these; the async `ingest` verb's
|
|
396
|
+
* rejection currently sets `code: 'GenericFailure'` — see the binding
|
|
397
|
+
* crate's `ingest` doc comment for the napi-rs-2.x rationale.
|
|
398
|
+
*
|
|
399
|
+
* The values are the literal strings written to `e.code`, matching the
|
|
400
|
+
* Rust constants `SDK_ERROR_CODE` / `IO_ERROR_CODE` / `INVALID_ARGUMENT_ERROR_CODE`.
|
|
401
|
+
*/
|
|
402
|
+
export declare const BurnErrorCode: {
|
|
403
|
+
readonly Sdk: 'BURN_SDK';
|
|
404
|
+
readonly Io: 'BURN_IO';
|
|
405
|
+
readonly InvalidArgument: 'BURN_INVALID_ARGUMENT';
|
|
406
|
+
};
|
|
407
|
+
export type BurnErrorCodeValue = (typeof BurnErrorCode)[keyof typeof BurnErrorCode];
|
|
408
|
+
|
|
409
|
+
/** Wire-value enum for `OverheadOptions.kind` and `OverheadTrimOptions.kind`. */
|
|
410
|
+
export declare const OverheadFileKind: {
|
|
411
|
+
readonly ClaudeMd: 'claude-md';
|
|
412
|
+
readonly AgentsMd: 'agents-md';
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
/** Wire-value enum for `HotspotsOptions.groupBy`. */
|
|
416
|
+
export declare const HotspotsGroupBy: {
|
|
417
|
+
readonly Attribution: 'attribution';
|
|
418
|
+
readonly Bash: 'bash';
|
|
419
|
+
readonly BashVerb: 'bash-verb';
|
|
420
|
+
readonly File: 'file';
|
|
421
|
+
readonly Subagent: 'subagent';
|
|
422
|
+
};
|
package/src/index.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// Thin ESM facade over the napi-rs binding. The verbs here re-export the
|
|
2
|
+
// matching `#[napi]` exports from the platform package resolved by
|
|
3
|
+
// `./binding.cjs`, with two adjustments to match the TS 1.x contract at
|
|
4
|
+
// `packages/sdk/index.d.ts`:
|
|
5
|
+
//
|
|
6
|
+
// 1. The sync `#[napi]` verbs (`summary`, `sessionCost`, `overhead`,
|
|
7
|
+
// `overheadTrim`, `hotspots`, `compare`) are re-exported as `async`
|
|
8
|
+
// functions so callers receive `Promise<T>` (matching the 1.x
|
|
9
|
+
// `Promise<...>` return shape). Awaiting an `async` wrapper around a
|
|
10
|
+
// sync return is free and preserves the typed `e.code` thrown by the
|
|
11
|
+
// binding (`BurnErrorCode.Sdk` / `Io` / `InvalidArgument`).
|
|
12
|
+
// 2. `Ledger.open()` is a JS-side wrapper around the binding's
|
|
13
|
+
// `ledgerOpen()` smoke verb. The 1.x `Ledger` class only exposes a
|
|
14
|
+
// static `open(opts)` that returns a placeholder instance, so we
|
|
15
|
+
// keep the same shape here without adding a stateful `#[napi]` class
|
|
16
|
+
// (which would force `Mutex<LedgerHandle>` plumbing for no benefit).
|
|
17
|
+
//
|
|
18
|
+
// All query / compute logic lives in the Rust SDK (`crates/relayburn-sdk`);
|
|
19
|
+
// the binding crate (`crates/relayburn-sdk-node`) wraps it for napi-rs.
|
|
20
|
+
|
|
21
|
+
import { createRequire } from 'node:module';
|
|
22
|
+
|
|
23
|
+
const require = createRequire(import.meta.url);
|
|
24
|
+
const binding = require('./binding.cjs');
|
|
25
|
+
|
|
26
|
+
// napi-rs serializes Rust `u64` / `i64` as JS `BigInt`, but the TS 1.x
|
|
27
|
+
// `@relayburn/sdk` shape (mirrored in `src/index.d.ts`) emits plain
|
|
28
|
+
// `Number` for the same fields. To keep the conformance gate's
|
|
29
|
+
// `deepStrictEqual` checks honest — and to match the runtime shape that
|
|
30
|
+
// 1.x callers expect (e.g. `result.turnCount === 0`, not `=== 0n`) — we
|
|
31
|
+
// downcast every `BigInt` in a verb's return value to `Number` when it
|
|
32
|
+
// fits in `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`. Values
|
|
33
|
+
// outside that range are left as `BigInt`: realistic burn ledgers won't
|
|
34
|
+
// hit 2^53 tokens, but if one ever does, leaking a `BigInt` that crashes
|
|
35
|
+
// a `===` check is strictly safer than silently rounding to the nearest
|
|
36
|
+
// 1024. The TS shape declares `number | bigint` everywhere this matters
|
|
37
|
+
// so the type stays sound either way.
|
|
38
|
+
const MIN_SAFE = BigInt(Number.MIN_SAFE_INTEGER);
|
|
39
|
+
const MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);
|
|
40
|
+
|
|
41
|
+
function coerceBigInts(value) {
|
|
42
|
+
if (typeof value === 'bigint') {
|
|
43
|
+
return value >= MIN_SAFE && value <= MAX_SAFE ? Number(value) : value;
|
|
44
|
+
}
|
|
45
|
+
if (Array.isArray(value)) {
|
|
46
|
+
for (let i = 0; i < value.length; i++) {
|
|
47
|
+
value[i] = coerceBigInts(value[i]);
|
|
48
|
+
}
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
if (value !== null && typeof value === 'object') {
|
|
52
|
+
// Skip class instances we don't own (Date, Map, Set, Buffer, …) —
|
|
53
|
+
// walking their guts would be both wasteful and risky. Plain objects
|
|
54
|
+
// produced by napi-rs serde have a null or Object prototype.
|
|
55
|
+
const proto = Object.getPrototypeOf(value);
|
|
56
|
+
if (proto === null || proto === Object.prototype) {
|
|
57
|
+
for (const key of Object.keys(value)) {
|
|
58
|
+
value[key] = coerceBigInts(value[key]);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Stateful ledger handle. Mirrors the TS 1.x `Ledger` class shape from
|
|
68
|
+
* `packages/sdk/index.d.ts`. The 1.x version only exposes the static
|
|
69
|
+
* `open(opts)` constructor — instance methods are reserved for a future
|
|
70
|
+
* PR — so we replicate that surface and stash the resolved home for
|
|
71
|
+
* introspection.
|
|
72
|
+
*/
|
|
73
|
+
export class Ledger {
|
|
74
|
+
constructor(home) {
|
|
75
|
+
/** @type {string} */
|
|
76
|
+
this.home = home;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Open and validate a ledger at `opts.home` (or `RELAYBURN_HOME`).
|
|
80
|
+
* Returns a `Promise<Ledger>` to mirror the 1.x async signature even
|
|
81
|
+
* though the underlying `ledgerOpen` binding is synchronous.
|
|
82
|
+
*
|
|
83
|
+
* @param {{ home?: string, contentHome?: string }} [opts]
|
|
84
|
+
* @returns {Promise<Ledger>}
|
|
85
|
+
*/
|
|
86
|
+
static async open(opts) {
|
|
87
|
+
const home = binding.ledgerOpen(opts);
|
|
88
|
+
return new Ledger(home);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export async function ingest(opts) {
|
|
93
|
+
return coerceBigInts(await binding.ingest(opts));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export async function summary(opts) {
|
|
97
|
+
return coerceBigInts(await binding.summary(opts));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export async function sessionCost(opts) {
|
|
101
|
+
return coerceBigInts(await binding.sessionCost(opts));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function overhead(opts) {
|
|
105
|
+
return coerceBigInts(await binding.overhead(opts));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export async function overheadTrim(opts) {
|
|
109
|
+
return coerceBigInts(await binding.overheadTrim(opts));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export async function hotspots(opts) {
|
|
113
|
+
return coerceBigInts(await binding.hotspots(opts));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export async function compare(opts) {
|
|
117
|
+
return coerceBigInts(await binding.compare(opts));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 2.x extensions — exposed by the Rust SDK but not declared in
|
|
121
|
+
// `packages/sdk/index.d.ts` (the 1.x TS surface). Per the SDK shape rule,
|
|
122
|
+
// pre-1.0 widening is allowed; these are surfaced here so embedders can
|
|
123
|
+
// reach the FTS5 search index and the JSONL export iterators without
|
|
124
|
+
// dropping into the binding directly.
|
|
125
|
+
export async function search(opts) {
|
|
126
|
+
return coerceBigInts(await binding.search(opts));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export async function exportLedger(opts) {
|
|
130
|
+
return coerceBigInts(await binding.exportLedger(opts));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export async function exportStamps(opts) {
|
|
134
|
+
return coerceBigInts(await binding.exportStamps(opts));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Re-exported enums from the Rust binding. These come across as plain
|
|
138
|
+
// string-valued objects (`{ Sdk: 'BURN_SDK', ... }`) and let JS callers
|
|
139
|
+
// branch on `e.code === BurnErrorCode.Sdk` without stringly-typed
|
|
140
|
+
// literals. `OverheadFileKind` and `HotspotsGroupBy` are likewise the
|
|
141
|
+
// canonical wire values for the matching option-struct fields.
|
|
142
|
+
export const BurnErrorCode = binding.BurnErrorCode;
|
|
143
|
+
export const OverheadFileKind = binding.OverheadFileKind;
|
|
144
|
+
export const HotspotsGroupBy = binding.HotspotsGroupBy;
|