@modelprofile.com/flexharness 9.10.0 → 10.1.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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.flexharness.d.ts +2 -0
- package/dist_ts/classes.flexharness.js +101 -7
- package/dist_ts/classes.stores.js +11 -119
- package/dist_ts/errors.d.ts +7 -2
- package/dist_ts/errors.js +1 -1
- package/dist_ts/interfaces.d.ts +1 -0
- package/dist_ts/utils.harnessoptions.js +2 -1
- package/dist_ts/utils.storerules.d.ts +28 -0
- package/dist_ts/utils.storerules.js +107 -0
- package/dist_ts_chat_harness/classes.transcript.d.ts +88 -0
- package/dist_ts_chat_harness/classes.transcript.js +268 -0
- package/dist_ts_chat_harness/functions.intents.d.ts +62 -0
- package/dist_ts_chat_harness/functions.intents.js +96 -0
- package/dist_ts_chat_harness/functions.mapping.d.ts +33 -0
- package/dist_ts_chat_harness/functions.mapping.js +220 -0
- package/dist_ts_chat_harness/index.d.ts +3 -0
- package/dist_ts_chat_harness/index.js +4 -0
- package/dist_ts_chat_harness/plugins.d.ts +1 -0
- package/dist_ts_chat_harness/plugins.js +2 -0
- package/dist_ts_kvm/classes.browserkvm.js +3 -3
- package/dist_ts_kvm/plugins.d.ts +1 -1
- package/dist_ts_kvm/plugins.js +2 -2
- package/dist_ts_stores_nosqldb/classes.nosqldbstores.d.ts +31 -0
- package/dist_ts_stores_nosqldb/classes.nosqldbstores.js +312 -0
- package/dist_ts_stores_nosqldb/classes.recordstore.d.ts +110 -0
- package/dist_ts_stores_nosqldb/classes.recordstore.js +437 -0
- package/dist_ts_stores_nosqldb/index.d.ts +2 -0
- package/dist_ts_stores_nosqldb/index.js +3 -0
- package/dist_ts_stores_nosqldb/plugins.d.ts +7 -0
- package/dist_ts_stores_nosqldb/plugins.js +10 -0
- package/package.json +27 -7
- package/readme.md +14 -6
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.flexharness.ts +102 -7
- package/ts/classes.stores.ts +28 -172
- package/ts/errors.ts +8 -2
- package/ts/interfaces.ts +1 -0
- package/ts/readme.md +14 -6
- package/ts/utils.harnessoptions.ts +1 -0
- package/ts/utils.storerules.ts +177 -0
- package/ts_chat_harness/classes.transcript.ts +365 -0
- package/ts_chat_harness/functions.intents.ts +169 -0
- package/ts_chat_harness/functions.mapping.ts +267 -0
- package/ts_chat_harness/index.ts +33 -0
- package/ts_chat_harness/plugins.ts +18 -0
- package/ts_chat_harness/readme.md +114 -0
- package/ts_kvm/classes.browserkvm.ts +2 -2
- package/ts_kvm/plugins.ts +1 -1
- package/ts_stores_nosqldb/classes.nosqldbstores.ts +465 -0
- package/ts_stores_nosqldb/classes.recordstore.ts +560 -0
- package/ts_stores_nosqldb/index.ts +9 -0
- package/ts_stores_nosqldb/plugins.ts +38 -0
- package/ts_stores_nosqldb/readme.md +53 -0
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { FlexHarnessStoreCommitUncertainError, FlexHarnessStoreFormatError, FlexHarnessValidationError, } from '../dist_ts/errors.js';
|
|
3
|
+
export const FLEX_RECORD_COLLECTION = 'flexharness_records';
|
|
4
|
+
export const FLEX_CHUNK_COLLECTION = 'flexharness_chunks';
|
|
5
|
+
/**
|
|
6
|
+
* UTF-16 code units a record holds inline, and the size of each chunk of a longer payload. A
|
|
7
|
+
* chunk stays below 3 MiB of UTF-8, far under the 16 MiB document limit NoSQLDB and MongoDB
|
|
8
|
+
* enforce, so a record and each of its chunks always fit one document.
|
|
9
|
+
*/
|
|
10
|
+
export const FLEX_RECORD_CHUNK_CODE_UNITS = 1024 * 1024;
|
|
11
|
+
const mutationAttempts = 8;
|
|
12
|
+
const mutationBackoffBaseMs = 5;
|
|
13
|
+
const mutationBackoffMaxMs = 200;
|
|
14
|
+
const chunkReadAttempts = 4;
|
|
15
|
+
const defaultOperationTimeoutMs = 30_000;
|
|
16
|
+
/**
|
|
17
|
+
* The head of one record. A payload up to one chunk is stored inline; a longer one lives in
|
|
18
|
+
* immutable chunks named by `blobId`. `writeToken` changes on every committed write and is the
|
|
19
|
+
* compare-and-swap fence. A head without payload or blob is a placeholder that reserves the
|
|
20
|
+
* record for a chunked first write; it reads as absent.
|
|
21
|
+
*/
|
|
22
|
+
export class FlexRecordDocument extends plugins.SmartDataDbDoc {
|
|
23
|
+
recordId;
|
|
24
|
+
domain;
|
|
25
|
+
ownerKey;
|
|
26
|
+
namespaceKey;
|
|
27
|
+
revision;
|
|
28
|
+
writeToken;
|
|
29
|
+
payload;
|
|
30
|
+
blobId;
|
|
31
|
+
chunkCount;
|
|
32
|
+
payloadSha256;
|
|
33
|
+
/** Set before the first chunk of this record is written; the record's writes then sweep. */
|
|
34
|
+
chunked;
|
|
35
|
+
sweepCount;
|
|
36
|
+
}
|
|
37
|
+
/** One immutable piece of a chunked payload, written against the head token it will replace. */
|
|
38
|
+
export class FlexChunkDocument extends plugins.SmartDataDbDoc {
|
|
39
|
+
chunkId;
|
|
40
|
+
recordId;
|
|
41
|
+
domain;
|
|
42
|
+
ownerKey;
|
|
43
|
+
namespaceKey;
|
|
44
|
+
blobId;
|
|
45
|
+
baseToken;
|
|
46
|
+
index;
|
|
47
|
+
data;
|
|
48
|
+
}
|
|
49
|
+
function bindModels(db) {
|
|
50
|
+
class BoundRecord extends FlexRecordDocument {
|
|
51
|
+
}
|
|
52
|
+
class BoundChunk extends FlexChunkDocument {
|
|
53
|
+
}
|
|
54
|
+
plugins.defineCollectionModel(BoundRecord, db, {
|
|
55
|
+
collectionName: FLEX_RECORD_COLLECTION,
|
|
56
|
+
persistedFields: [
|
|
57
|
+
'recordId',
|
|
58
|
+
'domain',
|
|
59
|
+
'ownerKey',
|
|
60
|
+
'namespaceKey',
|
|
61
|
+
'revision',
|
|
62
|
+
'writeToken',
|
|
63
|
+
'payload',
|
|
64
|
+
'blobId',
|
|
65
|
+
'chunkCount',
|
|
66
|
+
'payloadSha256',
|
|
67
|
+
'chunked',
|
|
68
|
+
'sweepCount',
|
|
69
|
+
],
|
|
70
|
+
numericFields: ['revision', 'chunkCount', 'sweepCount'],
|
|
71
|
+
identityFields: ['recordId'],
|
|
72
|
+
indexes: [
|
|
73
|
+
{ name: 'flexharness_record_id', key: { recordId: 1 }, options: { unique: true } },
|
|
74
|
+
{ name: 'flexharness_record_owner', key: { ownerKey: 1, domain: 1 } },
|
|
75
|
+
{ name: 'flexharness_record_namespace', key: { namespaceKey: 1, domain: 1 } },
|
|
76
|
+
],
|
|
77
|
+
});
|
|
78
|
+
plugins.defineCollectionModel(BoundChunk, db, {
|
|
79
|
+
collectionName: FLEX_CHUNK_COLLECTION,
|
|
80
|
+
persistedFields: [
|
|
81
|
+
'chunkId',
|
|
82
|
+
'recordId',
|
|
83
|
+
'domain',
|
|
84
|
+
'ownerKey',
|
|
85
|
+
'namespaceKey',
|
|
86
|
+
'blobId',
|
|
87
|
+
'baseToken',
|
|
88
|
+
'index',
|
|
89
|
+
'data',
|
|
90
|
+
],
|
|
91
|
+
numericFields: ['index'],
|
|
92
|
+
identityFields: ['chunkId'],
|
|
93
|
+
indexes: [
|
|
94
|
+
{ name: 'flexharness_chunk_id', key: { chunkId: 1 }, options: { unique: true } },
|
|
95
|
+
{ name: 'flexharness_chunk_blob', key: { blobId: 1 } },
|
|
96
|
+
{ name: 'flexharness_chunk_record', key: { recordId: 1 } },
|
|
97
|
+
{ name: 'flexharness_chunk_owner', key: { ownerKey: 1, domain: 1 } },
|
|
98
|
+
{ name: 'flexharness_chunk_namespace', key: { namespaceKey: 1, domain: 1 } },
|
|
99
|
+
],
|
|
100
|
+
});
|
|
101
|
+
return { records: BoundRecord, chunks: BoundChunk };
|
|
102
|
+
}
|
|
103
|
+
const digest = (value) => plugins.crypto.createHash('sha256').update(value, 'utf8').digest('hex');
|
|
104
|
+
function splitPayload(text) {
|
|
105
|
+
const chunks = [];
|
|
106
|
+
let start = 0;
|
|
107
|
+
while (start < text.length) {
|
|
108
|
+
let end = Math.min(start + FLEX_RECORD_CHUNK_CODE_UNITS, text.length);
|
|
109
|
+
const last = text.charCodeAt(end - 1);
|
|
110
|
+
if (end < text.length && last >= 0xd800 && last <= 0xdbff)
|
|
111
|
+
end--;
|
|
112
|
+
chunks.push(text.slice(start, end));
|
|
113
|
+
start = end;
|
|
114
|
+
}
|
|
115
|
+
return chunks;
|
|
116
|
+
}
|
|
117
|
+
/** A rejection the database states before anything is written; every other failure may have applied. */
|
|
118
|
+
function isDefiniteRejection(error) {
|
|
119
|
+
return error instanceof plugins.SmartdataPersistenceError && [
|
|
120
|
+
'invalid_argument',
|
|
121
|
+
'invalid_configuration',
|
|
122
|
+
'invalid_document',
|
|
123
|
+
'unsupported_operation',
|
|
124
|
+
'unique_conflict',
|
|
125
|
+
].includes(error.code);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Waits before retrying a lost head swap: exponential from 5 ms, capped at 200 ms, with full
|
|
129
|
+
* jitter over its upper half, so writers that lost the same race spread out.
|
|
130
|
+
*/
|
|
131
|
+
function mutationBackoff(attempt) {
|
|
132
|
+
const ceiling = Math.min(mutationBackoffMaxMs, mutationBackoffBaseMs * 2 ** (attempt - 1));
|
|
133
|
+
const delayMs = ceiling / 2 + Math.random() * (ceiling / 2);
|
|
134
|
+
return new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
135
|
+
}
|
|
136
|
+
function isUniqueConflict(error) {
|
|
137
|
+
return error instanceof plugins.SmartdataPersistenceError && error.code === 'unique_conflict';
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Compare-and-swap records on `@lossless.org/client/nosqldb`. A write reads the head, decides,
|
|
141
|
+
* writes any chunks, and swaps the head only while its `writeToken` is unchanged. Chunks of a
|
|
142
|
+
* replaced or abandoned payload are swept in a transaction that also touches the head, so a
|
|
143
|
+
* concurrent deletion or writer can never lose chunks its head references.
|
|
144
|
+
*/
|
|
145
|
+
export class FlexRecordStore {
|
|
146
|
+
db;
|
|
147
|
+
timeoutMs;
|
|
148
|
+
records;
|
|
149
|
+
chunks;
|
|
150
|
+
preparation;
|
|
151
|
+
constructor(options) {
|
|
152
|
+
const timeoutMs = options.operationTimeoutMs ?? defaultOperationTimeoutMs;
|
|
153
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 120_000) {
|
|
154
|
+
throw new FlexHarnessValidationError('operationTimeoutMs must be an integer from 1 to 120000.');
|
|
155
|
+
}
|
|
156
|
+
this.db = options.db;
|
|
157
|
+
this.timeoutMs = timeoutMs;
|
|
158
|
+
({ records: this.records, chunks: this.chunks } = bindModels(options.db));
|
|
159
|
+
}
|
|
160
|
+
/** Creates or verifies both collections and their indexes once; a failed attempt is retried. */
|
|
161
|
+
prepare() {
|
|
162
|
+
this.preparation ??= this.prepareCollections().catch((error) => {
|
|
163
|
+
this.preparation = undefined;
|
|
164
|
+
throw error;
|
|
165
|
+
});
|
|
166
|
+
return this.preparation;
|
|
167
|
+
}
|
|
168
|
+
async prepareCollections() {
|
|
169
|
+
const capabilities = this.db.capabilities;
|
|
170
|
+
if (!capabilities) {
|
|
171
|
+
throw new FlexHarnessValidationError('NoSqlFlexHarnessStores requires an initialized SmartdataDb.');
|
|
172
|
+
}
|
|
173
|
+
if (capabilities.transactions === 'unsupported') {
|
|
174
|
+
throw new FlexHarnessValidationError('NoSqlFlexHarnessStores requires a database that supports transactions.');
|
|
175
|
+
}
|
|
176
|
+
const options = { mode: 'ensureCompatible', timeoutMs: this.timeoutMs };
|
|
177
|
+
await this.records.prepareCollection(options);
|
|
178
|
+
await this.chunks.prepareCollection(options);
|
|
179
|
+
}
|
|
180
|
+
resolve(address) {
|
|
181
|
+
const recordId = digest(JSON.stringify([
|
|
182
|
+
address.domain,
|
|
183
|
+
address.storageKey,
|
|
184
|
+
address.sessionId ?? null,
|
|
185
|
+
address.archiveId ?? null,
|
|
186
|
+
]));
|
|
187
|
+
return {
|
|
188
|
+
recordId,
|
|
189
|
+
domain: address.domain,
|
|
190
|
+
ownerKey: digest(JSON.stringify([address.storageKey, address.sessionId ?? null])),
|
|
191
|
+
namespaceKey: digest(address.storageKey),
|
|
192
|
+
path: `${FLEX_RECORD_COLLECTION}/${address.domain}/${recordId}`,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
async read(address, validate) {
|
|
196
|
+
await this.prepare();
|
|
197
|
+
const resolved = this.resolve(address);
|
|
198
|
+
return this.parse(resolved, await this.readHead(resolved), validate);
|
|
199
|
+
}
|
|
200
|
+
async mutate(address, mutation) {
|
|
201
|
+
await this.prepare();
|
|
202
|
+
const resolved = this.resolve(address);
|
|
203
|
+
let actualRevision = 0;
|
|
204
|
+
for (let attempt = 0; attempt < mutationAttempts; attempt++) {
|
|
205
|
+
if (attempt > 0)
|
|
206
|
+
await mutationBackoff(attempt);
|
|
207
|
+
const head = await this.readHead(resolved);
|
|
208
|
+
const current = this.parse(resolved, head, mutation.validate);
|
|
209
|
+
actualRevision = head.document?.revision ?? 0;
|
|
210
|
+
const write = mutation.decide(current);
|
|
211
|
+
if (!write)
|
|
212
|
+
return;
|
|
213
|
+
if (await this.commit(resolved, head.document, write))
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
throw mutation.contention(actualRevision);
|
|
217
|
+
}
|
|
218
|
+
/** Deletes every record and chunk one session owns in the given domains. */
|
|
219
|
+
async deleteOwner(storageKey, sessionId, domains) {
|
|
220
|
+
await this.prepare();
|
|
221
|
+
const ownerKey = digest(JSON.stringify([storageKey, sessionId]));
|
|
222
|
+
await this.deleteInTransaction(`${FLEX_RECORD_COLLECTION}/${domains.join('+')}/owner/${ownerKey}`, { ownerKey, domain: { $in: [...domains] } });
|
|
223
|
+
}
|
|
224
|
+
/** Deletes every record and chunk of one domain in a storage namespace. */
|
|
225
|
+
async purgeNamespace(storageKey, domain) {
|
|
226
|
+
await this.prepare();
|
|
227
|
+
const namespaceKey = digest(storageKey);
|
|
228
|
+
await this.deleteInTransaction(`${FLEX_RECORD_COLLECTION}/${domain}/namespace/${namespaceKey}`, { namespaceKey, domain });
|
|
229
|
+
}
|
|
230
|
+
async deleteInTransaction(path, selector) {
|
|
231
|
+
const session = this.db.createSession();
|
|
232
|
+
try {
|
|
233
|
+
await session.withTransaction(async (transaction) => {
|
|
234
|
+
await this.records.atomicDeleteMany(selector, { session: transaction });
|
|
235
|
+
await this.chunks.atomicDeleteMany(selector, { session: transaction });
|
|
236
|
+
}, { timeoutMS: this.timeoutMs });
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
if (plugins.SmartdataSession.getCommitOutcome(error) === 'not_committed')
|
|
240
|
+
throw error;
|
|
241
|
+
throw new FlexHarnessStoreCommitUncertainError(path, 'delete', { cause: error });
|
|
242
|
+
}
|
|
243
|
+
finally {
|
|
244
|
+
await session.close();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
parse(resolved, head, validate) {
|
|
248
|
+
if (head.text === undefined)
|
|
249
|
+
return undefined;
|
|
250
|
+
let parsed;
|
|
251
|
+
try {
|
|
252
|
+
parsed = JSON.parse(head.text);
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
throw new FlexHarnessStoreFormatError(`Malformed JSON at ${resolved.path}.`, { cause: error });
|
|
256
|
+
}
|
|
257
|
+
try {
|
|
258
|
+
return validate(parsed);
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
if (error instanceof FlexHarnessStoreFormatError) {
|
|
262
|
+
throw new FlexHarnessStoreFormatError(`Invalid record at ${resolved.path}: ${error.message}`, {
|
|
263
|
+
cause: error,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
throw error;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
findHead(resolved) {
|
|
270
|
+
return this.records.getInstance({ recordId: resolved.recordId }, { timeoutMS: this.timeoutMs });
|
|
271
|
+
}
|
|
272
|
+
async readHead(resolved) {
|
|
273
|
+
for (let attempt = 0; attempt < chunkReadAttempts; attempt++) {
|
|
274
|
+
const document = await this.findHead(resolved);
|
|
275
|
+
if (!document)
|
|
276
|
+
return {};
|
|
277
|
+
if (document.payload !== null)
|
|
278
|
+
return { document, text: document.payload };
|
|
279
|
+
if (document.blobId === null)
|
|
280
|
+
return { document };
|
|
281
|
+
const text = await this.readBlob(document);
|
|
282
|
+
if (text !== undefined)
|
|
283
|
+
return { document, text };
|
|
284
|
+
const latest = await this.findHead(resolved);
|
|
285
|
+
if (latest?.writeToken === document.writeToken) {
|
|
286
|
+
throw new FlexHarnessStoreFormatError(`${resolved.path} references ${document.chunkCount} chunks of blob "${document.blobId}", but they are incomplete.`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
throw new FlexHarnessStoreFormatError(`${resolved.path} changed during ${chunkReadAttempts} consecutive reads.`);
|
|
290
|
+
}
|
|
291
|
+
async readBlob(document) {
|
|
292
|
+
const stored = await this.chunks.getInstances({ blobId: document.blobId }, { timeoutMS: this.timeoutMs });
|
|
293
|
+
if (stored.length !== document.chunkCount)
|
|
294
|
+
return undefined;
|
|
295
|
+
const text = stored
|
|
296
|
+
.sort((left, right) => left.index - right.index)
|
|
297
|
+
.map((chunk) => chunk.data)
|
|
298
|
+
.join('');
|
|
299
|
+
return digest(text) === document.payloadSha256 ? text : undefined;
|
|
300
|
+
}
|
|
301
|
+
/** Returns false when another writer swapped the head first; nothing of this write remains. */
|
|
302
|
+
async commit(resolved, stored, write) {
|
|
303
|
+
const text = JSON.stringify(write.value);
|
|
304
|
+
const chunked = text.length > FLEX_RECORD_CHUNK_CODE_UNITS;
|
|
305
|
+
let current = stored;
|
|
306
|
+
if (!current) {
|
|
307
|
+
if (!chunked)
|
|
308
|
+
return this.insertHead(resolved, write.revision, text);
|
|
309
|
+
current = await this.insertPlaceholder(resolved);
|
|
310
|
+
if (!current)
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
313
|
+
else if (current.chunked) {
|
|
314
|
+
await this.sweep(current);
|
|
315
|
+
}
|
|
316
|
+
else if (chunked && !await this.markChunked(current)) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
const blobId = chunked ? await this.writeBlob(resolved, current.writeToken, text) : null;
|
|
320
|
+
let swapped;
|
|
321
|
+
try {
|
|
322
|
+
const outcome = await this.records.atomicUpdate({ recordId: resolved.recordId, writeToken: current.writeToken }, {
|
|
323
|
+
$set: {
|
|
324
|
+
revision: write.revision,
|
|
325
|
+
writeToken: plugins.crypto.randomUUID(),
|
|
326
|
+
payload: chunked ? null : text,
|
|
327
|
+
blobId,
|
|
328
|
+
chunkCount: chunked ? splitPayload(text).length : 0,
|
|
329
|
+
payloadSha256: chunked ? digest(text) : null,
|
|
330
|
+
},
|
|
331
|
+
}, { timeoutMS: this.timeoutMs });
|
|
332
|
+
swapped = outcome.matchedCount === 1;
|
|
333
|
+
}
|
|
334
|
+
catch (error) {
|
|
335
|
+
if (isDefiniteRejection(error))
|
|
336
|
+
throw error;
|
|
337
|
+
throw new FlexHarnessStoreCommitUncertainError(resolved.path, 'write', { cause: error });
|
|
338
|
+
}
|
|
339
|
+
if (!swapped && blobId !== null) {
|
|
340
|
+
await this.chunks.atomicDeleteMany({ blobId }, { timeoutMS: this.timeoutMs });
|
|
341
|
+
}
|
|
342
|
+
return swapped;
|
|
343
|
+
}
|
|
344
|
+
newHead(resolved) {
|
|
345
|
+
const head = new this.records();
|
|
346
|
+
head.recordId = resolved.recordId;
|
|
347
|
+
head.domain = resolved.domain;
|
|
348
|
+
head.ownerKey = resolved.ownerKey;
|
|
349
|
+
head.namespaceKey = resolved.namespaceKey;
|
|
350
|
+
head.writeToken = plugins.crypto.randomUUID();
|
|
351
|
+
head.blobId = null;
|
|
352
|
+
head.chunkCount = 0;
|
|
353
|
+
head.payloadSha256 = null;
|
|
354
|
+
head.sweepCount = 0;
|
|
355
|
+
return head;
|
|
356
|
+
}
|
|
357
|
+
async insertHead(resolved, revision, text) {
|
|
358
|
+
const head = this.newHead(resolved);
|
|
359
|
+
head.revision = revision;
|
|
360
|
+
head.payload = text;
|
|
361
|
+
head.chunked = false;
|
|
362
|
+
try {
|
|
363
|
+
await this.records.insert(head, { timeoutMS: this.timeoutMs });
|
|
364
|
+
return true;
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
if (isUniqueConflict(error))
|
|
368
|
+
return false;
|
|
369
|
+
if (isDefiniteRejection(error))
|
|
370
|
+
throw error;
|
|
371
|
+
throw new FlexHarnessStoreCommitUncertainError(resolved.path, 'write', { cause: error });
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
/** Reserves the record for a chunked first write, so its chunks have a head token to replace. */
|
|
375
|
+
async insertPlaceholder(resolved) {
|
|
376
|
+
const head = this.newHead(resolved);
|
|
377
|
+
head.revision = 0;
|
|
378
|
+
head.payload = null;
|
|
379
|
+
head.chunked = true;
|
|
380
|
+
try {
|
|
381
|
+
await this.records.insert(head, { timeoutMS: this.timeoutMs });
|
|
382
|
+
return head;
|
|
383
|
+
}
|
|
384
|
+
catch (error) {
|
|
385
|
+
if (isUniqueConflict(error))
|
|
386
|
+
return undefined;
|
|
387
|
+
throw error;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
async markChunked(current) {
|
|
391
|
+
const outcome = await this.records.atomicUpdate({ recordId: current.recordId, writeToken: current.writeToken }, { $set: { chunked: true } }, { timeoutMS: this.timeoutMs });
|
|
392
|
+
return outcome.matchedCount === 1;
|
|
393
|
+
}
|
|
394
|
+
async writeBlob(resolved, baseToken, text) {
|
|
395
|
+
const blobId = plugins.crypto.randomUUID();
|
|
396
|
+
const pieces = splitPayload(text);
|
|
397
|
+
for (let index = 0; index < pieces.length; index++) {
|
|
398
|
+
const chunk = new this.chunks();
|
|
399
|
+
chunk.chunkId = `${blobId}:${index}`;
|
|
400
|
+
chunk.recordId = resolved.recordId;
|
|
401
|
+
chunk.domain = resolved.domain;
|
|
402
|
+
chunk.ownerKey = resolved.ownerKey;
|
|
403
|
+
chunk.namespaceKey = resolved.namespaceKey;
|
|
404
|
+
chunk.blobId = blobId;
|
|
405
|
+
chunk.baseToken = baseToken;
|
|
406
|
+
chunk.index = index;
|
|
407
|
+
chunk.data = pieces[index];
|
|
408
|
+
await this.chunks.insert(chunk, { timeoutMS: this.timeoutMs });
|
|
409
|
+
}
|
|
410
|
+
return blobId;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Deletes the record's chunks that no head can reference any more: every blob but the current
|
|
414
|
+
* one that was written against another head token. A writer that read the current token keeps
|
|
415
|
+
* its chunks. Touching the head in the same transaction makes a concurrent deletion conflict,
|
|
416
|
+
* so chunks written after a deletion are never swept by a transaction that predates it.
|
|
417
|
+
*/
|
|
418
|
+
async sweep(current) {
|
|
419
|
+
const session = this.db.createSession();
|
|
420
|
+
try {
|
|
421
|
+
await session.withTransaction(async (transaction) => {
|
|
422
|
+
const touched = await this.records.atomicUpdate({ recordId: current.recordId, writeToken: current.writeToken }, { $inc: { sweepCount: 1 } }, { session: transaction });
|
|
423
|
+
if (touched.matchedCount !== 1)
|
|
424
|
+
return;
|
|
425
|
+
await this.chunks.atomicDeleteMany({
|
|
426
|
+
recordId: current.recordId,
|
|
427
|
+
baseToken: { $ne: current.writeToken },
|
|
428
|
+
...(current.blobId === null ? {} : { blobId: { $ne: current.blobId } }),
|
|
429
|
+
}, { session: transaction });
|
|
430
|
+
}, { timeoutMS: this.timeoutMs });
|
|
431
|
+
}
|
|
432
|
+
finally {
|
|
433
|
+
await session.close();
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5yZWNvcmRzdG9yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX3N0b3Jlc19ub3NxbGRiL2NsYXNzZXMucmVjb3Jkc3RvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFDeEMsT0FBTyxFQUNMLG9DQUFvQyxFQUNwQywyQkFBMkIsRUFDM0IsMEJBQTBCLEdBQzNCLE1BQU0saUJBQWlCLENBQUM7QUFpQ3pCLE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFHLHFCQUFxQixDQUFDO0FBQzVELE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLG9CQUFvQixDQUFDO0FBRTFEOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSw0QkFBNEIsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBRXhELE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDO0FBQzNCLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxDQUFDO0FBQ2hDLE1BQU0sb0JBQW9CLEdBQUcsR0FBRyxDQUFDO0FBQ2pDLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0FBQzVCLE1BQU0seUJBQXlCLEdBQUcsTUFBTSxDQUFDO0FBRXpDOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLGtCQUFtQixTQUFRLE9BQU8sQ0FBQyxjQUFzRDtJQUM3RixRQUFRLENBQVU7SUFDbEIsTUFBTSxDQUFxQjtJQUMzQixRQUFRLENBQVU7SUFDbEIsWUFBWSxDQUFVO0lBQ3RCLFFBQVEsQ0FBVTtJQUNsQixVQUFVLENBQVU7SUFDcEIsT0FBTyxDQUFpQjtJQUN4QixNQUFNLENBQWlCO0lBQ3ZCLFVBQVUsQ0FBVTtJQUNwQixhQUFhLENBQWlCO0lBQ3JDLDRGQUE0RjtJQUNyRixPQUFPLENBQVc7SUFDbEIsVUFBVSxDQUFVO0NBQzVCO0FBRUQsZ0dBQWdHO0FBQ2hHLE1BQU0sT0FBTyxpQkFBa0IsU0FBUSxPQUFPLENBQUMsY0FB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
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { NoSqlFlexHarnessStores, } from './classes.nosqldbstores.js';
|
|
2
|
+
export { FLEX_CHUNK_COLLECTION, FLEX_RECORD_CHUNK_CODE_UNITS, FLEX_RECORD_COLLECTION, } from './classes.recordstore.js';
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c19zdG9yZXNfbm9zcWxkYi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsc0JBQXNCLEdBRXZCLE1BQU0sNEJBQTRCLENBQUM7QUFDcEMsT0FBTyxFQUNMLHFCQUFxQixFQUNyQiw0QkFBNEIsRUFDNUIsc0JBQXNCLEdBQ3ZCLE1BQU0sMEJBQTBCLENBQUMifQ==
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as crypto from 'node:crypto';
|
|
2
|
+
export { crypto };
|
|
3
|
+
import { AgentEventStoreConflictError, ToolJobStoreConflictError } from '@modelprofile.com/flexharness-agent';
|
|
4
|
+
export { AgentEventStoreConflictError, ToolJobStoreConflictError };
|
|
5
|
+
export type { IAgentEventArchiveV2, IAgentEventSnapshotV2, IAgentEventStoreV2, IToolJobSnapshot, IToolJobState, IToolJobStore, TAgentEvent, } from '@modelprofile.com/flexharness-agent';
|
|
6
|
+
import { SmartDataDbDoc, SmartdataDb, SmartdataPersistenceError, SmartdataSession, defineCollectionModel } from '@lossless.org/client/nosqldb';
|
|
7
|
+
export { SmartDataDbDoc, SmartdataDb, SmartdataPersistenceError, SmartdataSession, defineCollectionModel, };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// node native scope
|
|
2
|
+
import * as crypto from 'node:crypto';
|
|
3
|
+
export { crypto };
|
|
4
|
+
// @modelprofile.com scope
|
|
5
|
+
import { AgentEventStoreConflictError, ToolJobStoreConflictError, } from '@modelprofile.com/flexharness-agent';
|
|
6
|
+
export { AgentEventStoreConflictError, ToolJobStoreConflictError };
|
|
7
|
+
// @lossless.org scope
|
|
8
|
+
import { SmartDataDbDoc, SmartdataDb, SmartdataPersistenceError, SmartdataSession, defineCollectionModel, } from '@lossless.org/client/nosqldb';
|
|
9
|
+
export { SmartDataDbDoc, SmartdataDb, SmartdataPersistenceError, SmartdataSession, defineCollectionModel, };
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX3N0b3Jlc19ub3NxbGRiL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBRXRDLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQztBQUVsQiwwQkFBMEI7QUFDMUIsT0FBTyxFQUNMLDRCQUE0QixFQUM1Qix5QkFBeUIsR0FDMUIsTUFBTSxxQ0FBcUMsQ0FBQztBQUU3QyxPQUFPLEVBQUUsNEJBQTRCLEVBQUUseUJBQXlCLEVBQUUsQ0FBQztBQVduRSxzQkFBc0I7QUFDdEIsT0FBTyxFQUNMLGNBQWMsRUFDZCxXQUFXLEVBQ1gseUJBQXlCLEVBQ3pCLGdCQUFnQixFQUNoQixxQkFBcUIsR0FDdEIsTUFBTSw4QkFBOEIsQ0FBQztBQUV0QyxPQUFPLEVBQ0wsY0FBYyxFQUNkLFdBQVcsRUFDWCx5QkFBeUIsRUFDekIsZ0JBQWdCLEVBQ2hCLHFCQUFxQixHQUN0QixDQUFDIn0=
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"author": "Task Venture Capital GmbH",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"name": "@modelprofile.com/flexharness",
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "10.1.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"description": "Managed agent sessions with tools, MCP, chat, OCR, documents and browser control through focused subpath imports.",
|
|
8
8
|
"main": "./dist_ts/index.js",
|
|
@@ -59,14 +59,22 @@
|
|
|
59
59
|
"./chat/web": {
|
|
60
60
|
"types": "./dist_ts_chat_web/index.d.ts",
|
|
61
61
|
"import": "./dist_ts_chat_web/index.js"
|
|
62
|
+
},
|
|
63
|
+
"./chat/harness": {
|
|
64
|
+
"types": "./dist_ts_chat_harness/index.d.ts",
|
|
65
|
+
"import": "./dist_ts_chat_harness/index.js"
|
|
66
|
+
},
|
|
67
|
+
"./stores/nosqldb": {
|
|
68
|
+
"types": "./dist_ts_stores_nosqldb/index.d.ts",
|
|
69
|
+
"import": "./dist_ts_stores_nosqldb/index.js"
|
|
62
70
|
}
|
|
63
71
|
},
|
|
64
72
|
"dependencies": {
|
|
65
|
-
"@modelprofile.com/flexharness-agent": "
|
|
66
|
-
"@modelprofile.com/flexharness-models": "
|
|
67
|
-
"@push.rocks/smartrequest": "^5.
|
|
68
|
-
"ai": "^7.0.
|
|
69
|
-
"zod": "^4.
|
|
73
|
+
"@modelprofile.com/flexharness-agent": "10.1.0",
|
|
74
|
+
"@modelprofile.com/flexharness-models": "10.1.0",
|
|
75
|
+
"@push.rocks/smartrequest": "^5.5.1",
|
|
76
|
+
"ai": "^7.0.111",
|
|
77
|
+
"zod": "^4.6.5"
|
|
70
78
|
},
|
|
71
79
|
"peerDependencies": {
|
|
72
80
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
@@ -77,7 +85,9 @@
|
|
|
77
85
|
"ink-text-input": "^6.0.0",
|
|
78
86
|
"react": "^19.2.5",
|
|
79
87
|
"lit": "^3.2.0",
|
|
80
|
-
"@types/react": "^19.0.0"
|
|
88
|
+
"@types/react": "^19.0.0",
|
|
89
|
+
"@lossless.org/client": "^1.17.0",
|
|
90
|
+
"@design.estate/dees-catalog": "^17.0.0"
|
|
81
91
|
},
|
|
82
92
|
"peerDependenciesMeta": {
|
|
83
93
|
"@modelcontextprotocol/sdk": {
|
|
@@ -106,6 +116,12 @@
|
|
|
106
116
|
},
|
|
107
117
|
"@types/react": {
|
|
108
118
|
"optional": true
|
|
119
|
+
},
|
|
120
|
+
"@lossless.org/client": {
|
|
121
|
+
"optional": true
|
|
122
|
+
},
|
|
123
|
+
"@design.estate/dees-catalog": {
|
|
124
|
+
"optional": true
|
|
109
125
|
}
|
|
110
126
|
},
|
|
111
127
|
"engines": {
|
|
@@ -141,6 +157,10 @@
|
|
|
141
157
|
"dist_ts_chat_cli",
|
|
142
158
|
"ts_chat_web",
|
|
143
159
|
"dist_ts_chat_web",
|
|
160
|
+
"ts_chat_harness",
|
|
161
|
+
"dist_ts_chat_harness",
|
|
162
|
+
"ts_stores_nosqldb",
|
|
163
|
+
"dist_ts_stores_nosqldb",
|
|
144
164
|
"readme.md",
|
|
145
165
|
"license.md"
|
|
146
166
|
]
|