@net-mesh/sdk 0.19.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/README.md +1684 -0
- package/dist/_internal.d.ts +25 -0
- package/dist/_internal.js +60 -0
- package/dist/capabilities.d.ts +271 -0
- package/dist/capabilities.js +186 -0
- package/dist/capability-enhancements.d.ts +574 -0
- package/dist/capability-enhancements.js +1324 -0
- package/dist/capability-schema.d.ts +112 -0
- package/dist/capability-schema.js +317 -0
- package/dist/channel.d.ts +56 -0
- package/dist/channel.js +95 -0
- package/dist/compute.d.ts +546 -0
- package/dist/compute.js +741 -0
- package/dist/cortex.d.ts +236 -0
- package/dist/cortex.js +584 -0
- package/dist/deck.d.ts +342 -0
- package/dist/deck.js +717 -0
- package/dist/groups.d.ts +208 -0
- package/dist/groups.js +431 -0
- package/dist/identity.d.ts +149 -0
- package/dist/identity.js +264 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +147 -0
- package/dist/mesh.d.ts +369 -0
- package/dist/mesh.js +433 -0
- package/dist/meshdb.d.ts +87 -0
- package/dist/meshdb.js +111 -0
- package/dist/meshos.d.ts +277 -0
- package/dist/meshos.js +359 -0
- package/dist/node.d.ts +120 -0
- package/dist/node.js +246 -0
- package/dist/redis-dedup.d.ts +48 -0
- package/dist/redis-dedup.js +52 -0
- package/dist/stream.d.ts +47 -0
- package/dist/stream.js +118 -0
- package/dist/subnets.d.ts +75 -0
- package/dist/subnets.js +54 -0
- package/dist/types.d.ts +102 -0
- package/dist/types.js +5 -0
- package/package.json +43 -0
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capability-System Enhancements — TypeScript surface.
|
|
3
|
+
*
|
|
4
|
+
* This module mirrors the substrate's enhancement-track types:
|
|
5
|
+
*
|
|
6
|
+
* - Typed taxonomy ({@link Tag}, {@link TagKey}, {@link TaxonomyAxis})
|
|
7
|
+
* with reserved-prefix enforcement at construction time.
|
|
8
|
+
* - Fluent {@link Predicate} builder (`p.*`) producing the canonical
|
|
9
|
+
* wire IR (`PredicateWire`) consumed by `net-where` headers.
|
|
10
|
+
* - {@link diffCapabilities} returning the same `CapabilitySetDiff`
|
|
11
|
+
* shape the cross-binding fixtures pin.
|
|
12
|
+
* - {@link requireTag} / {@link requireAxisValue} chain helpers
|
|
13
|
+
* producing `{ tags, metadata }` directly.
|
|
14
|
+
* - {@link StandardPlacement} configuration object + the
|
|
15
|
+
* {@link placementFilterFromFn} callback shape.
|
|
16
|
+
*
|
|
17
|
+
* All wire-format types match the JSON shape the substrate emits via
|
|
18
|
+
* `serde_json` — the cross-binding tests in
|
|
19
|
+
* `tests/cross_lang_capability/` pin the canonical bytes.
|
|
20
|
+
*
|
|
21
|
+
* @packageDocumentation
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Canonical capability axis. Mirrors `TaxonomyAxis` in the substrate
|
|
25
|
+
* (`adapter::net::behavior::tag::TaxonomyAxis`). The wire form is the
|
|
26
|
+
* lowercase string.
|
|
27
|
+
*/
|
|
28
|
+
export type TaxonomyAxis = 'hardware' | 'software' | 'devices' | 'dataforts';
|
|
29
|
+
/** Every axis the substrate knows about. */
|
|
30
|
+
export declare const TAXONOMY_AXES: readonly TaxonomyAxis[];
|
|
31
|
+
/**
|
|
32
|
+
* Reserved cross-axis prefixes. Substrate-privileged paths
|
|
33
|
+
* (`announceChain`, fork-coordination, scope helpers) emit these;
|
|
34
|
+
* user code calling {@link tagFromUserString} is rejected.
|
|
35
|
+
*/
|
|
36
|
+
export declare const RESERVED_PREFIXES: readonly string[];
|
|
37
|
+
/**
|
|
38
|
+
* `<axis>.<key>` identifier — the addressing pair for axis-prefixed
|
|
39
|
+
* tags and axis-keyed predicates.
|
|
40
|
+
*/
|
|
41
|
+
export interface TagKey {
|
|
42
|
+
axis: TaxonomyAxis;
|
|
43
|
+
/** Key within the axis namespace (e.g. `gpu`, `runtime.python`). */
|
|
44
|
+
key: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Build a {@link TagKey}. Throws on empty key — matches the substrate's
|
|
48
|
+
* `TagKey::new` contract (the constructor is fallible-by-debug-assert
|
|
49
|
+
* there; we surface as a thrown error here).
|
|
50
|
+
*/
|
|
51
|
+
export declare function tagKey(axis: TaxonomyAxis, key: string): TagKey;
|
|
52
|
+
/** Separator between an axis-tag's key and its value. */
|
|
53
|
+
export type AxisSeparator = ':' | '=';
|
|
54
|
+
/**
|
|
55
|
+
* Typed tag. Mirrors `Tag` in the substrate. The wire form is the
|
|
56
|
+
* canonical Display string ({@link tagToString}).
|
|
57
|
+
*
|
|
58
|
+
* - `axisPresent` — `<axis>.<key>` (no value).
|
|
59
|
+
* - `axisValue` — `<axis>.<key>=<value>` or `<axis>.<key>:<value>`.
|
|
60
|
+
* - `reserved` — one of the {@link RESERVED_PREFIXES} cross-axis tags.
|
|
61
|
+
* - `legacy` — arbitrary string outside the typed taxonomy. The
|
|
62
|
+
* substrate keeps these as-is for forward compatibility.
|
|
63
|
+
*/
|
|
64
|
+
export type Tag = {
|
|
65
|
+
kind: 'axisPresent';
|
|
66
|
+
axis: TaxonomyAxis;
|
|
67
|
+
key: string;
|
|
68
|
+
} | {
|
|
69
|
+
kind: 'axisValue';
|
|
70
|
+
axis: TaxonomyAxis;
|
|
71
|
+
key: string;
|
|
72
|
+
value: string;
|
|
73
|
+
separator: AxisSeparator;
|
|
74
|
+
} | {
|
|
75
|
+
kind: 'reserved';
|
|
76
|
+
prefix: string;
|
|
77
|
+
body: string;
|
|
78
|
+
} | {
|
|
79
|
+
kind: 'legacy';
|
|
80
|
+
raw: string;
|
|
81
|
+
};
|
|
82
|
+
/** True iff `s` starts with one of the {@link RESERVED_PREFIXES}. */
|
|
83
|
+
export declare function startsWithReservedPrefix(s: string): string | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Render a {@link Tag} to its canonical wire string. Matches the
|
|
86
|
+
* substrate's `Display` impl for `Tag`.
|
|
87
|
+
*/
|
|
88
|
+
export declare function tagToString(tag: Tag): string;
|
|
89
|
+
/**
|
|
90
|
+
* Parse a wire string into a {@link Tag}. Privileged path — does
|
|
91
|
+
* NOT reject reserved prefixes (substrate code that legitimately
|
|
92
|
+
* needs to round-trip e.g. `scope:tenant:foo` calls this).
|
|
93
|
+
*
|
|
94
|
+
* User code should prefer {@link tagFromUserString}, which rejects
|
|
95
|
+
* reserved prefixes.
|
|
96
|
+
*/
|
|
97
|
+
export declare function tagFromString(s: string): Tag;
|
|
98
|
+
/**
|
|
99
|
+
* Parse a wire string from user code. Rejects the reserved
|
|
100
|
+
* cross-axis prefixes ({@link RESERVED_PREFIXES}) — application code
|
|
101
|
+
* cannot emit those by design. Mirrors the substrate's
|
|
102
|
+
* `Tag::parse_user`.
|
|
103
|
+
*/
|
|
104
|
+
export declare function tagFromUserString(s: string): Tag;
|
|
105
|
+
/** Numeric kinds — match the substrate's wire `kind` strings exactly. */
|
|
106
|
+
export type PredicateNode = {
|
|
107
|
+
kind: 'exists';
|
|
108
|
+
key: TagKey;
|
|
109
|
+
} | {
|
|
110
|
+
kind: 'equals';
|
|
111
|
+
key: TagKey;
|
|
112
|
+
value: string;
|
|
113
|
+
} | {
|
|
114
|
+
kind: 'numeric_at_least';
|
|
115
|
+
key: TagKey;
|
|
116
|
+
threshold: number;
|
|
117
|
+
} | {
|
|
118
|
+
kind: 'numeric_at_most';
|
|
119
|
+
key: TagKey;
|
|
120
|
+
threshold: number;
|
|
121
|
+
} | {
|
|
122
|
+
kind: 'numeric_in_range';
|
|
123
|
+
key: TagKey;
|
|
124
|
+
min: number;
|
|
125
|
+
max: number;
|
|
126
|
+
} | {
|
|
127
|
+
kind: 'semver_at_least';
|
|
128
|
+
key: TagKey;
|
|
129
|
+
version: string;
|
|
130
|
+
} | {
|
|
131
|
+
kind: 'semver_at_most';
|
|
132
|
+
key: TagKey;
|
|
133
|
+
version: string;
|
|
134
|
+
} | {
|
|
135
|
+
kind: 'semver_compatible';
|
|
136
|
+
key: TagKey;
|
|
137
|
+
version: string;
|
|
138
|
+
} | {
|
|
139
|
+
kind: 'string_prefix';
|
|
140
|
+
key: TagKey;
|
|
141
|
+
prefix: string;
|
|
142
|
+
} | {
|
|
143
|
+
kind: 'string_matches';
|
|
144
|
+
key: TagKey;
|
|
145
|
+
pattern: string;
|
|
146
|
+
} | {
|
|
147
|
+
kind: 'metadata_exists';
|
|
148
|
+
key: string;
|
|
149
|
+
} | {
|
|
150
|
+
kind: 'metadata_equals';
|
|
151
|
+
key: string;
|
|
152
|
+
value: string;
|
|
153
|
+
} | {
|
|
154
|
+
kind: 'metadata_matches';
|
|
155
|
+
key: string;
|
|
156
|
+
pattern: string;
|
|
157
|
+
} | {
|
|
158
|
+
kind: 'metadata_numeric_at_least';
|
|
159
|
+
key: string;
|
|
160
|
+
threshold: number;
|
|
161
|
+
} | {
|
|
162
|
+
kind: 'and';
|
|
163
|
+
children: number[];
|
|
164
|
+
} | {
|
|
165
|
+
kind: 'or';
|
|
166
|
+
children: number[];
|
|
167
|
+
} | {
|
|
168
|
+
kind: 'not';
|
|
169
|
+
child: number;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Wire-format predicate. The exact JSON shape the substrate's
|
|
173
|
+
* `net-where` request header carries; pinned by the
|
|
174
|
+
* `predicate_nrpc_envelope.json` cross-binding fixture.
|
|
175
|
+
*/
|
|
176
|
+
export interface PredicateWire {
|
|
177
|
+
nodes: PredicateNode[];
|
|
178
|
+
root_idx: number;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* In-memory predicate AST. Sugar over {@link PredicateWire} — the
|
|
182
|
+
* fluent {@link p} builder constructs these and {@link predicateToWire}
|
|
183
|
+
* flattens them.
|
|
184
|
+
*/
|
|
185
|
+
export type Predicate = {
|
|
186
|
+
type: 'exists';
|
|
187
|
+
key: TagKey;
|
|
188
|
+
} | {
|
|
189
|
+
type: 'equals';
|
|
190
|
+
key: TagKey;
|
|
191
|
+
value: string;
|
|
192
|
+
} | {
|
|
193
|
+
type: 'numericAtLeast';
|
|
194
|
+
key: TagKey;
|
|
195
|
+
threshold: number;
|
|
196
|
+
} | {
|
|
197
|
+
type: 'numericAtMost';
|
|
198
|
+
key: TagKey;
|
|
199
|
+
threshold: number;
|
|
200
|
+
} | {
|
|
201
|
+
type: 'numericInRange';
|
|
202
|
+
key: TagKey;
|
|
203
|
+
min: number;
|
|
204
|
+
max: number;
|
|
205
|
+
} | {
|
|
206
|
+
type: 'semverAtLeast';
|
|
207
|
+
key: TagKey;
|
|
208
|
+
version: string;
|
|
209
|
+
} | {
|
|
210
|
+
type: 'semverAtMost';
|
|
211
|
+
key: TagKey;
|
|
212
|
+
version: string;
|
|
213
|
+
} | {
|
|
214
|
+
type: 'semverCompatible';
|
|
215
|
+
key: TagKey;
|
|
216
|
+
version: string;
|
|
217
|
+
} | {
|
|
218
|
+
type: 'stringPrefix';
|
|
219
|
+
key: TagKey;
|
|
220
|
+
prefix: string;
|
|
221
|
+
} | {
|
|
222
|
+
type: 'stringMatches';
|
|
223
|
+
key: TagKey;
|
|
224
|
+
pattern: string;
|
|
225
|
+
} | {
|
|
226
|
+
type: 'metadataExists';
|
|
227
|
+
key: string;
|
|
228
|
+
} | {
|
|
229
|
+
type: 'metadataEquals';
|
|
230
|
+
key: string;
|
|
231
|
+
value: string;
|
|
232
|
+
} | {
|
|
233
|
+
type: 'metadataMatches';
|
|
234
|
+
key: string;
|
|
235
|
+
pattern: string;
|
|
236
|
+
} | {
|
|
237
|
+
type: 'metadataNumericAtLeast';
|
|
238
|
+
key: string;
|
|
239
|
+
threshold: number;
|
|
240
|
+
} | {
|
|
241
|
+
type: 'and';
|
|
242
|
+
children: Predicate[];
|
|
243
|
+
} | {
|
|
244
|
+
type: 'or';
|
|
245
|
+
children: Predicate[];
|
|
246
|
+
} | {
|
|
247
|
+
type: 'not';
|
|
248
|
+
child: Predicate;
|
|
249
|
+
};
|
|
250
|
+
/**
|
|
251
|
+
* Fluent predicate constructors. Match the substrate's `Predicate::*`
|
|
252
|
+
* factory methods one-to-one.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```ts
|
|
256
|
+
* import { p, predicateToWire } from '@net-mesh/sdk';
|
|
257
|
+
*
|
|
258
|
+
* const pred = p.and(
|
|
259
|
+
* p.exists({ axis: 'hardware', key: 'gpu' }),
|
|
260
|
+
* p.numericAtLeast({ axis: 'hardware', key: 'memory_gb' }, 64),
|
|
261
|
+
* p.metadataEquals('intent', 'ml-training'),
|
|
262
|
+
* );
|
|
263
|
+
* const wire = predicateToWire(pred);
|
|
264
|
+
* ```
|
|
265
|
+
*/
|
|
266
|
+
export declare const p: {
|
|
267
|
+
readonly exists: (key: TagKey) => Predicate;
|
|
268
|
+
readonly equals: (key: TagKey, value: string) => Predicate;
|
|
269
|
+
readonly numericAtLeast: (key: TagKey, threshold: number) => Predicate;
|
|
270
|
+
readonly numericAtMost: (key: TagKey, threshold: number) => Predicate;
|
|
271
|
+
readonly numericInRange: (key: TagKey, min: number, max: number) => Predicate;
|
|
272
|
+
readonly semverAtLeast: (key: TagKey, version: string) => Predicate;
|
|
273
|
+
readonly semverAtMost: (key: TagKey, version: string) => Predicate;
|
|
274
|
+
readonly semverCompatible: (key: TagKey, version: string) => Predicate;
|
|
275
|
+
readonly stringPrefix: (key: TagKey, prefix: string) => Predicate;
|
|
276
|
+
readonly stringMatches: (key: TagKey, pattern: string) => Predicate;
|
|
277
|
+
readonly metadataExists: (key: string) => Predicate;
|
|
278
|
+
readonly metadataEquals: (key: string, value: string) => Predicate;
|
|
279
|
+
readonly metadataMatches: (key: string, pattern: string) => Predicate;
|
|
280
|
+
readonly metadataNumericAtLeast: (key: string, threshold: number) => Predicate;
|
|
281
|
+
readonly and: (...children: Predicate[]) => Predicate;
|
|
282
|
+
readonly or: (...children: Predicate[]) => Predicate;
|
|
283
|
+
readonly not: (child: Predicate) => Predicate;
|
|
284
|
+
};
|
|
285
|
+
/** Flatten an AST into the wire IR. Children always sit at lower
|
|
286
|
+
* indices than their parents (post-order). */
|
|
287
|
+
export declare function predicateToWire(pred: Predicate): PredicateWire;
|
|
288
|
+
/** Inverse of {@link predicateToWire}. Rebuilds the AST from a wire
|
|
289
|
+
* IR. Throws on out-of-range indices or malformed nodes. */
|
|
290
|
+
export declare function predicateFromWire(wire: PredicateWire): Predicate;
|
|
291
|
+
/** Header the substrate uses to carry a predicate over nRPC. */
|
|
292
|
+
export declare const RPC_WHERE_HEADER = "net-where";
|
|
293
|
+
/** Encode a predicate into the request-header value. The substrate
|
|
294
|
+
* pins this as the canonical JSON-encoded {@link PredicateWire}. */
|
|
295
|
+
export declare function predicateToRpcHeader(pred: Predicate): string;
|
|
296
|
+
/** Decode a `net-where` header value back into an AST. Throws
|
|
297
|
+
* on malformed JSON or out-of-range indices. */
|
|
298
|
+
export declare function predicateFromRpcHeader(value: string): Predicate;
|
|
299
|
+
/**
|
|
300
|
+
* Build the `net-where:` request-header entry for a
|
|
301
|
+
* Phase 9b predicate-pushdown call. Drops straight into a
|
|
302
|
+
* `MeshRpc.call` `CallOptions.requestHeaders` array.
|
|
303
|
+
*
|
|
304
|
+
* @example
|
|
305
|
+
* ```ts
|
|
306
|
+
* import { p, tagKey, whereHeader } from '@net-mesh/sdk';
|
|
307
|
+
* const pred = p.exists(tagKey('hardware', 'gpu'));
|
|
308
|
+
* await rpc.call(targetNodeId, 'filter-svc', body, {
|
|
309
|
+
* requestHeaders: [whereHeader(pred)],
|
|
310
|
+
* });
|
|
311
|
+
* ```
|
|
312
|
+
*
|
|
313
|
+
* The header value is the canonical JSON-encoded `PredicateWire`
|
|
314
|
+
* pinned by `predicate_nrpc_envelope.json`.
|
|
315
|
+
*/
|
|
316
|
+
export declare function whereHeader(pred: Predicate): {
|
|
317
|
+
name: string;
|
|
318
|
+
value: Buffer;
|
|
319
|
+
};
|
|
320
|
+
/** Wire-format capability shape — string tags + string→string metadata. */
|
|
321
|
+
export interface CapabilitySetWire {
|
|
322
|
+
tags: string[];
|
|
323
|
+
metadata: Record<string, string>;
|
|
324
|
+
}
|
|
325
|
+
/** Per-key metadata change. Mirrors `MetadataChange` in the substrate. */
|
|
326
|
+
export type MetadataChange = {
|
|
327
|
+
kind: 'added';
|
|
328
|
+
key: string;
|
|
329
|
+
value: string;
|
|
330
|
+
} | {
|
|
331
|
+
kind: 'removed';
|
|
332
|
+
key: string;
|
|
333
|
+
prev_value: string;
|
|
334
|
+
} | {
|
|
335
|
+
kind: 'updated';
|
|
336
|
+
key: string;
|
|
337
|
+
prev_value: string;
|
|
338
|
+
new_value: string;
|
|
339
|
+
};
|
|
340
|
+
/** Diff between two capability snapshots. Mirrors
|
|
341
|
+
* `CapabilitySetDiff` in the substrate. */
|
|
342
|
+
export interface CapabilitySetDiff {
|
|
343
|
+
added_tags: string[];
|
|
344
|
+
removed_tags: string[];
|
|
345
|
+
metadata_changes: MetadataChange[];
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Compute `curr.diff(prev)`. Pinned by the
|
|
349
|
+
* `capability_set_diff.json` cross-binding fixture.
|
|
350
|
+
*
|
|
351
|
+
* - Tag arrays are sorted by wire string.
|
|
352
|
+
* - Metadata changes are sorted by key (BTreeMap semantics in the
|
|
353
|
+
* substrate).
|
|
354
|
+
* - A key rename surfaces as Removed + Added (NOT Updated). Only a
|
|
355
|
+
* value change for the same key is Updated.
|
|
356
|
+
*/
|
|
357
|
+
export declare function diffCapabilities(prev: CapabilitySetWire, curr: CapabilitySetWire): CapabilitySetDiff;
|
|
358
|
+
/**
|
|
359
|
+
* Add an axis-tag (no value) to the wire shape. Idempotent; no-op
|
|
360
|
+
* if the tag is already present.
|
|
361
|
+
*/
|
|
362
|
+
export declare function requireTag(caps: CapabilitySetWire, axis: TaxonomyAxis, key: string): CapabilitySetWire;
|
|
363
|
+
/**
|
|
364
|
+
* Add an axis-value tag (`<axis>.<key>=<value>` by default) to the
|
|
365
|
+
* wire shape. Idempotent for the exact (axis, key, value, separator)
|
|
366
|
+
* triple.
|
|
367
|
+
*/
|
|
368
|
+
export declare function requireAxisValue(caps: CapabilitySetWire, axis: TaxonomyAxis, key: string, value: string, separator?: AxisSeparator): CapabilitySetWire;
|
|
369
|
+
/** Set / overwrite a metadata entry. */
|
|
370
|
+
export declare function withMetadata(caps: CapabilitySetWire, key: string, value: string): CapabilitySetWire;
|
|
371
|
+
/** Empty wire-format capability set. */
|
|
372
|
+
export declare function emptyCapabilities(): CapabilitySetWire;
|
|
373
|
+
/**
|
|
374
|
+
* Configuration for the substrate's `StandardPlacement` filter. All
|
|
375
|
+
* fields are optional — an empty config matches every node.
|
|
376
|
+
*
|
|
377
|
+
* The wire shape is JSON-friendly (`predicate` carries a
|
|
378
|
+
* {@link PredicateWire}, not the AST). Bindings encode this object
|
|
379
|
+
* before handing it to the runtime.
|
|
380
|
+
*/
|
|
381
|
+
export interface StandardPlacement {
|
|
382
|
+
/**
|
|
383
|
+
* Required tags — every listed wire-string must be present. Use
|
|
384
|
+
* {@link tagToString} to turn typed {@link Tag} values into
|
|
385
|
+
* wire form.
|
|
386
|
+
*/
|
|
387
|
+
requireTags?: string[];
|
|
388
|
+
/**
|
|
389
|
+
* Forbidden tags — none of these may be present. Same wire form
|
|
390
|
+
* as {@link requireTags}.
|
|
391
|
+
*/
|
|
392
|
+
forbidTags?: string[];
|
|
393
|
+
/** Required metadata key/value equalities. */
|
|
394
|
+
requireMetadata?: Record<string, string>;
|
|
395
|
+
/**
|
|
396
|
+
* Free-form predicate evaluated against each candidate's tag set
|
|
397
|
+
* + metadata. Combined with the tag/metadata constraints via AND.
|
|
398
|
+
*/
|
|
399
|
+
predicate?: PredicateWire;
|
|
400
|
+
/**
|
|
401
|
+
* Maximum candidates to return. The runtime picks deterministically
|
|
402
|
+
* by node id when more match.
|
|
403
|
+
*/
|
|
404
|
+
limit?: number;
|
|
405
|
+
/**
|
|
406
|
+
* Custom placement filter — a string id resolved by the runtime
|
|
407
|
+
* to a registered callback (see {@link placementFilterFromFn}).
|
|
408
|
+
*/
|
|
409
|
+
customFilterId?: string;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Builder for {@link StandardPlacement}. Returns a frozen config
|
|
413
|
+
* object suitable for handing to the runtime.
|
|
414
|
+
*/
|
|
415
|
+
export declare class StandardPlacementBuilder {
|
|
416
|
+
private cfg;
|
|
417
|
+
requireTag(axis: TaxonomyAxis, key: string): this;
|
|
418
|
+
requireAxisValue(axis: TaxonomyAxis, key: string, value: string, separator?: AxisSeparator): this;
|
|
419
|
+
forbidTag(axis: TaxonomyAxis, key: string): this;
|
|
420
|
+
requireMetadata(key: string, value: string): this;
|
|
421
|
+
withPredicate(pred: Predicate | PredicateWire): this;
|
|
422
|
+
withLimit(n: number): this;
|
|
423
|
+
withCustomFilterId(id: string): this;
|
|
424
|
+
build(): StandardPlacement;
|
|
425
|
+
}
|
|
426
|
+
/** Convenience constructor for a {@link StandardPlacementBuilder}. */
|
|
427
|
+
export declare function standardPlacement(): StandardPlacementBuilder;
|
|
428
|
+
/**
|
|
429
|
+
* Candidate handed to a custom placement-filter callback. The
|
|
430
|
+
* runtime materializes one of these per candidate before evaluating
|
|
431
|
+
* the user predicate.
|
|
432
|
+
*/
|
|
433
|
+
export interface PlacementCandidate {
|
|
434
|
+
nodeId: bigint;
|
|
435
|
+
tags: string[];
|
|
436
|
+
metadata: Record<string, string>;
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Synchronous predicate: `true` to keep, `false` to drop.
|
|
440
|
+
*
|
|
441
|
+
* Custom filters run under the placement hot path — keep them tight
|
|
442
|
+
* and avoid I/O. The runtime registers them by id; the daemon's
|
|
443
|
+
* {@link StandardPlacement} references that id via
|
|
444
|
+
* {@link StandardPlacement.customFilterId}.
|
|
445
|
+
*/
|
|
446
|
+
export type PlacementFilterFn = (candidate: PlacementCandidate) => boolean;
|
|
447
|
+
/**
|
|
448
|
+
* Wrap a user-supplied predicate as a placement filter. Returns a
|
|
449
|
+
* `{ id, fn }` pair the binding can register with the runtime —
|
|
450
|
+
* future `StandardPlacement.customFilterId = id` uses route through
|
|
451
|
+
* the wrapped function.
|
|
452
|
+
*
|
|
453
|
+
* The default id generator uses a counter; callers can supply an
|
|
454
|
+
* explicit id when they want stable identity (e.g. for hot-reload).
|
|
455
|
+
*/
|
|
456
|
+
export interface RegisteredPlacementFilter {
|
|
457
|
+
id: string;
|
|
458
|
+
fn: PlacementFilterFn;
|
|
459
|
+
}
|
|
460
|
+
export declare function placementFilterFromFn(fn: PlacementFilterFn, explicitId?: string): RegisteredPlacementFilter;
|
|
461
|
+
/**
|
|
462
|
+
* Evaluate a {@link Predicate} against a wire-format `(tags, metadata)`
|
|
463
|
+
* context. Mirrors the substrate's `Predicate::evaluate_unplanned`
|
|
464
|
+
* — children of `and` / `or` evaluate in declaration order with
|
|
465
|
+
* standard short-circuit semantics.
|
|
466
|
+
*
|
|
467
|
+
* Pinned across bindings by `predicate_eval.json`. Use this for local
|
|
468
|
+
* pre-filtering of result sets before sending an nRPC `where:`
|
|
469
|
+
* predicate over the wire, or for client-side validation of a
|
|
470
|
+
* predicate against a known capability set.
|
|
471
|
+
*/
|
|
472
|
+
export declare function evaluatePredicate(pred: Predicate, tags: readonly string[], metadata: Readonly<Record<string, string>>): boolean;
|
|
473
|
+
/**
|
|
474
|
+
* Per-clause trace entry. Mirrors the substrate's `ClauseTrace`:
|
|
475
|
+
* each leaf carries a one-line `label` + the boolean `result`;
|
|
476
|
+
* composites carry the planner-ordered subset of children that
|
|
477
|
+
* actually ran.
|
|
478
|
+
*/
|
|
479
|
+
export interface ClauseTrace {
|
|
480
|
+
label: string;
|
|
481
|
+
result: boolean;
|
|
482
|
+
children: ClauseTrace[];
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Evaluate a predicate against `(tags, metadata)` and produce a
|
|
486
|
+
* trace tree.
|
|
487
|
+
*
|
|
488
|
+
* Mirrors the substrate's `Predicate::evaluate_with_trace`:
|
|
489
|
+
* - `And` / `Or` children evaluated in cost-ascending order.
|
|
490
|
+
* - Short-circuited siblings DON'T appear in the trace — operators
|
|
491
|
+
* see "the metadata clause failed; we never got to the GPU
|
|
492
|
+
* check."
|
|
493
|
+
* - `Not`'s child carries the pre-negation result; `Not`'s own node
|
|
494
|
+
* carries the post-negation result.
|
|
495
|
+
*
|
|
496
|
+
* Pinned across bindings by `predicate_trace.json`. Useful for
|
|
497
|
+
* client-side debugging of why a candidate did / didn't match
|
|
498
|
+
* before hitting the wire.
|
|
499
|
+
*/
|
|
500
|
+
export declare function evaluatePredicateWithTrace(pred: Predicate, tags: readonly string[], metadata: Readonly<Record<string, string>>): {
|
|
501
|
+
result: boolean;
|
|
502
|
+
trace: ClauseTrace;
|
|
503
|
+
};
|
|
504
|
+
/**
|
|
505
|
+
* Per-clause aggregated stats. Mirrors the substrate's `ClauseStats`.
|
|
506
|
+
*/
|
|
507
|
+
export interface ClauseStats {
|
|
508
|
+
/** Clause label — same string as `ClauseTrace.label`. */
|
|
509
|
+
label: string;
|
|
510
|
+
/** Number of candidates that reached this clause (not short-circuited). */
|
|
511
|
+
evaluated: number;
|
|
512
|
+
/** Number of those evaluations that returned `true`. */
|
|
513
|
+
matched: number;
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Wire-format debug report. The `clause_stats` array is sorted by
|
|
517
|
+
* label (BTreeMap semantics in the substrate); bindings produce that
|
|
518
|
+
* canonical order.
|
|
519
|
+
*/
|
|
520
|
+
export interface PredicateDebugReport {
|
|
521
|
+
total_candidates: number;
|
|
522
|
+
matched: number;
|
|
523
|
+
clause_stats: ClauseStats[];
|
|
524
|
+
}
|
|
525
|
+
/** Wire-format evaluation context — what `evaluate*` consumes. */
|
|
526
|
+
export interface EvalContextWire {
|
|
527
|
+
tags: string[];
|
|
528
|
+
metadata: Record<string, string>;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Run `pred` against each context in `contexts`, accumulating
|
|
532
|
+
* per-clause hit / miss stats. Mirrors the substrate's
|
|
533
|
+
* `PredicateDebugReport::from_evaluations`.
|
|
534
|
+
*
|
|
535
|
+
* The returned report's `clause_stats` is sorted by label
|
|
536
|
+
* (BTreeMap semantics) so bindings produce byte-identical output
|
|
537
|
+
* for the same input corpus.
|
|
538
|
+
*/
|
|
539
|
+
export declare function predicateDebugReport(pred: Predicate, contexts: readonly EvalContextWire[]): PredicateDebugReport;
|
|
540
|
+
/**
|
|
541
|
+
* Redact metadata-clause values in a {@link PredicateDebugReport}.
|
|
542
|
+
*
|
|
543
|
+
* Walks the report's `clause_stats` and rewrites any label whose
|
|
544
|
+
* metadata key is in the supplied `keys` list:
|
|
545
|
+
*
|
|
546
|
+
* - `MetadataEquals(<key>=<value>)` → `MetadataEquals(<key>=<redacted>)`
|
|
547
|
+
* - `MetadataMatches(<key> contains "<pattern>")` → `MetadataMatches(<key> contains "<redacted>")`
|
|
548
|
+
* - `MetadataNumericAtLeast(<key> >= <threshold>)` → `MetadataNumericAtLeast(<key> >= <redacted>)`
|
|
549
|
+
* - `MetadataExists(<key>)` — unchanged (no value to redact)
|
|
550
|
+
* - All non-metadata labels (Exists, Equals, Numeric*, Semver*,
|
|
551
|
+
* String*, And, Or, Not on tags) unchanged.
|
|
552
|
+
*
|
|
553
|
+
* After rewriting, stats with the same redacted label are merged
|
|
554
|
+
* (`evaluated` and `matched` summed). Output is sorted by label.
|
|
555
|
+
*
|
|
556
|
+
* Use this before persisting a debug report to disk or sharing with
|
|
557
|
+
* a teammate when the predicate's authored metadata values are
|
|
558
|
+
* sensitive (PII, secrets, internal classifications).
|
|
559
|
+
*
|
|
560
|
+
* Pinned across bindings by `predicate_debug_report_redacted.json`.
|
|
561
|
+
*/
|
|
562
|
+
export declare function redactMetadataKeys(report: PredicateDebugReport, keys: readonly string[]): PredicateDebugReport;
|
|
563
|
+
/**
|
|
564
|
+
* Reconstruct a {@link PredicateDebugReport} from its wire JSON form
|
|
565
|
+
* (the shape produced by JSON-stringifying the report). Validates
|
|
566
|
+
* required fields; on malformed input throws a descriptive error.
|
|
567
|
+
*
|
|
568
|
+
* Symmetric inverse of `JSON.stringify(report)` — call
|
|
569
|
+
* `predicateDebugReportFromWire(JSON.parse(text))` to round-trip a
|
|
570
|
+
* report through disk.
|
|
571
|
+
*/
|
|
572
|
+
export declare function predicateDebugReportFromWire(wire: unknown): PredicateDebugReport;
|
|
573
|
+
/** Render a one-line-per-clause text summary suitable for CLI output. */
|
|
574
|
+
export declare function renderDebugReport(report: PredicateDebugReport): string;
|