@superdoc/sdk 2.18.0-next.2 → 2.18.0-next.3
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/agent/doc-snapshot.cjs +38 -3
- package/dist/agent/doc-snapshot.d.ts +2 -0
- package/dist/agent/doc-snapshot.js +36 -3
- package/dist/agent/execution-context.cjs +12 -4
- package/dist/agent/execution-context.d.ts +1 -0
- package/dist/agent/execution-context.js +14 -6
- package/dist/generated/contract.cjs +1 -1
- package/dist/generated/contract.js +1 -1
- package/dist/index.cjs +4 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -1
- package/dist/runtime/document-evidence.cjs +9 -2
- package/dist/runtime/document-evidence.d.ts +2 -1
- package/dist/runtime/document-evidence.js +8 -2
- package/dist/runtime/host.cjs +49 -7
- package/dist/runtime/host.d.ts +2 -0
- package/dist/runtime/host.js +50 -8
- package/dist/runtime/process.cjs +3 -0
- package/dist/runtime/process.d.ts +1 -0
- package/dist/runtime/process.js +3 -0
- package/dist/runtime/sdk-version.generated.cjs +1 -1
- package/dist/runtime/sdk-version.generated.d.ts +1 -1
- package/dist/runtime/sdk-version.generated.js +1 -1
- package/dist/runtime/transport-common.cjs +90 -0
- package/dist/runtime/transport-common.d.ts +1 -0
- package/dist/runtime/transport-common.js +89 -0
- package/package.json +7 -7
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var documentEvidence = require('../runtime/document-evidence.cjs');
|
|
4
|
+
|
|
3
5
|
function asString(v, fallback = '') {
|
|
4
6
|
return typeof v === 'string' ? v : fallback;
|
|
5
7
|
}
|
|
@@ -278,14 +280,34 @@ async function buildDocumentSnapshot(doc, options = {}) {
|
|
|
278
280
|
};
|
|
279
281
|
}
|
|
280
282
|
// Blocks
|
|
281
|
-
const includeBlocksInSnapshot = includesDomain(requestedDomains, 'blocks');
|
|
282
|
-
const needBlocksRead = includeBlocksInSnapshot || includesDomain(requestedDomains, 'tables');
|
|
283
|
+
const includeBlocksInSnapshot = !options.countSummary && includesDomain(requestedDomains, 'blocks');
|
|
284
|
+
const needBlocksRead = options.countSummary || includeBlocksInSnapshot || includesDomain(requestedDomains, 'tables');
|
|
283
285
|
const blocksFn = maybeMethod(doc, ['blocks', 'list']);
|
|
284
286
|
const blocksRaw = needBlocksRead && blocksFn
|
|
285
|
-
? await safeCall(() => blocksFn({
|
|
287
|
+
? await safeCall(() => blocksFn({
|
|
288
|
+
offset: options.countSummary ? Number.MAX_SAFE_INTEGER : blockOffset,
|
|
289
|
+
limit: options.countSummary ? 1 : blockLimit,
|
|
290
|
+
includeText: includeBlocksInSnapshot,
|
|
291
|
+
}), null, recordError('blocks.list'))
|
|
286
292
|
: null;
|
|
287
293
|
const blocksRec = asRecord(blocksRaw);
|
|
288
294
|
const totalBlocks = explicitCount(blocksRec ?? {}, 'total') ?? countsFromInfo.blocks;
|
|
295
|
+
if (options.countSummary && blocksFn) {
|
|
296
|
+
if (blocksRec?.revision !== revision)
|
|
297
|
+
throw new MutationSnapshotError('REVISION_CONFLICT', 'Count summary revision changed.');
|
|
298
|
+
for (const [key, nodeType] of [
|
|
299
|
+
['paragraphs', 'paragraph'],
|
|
300
|
+
['headings', 'heading'],
|
|
301
|
+
['tables', 'table'],
|
|
302
|
+
]) {
|
|
303
|
+
if (countsFromInfo[key] !== 0)
|
|
304
|
+
continue;
|
|
305
|
+
const page = asRecord(await blocksFn({ nodeTypes: [nodeType], offset: Number.MAX_SAFE_INTEGER, limit: 1, includeText: false }));
|
|
306
|
+
if (page?.revision !== revision || typeof page.total !== 'number')
|
|
307
|
+
throw new MutationSnapshotError('REVISION_CONFLICT', 'Required count summary is unavailable.');
|
|
308
|
+
countsFromInfo[key] = page.total;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
289
311
|
const rawBlocks = Array.isArray(blocksRec?.blocks) ? blocksRec.blocks : [];
|
|
290
312
|
const fullBlockText = new Map();
|
|
291
313
|
const normalizedBlocks = rawBlocks.map((b, index) => {
|
|
@@ -743,6 +765,18 @@ class MutationSnapshotError extends Error {
|
|
|
743
765
|
this.name = 'MutationSnapshotError';
|
|
744
766
|
}
|
|
745
767
|
}
|
|
768
|
+
async function buildExecutionSummary(doc) {
|
|
769
|
+
const summary = await buildDocumentSnapshot(doc, { countSummary: true });
|
|
770
|
+
if (summary.revision === 'unknown' ||
|
|
771
|
+
summary.diagnostics.some((item) => ['info', 'blocks.list'].includes(item.section)))
|
|
772
|
+
throw new MutationSnapshotError('SNAPSHOT_INCOMPLETE', 'Required summary evidence is unavailable.');
|
|
773
|
+
const readRevision = documentEvidence.getDocumentRevisionReader(doc);
|
|
774
|
+
const revision = readRevision
|
|
775
|
+
? await readRevision()
|
|
776
|
+
: (await doc.blocks.list({ offset: Number.MAX_SAFE_INTEGER, limit: 1 })).revision;
|
|
777
|
+
assertMutationSnapshotRevision(summary.revision, revision ?? 'unknown');
|
|
778
|
+
return summary;
|
|
779
|
+
}
|
|
746
780
|
const MUTATION_BLOCK_PAGE_SIZE = 1000;
|
|
747
781
|
const MUTATION_BLOCK_PAGE_CONCURRENCY = 4;
|
|
748
782
|
const MUTATION_NON_TABLE_DOMAINS = [
|
|
@@ -1009,6 +1043,7 @@ function resolveSnapshotSelector(snapshot, selector) {
|
|
|
1009
1043
|
exports.AmbiguousSelectorError = AmbiguousSelectorError;
|
|
1010
1044
|
exports.MutationSnapshotError = MutationSnapshotError;
|
|
1011
1045
|
exports.buildDocumentSnapshot = buildDocumentSnapshot;
|
|
1046
|
+
exports.buildExecutionSummary = buildExecutionSummary;
|
|
1012
1047
|
exports.buildMutationSnapshot = buildMutationSnapshot;
|
|
1013
1048
|
exports.matchRunsForBlock = matchRunsForBlock;
|
|
1014
1049
|
exports.normalizeSnapshotBlock = normalizeSnapshotBlock;
|
|
@@ -234,6 +234,7 @@ export type DocumentSnapshot = {
|
|
|
234
234
|
export declare function matchRunsForBlock(queryFn: (args: Record<string, unknown>) => Promise<unknown>, text: string, nodeId: string): Promise<SnapshotRun[]>;
|
|
235
235
|
type SnapshotOptions = {
|
|
236
236
|
countsOnly?: boolean;
|
|
237
|
+
countSummary?: boolean;
|
|
237
238
|
includeDomains?: readonly SnapshotDomain[];
|
|
238
239
|
blockNodeTypes?: readonly string[];
|
|
239
240
|
blockTextLimit?: number;
|
|
@@ -319,6 +320,7 @@ export declare class MutationSnapshotError extends Error {
|
|
|
319
320
|
readonly code: 'SNAPSHOT_INCOMPLETE' | 'REVISION_CONFLICT';
|
|
320
321
|
constructor(code: 'SNAPSHOT_INCOMPLETE' | 'REVISION_CONFLICT', message: string);
|
|
321
322
|
}
|
|
323
|
+
export declare function buildExecutionSummary(doc: BoundDocApi): Promise<DocumentSnapshot>;
|
|
322
324
|
/**
|
|
323
325
|
* Build the complete block index used to authorize mutations. Inspection
|
|
324
326
|
* snapshots stay windowed; mutation selectors must not treat that presentation
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getDocumentRevisionReader } from '../runtime/document-evidence.js';
|
|
1
2
|
function asString(v, fallback = '') {
|
|
2
3
|
return typeof v === 'string' ? v : fallback;
|
|
3
4
|
}
|
|
@@ -276,14 +277,34 @@ export async function buildDocumentSnapshot(doc, options = {}) {
|
|
|
276
277
|
};
|
|
277
278
|
}
|
|
278
279
|
// Blocks
|
|
279
|
-
const includeBlocksInSnapshot = includesDomain(requestedDomains, 'blocks');
|
|
280
|
-
const needBlocksRead = includeBlocksInSnapshot || includesDomain(requestedDomains, 'tables');
|
|
280
|
+
const includeBlocksInSnapshot = !options.countSummary && includesDomain(requestedDomains, 'blocks');
|
|
281
|
+
const needBlocksRead = options.countSummary || includeBlocksInSnapshot || includesDomain(requestedDomains, 'tables');
|
|
281
282
|
const blocksFn = maybeMethod(doc, ['blocks', 'list']);
|
|
282
283
|
const blocksRaw = needBlocksRead && blocksFn
|
|
283
|
-
? await safeCall(() => blocksFn({
|
|
284
|
+
? await safeCall(() => blocksFn({
|
|
285
|
+
offset: options.countSummary ? Number.MAX_SAFE_INTEGER : blockOffset,
|
|
286
|
+
limit: options.countSummary ? 1 : blockLimit,
|
|
287
|
+
includeText: includeBlocksInSnapshot,
|
|
288
|
+
}), null, recordError('blocks.list'))
|
|
284
289
|
: null;
|
|
285
290
|
const blocksRec = asRecord(blocksRaw);
|
|
286
291
|
const totalBlocks = explicitCount(blocksRec ?? {}, 'total') ?? countsFromInfo.blocks;
|
|
292
|
+
if (options.countSummary && blocksFn) {
|
|
293
|
+
if (blocksRec?.revision !== revision)
|
|
294
|
+
throw new MutationSnapshotError('REVISION_CONFLICT', 'Count summary revision changed.');
|
|
295
|
+
for (const [key, nodeType] of [
|
|
296
|
+
['paragraphs', 'paragraph'],
|
|
297
|
+
['headings', 'heading'],
|
|
298
|
+
['tables', 'table'],
|
|
299
|
+
]) {
|
|
300
|
+
if (countsFromInfo[key] !== 0)
|
|
301
|
+
continue;
|
|
302
|
+
const page = asRecord(await blocksFn({ nodeTypes: [nodeType], offset: Number.MAX_SAFE_INTEGER, limit: 1, includeText: false }));
|
|
303
|
+
if (page?.revision !== revision || typeof page.total !== 'number')
|
|
304
|
+
throw new MutationSnapshotError('REVISION_CONFLICT', 'Required count summary is unavailable.');
|
|
305
|
+
countsFromInfo[key] = page.total;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
287
308
|
const rawBlocks = Array.isArray(blocksRec?.blocks) ? blocksRec.blocks : [];
|
|
288
309
|
const fullBlockText = new Map();
|
|
289
310
|
const normalizedBlocks = rawBlocks.map((b, index) => {
|
|
@@ -741,6 +762,18 @@ export class MutationSnapshotError extends Error {
|
|
|
741
762
|
this.name = 'MutationSnapshotError';
|
|
742
763
|
}
|
|
743
764
|
}
|
|
765
|
+
export async function buildExecutionSummary(doc) {
|
|
766
|
+
const summary = await buildDocumentSnapshot(doc, { countSummary: true });
|
|
767
|
+
if (summary.revision === 'unknown' ||
|
|
768
|
+
summary.diagnostics.some((item) => ['info', 'blocks.list'].includes(item.section)))
|
|
769
|
+
throw new MutationSnapshotError('SNAPSHOT_INCOMPLETE', 'Required summary evidence is unavailable.');
|
|
770
|
+
const readRevision = getDocumentRevisionReader(doc);
|
|
771
|
+
const revision = readRevision
|
|
772
|
+
? await readRevision()
|
|
773
|
+
: (await doc.blocks.list({ offset: Number.MAX_SAFE_INTEGER, limit: 1 })).revision;
|
|
774
|
+
assertMutationSnapshotRevision(summary.revision, revision ?? 'unknown');
|
|
775
|
+
return summary;
|
|
776
|
+
}
|
|
744
777
|
const MUTATION_BLOCK_PAGE_SIZE = 1000;
|
|
745
778
|
const MUTATION_BLOCK_PAGE_CONCURRENCY = 4;
|
|
746
779
|
const MUTATION_NON_TABLE_DOMAINS = [
|
|
@@ -184,6 +184,7 @@ class ExecutionContext {
|
|
|
184
184
|
fallbackReason;
|
|
185
185
|
currentRevision;
|
|
186
186
|
legacyRevisionOnly = false;
|
|
187
|
+
preserveSummaryCounts = false;
|
|
187
188
|
constructor(source, requirements = {}) {
|
|
188
189
|
this.source = source;
|
|
189
190
|
this.requirements = requirements;
|
|
@@ -268,9 +269,11 @@ class ExecutionContext {
|
|
|
268
269
|
? 'verification requires complete evidence'
|
|
269
270
|
: undefined);
|
|
270
271
|
const complete = evidence === 'full' || this.fallbackReason ? await docSnapshot.buildMutationSnapshot(this.source) : undefined;
|
|
272
|
+
this.preserveSummaryCounts = !complete && documentEvidence.requiresSummaryCounts(this.source);
|
|
273
|
+
const summary = this.preserveSummaryCounts ? await docSnapshot.buildExecutionSummary(this.source) : undefined;
|
|
271
274
|
if (complete && (complete.revision === 'unknown' || complete.diagnostics.some((item) => item.section === 'info')))
|
|
272
275
|
throw new errors.SuperDocCliError('Required complete evidence is unavailable.', { code: 'EVIDENCE_UNAVAILABLE' });
|
|
273
|
-
this.pre = new DocumentFacts(this.source, complete?.revision ?? compactRevision ?? (await readPublicRevision(this.source)), complete);
|
|
276
|
+
this.pre = new DocumentFacts(this.source, complete?.revision ?? summary?.revision ?? compactRevision ?? (await readPublicRevision(this.source)), complete, summary?.counts);
|
|
274
277
|
this.currentRevision = this.pre.revision;
|
|
275
278
|
await this.pre.prepare(checks);
|
|
276
279
|
return this.pre;
|
|
@@ -278,7 +281,11 @@ class ExecutionContext {
|
|
|
278
281
|
async finishRevision() {
|
|
279
282
|
if (this.requirements.evidence === 'full')
|
|
280
283
|
return this.finish();
|
|
281
|
-
const summary = this.
|
|
284
|
+
const summary = this.preserveSummaryCounts
|
|
285
|
+
? await docSnapshot.buildExecutionSummary(this.source)
|
|
286
|
+
: this.pre?.complete
|
|
287
|
+
? await docSnapshot.buildDocumentSnapshot(this.source, { countsOnly: true })
|
|
288
|
+
: undefined;
|
|
282
289
|
if (summary && (summary.revision === 'unknown' || summary.diagnostics.some((item) => item.section === 'info')))
|
|
283
290
|
throw new errors.SuperDocCliError('Required summary is unavailable.', { code: 'EVIDENCE_UNAVAILABLE' });
|
|
284
291
|
const revision = summary?.revision ?? (await readPublicRevision(this.source));
|
|
@@ -289,11 +296,12 @@ class ExecutionContext {
|
|
|
289
296
|
}
|
|
290
297
|
async finish() {
|
|
291
298
|
const complete = this.pre?.complete ? await docSnapshot.buildMutationSnapshot(this.source) : undefined;
|
|
299
|
+
const summary = this.preserveSummaryCounts ? await docSnapshot.buildExecutionSummary(this.source) : undefined;
|
|
292
300
|
if (complete && (complete.revision === 'unknown' || complete.diagnostics.some((item) => item.section === 'info')))
|
|
293
301
|
throw new errors.SuperDocCliError('Required complete evidence is unavailable.', { code: 'EVIDENCE_UNAVAILABLE' });
|
|
294
|
-
const revision = complete?.revision ?? (await readPublicRevision(this.source));
|
|
302
|
+
const revision = complete?.revision ?? summary?.revision ?? (await readPublicRevision(this.source));
|
|
295
303
|
this.assertExecutionRevision(revision);
|
|
296
|
-
this.post = new DocumentFacts(this.source, revision, complete);
|
|
304
|
+
this.post = new DocumentFacts(this.source, revision, complete, summary?.counts);
|
|
297
305
|
this.currentRevision = this.post.revision;
|
|
298
306
|
return this.post;
|
|
299
307
|
}
|
|
@@ -86,6 +86,7 @@ export declare class ExecutionContext {
|
|
|
86
86
|
fallbackReason?: string;
|
|
87
87
|
private currentRevision?;
|
|
88
88
|
private legacyRevisionOnly;
|
|
89
|
+
private preserveSummaryCounts;
|
|
89
90
|
constructor(source: BoundDocApi, requirements?: EvidenceRequirements);
|
|
90
91
|
start(): Promise<DocumentFacts>;
|
|
91
92
|
finishRevision(): Promise<DocumentFacts>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { getDocumentRevisionReader, supportsDocumentFacts, forwardDocumentEvidence, getMutationRevision, } from '../runtime/document-evidence.js';
|
|
1
|
+
import { getDocumentRevisionReader, supportsDocumentFacts, requiresSummaryCounts, forwardDocumentEvidence, getMutationRevision, } from '../runtime/document-evidence.js';
|
|
2
2
|
import { SuperDocCliError } from '../runtime/errors.js';
|
|
3
|
-
import { buildDocumentSnapshot, buildMutationSnapshot, resolveSnapshotSelector, } from './doc-snapshot.js';
|
|
3
|
+
import { buildDocumentSnapshot, buildMutationSnapshot, buildExecutionSummary, resolveSnapshotSelector, } from './doc-snapshot.js';
|
|
4
4
|
import { getOperationCatalogEntry } from './operation-catalog.js';
|
|
5
5
|
export function supportsLocalSelector(selector) {
|
|
6
6
|
return (selector.kind === 'nodeId' ||
|
|
@@ -181,6 +181,7 @@ export class ExecutionContext {
|
|
|
181
181
|
fallbackReason;
|
|
182
182
|
currentRevision;
|
|
183
183
|
legacyRevisionOnly = false;
|
|
184
|
+
preserveSummaryCounts = false;
|
|
184
185
|
constructor(source, requirements = {}) {
|
|
185
186
|
this.source = source;
|
|
186
187
|
this.requirements = requirements;
|
|
@@ -265,9 +266,11 @@ export class ExecutionContext {
|
|
|
265
266
|
? 'verification requires complete evidence'
|
|
266
267
|
: undefined);
|
|
267
268
|
const complete = evidence === 'full' || this.fallbackReason ? await buildMutationSnapshot(this.source) : undefined;
|
|
269
|
+
this.preserveSummaryCounts = !complete && requiresSummaryCounts(this.source);
|
|
270
|
+
const summary = this.preserveSummaryCounts ? await buildExecutionSummary(this.source) : undefined;
|
|
268
271
|
if (complete && (complete.revision === 'unknown' || complete.diagnostics.some((item) => item.section === 'info')))
|
|
269
272
|
throw new SuperDocCliError('Required complete evidence is unavailable.', { code: 'EVIDENCE_UNAVAILABLE' });
|
|
270
|
-
this.pre = new DocumentFacts(this.source, complete?.revision ?? compactRevision ?? (await readPublicRevision(this.source)), complete);
|
|
273
|
+
this.pre = new DocumentFacts(this.source, complete?.revision ?? summary?.revision ?? compactRevision ?? (await readPublicRevision(this.source)), complete, summary?.counts);
|
|
271
274
|
this.currentRevision = this.pre.revision;
|
|
272
275
|
await this.pre.prepare(checks);
|
|
273
276
|
return this.pre;
|
|
@@ -275,7 +278,11 @@ export class ExecutionContext {
|
|
|
275
278
|
async finishRevision() {
|
|
276
279
|
if (this.requirements.evidence === 'full')
|
|
277
280
|
return this.finish();
|
|
278
|
-
const summary = this.
|
|
281
|
+
const summary = this.preserveSummaryCounts
|
|
282
|
+
? await buildExecutionSummary(this.source)
|
|
283
|
+
: this.pre?.complete
|
|
284
|
+
? await buildDocumentSnapshot(this.source, { countsOnly: true })
|
|
285
|
+
: undefined;
|
|
279
286
|
if (summary && (summary.revision === 'unknown' || summary.diagnostics.some((item) => item.section === 'info')))
|
|
280
287
|
throw new SuperDocCliError('Required summary is unavailable.', { code: 'EVIDENCE_UNAVAILABLE' });
|
|
281
288
|
const revision = summary?.revision ?? (await readPublicRevision(this.source));
|
|
@@ -286,11 +293,12 @@ export class ExecutionContext {
|
|
|
286
293
|
}
|
|
287
294
|
async finish() {
|
|
288
295
|
const complete = this.pre?.complete ? await buildMutationSnapshot(this.source) : undefined;
|
|
296
|
+
const summary = this.preserveSummaryCounts ? await buildExecutionSummary(this.source) : undefined;
|
|
289
297
|
if (complete && (complete.revision === 'unknown' || complete.diagnostics.some((item) => item.section === 'info')))
|
|
290
298
|
throw new SuperDocCliError('Required complete evidence is unavailable.', { code: 'EVIDENCE_UNAVAILABLE' });
|
|
291
|
-
const revision = complete?.revision ?? (await readPublicRevision(this.source));
|
|
299
|
+
const revision = complete?.revision ?? summary?.revision ?? (await readPublicRevision(this.source));
|
|
292
300
|
this.assertExecutionRevision(revision);
|
|
293
|
-
this.post = new DocumentFacts(this.source, revision, complete);
|
|
301
|
+
this.post = new DocumentFacts(this.source, revision, complete, summary?.counts);
|
|
294
302
|
this.currentRevision = this.post.revision;
|
|
295
303
|
return this.post;
|
|
296
304
|
}
|