@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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wishknish/knishio-client-ts",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.8",
|
|
4
4
|
"productName": "Knish.IO TypeScript SDK Client",
|
|
5
5
|
"description": "TypeScript implementation of the Knish.IO SDK to consume Knish.IO GraphQL APIs with enhanced type safety.",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
package/src/KnishIOClient.ts
CHANGED
|
@@ -84,6 +84,7 @@ import QueryUserActivity from '@/query/QueryUserActivity'
|
|
|
84
84
|
import QueryToken from '@/query/QueryToken'
|
|
85
85
|
import QueryMetaTypeViaAtom from '@/query/QueryMetaTypeViaAtom'
|
|
86
86
|
import QueryMetaTypeViaMolecule from '@/query/QueryMetaTypeViaMolecule'
|
|
87
|
+
import QueryEmbeddingStatus from '@/query/QueryEmbeddingStatus'
|
|
87
88
|
|
|
88
89
|
// Mutation imports
|
|
89
90
|
import MutationCreateToken from '@/mutation/MutationCreateToken'
|
|
@@ -102,6 +103,10 @@ import MutationRequestAuthorizationGuest from '@/mutation/MutationRequestAuthori
|
|
|
102
103
|
import MutationLinkIdentifier from '@/mutation/MutationLinkIdentifier'
|
|
103
104
|
import MutationPeering from '@/mutation/MutationPeering'
|
|
104
105
|
import MutationAppendRequest from '@/mutation/MutationAppendRequest'
|
|
106
|
+
import MutationProposeMolecule from '@/mutation/MutationProposeMolecule'
|
|
107
|
+
|
|
108
|
+
// Response imports
|
|
109
|
+
import ResponseProposeMolecule from '@/response/ResponseProposeMolecule'
|
|
105
110
|
|
|
106
111
|
// Subscribe imports
|
|
107
112
|
import CreateMoleculeSubscribe from '@/subscribe/CreateMoleculeSubscribe'
|
|
@@ -116,7 +121,10 @@ import {
|
|
|
116
121
|
TransferBalanceException,
|
|
117
122
|
WalletShadowException,
|
|
118
123
|
StackableUnitAmountException,
|
|
119
|
-
AuthorizationRejectedException
|
|
124
|
+
AuthorizationRejectedException,
|
|
125
|
+
MolecularHashMismatchException,
|
|
126
|
+
SignatureMismatchException,
|
|
127
|
+
AtomIndexException
|
|
120
128
|
} from '@/exception'
|
|
121
129
|
|
|
122
130
|
// Type imports
|
|
@@ -150,6 +158,13 @@ export default class KnishIOClient {
|
|
|
150
158
|
private $__remainderWallet: Wallet | null = null
|
|
151
159
|
private lastMoleculeQuery: Mutation | null = null
|
|
152
160
|
private abortControllers: Map<string, AbortController> = new Map()
|
|
161
|
+
private $__capabilityCache: Record<string, boolean> = {}
|
|
162
|
+
// Promise-chain mutex serializing MutationProposeMolecule submissions on this
|
|
163
|
+
// client. Without it, concurrent createMolecule() calls both query the same
|
|
164
|
+
// ContinuID position and both sign with it — the second is rejected with
|
|
165
|
+
// OTS position reuse. Auth-token flow (MutationRequestAuthorization) inherits
|
|
166
|
+
// from MutationProposeMolecule so it's covered by the same lock.
|
|
167
|
+
private $__moleculeChain: Promise<unknown> = Promise.resolve()
|
|
153
168
|
|
|
154
169
|
/**
|
|
155
170
|
* Enhanced constructor with standardized configuration validation (Phase 2 Enhancement)
|
|
@@ -320,6 +335,7 @@ export default class KnishIOClient {
|
|
|
320
335
|
this.$__authToken = null
|
|
321
336
|
this.$__remainderWallet = null
|
|
322
337
|
this.lastMoleculeQuery = null
|
|
338
|
+
this.$__capabilityCache = {}
|
|
323
339
|
}
|
|
324
340
|
|
|
325
341
|
/**
|
|
@@ -344,6 +360,20 @@ export default class KnishIOClient {
|
|
|
344
360
|
}
|
|
345
361
|
}
|
|
346
362
|
|
|
363
|
+
/**
|
|
364
|
+
* Sets the WebSocket (subscription) endpoint for this session.
|
|
365
|
+
*
|
|
366
|
+
* F-8a (cross-SDK parity, 2026-06-03): `setUri` only updates the HTTP endpoint; the
|
|
367
|
+
* subscription socket is built once from the `socket.socketUri` passed at
|
|
368
|
+
* construction. This lets a caller re-point the socket when the endpoint changes
|
|
369
|
+
* (mirrors the JS SDK's `setSocketUri`).
|
|
370
|
+
*/
|
|
371
|
+
setSocketUri(socketUri: string): void {
|
|
372
|
+
if (this.$__client && 'setSocketUri' in this.$__client) {
|
|
373
|
+
(this.$__client as any).setSocketUri(socketUri)
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
347
377
|
/**
|
|
348
378
|
* Gets the Knish.IO server URIs
|
|
349
379
|
*/
|
|
@@ -433,6 +463,28 @@ export default class KnishIOClient {
|
|
|
433
463
|
secret = secret || this.getSecret()
|
|
434
464
|
bundle = bundle || this.getBundle()
|
|
435
465
|
|
|
466
|
+
// For non-USER source wallets (V/B isotopes), capture the current USER
|
|
467
|
+
// ContinuID position BEFORE overwriting the client's remainder wallet.
|
|
468
|
+
// This position is needed by addContinuIdAtom() for previousPosition metadata.
|
|
469
|
+
let continuIdPosition: string | null = null
|
|
470
|
+
if (sourceWallet && sourceWallet.token !== 'USER') {
|
|
471
|
+
if (this.lastMoleculeQuery &&
|
|
472
|
+
this.getRemainderWallet() &&
|
|
473
|
+
this.getRemainderWallet()?.token === 'USER' &&
|
|
474
|
+
this.lastMoleculeQuery.response() &&
|
|
475
|
+
this.lastMoleculeQuery.response()?.success()
|
|
476
|
+
) {
|
|
477
|
+
// Carry-forward: use last successful USER remainder wallet position
|
|
478
|
+
continuIdPosition = this.getRemainderWallet()?.position || null
|
|
479
|
+
this.log('info', `KnishIOClient::createMolecule() - Captured USER ContinuID position ${continuIdPosition?.substring(0, 16)}... for non-USER source wallet`)
|
|
480
|
+
} else {
|
|
481
|
+
// Query server for current ContinuID position
|
|
482
|
+
const userWallet = await this.getSourceWallet()
|
|
483
|
+
continuIdPosition = userWallet?.position || null
|
|
484
|
+
this.log('info', `KnishIOClient::createMolecule() - Queried USER ContinuID position ${continuIdPosition?.substring(0, 16)}... for non-USER source wallet`)
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
436
488
|
// Sets the source wallet as the last remainder wallet (to maintain ContinuID)
|
|
437
489
|
if (!sourceWallet &&
|
|
438
490
|
this.lastMoleculeQuery &&
|
|
@@ -463,7 +515,8 @@ export default class KnishIOClient {
|
|
|
463
515
|
sourceWallet,
|
|
464
516
|
remainderWallet: this.getRemainderWallet()!,
|
|
465
517
|
cellSlug: this.getCellSlug(),
|
|
466
|
-
version: this.getServerSdkVersion()
|
|
518
|
+
version: this.getServerSdkVersion(),
|
|
519
|
+
continuIdPosition
|
|
467
520
|
})
|
|
468
521
|
}
|
|
469
522
|
|
|
@@ -494,6 +547,24 @@ export default class KnishIOClient {
|
|
|
494
547
|
return mutation
|
|
495
548
|
}
|
|
496
549
|
|
|
550
|
+
/**
|
|
551
|
+
* Serializes the given async work behind a per-client promise chain. Used to
|
|
552
|
+
* guarantee that at most one MutationProposeMolecule submission runs at a
|
|
553
|
+
* time on this client — query position, sign, submit, observe response must
|
|
554
|
+
* complete before the next one starts, or two callers race for the same OTS
|
|
555
|
+
* position and the second gets rejected.
|
|
556
|
+
*
|
|
557
|
+
* `.then(fn, fn)` runs fn whether the previous holder resolved or rejected;
|
|
558
|
+
* the queue's `.catch` swallows the rejection so a single failure doesn't
|
|
559
|
+
* poison every subsequent caller, while the rejection still propagates to
|
|
560
|
+
* the caller whose fn threw.
|
|
561
|
+
*/
|
|
562
|
+
private withMoleculeLock<T>(fn: () => Promise<T>): Promise<T> {
|
|
563
|
+
const result = (this.$__moleculeChain as Promise<unknown>).then(fn, fn) as Promise<T>
|
|
564
|
+
this.$__moleculeChain = result.catch(() => undefined)
|
|
565
|
+
return result
|
|
566
|
+
}
|
|
567
|
+
|
|
497
568
|
/**
|
|
498
569
|
* Executes a query or mutation
|
|
499
570
|
*/
|
|
@@ -509,10 +580,42 @@ export default class KnishIOClient {
|
|
|
509
580
|
})
|
|
510
581
|
}
|
|
511
582
|
|
|
583
|
+
if (query instanceof MutationProposeMolecule) {
|
|
584
|
+
return await this.withMoleculeLock(async () => {
|
|
585
|
+
const response = await query.execute({ variables: variables || {} })
|
|
586
|
+
this.handlePositionDrift(response)
|
|
587
|
+
return response
|
|
588
|
+
})
|
|
589
|
+
}
|
|
590
|
+
|
|
512
591
|
// Execute the query
|
|
513
592
|
return await query.execute({ variables: variables || {} })
|
|
514
593
|
}
|
|
515
594
|
|
|
595
|
+
/**
|
|
596
|
+
* When a ProposeMolecule submission is rejected for a position-related
|
|
597
|
+
* reason (OTS reuse, ContinuID chain violation, molecular hash mismatch),
|
|
598
|
+
* the cached remainder wallet and lastMoleculeQuery are stale — the
|
|
599
|
+
* validator's chain has advanced past what we know. Clear them so the next
|
|
600
|
+
* createMolecule call re-queries queryContinuId for the authoritative
|
|
601
|
+
* position. Other failure modes (network, malformed meta, bad signature
|
|
602
|
+
* bytes) don't imply drift; leave cached state alone.
|
|
603
|
+
*/
|
|
604
|
+
private handlePositionDrift(response: Response | null): void {
|
|
605
|
+
if (!(response instanceof ResponseProposeMolecule)) return
|
|
606
|
+
const exc = response.toException()
|
|
607
|
+
if (!exc) return
|
|
608
|
+
if (
|
|
609
|
+
exc instanceof MolecularHashMismatchException ||
|
|
610
|
+
exc instanceof AtomIndexException ||
|
|
611
|
+
(exc instanceof SignatureMismatchException && exc.code === 'OTS_VERIFICATION_FAILED')
|
|
612
|
+
) {
|
|
613
|
+
this.$__remainderWallet = null
|
|
614
|
+
this.lastMoleculeQuery = null
|
|
615
|
+
this.log('warn', `KnishIOClient::executeQuery() - position drift detected (${exc.name}/${exc.code}); cleared cached remainder wallet`)
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
516
619
|
/**
|
|
517
620
|
* Sets the secret for this session
|
|
518
621
|
*/
|
|
@@ -1037,6 +1140,76 @@ export default class KnishIOClient {
|
|
|
1037
1140
|
return response
|
|
1038
1141
|
}
|
|
1039
1142
|
|
|
1143
|
+
/**
|
|
1144
|
+
* Probes the connected server to check whether it supports a named root query field.
|
|
1145
|
+
* Result is cached per URI so the network round-trip happens at most once per URI.
|
|
1146
|
+
*
|
|
1147
|
+
* Uses GraphQL introspection which is universally supported by spec-compliant servers.
|
|
1148
|
+
*
|
|
1149
|
+
* @param fieldName - The root Query field name to check (e.g. 'embeddingStatus')
|
|
1150
|
+
* @returns true if the server schema includes the field, false otherwise
|
|
1151
|
+
*/
|
|
1152
|
+
async hasQueryField(fieldName: string): Promise<boolean> {
|
|
1153
|
+
const uri = this.$__client.getUri()
|
|
1154
|
+
const cacheKey = `${uri}::${fieldName}`
|
|
1155
|
+
|
|
1156
|
+
if (typeof this.$__capabilityCache[cacheKey] === 'boolean') {
|
|
1157
|
+
return this.$__capabilityCache[cacheKey]!
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
try {
|
|
1161
|
+
const result = await this.$__client.query({
|
|
1162
|
+
query: '{ __schema { queryType { fields { name } } } }',
|
|
1163
|
+
variables: {}
|
|
1164
|
+
})
|
|
1165
|
+
|
|
1166
|
+
const data = result?.data as Record<string, any> | undefined
|
|
1167
|
+
const fields: Array<{ name: string }> = data?.__schema?.queryType?.fields || []
|
|
1168
|
+
const supported = fields.some((f: { name: string }) => f.name === fieldName)
|
|
1169
|
+
this.$__capabilityCache[cacheKey] = supported
|
|
1170
|
+
return supported
|
|
1171
|
+
} catch (err: any) {
|
|
1172
|
+
this.log('warn', `KnishIOClient::hasQueryField() - Capability probe for '${fieldName}' failed: ${err.message}`)
|
|
1173
|
+
this.$__capabilityCache[cacheKey] = false
|
|
1174
|
+
return false
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
* Queries embedding status for one or more meta instances (DataBraid observability).
|
|
1180
|
+
*
|
|
1181
|
+
* If the connected server does not support the embeddingStatus query,
|
|
1182
|
+
* returns null without throwing an error (graceful degradation).
|
|
1183
|
+
*
|
|
1184
|
+
* Single mode: queryEmbeddingStatus({ metaType: 'product', metaId: 'SKU-001' })
|
|
1185
|
+
* Bulk mode: queryEmbeddingStatus({ instances: [{ metaType: 'product', metaId: 'SKU-001' }, ...] })
|
|
1186
|
+
*
|
|
1187
|
+
* @returns Response with payload(), or null if the server does not support this query
|
|
1188
|
+
*/
|
|
1189
|
+
async queryEmbeddingStatus({
|
|
1190
|
+
metaType = null,
|
|
1191
|
+
metaId = null,
|
|
1192
|
+
instances = null
|
|
1193
|
+
}: {
|
|
1194
|
+
metaType?: string | null
|
|
1195
|
+
metaId?: string | null
|
|
1196
|
+
instances?: Array<{ metaType: string; metaId: string }> | null
|
|
1197
|
+
}): Promise<Response | null> {
|
|
1198
|
+
this.log('info', `KnishIOClient::queryEmbeddingStatus() - Checking embedding status for metaType: ${metaType || '(bulk)'}...`)
|
|
1199
|
+
|
|
1200
|
+
const supported = await this.hasQueryField('embeddingStatus')
|
|
1201
|
+
|
|
1202
|
+
if (!supported) {
|
|
1203
|
+
this.log('warn', 'KnishIOClient::queryEmbeddingStatus() - Server does not support embeddingStatus query. Returning null.')
|
|
1204
|
+
return null
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
const query = this.createQuery(QueryEmbeddingStatus)
|
|
1208
|
+
const variables = QueryEmbeddingStatus.createVariables({ metaType, metaId, instances })
|
|
1209
|
+
|
|
1210
|
+
return this.executeQuery(query, variables)
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1040
1213
|
/**
|
|
1041
1214
|
* Query cascading meta instances for batchId
|
|
1042
1215
|
*/
|
|
@@ -1496,9 +1669,13 @@ export default class KnishIOClient {
|
|
|
1496
1669
|
})
|
|
1497
1670
|
}
|
|
1498
1671
|
|
|
1499
|
-
// Create
|
|
1672
|
+
// Create remainder wallet from source (must be same token for V-isotope conservation)
|
|
1673
|
+
const remainderWallet = sourceWallet.createRemainder(this.getSecret())
|
|
1674
|
+
|
|
1675
|
+
// Create molecule with the token-specific source and remainder wallets
|
|
1500
1676
|
const molecule = await this.createMolecule({
|
|
1501
|
-
sourceWallet
|
|
1677
|
+
sourceWallet,
|
|
1678
|
+
remainderWallet
|
|
1502
1679
|
})
|
|
1503
1680
|
|
|
1504
1681
|
// Create a transfer to null address (burn)
|
|
@@ -1955,8 +2132,20 @@ export default class KnishIOClient {
|
|
|
1955
2132
|
})
|
|
1956
2133
|
}
|
|
1957
2134
|
|
|
2135
|
+
// Create remainder wallet from source (must be same token)
|
|
2136
|
+
const remainderWallet = sourceWallet.createRemainder(this.getSecret())
|
|
2137
|
+
|
|
2138
|
+
// Build the molecule with the token-specific source and remainder wallets
|
|
2139
|
+
const molecule = await this.createMolecule({
|
|
2140
|
+
sourceWallet,
|
|
2141
|
+
remainderWallet
|
|
2142
|
+
})
|
|
2143
|
+
|
|
1958
2144
|
// Create the molecule mutation
|
|
1959
|
-
const mutation = await this.createMoleculeMutation({
|
|
2145
|
+
const mutation = await this.createMoleculeMutation({
|
|
2146
|
+
mutationClass: MutationDepositBufferToken,
|
|
2147
|
+
molecule
|
|
2148
|
+
})
|
|
1960
2149
|
|
|
1961
2150
|
// Initialize the deposit buffer token mutation
|
|
1962
2151
|
await mutation.fillMolecule({
|
package/src/core/Molecule.ts
CHANGED
|
@@ -78,6 +78,7 @@ export default class Molecule {
|
|
|
78
78
|
public remainderWallet: Wallet | null
|
|
79
79
|
public atoms: Atom[]
|
|
80
80
|
public version: string | null | undefined
|
|
81
|
+
public continuIdPosition: string | null
|
|
81
82
|
public parentHashes: string[]
|
|
82
83
|
public local?: number
|
|
83
84
|
|
|
@@ -91,7 +92,8 @@ export default class Molecule {
|
|
|
91
92
|
sourceWallet = null,
|
|
92
93
|
remainderWallet = null,
|
|
93
94
|
cellSlug = null,
|
|
94
|
-
version = null
|
|
95
|
+
version = null,
|
|
96
|
+
continuIdPosition = null
|
|
95
97
|
}: {
|
|
96
98
|
secret?: string | null
|
|
97
99
|
bundle?: string | null
|
|
@@ -99,6 +101,7 @@ export default class Molecule {
|
|
|
99
101
|
remainderWallet?: Wallet | null
|
|
100
102
|
cellSlug?: string | null
|
|
101
103
|
version?: string | number | null
|
|
104
|
+
continuIdPosition?: string | null
|
|
102
105
|
} = {}) {
|
|
103
106
|
this.status = null
|
|
104
107
|
this.molecularHash = null
|
|
@@ -107,6 +110,7 @@ export default class Molecule {
|
|
|
107
110
|
this.secret = secret
|
|
108
111
|
this.bundle = bundle
|
|
109
112
|
this.sourceWallet = sourceWallet
|
|
113
|
+
this.continuIdPosition = continuIdPosition
|
|
110
114
|
this.atoms = []
|
|
111
115
|
this.parentHashes = []
|
|
112
116
|
|
|
@@ -209,8 +213,12 @@ export default class Molecule {
|
|
|
209
213
|
// ContinuID metadata for chain integrity validation
|
|
210
214
|
const continuIdMeta: Record<string, any> = {}
|
|
211
215
|
|
|
212
|
-
// previousPosition: the
|
|
213
|
-
|
|
216
|
+
// previousPosition: the current USER ContinuID position being consumed.
|
|
217
|
+
// For non-USER source wallets (V/B isotopes), use the explicitly passed
|
|
218
|
+
// continuIdPosition from createMolecule() instead of the TOKEN wallet position.
|
|
219
|
+
if (this.continuIdPosition) {
|
|
220
|
+
continuIdMeta.previousPosition = this.continuIdPosition
|
|
221
|
+
} else if (this.sourceWallet && this.sourceWallet.position) {
|
|
214
222
|
continuIdMeta.previousPosition = this.sourceWallet.position
|
|
215
223
|
}
|
|
216
224
|
|
|
@@ -251,14 +259,13 @@ export default class Molecule {
|
|
|
251
259
|
const atomMeta = new AtomMeta(meta)
|
|
252
260
|
atomMeta.addPolicy(policy)
|
|
253
261
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
262
|
+
// F-3 (cross-SDK parity, 2026-06-03): sign the policy (R-isotope) atom from the
|
|
263
|
+
// established ContinuID source wallet, NOT a freshly-derived Wallet.create() at a
|
|
264
|
+
// random position. As the signing atom in createPolicy(), a fresh-wallet position
|
|
265
|
+
// is unknown to the validator → "ContinuID chain validation failed: signing
|
|
266
|
+
// position … not found as wallet". Mirrors createRule(), which uses this.sourceWallet.
|
|
260
267
|
this.addAtom(Atom.create({
|
|
261
|
-
wallet
|
|
268
|
+
wallet: this.sourceWallet!,
|
|
262
269
|
isotope: 'R',
|
|
263
270
|
metaType,
|
|
264
271
|
metaId,
|
|
@@ -661,13 +668,29 @@ export default class Molecule {
|
|
|
661
668
|
throw new BalanceInsufficientException()
|
|
662
669
|
}
|
|
663
670
|
|
|
664
|
-
//
|
|
671
|
+
// Create burn address wallet (null bundle = token destruction)
|
|
672
|
+
const burnWallet = new Wallet({
|
|
673
|
+
bundle: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
674
|
+
token: this.sourceWallet.token
|
|
675
|
+
})
|
|
676
|
+
|
|
677
|
+
// V-atom 1: Debit full balance from source
|
|
665
678
|
this.addAtom(Atom.create({
|
|
666
679
|
isotope: 'V',
|
|
667
680
|
wallet: this.sourceWallet,
|
|
668
|
-
value: -
|
|
681
|
+
value: -Number(this.sourceWallet.balance)
|
|
669
682
|
}))
|
|
670
|
-
|
|
683
|
+
|
|
684
|
+
// V-atom 2: Credit burn amount to burn address
|
|
685
|
+
this.addAtom(Atom.create({
|
|
686
|
+
isotope: 'V',
|
|
687
|
+
wallet: burnWallet,
|
|
688
|
+
value: amount,
|
|
689
|
+
metaType: 'walletBundle',
|
|
690
|
+
metaId: burnWallet.bundle!
|
|
691
|
+
}))
|
|
692
|
+
|
|
693
|
+
// V-atom 3: Remainder back to source identity
|
|
671
694
|
this.addAtom(Atom.create({
|
|
672
695
|
isotope: 'V',
|
|
673
696
|
wallet: this.remainderWallet!,
|
package/src/index.ts
CHANGED
|
@@ -94,6 +94,9 @@ export { default as QueryAtom } from './query/QueryAtom'
|
|
|
94
94
|
export { default as QueryMetaType } from './query/QueryMetaType'
|
|
95
95
|
export { default as QueryMetaTypeViaAtom } from './query/QueryMetaTypeViaAtom'
|
|
96
96
|
|
|
97
|
+
// DataBraid Embedding Observability
|
|
98
|
+
export { default as QueryEmbeddingStatus } from './query/QueryEmbeddingStatus'
|
|
99
|
+
|
|
97
100
|
// Phase 2 Tier 2 Priority 3: Essential Query Operations
|
|
98
101
|
export { default as QueryContinuId } from './query/QueryContinuId'
|
|
99
102
|
export { default as QueryBatch } from './query/QueryBatch'
|
|
@@ -134,6 +137,10 @@ export { default as ResponseCreateMeta } from './response/ResponseCreateMeta'
|
|
|
134
137
|
export { default as ResponseMetaType } from './response/ResponseMetaType'
|
|
135
138
|
export { default as ResponseMetaTypeViaAtom } from './response/ResponseMetaTypeViaAtom'
|
|
136
139
|
|
|
140
|
+
// DataBraid Embedding Observability
|
|
141
|
+
export { default as ResponseEmbeddingStatus } from './response/ResponseEmbeddingStatus'
|
|
142
|
+
export type { EmbeddingStatusItem } from './response/ResponseEmbeddingStatus'
|
|
143
|
+
|
|
137
144
|
// Phase 2 Tier 2 Priority 2: Token Operations
|
|
138
145
|
export { default as ResponseCreateToken } from './response/ResponseCreateToken'
|
|
139
146
|
export { default as ResponseRequestTokens } from './response/ResponseRequestTokens'
|
|
@@ -301,6 +301,21 @@ export default class GraphQLClient implements IGraphQLClient {
|
|
|
301
301
|
})
|
|
302
302
|
}
|
|
303
303
|
|
|
304
|
+
/**
|
|
305
|
+
* F-8a (cross-SDK parity, 2026-06-03): re-point the GraphQL-subscription WebSocket
|
|
306
|
+
* without changing the HTTP endpoint. `setUri` only updates `serverUri`, leaving the
|
|
307
|
+
* subscription socket pinned to whatever was passed at construction; this lets a
|
|
308
|
+
* caller re-derive the socket when the endpoint changes.
|
|
309
|
+
*/
|
|
310
|
+
setSocketUri(socketUri: string): void {
|
|
311
|
+
this.socketUri = socketUri
|
|
312
|
+
this.$__client = this.createUrqlClient({
|
|
313
|
+
serverUri: this.serverUri,
|
|
314
|
+
socket: { socketUri },
|
|
315
|
+
encrypt: this.cipherLink
|
|
316
|
+
})
|
|
317
|
+
}
|
|
318
|
+
|
|
304
319
|
socketDisconnect(): void {
|
|
305
320
|
if (this.socketUri) {
|
|
306
321
|
this.unsubscribeAll()
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/*
|
|
2
|
+
(
|
|
3
|
+
(/(
|
|
4
|
+
(//(
|
|
5
|
+
(///(
|
|
6
|
+
(/////(
|
|
7
|
+
(//////( )
|
|
8
|
+
(////////( (/)
|
|
9
|
+
(////////( (///)
|
|
10
|
+
(//////////( (////)
|
|
11
|
+
(//////////( (//////)
|
|
12
|
+
(////////////( (///////)
|
|
13
|
+
(/////////////( (/////////)
|
|
14
|
+
(//////////////( (///////////)
|
|
15
|
+
(///////////////( (/////////////)
|
|
16
|
+
(////////////////( (//////////////)
|
|
17
|
+
((((((((((((((((((( (((((((((((((((
|
|
18
|
+
((((((((((((((((((( ((((((((((((((
|
|
19
|
+
((((((((((((((((((( ((((((((((((((
|
|
20
|
+
(((((((((((((((((((( (((((((((((((
|
|
21
|
+
(((((((((((((((((((( ((((((((((((
|
|
22
|
+
((((((((((((((((((( ((((((((((((
|
|
23
|
+
((((((((((((((((((( ((((((((((
|
|
24
|
+
((((((((((((((((((/ (((((((((
|
|
25
|
+
(((((((((((((((((( ((((((((
|
|
26
|
+
((((((((((((((((( (((((((
|
|
27
|
+
(((((((((((((((((( (((((
|
|
28
|
+
################# ##
|
|
29
|
+
################ #
|
|
30
|
+
################# ##
|
|
31
|
+
%################ ###
|
|
32
|
+
###############( ####
|
|
33
|
+
############### ####
|
|
34
|
+
############### ######
|
|
35
|
+
%#############( (#######
|
|
36
|
+
%############# #########
|
|
37
|
+
############( ##########
|
|
38
|
+
########### #############
|
|
39
|
+
######### ##############
|
|
40
|
+
%######
|
|
41
|
+
|
|
42
|
+
Powered by Knish.IO: Connecting a Decentralized World
|
|
43
|
+
|
|
44
|
+
Please visit https://github.com/WishKnish/KnishIO-Client-TS for information.
|
|
45
|
+
|
|
46
|
+
License: https://github.com/WishKnish/KnishIO-Client-TS/blob/master/LICENSE
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
import Query from './Query'
|
|
50
|
+
import ResponseEmbeddingStatus from '../response/ResponseEmbeddingStatus'
|
|
51
|
+
import { gql } from '@urql/core'
|
|
52
|
+
import type { GraphQLClient } from '../types/graphql'
|
|
53
|
+
import type KnishIOClient from '../KnishIOClient'
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* QueryEmbeddingStatus - Query for retrieving DataBraid embedding status.
|
|
57
|
+
*
|
|
58
|
+
* Supports both single-instance and bulk modes:
|
|
59
|
+
* - Single: { metaType: 'product', metaId: 'SKU-001' }
|
|
60
|
+
* - Bulk: { instances: [{ metaType: 'product', metaId: 'SKU-001' }, ...] }
|
|
61
|
+
*
|
|
62
|
+
* Returns embedding state (PENDING, STALE, COMPLETE) for each instance,
|
|
63
|
+
* allowing apps to render spinner badges and completion indicators.
|
|
64
|
+
*
|
|
65
|
+
* NOTE: Only available on servers with EMBEDDING_ENABLED=true.
|
|
66
|
+
* Use KnishIOClient.queryEmbeddingStatus() which handles capability
|
|
67
|
+
* detection and returns null for unsupported servers.
|
|
68
|
+
*/
|
|
69
|
+
export default class QueryEmbeddingStatus extends Query {
|
|
70
|
+
/**
|
|
71
|
+
* Create new QueryEmbeddingStatus instance
|
|
72
|
+
*/
|
|
73
|
+
constructor(graphQLClient: GraphQLClient, knishIOClient: KnishIOClient) {
|
|
74
|
+
super(graphQLClient, knishIOClient)
|
|
75
|
+
|
|
76
|
+
this.$__query = gql`query( $metaType: String, $metaId: String, $instances: [EmbeddingStatusInput!] ) {
|
|
77
|
+
embeddingStatus( metaType: $metaType, metaId: $metaId, instances: $instances ) {
|
|
78
|
+
metaType,
|
|
79
|
+
metaId,
|
|
80
|
+
state,
|
|
81
|
+
totalMetas,
|
|
82
|
+
embeddedCount,
|
|
83
|
+
embeddedAt,
|
|
84
|
+
model
|
|
85
|
+
}
|
|
86
|
+
}`
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Builds a GraphQL-friendly variables object for embedding status queries.
|
|
91
|
+
*
|
|
92
|
+
* Single mode: createVariables({ metaType: 'product', metaId: 'SKU-001' })
|
|
93
|
+
* Bulk mode: createVariables({ instances: [{ metaType: 'product', metaId: 'SKU-001' }, ...] })
|
|
94
|
+
*/
|
|
95
|
+
static createVariables({
|
|
96
|
+
metaType = null,
|
|
97
|
+
metaId = null,
|
|
98
|
+
instances = null
|
|
99
|
+
}: {
|
|
100
|
+
metaType?: string | null
|
|
101
|
+
metaId?: string | null
|
|
102
|
+
instances?: Array<{ metaType: string; metaId: string }> | null
|
|
103
|
+
} = {}): Record<string, any> {
|
|
104
|
+
const variables: Record<string, any> = {}
|
|
105
|
+
|
|
106
|
+
if (instances && instances.length > 0) {
|
|
107
|
+
variables.instances = instances
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (metaType) {
|
|
111
|
+
variables.metaType = metaType
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (metaId) {
|
|
115
|
+
variables.metaId = metaId
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return variables
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Returns a Response object
|
|
123
|
+
*/
|
|
124
|
+
override createResponse(json: any): ResponseEmbeddingStatus {
|
|
125
|
+
return new ResponseEmbeddingStatus({
|
|
126
|
+
query: this,
|
|
127
|
+
json
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/*
|
|
2
|
+
(
|
|
3
|
+
(/(
|
|
4
|
+
(//(
|
|
5
|
+
(///(
|
|
6
|
+
(/////(
|
|
7
|
+
(//////( )
|
|
8
|
+
(////////( (/)
|
|
9
|
+
(////////( (///)
|
|
10
|
+
(//////////( (////)
|
|
11
|
+
(//////////( (//////)
|
|
12
|
+
(////////////( (///////)
|
|
13
|
+
(/////////////( (/////////)
|
|
14
|
+
(//////////////( (///////////)
|
|
15
|
+
(///////////////( (/////////////)
|
|
16
|
+
(////////////////( (//////////////)
|
|
17
|
+
((((((((((((((((((( (((((((((((((((
|
|
18
|
+
((((((((((((((((((( ((((((((((((((
|
|
19
|
+
((((((((((((((((((( ((((((((((((((
|
|
20
|
+
(((((((((((((((((((( (((((((((((((
|
|
21
|
+
(((((((((((((((((((( ((((((((((((
|
|
22
|
+
((((((((((((((((((( ((((((((((((
|
|
23
|
+
((((((((((((((((((( ((((((((((
|
|
24
|
+
((((((((((((((((((/ (((((((((
|
|
25
|
+
(((((((((((((((((( ((((((((
|
|
26
|
+
((((((((((((((((( (((((((
|
|
27
|
+
(((((((((((((((((( (((((
|
|
28
|
+
################# ##
|
|
29
|
+
################ #
|
|
30
|
+
################# ##
|
|
31
|
+
%################ ###
|
|
32
|
+
###############( ####
|
|
33
|
+
############### ####
|
|
34
|
+
############### ######
|
|
35
|
+
%#############( (#######
|
|
36
|
+
%############# #########
|
|
37
|
+
############( ##########
|
|
38
|
+
########### #############
|
|
39
|
+
######### ##############
|
|
40
|
+
%######
|
|
41
|
+
|
|
42
|
+
Powered by Knish.IO: Connecting a Decentralized World
|
|
43
|
+
|
|
44
|
+
Please visit https://github.com/WishKnish/KnishIO-Client-TS for information.
|
|
45
|
+
|
|
46
|
+
License: https://github.com/WishKnish/KnishIO-Client-TS/blob/master/LICENSE
|
|
47
|
+
*/
|
|
48
|
+
|
|
49
|
+
import type Query from '../query/Query'
|
|
50
|
+
import Response from './Response'
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* EmbeddingStatusItem shape returned by the server.
|
|
54
|
+
*/
|
|
55
|
+
export interface EmbeddingStatusItem {
|
|
56
|
+
/** Metadata type (echoed from input) */
|
|
57
|
+
metaType: string
|
|
58
|
+
/** Instance identifier (echoed from input) */
|
|
59
|
+
metaId: string
|
|
60
|
+
/** Embedding state: 'PENDING' | 'STALE' | 'COMPLETE' */
|
|
61
|
+
state: 'PENDING' | 'STALE' | 'COMPLETE'
|
|
62
|
+
/** Total meta rows for this instance */
|
|
63
|
+
totalMetas: number
|
|
64
|
+
/** Rows with current-model embeddings */
|
|
65
|
+
embeddedCount: number
|
|
66
|
+
/** Unix epoch of most recent embedding, or null */
|
|
67
|
+
embeddedAt: number | null
|
|
68
|
+
/** Model name used for embeddings, or null */
|
|
69
|
+
model: string | null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* ResponseEmbeddingStatus - Response for EmbeddingStatus Query
|
|
74
|
+
*
|
|
75
|
+
* Payload is an array of EmbeddingStatusItem objects.
|
|
76
|
+
*/
|
|
77
|
+
export default class ResponseEmbeddingStatus extends Response {
|
|
78
|
+
/**
|
|
79
|
+
* Class constructor
|
|
80
|
+
*/
|
|
81
|
+
constructor({
|
|
82
|
+
query,
|
|
83
|
+
json
|
|
84
|
+
}: {
|
|
85
|
+
query: Query
|
|
86
|
+
json: any
|
|
87
|
+
}) {
|
|
88
|
+
super({
|
|
89
|
+
query,
|
|
90
|
+
json,
|
|
91
|
+
dataKey: 'data.embeddingStatus'
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Returns the array of embedding status items, or null if empty.
|
|
97
|
+
*/
|
|
98
|
+
override payload(): EmbeddingStatusItem[] | null {
|
|
99
|
+
const items = this.data()
|
|
100
|
+
|
|
101
|
+
if (!items || !Array.isArray(items) || items.length === 0) {
|
|
102
|
+
return null
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return items as EmbeddingStatusItem[]
|
|
106
|
+
}
|
|
107
|
+
}
|