@wishknish/knishio-client-ts 0.7.6 → 0.7.8
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 +68 -0
- package/dist/index.cjs +305 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +75 -27
- package/dist/index.d.ts +75 -27
- package/dist/index.iife.js +307 -12
- package/dist/index.iife.js.map +1 -1
- package/dist/index.js +304 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/KnishIOClient.ts +194 -5
- package/src/core/Molecule.ts +36 -13
- package/src/index.ts +7 -0
- package/src/libraries/GraphQLClient.ts +15 -0
- package/src/query/QueryEmbeddingStatus.ts +130 -0
- package/src/response/ResponseEmbeddingStatus.ts +107 -0
- package/src/response/ResponseProposeMolecule.ts +47 -0
package/README.md
CHANGED
|
@@ -253,6 +253,73 @@ This document will explain both ways.
|
|
|
253
253
|
console.log(fingerprintData);
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
+
### DataBraid: Embedding Status (Observability)
|
|
257
|
+
|
|
258
|
+
When the validator has DataBraid embeddings enabled (`EMBEDDING_ENABLED=true`), the SDK can query the embedding state of meta assets. This allows apps to render UI indicators such as spinner badges for in-progress embeddings or completion checkmarks.
|
|
259
|
+
|
|
260
|
+
The SDK automatically detects whether the connected server supports this feature. If it does not, `queryEmbeddingStatus()` returns `null` instead of throwing an error.
|
|
261
|
+
|
|
262
|
+
- Query embedding status for a **single Meta Asset**:
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
import type { EmbeddingStatusItem } from '@wishknish/knishio-client-ts'
|
|
266
|
+
|
|
267
|
+
const response = await client.queryEmbeddingStatus({
|
|
268
|
+
metaType: 'Vehicle',
|
|
269
|
+
metaId: 'VIN-12345'
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
if (response) {
|
|
273
|
+
const items: EmbeddingStatusItem[] | null = response.payload();
|
|
274
|
+
// items[0] = {
|
|
275
|
+
// metaType: 'Vehicle',
|
|
276
|
+
// metaId: 'VIN-12345',
|
|
277
|
+
// state: 'COMPLETE', // 'PENDING' | 'STALE' | 'COMPLETE'
|
|
278
|
+
// totalMetas: 5, // Total meta rows for this instance
|
|
279
|
+
// embeddedCount: 5, // Rows with embeddings
|
|
280
|
+
// embeddedAt: 1713100800, // Unix timestamp of last embedding
|
|
281
|
+
// model: 'nomic-embed-text-v1.5'
|
|
282
|
+
// }
|
|
283
|
+
} else {
|
|
284
|
+
// Server does not support embedding status
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
- **Bulk** embedding status for multiple assets in a single request:
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
const response = await client.queryEmbeddingStatus({
|
|
292
|
+
instances: [
|
|
293
|
+
{ metaType: 'Vehicle', metaId: 'VIN-12345' },
|
|
294
|
+
{ metaType: 'Vehicle', metaId: 'VIN-67890' },
|
|
295
|
+
{ metaType: 'Profile', metaId: 'user_42' }
|
|
296
|
+
]
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
if (response) {
|
|
300
|
+
const items = response.payload();
|
|
301
|
+
// items.length === 3, one per input, in the same order
|
|
302
|
+
for (const item of items!) {
|
|
303
|
+
console.log(`${item.metaType}:${item.metaId} → ${item.state}`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
- **Capability detection** — check if the server supports a query field before calling it:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
const supported: boolean = await client.hasQueryField('embeddingStatus');
|
|
312
|
+
// true if the server's GraphQL schema includes the field, false otherwise
|
|
313
|
+
// Result is cached per URI — no repeated network round-trips
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**Embedding States:**
|
|
317
|
+
| State | Meaning | Suggested UI |
|
|
318
|
+
|-------|---------|-------------|
|
|
319
|
+
| `PENDING` | No embeddings generated yet | Spinner / gray badge |
|
|
320
|
+
| `STALE` | Embeddings exist but model has changed | Refresh indicator |
|
|
321
|
+
| `COMPLETE` | All meta rows have current-model embeddings | Green checkmark |
|
|
322
|
+
|
|
256
323
|
## Advanced Usage: Working with Molecules
|
|
257
324
|
|
|
258
325
|
For more granular control, you can work directly with Molecules:
|
|
@@ -419,6 +486,7 @@ This method involves individually building Atoms and Molecules, triggering the s
|
|
|
419
486
|
1. `QueryBalance` and `QueryContinuId` -> returns a `Wallet` instance
|
|
420
487
|
2. `QueryWalletList` -> returns a list of `Wallet` instances
|
|
421
488
|
3. `MutationProposeMolecule`, `MutationRequestAuthorization`, `MutationCreateIdentifier`, `MutationLinkIdentifier`, `MutationClaimShadowWallet`, `MutationCreateToken`, `MutationRequestTokens`, and `MutationTransferTokens` -> returns molecule metadata
|
|
489
|
+
4. `QueryEmbeddingStatus` -> returns an array of `EmbeddingStatusItem` objects (`{ metaType, metaId, state, totalMetas, embeddedCount, embeddedAt, model }`)
|
|
422
490
|
|
|
423
491
|
## Getting Help
|
|
424
492
|
|
package/dist/index.cjs
CHANGED
|
@@ -4809,6 +4809,7 @@ var Molecule = class _Molecule {
|
|
|
4809
4809
|
remainderWallet;
|
|
4810
4810
|
atoms;
|
|
4811
4811
|
version;
|
|
4812
|
+
continuIdPosition;
|
|
4812
4813
|
parentHashes;
|
|
4813
4814
|
local;
|
|
4814
4815
|
/**
|
|
@@ -4821,7 +4822,8 @@ var Molecule = class _Molecule {
|
|
|
4821
4822
|
sourceWallet = null,
|
|
4822
4823
|
remainderWallet = null,
|
|
4823
4824
|
cellSlug = null,
|
|
4824
|
-
version = null
|
|
4825
|
+
version = null,
|
|
4826
|
+
continuIdPosition = null
|
|
4825
4827
|
} = {}) {
|
|
4826
4828
|
this.status = null;
|
|
4827
4829
|
this.molecularHash = null;
|
|
@@ -4830,6 +4832,7 @@ var Molecule = class _Molecule {
|
|
|
4830
4832
|
this.secret = secret;
|
|
4831
4833
|
this.bundle = bundle;
|
|
4832
4834
|
this.sourceWallet = sourceWallet;
|
|
4835
|
+
this.continuIdPosition = continuIdPosition;
|
|
4833
4836
|
this.atoms = [];
|
|
4834
4837
|
this.parentHashes = [];
|
|
4835
4838
|
const versionRegistry = versions_default;
|
|
@@ -4907,7 +4910,9 @@ var Molecule = class _Molecule {
|
|
|
4907
4910
|
});
|
|
4908
4911
|
}
|
|
4909
4912
|
const continuIdMeta = {};
|
|
4910
|
-
if (this.
|
|
4913
|
+
if (this.continuIdPosition) {
|
|
4914
|
+
continuIdMeta.previousPosition = this.continuIdPosition;
|
|
4915
|
+
} else if (this.sourceWallet && this.sourceWallet.position) {
|
|
4911
4916
|
continuIdMeta.previousPosition = this.sourceWallet.position;
|
|
4912
4917
|
}
|
|
4913
4918
|
if (this.remainderWallet.pubkey) {
|
|
@@ -4936,13 +4941,8 @@ var Molecule = class _Molecule {
|
|
|
4936
4941
|
}) {
|
|
4937
4942
|
const atomMeta = new AtomMeta(meta);
|
|
4938
4943
|
atomMeta.addPolicy(policy);
|
|
4939
|
-
const wallet = Wallet.create({
|
|
4940
|
-
secret: this.secret,
|
|
4941
|
-
bundle: this.sourceWallet.bundle,
|
|
4942
|
-
token: "USER"
|
|
4943
|
-
});
|
|
4944
4944
|
this.addAtom(Atom.create({
|
|
4945
|
-
wallet,
|
|
4945
|
+
wallet: this.sourceWallet,
|
|
4946
4946
|
isotope: "R",
|
|
4947
4947
|
metaType,
|
|
4948
4948
|
metaId,
|
|
@@ -5251,10 +5251,21 @@ var Molecule = class _Molecule {
|
|
|
5251
5251
|
if (Number(this.sourceWallet.balance) - amount < 0) {
|
|
5252
5252
|
throw new BalanceInsufficientException();
|
|
5253
5253
|
}
|
|
5254
|
+
const burnWallet = new Wallet({
|
|
5255
|
+
bundle: "0000000000000000000000000000000000000000000000000000000000000000",
|
|
5256
|
+
token: this.sourceWallet.token
|
|
5257
|
+
});
|
|
5254
5258
|
this.addAtom(Atom.create({
|
|
5255
5259
|
isotope: "V",
|
|
5256
5260
|
wallet: this.sourceWallet,
|
|
5257
|
-
value: -
|
|
5261
|
+
value: -Number(this.sourceWallet.balance)
|
|
5262
|
+
}));
|
|
5263
|
+
this.addAtom(Atom.create({
|
|
5264
|
+
isotope: "V",
|
|
5265
|
+
wallet: burnWallet,
|
|
5266
|
+
value: amount,
|
|
5267
|
+
metaType: "walletBundle",
|
|
5268
|
+
metaId: burnWallet.bundle
|
|
5258
5269
|
}));
|
|
5259
5270
|
this.addAtom(Atom.create({
|
|
5260
5271
|
isotope: "V",
|
|
@@ -5916,6 +5927,20 @@ var GraphQLClient = class {
|
|
|
5916
5927
|
encrypt: this.cipherLink
|
|
5917
5928
|
});
|
|
5918
5929
|
}
|
|
5930
|
+
/**
|
|
5931
|
+
* F-8a (cross-SDK parity, 2026-06-03): re-point the GraphQL-subscription WebSocket
|
|
5932
|
+
* without changing the HTTP endpoint. `setUri` only updates `serverUri`, leaving the
|
|
5933
|
+
* subscription socket pinned to whatever was passed at construction; this lets a
|
|
5934
|
+
* caller re-derive the socket when the endpoint changes.
|
|
5935
|
+
*/
|
|
5936
|
+
setSocketUri(socketUri) {
|
|
5937
|
+
this.socketUri = socketUri;
|
|
5938
|
+
this.$__client = this.createUrqlClient({
|
|
5939
|
+
serverUri: this.serverUri,
|
|
5940
|
+
socket: { socketUri },
|
|
5941
|
+
encrypt: this.cipherLink
|
|
5942
|
+
});
|
|
5943
|
+
}
|
|
5919
5944
|
socketDisconnect() {
|
|
5920
5945
|
if (this.socketUri) {
|
|
5921
5946
|
this.unsubscribeAll();
|
|
@@ -8816,9 +8841,91 @@ var QueryMetaTypeViaMolecule = class extends Query {
|
|
|
8816
8841
|
}
|
|
8817
8842
|
};
|
|
8818
8843
|
|
|
8844
|
+
// src/response/ResponseEmbeddingStatus.ts
|
|
8845
|
+
init_Response();
|
|
8846
|
+
var ResponseEmbeddingStatus = class extends exports.Response {
|
|
8847
|
+
/**
|
|
8848
|
+
* Class constructor
|
|
8849
|
+
*/
|
|
8850
|
+
constructor({
|
|
8851
|
+
query,
|
|
8852
|
+
json
|
|
8853
|
+
}) {
|
|
8854
|
+
super({
|
|
8855
|
+
query,
|
|
8856
|
+
json,
|
|
8857
|
+
dataKey: "data.embeddingStatus"
|
|
8858
|
+
});
|
|
8859
|
+
}
|
|
8860
|
+
/**
|
|
8861
|
+
* Returns the array of embedding status items, or null if empty.
|
|
8862
|
+
*/
|
|
8863
|
+
payload() {
|
|
8864
|
+
const items = this.data();
|
|
8865
|
+
if (!items || !Array.isArray(items) || items.length === 0) {
|
|
8866
|
+
return null;
|
|
8867
|
+
}
|
|
8868
|
+
return items;
|
|
8869
|
+
}
|
|
8870
|
+
};
|
|
8871
|
+
var QueryEmbeddingStatus = class extends Query {
|
|
8872
|
+
/**
|
|
8873
|
+
* Create new QueryEmbeddingStatus instance
|
|
8874
|
+
*/
|
|
8875
|
+
constructor(graphQLClient, knishIOClient) {
|
|
8876
|
+
super(graphQLClient, knishIOClient);
|
|
8877
|
+
this.$__query = core.gql`query( $metaType: String, $metaId: String, $instances: [EmbeddingStatusInput!] ) {
|
|
8878
|
+
embeddingStatus( metaType: $metaType, metaId: $metaId, instances: $instances ) {
|
|
8879
|
+
metaType,
|
|
8880
|
+
metaId,
|
|
8881
|
+
state,
|
|
8882
|
+
totalMetas,
|
|
8883
|
+
embeddedCount,
|
|
8884
|
+
embeddedAt,
|
|
8885
|
+
model
|
|
8886
|
+
}
|
|
8887
|
+
}`;
|
|
8888
|
+
}
|
|
8889
|
+
/**
|
|
8890
|
+
* Builds a GraphQL-friendly variables object for embedding status queries.
|
|
8891
|
+
*
|
|
8892
|
+
* Single mode: createVariables({ metaType: 'product', metaId: 'SKU-001' })
|
|
8893
|
+
* Bulk mode: createVariables({ instances: [{ metaType: 'product', metaId: 'SKU-001' }, ...] })
|
|
8894
|
+
*/
|
|
8895
|
+
static createVariables({
|
|
8896
|
+
metaType = null,
|
|
8897
|
+
metaId = null,
|
|
8898
|
+
instances = null
|
|
8899
|
+
} = {}) {
|
|
8900
|
+
const variables = {};
|
|
8901
|
+
if (instances && instances.length > 0) {
|
|
8902
|
+
variables.instances = instances;
|
|
8903
|
+
}
|
|
8904
|
+
if (metaType) {
|
|
8905
|
+
variables.metaType = metaType;
|
|
8906
|
+
}
|
|
8907
|
+
if (metaId) {
|
|
8908
|
+
variables.metaId = metaId;
|
|
8909
|
+
}
|
|
8910
|
+
return variables;
|
|
8911
|
+
}
|
|
8912
|
+
/**
|
|
8913
|
+
* Returns a Response object
|
|
8914
|
+
*/
|
|
8915
|
+
createResponse(json) {
|
|
8916
|
+
return new ResponseEmbeddingStatus({
|
|
8917
|
+
query: this,
|
|
8918
|
+
json
|
|
8919
|
+
});
|
|
8920
|
+
}
|
|
8921
|
+
};
|
|
8922
|
+
|
|
8819
8923
|
// src/response/ResponseProposeMolecule.ts
|
|
8820
8924
|
init_Response();
|
|
8821
8925
|
init_Dot();
|
|
8926
|
+
init_MolecularHashMismatchException();
|
|
8927
|
+
init_SignatureMismatchException();
|
|
8928
|
+
init_AtomIndexException();
|
|
8822
8929
|
var ResponseProposeMolecule = class extends exports.Response {
|
|
8823
8930
|
$__clientMolecule;
|
|
8824
8931
|
/**
|
|
@@ -8890,6 +8997,47 @@ var ResponseProposeMolecule = class extends exports.Response {
|
|
|
8890
8997
|
reason() {
|
|
8891
8998
|
return exports.Dot.get(this.data(), "reason", "Invalid response from server");
|
|
8892
8999
|
}
|
|
9000
|
+
/**
|
|
9001
|
+
* Map this rejection to a typed SDK exception when the failure mode is one
|
|
9002
|
+
* we know about. Returns null on success or for rejections we don't have a
|
|
9003
|
+
* typed class for.
|
|
9004
|
+
*
|
|
9005
|
+
* This is the single place pattern-matching against validator reason strings
|
|
9006
|
+
* lives — consumers (KnishIOClient cache invalidation, callers needing to
|
|
9007
|
+
* branch on failure mode) can `instanceof`-switch on the result instead.
|
|
9008
|
+
* Future validator versions can rephrase reasons (or populate a structured
|
|
9009
|
+
* field in the response payload) without breaking callers.
|
|
9010
|
+
*/
|
|
9011
|
+
toException() {
|
|
9012
|
+
if (this.success()) return null;
|
|
9013
|
+
const reason = this.reason();
|
|
9014
|
+
const lc = reason.toLowerCase();
|
|
9015
|
+
if (/molecularhashmismatch|hash.*mismatch/.test(lc)) {
|
|
9016
|
+
return new exports.MolecularHashMismatchException(reason, {
|
|
9017
|
+
details: { reason },
|
|
9018
|
+
code: "HASH_MISMATCH"
|
|
9019
|
+
});
|
|
9020
|
+
}
|
|
9021
|
+
if (/ots.*position.*reuse|position.*already.*used|ots.*verification/.test(lc)) {
|
|
9022
|
+
return new exports.SignatureMismatchException(reason, {
|
|
9023
|
+
details: { reason },
|
|
9024
|
+
code: "OTS_VERIFICATION_FAILED"
|
|
9025
|
+
});
|
|
9026
|
+
}
|
|
9027
|
+
if (/continuid.*chain|previousposition|chain.*violation/.test(lc)) {
|
|
9028
|
+
return new exports.AtomIndexException(reason, {
|
|
9029
|
+
details: { reason },
|
|
9030
|
+
code: "INDEX_CONFLICT"
|
|
9031
|
+
});
|
|
9032
|
+
}
|
|
9033
|
+
if (/signature.*verification|signature.*invalid/.test(lc)) {
|
|
9034
|
+
return new exports.SignatureMismatchException(reason, {
|
|
9035
|
+
details: { reason },
|
|
9036
|
+
code: "VERIFICATION_FAILED"
|
|
9037
|
+
});
|
|
9038
|
+
}
|
|
9039
|
+
return null;
|
|
9040
|
+
}
|
|
8893
9041
|
/**
|
|
8894
9042
|
* Returns payload object
|
|
8895
9043
|
* Matches JavaScript SDK payload method exactly
|
|
@@ -9927,6 +10075,13 @@ var KnishIOClient = class {
|
|
|
9927
10075
|
$__remainderWallet = null;
|
|
9928
10076
|
lastMoleculeQuery = null;
|
|
9929
10077
|
abortControllers = /* @__PURE__ */ new Map();
|
|
10078
|
+
$__capabilityCache = {};
|
|
10079
|
+
// Promise-chain mutex serializing MutationProposeMolecule submissions on this
|
|
10080
|
+
// client. Without it, concurrent createMolecule() calls both query the same
|
|
10081
|
+
// ContinuID position and both sign with it — the second is rejected with
|
|
10082
|
+
// OTS position reuse. Auth-token flow (MutationRequestAuthorization) inherits
|
|
10083
|
+
// from MutationProposeMolecule so it's covered by the same lock.
|
|
10084
|
+
$__moleculeChain = Promise.resolve();
|
|
9930
10085
|
/**
|
|
9931
10086
|
* Enhanced constructor with standardized configuration validation (Phase 2 Enhancement)
|
|
9932
10087
|
*/
|
|
@@ -10051,6 +10206,7 @@ var KnishIOClient = class {
|
|
|
10051
10206
|
this.$__authToken = null;
|
|
10052
10207
|
this.$__remainderWallet = null;
|
|
10053
10208
|
this.lastMoleculeQuery = null;
|
|
10209
|
+
this.$__capabilityCache = {};
|
|
10054
10210
|
}
|
|
10055
10211
|
/**
|
|
10056
10212
|
* Get the GraphQL client
|
|
@@ -10071,6 +10227,19 @@ var KnishIOClient = class {
|
|
|
10071
10227
|
this.$__client.setUri(this.getRandomUri());
|
|
10072
10228
|
}
|
|
10073
10229
|
}
|
|
10230
|
+
/**
|
|
10231
|
+
* Sets the WebSocket (subscription) endpoint for this session.
|
|
10232
|
+
*
|
|
10233
|
+
* F-8a (cross-SDK parity, 2026-06-03): `setUri` only updates the HTTP endpoint; the
|
|
10234
|
+
* subscription socket is built once from the `socket.socketUri` passed at
|
|
10235
|
+
* construction. This lets a caller re-point the socket when the endpoint changes
|
|
10236
|
+
* (mirrors the JS SDK's `setSocketUri`).
|
|
10237
|
+
*/
|
|
10238
|
+
setSocketUri(socketUri) {
|
|
10239
|
+
if (this.$__client && "setSocketUri" in this.$__client) {
|
|
10240
|
+
this.$__client.setSocketUri(socketUri);
|
|
10241
|
+
}
|
|
10242
|
+
}
|
|
10074
10243
|
/**
|
|
10075
10244
|
* Gets the Knish.IO server URIs
|
|
10076
10245
|
*/
|
|
@@ -10144,6 +10313,17 @@ var KnishIOClient = class {
|
|
|
10144
10313
|
this.log("info", "KnishIOClient::createMolecule() - Creating a new molecule...");
|
|
10145
10314
|
secret = secret || this.getSecret();
|
|
10146
10315
|
bundle = bundle || this.getBundle();
|
|
10316
|
+
let continuIdPosition = null;
|
|
10317
|
+
if (sourceWallet && sourceWallet.token !== "USER") {
|
|
10318
|
+
if (this.lastMoleculeQuery && this.getRemainderWallet() && this.getRemainderWallet()?.token === "USER" && this.lastMoleculeQuery.response() && this.lastMoleculeQuery.response()?.success()) {
|
|
10319
|
+
continuIdPosition = this.getRemainderWallet()?.position || null;
|
|
10320
|
+
this.log("info", `KnishIOClient::createMolecule() - Captured USER ContinuID position ${continuIdPosition?.substring(0, 16)}... for non-USER source wallet`);
|
|
10321
|
+
} else {
|
|
10322
|
+
const userWallet = await this.getSourceWallet();
|
|
10323
|
+
continuIdPosition = userWallet?.position || null;
|
|
10324
|
+
this.log("info", `KnishIOClient::createMolecule() - Queried USER ContinuID position ${continuIdPosition?.substring(0, 16)}... for non-USER source wallet`);
|
|
10325
|
+
}
|
|
10326
|
+
}
|
|
10147
10327
|
if (!sourceWallet && this.lastMoleculeQuery && this.getRemainderWallet()?.token === "USER" && this.lastMoleculeQuery.response() && this.lastMoleculeQuery.response()?.success()) {
|
|
10148
10328
|
sourceWallet = this.getRemainderWallet();
|
|
10149
10329
|
this.log("info", `KnishIOClient::createMolecule() - Using carry-forward remainder wallet at position ${sourceWallet?.position?.substring(0, 16)}...`);
|
|
@@ -10163,7 +10343,8 @@ var KnishIOClient = class {
|
|
|
10163
10343
|
sourceWallet,
|
|
10164
10344
|
remainderWallet: this.getRemainderWallet(),
|
|
10165
10345
|
cellSlug: this.getCellSlug(),
|
|
10166
|
-
version: this.getServerSdkVersion()
|
|
10346
|
+
version: this.getServerSdkVersion(),
|
|
10347
|
+
continuIdPosition
|
|
10167
10348
|
});
|
|
10168
10349
|
}
|
|
10169
10350
|
/**
|
|
@@ -10182,6 +10363,23 @@ var KnishIOClient = class {
|
|
|
10182
10363
|
this.lastMoleculeQuery = mutation;
|
|
10183
10364
|
return mutation;
|
|
10184
10365
|
}
|
|
10366
|
+
/**
|
|
10367
|
+
* Serializes the given async work behind a per-client promise chain. Used to
|
|
10368
|
+
* guarantee that at most one MutationProposeMolecule submission runs at a
|
|
10369
|
+
* time on this client — query position, sign, submit, observe response must
|
|
10370
|
+
* complete before the next one starts, or two callers race for the same OTS
|
|
10371
|
+
* position and the second gets rejected.
|
|
10372
|
+
*
|
|
10373
|
+
* `.then(fn, fn)` runs fn whether the previous holder resolved or rejected;
|
|
10374
|
+
* the queue's `.catch` swallows the rejection so a single failure doesn't
|
|
10375
|
+
* poison every subsequent caller, while the rejection still propagates to
|
|
10376
|
+
* the caller whose fn threw.
|
|
10377
|
+
*/
|
|
10378
|
+
withMoleculeLock(fn) {
|
|
10379
|
+
const result = this.$__moleculeChain.then(fn, fn);
|
|
10380
|
+
this.$__moleculeChain = result.catch(() => void 0);
|
|
10381
|
+
return result;
|
|
10382
|
+
}
|
|
10185
10383
|
/**
|
|
10186
10384
|
* Executes a query or mutation
|
|
10187
10385
|
*/
|
|
@@ -10194,8 +10392,34 @@ var KnishIOClient = class {
|
|
|
10194
10392
|
encrypt: this.$__encrypt
|
|
10195
10393
|
});
|
|
10196
10394
|
}
|
|
10395
|
+
if (query instanceof MutationProposeMolecule) {
|
|
10396
|
+
return await this.withMoleculeLock(async () => {
|
|
10397
|
+
const response = await query.execute({ variables: variables || {} });
|
|
10398
|
+
this.handlePositionDrift(response);
|
|
10399
|
+
return response;
|
|
10400
|
+
});
|
|
10401
|
+
}
|
|
10197
10402
|
return await query.execute({ variables: variables || {} });
|
|
10198
10403
|
}
|
|
10404
|
+
/**
|
|
10405
|
+
* When a ProposeMolecule submission is rejected for a position-related
|
|
10406
|
+
* reason (OTS reuse, ContinuID chain violation, molecular hash mismatch),
|
|
10407
|
+
* the cached remainder wallet and lastMoleculeQuery are stale — the
|
|
10408
|
+
* validator's chain has advanced past what we know. Clear them so the next
|
|
10409
|
+
* createMolecule call re-queries queryContinuId for the authoritative
|
|
10410
|
+
* position. Other failure modes (network, malformed meta, bad signature
|
|
10411
|
+
* bytes) don't imply drift; leave cached state alone.
|
|
10412
|
+
*/
|
|
10413
|
+
handlePositionDrift(response) {
|
|
10414
|
+
if (!(response instanceof ResponseProposeMolecule)) return;
|
|
10415
|
+
const exc = response.toException();
|
|
10416
|
+
if (!exc) return;
|
|
10417
|
+
if (exc instanceof exports.MolecularHashMismatchException || exc instanceof exports.AtomIndexException || exc instanceof exports.SignatureMismatchException && exc.code === "OTS_VERIFICATION_FAILED") {
|
|
10418
|
+
this.$__remainderWallet = null;
|
|
10419
|
+
this.lastMoleculeQuery = null;
|
|
10420
|
+
this.log("warn", `KnishIOClient::executeQuery() - position drift detected (${exc.name}/${exc.code}); cleared cached remainder wallet`);
|
|
10421
|
+
}
|
|
10422
|
+
}
|
|
10199
10423
|
/**
|
|
10200
10424
|
* Sets the secret for this session
|
|
10201
10425
|
*/
|
|
@@ -10575,6 +10799,63 @@ var KnishIOClient = class {
|
|
|
10575
10799
|
}
|
|
10576
10800
|
return response;
|
|
10577
10801
|
}
|
|
10802
|
+
/**
|
|
10803
|
+
* Probes the connected server to check whether it supports a named root query field.
|
|
10804
|
+
* Result is cached per URI so the network round-trip happens at most once per URI.
|
|
10805
|
+
*
|
|
10806
|
+
* Uses GraphQL introspection which is universally supported by spec-compliant servers.
|
|
10807
|
+
*
|
|
10808
|
+
* @param fieldName - The root Query field name to check (e.g. 'embeddingStatus')
|
|
10809
|
+
* @returns true if the server schema includes the field, false otherwise
|
|
10810
|
+
*/
|
|
10811
|
+
async hasQueryField(fieldName) {
|
|
10812
|
+
const uri = this.$__client.getUri();
|
|
10813
|
+
const cacheKey = `${uri}::${fieldName}`;
|
|
10814
|
+
if (typeof this.$__capabilityCache[cacheKey] === "boolean") {
|
|
10815
|
+
return this.$__capabilityCache[cacheKey];
|
|
10816
|
+
}
|
|
10817
|
+
try {
|
|
10818
|
+
const result = await this.$__client.query({
|
|
10819
|
+
query: "{ __schema { queryType { fields { name } } } }",
|
|
10820
|
+
variables: {}
|
|
10821
|
+
});
|
|
10822
|
+
const data = result?.data;
|
|
10823
|
+
const fields = data?.__schema?.queryType?.fields || [];
|
|
10824
|
+
const supported = fields.some((f) => f.name === fieldName);
|
|
10825
|
+
this.$__capabilityCache[cacheKey] = supported;
|
|
10826
|
+
return supported;
|
|
10827
|
+
} catch (err) {
|
|
10828
|
+
this.log("warn", `KnishIOClient::hasQueryField() - Capability probe for '${fieldName}' failed: ${err.message}`);
|
|
10829
|
+
this.$__capabilityCache[cacheKey] = false;
|
|
10830
|
+
return false;
|
|
10831
|
+
}
|
|
10832
|
+
}
|
|
10833
|
+
/**
|
|
10834
|
+
* Queries embedding status for one or more meta instances (DataBraid observability).
|
|
10835
|
+
*
|
|
10836
|
+
* If the connected server does not support the embeddingStatus query,
|
|
10837
|
+
* returns null without throwing an error (graceful degradation).
|
|
10838
|
+
*
|
|
10839
|
+
* Single mode: queryEmbeddingStatus({ metaType: 'product', metaId: 'SKU-001' })
|
|
10840
|
+
* Bulk mode: queryEmbeddingStatus({ instances: [{ metaType: 'product', metaId: 'SKU-001' }, ...] })
|
|
10841
|
+
*
|
|
10842
|
+
* @returns Response with payload(), or null if the server does not support this query
|
|
10843
|
+
*/
|
|
10844
|
+
async queryEmbeddingStatus({
|
|
10845
|
+
metaType = null,
|
|
10846
|
+
metaId = null,
|
|
10847
|
+
instances = null
|
|
10848
|
+
}) {
|
|
10849
|
+
this.log("info", `KnishIOClient::queryEmbeddingStatus() - Checking embedding status for metaType: ${metaType || "(bulk)"}...`);
|
|
10850
|
+
const supported = await this.hasQueryField("embeddingStatus");
|
|
10851
|
+
if (!supported) {
|
|
10852
|
+
this.log("warn", "KnishIOClient::queryEmbeddingStatus() - Server does not support embeddingStatus query. Returning null.");
|
|
10853
|
+
return null;
|
|
10854
|
+
}
|
|
10855
|
+
const query = this.createQuery(QueryEmbeddingStatus);
|
|
10856
|
+
const variables = QueryEmbeddingStatus.createVariables({ metaType, metaId, instances });
|
|
10857
|
+
return this.executeQuery(query, variables);
|
|
10858
|
+
}
|
|
10578
10859
|
/**
|
|
10579
10860
|
* Query cascading meta instances for batchId
|
|
10580
10861
|
*/
|
|
@@ -10894,8 +11175,10 @@ var KnishIOClient = class {
|
|
|
10894
11175
|
amount: amount || 0
|
|
10895
11176
|
});
|
|
10896
11177
|
}
|
|
11178
|
+
const remainderWallet = sourceWallet.createRemainder(this.getSecret());
|
|
10897
11179
|
const molecule = await this.createMolecule({
|
|
10898
|
-
sourceWallet
|
|
11180
|
+
sourceWallet,
|
|
11181
|
+
remainderWallet
|
|
10899
11182
|
});
|
|
10900
11183
|
const mutation = await this.createMoleculeMutation({
|
|
10901
11184
|
mutationClass: MutationTransferTokens,
|
|
@@ -11191,7 +11474,15 @@ var KnishIOClient = class {
|
|
|
11191
11474
|
amount
|
|
11192
11475
|
});
|
|
11193
11476
|
}
|
|
11194
|
-
const
|
|
11477
|
+
const remainderWallet = sourceWallet.createRemainder(this.getSecret());
|
|
11478
|
+
const molecule = await this.createMolecule({
|
|
11479
|
+
sourceWallet,
|
|
11480
|
+
remainderWallet
|
|
11481
|
+
});
|
|
11482
|
+
const mutation = await this.createMoleculeMutation({
|
|
11483
|
+
mutationClass: MutationDepositBufferToken,
|
|
11484
|
+
molecule
|
|
11485
|
+
});
|
|
11195
11486
|
await mutation.fillMolecule({
|
|
11196
11487
|
amount: typeof amount === "string" ? Number(amount) : amount,
|
|
11197
11488
|
tradeRates
|
|
@@ -11556,6 +11847,7 @@ exports.QueryAtom = QueryAtom;
|
|
|
11556
11847
|
exports.QueryBalance = QueryBalance;
|
|
11557
11848
|
exports.QueryBatch = QueryBatch;
|
|
11558
11849
|
exports.QueryContinuId = QueryContinuId;
|
|
11850
|
+
exports.QueryEmbeddingStatus = QueryEmbeddingStatus;
|
|
11559
11851
|
exports.QueryMetaType = QueryMetaType;
|
|
11560
11852
|
exports.QueryMetaTypeViaAtom = QueryMetaTypeViaAtom;
|
|
11561
11853
|
exports.QueryWalletBundle = QueryWalletBundle;
|
|
@@ -11567,6 +11859,7 @@ exports.ResponseContinuId = ResponseContinuId;
|
|
|
11567
11859
|
exports.ResponseCreateMeta = ResponseCreateMeta;
|
|
11568
11860
|
exports.ResponseCreateToken = ResponseCreateToken;
|
|
11569
11861
|
exports.ResponseCreateWallet = ResponseCreateWallet;
|
|
11862
|
+
exports.ResponseEmbeddingStatus = ResponseEmbeddingStatus;
|
|
11570
11863
|
exports.ResponseMetaType = ResponseMetaType;
|
|
11571
11864
|
exports.ResponseMetaTypeViaAtom = ResponseMetaTypeViaAtom;
|
|
11572
11865
|
exports.ResponsePeering = ResponsePeering;
|