@adcp/sdk 15.2.2 → 15.4.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/lib/core/ConversationTypes.d.mts +5 -0
- package/dist/lib/core/ConversationTypes.d.ts +5 -0
- package/dist/lib/core/SingleAgentClient.d.mts +19 -1
- package/dist/lib/core/SingleAgentClient.d.ts +19 -1
- package/dist/lib/core/SingleAgentClient.js +38 -7
- package/dist/lib/core/SingleAgentClient.mjs +38 -7
- package/dist/lib/index.d.mts +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/reporting/ledger/handler.d.mts +6 -0
- package/dist/lib/reporting/ledger/handler.d.ts +6 -0
- package/dist/lib/reporting/ledger/handler.js +36 -7
- package/dist/lib/reporting/ledger/handler.mjs +35 -7
- package/dist/lib/reporting/ledger/index.d.mts +1 -0
- package/dist/lib/reporting/ledger/index.d.ts +1 -0
- package/dist/lib/reporting/ledger/index.js +3 -1
- package/dist/lib/reporting/ledger/index.mjs +1 -0
- package/dist/lib/reporting/ledger/lifecycle.js +3 -2
- package/dist/lib/reporting/ledger/lifecycle.mjs +3 -2
- package/dist/lib/reporting/ledger/managed-postgres.js +5 -5
- package/dist/lib/reporting/ledger/managed-postgres.mjs +5 -5
- package/dist/lib/reporting/ledger/postgres.d.mts +4 -1
- package/dist/lib/reporting/ledger/postgres.d.ts +4 -1
- package/dist/lib/reporting/ledger/postgres.js +38 -0
- package/dist/lib/reporting/ledger/postgres.mjs +38 -0
- package/dist/lib/reporting/ledger/producer.js +3 -2
- package/dist/lib/reporting/ledger/producer.mjs +3 -2
- package/dist/lib/reporting/ledger/revision-metadata.d.mts +17 -0
- package/dist/lib/reporting/ledger/revision-metadata.d.ts +17 -0
- package/dist/lib/reporting/ledger/revision-metadata.js +71 -0
- package/dist/lib/reporting/ledger/revision-metadata.mjs +44 -0
- package/dist/lib/reporting/ledger/row-encoding.d.mts +128 -0
- package/dist/lib/reporting/ledger/row-encoding.d.ts +128 -0
- package/dist/lib/reporting/ledger/row-encoding.js +355 -0
- package/dist/lib/reporting/ledger/row-encoding.mjs +315 -0
- package/dist/lib/reporting/ledger/types.d.mts +37 -0
- package/dist/lib/reporting/ledger/types.d.ts +37 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/docs/TYPE-SUMMARY.md +2 -1
- package/docs/guides/PUSH-NOTIFICATION-CONFIG.md +39 -0
- package/docs/llms.txt +1 -1
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/package.json +1 -1
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import { createHash } from "crypto";
|
|
2
|
+
import { canonicalize } from "../../utils/jcs.mjs";
|
|
3
|
+
const REPORTING_ROW_ENCODING_V1 = "adcp_canonical_jsonl_v1";
|
|
4
|
+
const REPORTING_ROW_SEGMENT_MAX_ROWS = 500;
|
|
5
|
+
const REPORTING_ROW_CHUNK_MAX_SEGMENTS = 20;
|
|
6
|
+
const REPORTING_ROW_CHUNK_MAX_ROWS = REPORTING_ROW_SEGMENT_MAX_ROWS * REPORTING_ROW_CHUNK_MAX_SEGMENTS;
|
|
7
|
+
const REPORTING_ROW_CHUNK_MAX_BYTES = 8 * 1024 * 1024;
|
|
8
|
+
const NEWLINE = 10;
|
|
9
|
+
const COMMA = Buffer.from(",", "utf8");
|
|
10
|
+
const LONE_SURROGATE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/;
|
|
11
|
+
class ReportingRowEncodingError extends Error {
|
|
12
|
+
constructor(code, detail) {
|
|
13
|
+
super(`Reporting row encoding: ${code}: ${detail}`);
|
|
14
|
+
this.code = code;
|
|
15
|
+
this.name = "ReportingRowEncodingError";
|
|
16
|
+
Object.defineProperty(this, /* @__PURE__ */ Symbol.for("adcp.reportingRowEncodingError"), { value: true });
|
|
17
|
+
}
|
|
18
|
+
code;
|
|
19
|
+
}
|
|
20
|
+
function isReportingRowEncodingError(error) {
|
|
21
|
+
return !!error && typeof error === "object" && error[/* @__PURE__ */ Symbol.for("adcp.reportingRowEncodingError")] === true;
|
|
22
|
+
}
|
|
23
|
+
function canonicalReportingRowV1(row, ordinal = 0) {
|
|
24
|
+
if (!row || typeof row !== "object" || Array.isArray(row)) {
|
|
25
|
+
throw new ReportingRowEncodingError("INVALID_ROW", `row ${ordinal} is not a JSON object`);
|
|
26
|
+
}
|
|
27
|
+
assertPortableNumbers(row, ordinal);
|
|
28
|
+
let canonical;
|
|
29
|
+
try {
|
|
30
|
+
canonical = canonicalize(row);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
throw new ReportingRowEncodingError(
|
|
33
|
+
"INVALID_ROW",
|
|
34
|
+
`row ${ordinal} is not canonical JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
if (LONE_SURROGATE.test(canonical)) {
|
|
38
|
+
throw new ReportingRowEncodingError("INVALID_ROW", `row ${ordinal} contains a lone surrogate`);
|
|
39
|
+
}
|
|
40
|
+
return canonical;
|
|
41
|
+
}
|
|
42
|
+
function encodeReportingRowsV1(rows) {
|
|
43
|
+
const chunks = [];
|
|
44
|
+
let chunkLines = [];
|
|
45
|
+
let chunkBytes = 0;
|
|
46
|
+
let chunkFirstOrdinal = 0;
|
|
47
|
+
const closeChunk = () => {
|
|
48
|
+
if (chunkLines.length === 0) return;
|
|
49
|
+
chunks.push(buildChunk(chunks.length, chunkFirstOrdinal, chunkLines));
|
|
50
|
+
chunkLines = [];
|
|
51
|
+
chunkBytes = 0;
|
|
52
|
+
};
|
|
53
|
+
rows.forEach((row, ordinal) => {
|
|
54
|
+
const line = Buffer.from(canonicalReportingRowV1(row, ordinal) + "\n", "utf8");
|
|
55
|
+
if (chunkLines.length === REPORTING_ROW_CHUNK_MAX_ROWS || chunkLines.length > 0 && chunkBytes + line.byteLength > REPORTING_ROW_CHUNK_MAX_BYTES) {
|
|
56
|
+
closeChunk();
|
|
57
|
+
}
|
|
58
|
+
if (chunkLines.length === 0) chunkFirstOrdinal = ordinal;
|
|
59
|
+
chunkLines.push(line);
|
|
60
|
+
chunkBytes += line.byteLength;
|
|
61
|
+
});
|
|
62
|
+
closeChunk();
|
|
63
|
+
const manifests = chunks.map((chunk) => chunk.manifest);
|
|
64
|
+
return {
|
|
65
|
+
encoding: REPORTING_ROW_ENCODING_V1,
|
|
66
|
+
rowCount: rows.length,
|
|
67
|
+
byteCount: chunks.reduce((total, chunk) => total + chunk.manifest.byte_count, 0),
|
|
68
|
+
chunks,
|
|
69
|
+
manifests,
|
|
70
|
+
rowManifestSha256: reportingRowManifestSha256V1(manifests)
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function reportingRowManifestSha256V1(manifests) {
|
|
74
|
+
return sha256Hex(
|
|
75
|
+
canonicalize(
|
|
76
|
+
manifests.map((manifest) => ({
|
|
77
|
+
chunk_index: manifest.chunk_index,
|
|
78
|
+
first_ordinal: manifest.first_ordinal,
|
|
79
|
+
row_count: manifest.row_count,
|
|
80
|
+
byte_count: manifest.byte_count,
|
|
81
|
+
sha256: manifest.sha256,
|
|
82
|
+
segments: manifest.segments.map((segment) => ({
|
|
83
|
+
first_ordinal: segment.first_ordinal,
|
|
84
|
+
row_count: segment.row_count,
|
|
85
|
+
byte_offset: segment.byte_offset,
|
|
86
|
+
byte_count: segment.byte_count,
|
|
87
|
+
sha256: segment.sha256
|
|
88
|
+
}))
|
|
89
|
+
}))
|
|
90
|
+
)
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
function verifyReportingRowManifestsV1(manifests, expected) {
|
|
94
|
+
if (reportingRowManifestSha256V1(manifests) !== expected.rowManifestSha256.toLowerCase()) {
|
|
95
|
+
throw new ReportingRowEncodingError("MANIFEST_MISMATCH", "chunk manifest digest does not match the header");
|
|
96
|
+
}
|
|
97
|
+
let nextOrdinal = 0;
|
|
98
|
+
manifests.forEach((manifest, index) => {
|
|
99
|
+
if (manifest.chunk_index !== index || manifest.first_ordinal !== nextOrdinal) {
|
|
100
|
+
throw new ReportingRowEncodingError("MANIFEST_MISMATCH", `chunk ${index} is out of order`);
|
|
101
|
+
}
|
|
102
|
+
if (manifest.row_count < 1 || manifest.row_count > REPORTING_ROW_CHUNK_MAX_ROWS || manifest.segments.length < 1 || manifest.segments.length > REPORTING_ROW_CHUNK_MAX_SEGMENTS) {
|
|
103
|
+
throw new ReportingRowEncodingError("MANIFEST_MISMATCH", `chunk ${index} exceeds contract limits`);
|
|
104
|
+
}
|
|
105
|
+
let segmentOrdinal = manifest.first_ordinal;
|
|
106
|
+
let segmentOffset = 0;
|
|
107
|
+
manifest.segments.forEach((segment, segmentIndex) => {
|
|
108
|
+
const last = segmentIndex === manifest.segments.length - 1;
|
|
109
|
+
if (segment.first_ordinal !== segmentOrdinal || segment.byte_offset !== segmentOffset || segment.row_count < 1 || segment.byte_count < 1 || segment.row_count > REPORTING_ROW_SEGMENT_MAX_ROWS || !last && segment.row_count !== REPORTING_ROW_SEGMENT_MAX_ROWS) {
|
|
110
|
+
throw new ReportingRowEncodingError("MANIFEST_MISMATCH", `chunk ${index} segment ${segmentIndex} is invalid`);
|
|
111
|
+
}
|
|
112
|
+
segmentOrdinal += segment.row_count;
|
|
113
|
+
segmentOffset += segment.byte_count;
|
|
114
|
+
});
|
|
115
|
+
if (segmentOrdinal !== manifest.first_ordinal + manifest.row_count || segmentOffset !== manifest.byte_count) {
|
|
116
|
+
throw new ReportingRowEncodingError("MANIFEST_MISMATCH", `chunk ${index} segments do not tile the chunk`);
|
|
117
|
+
}
|
|
118
|
+
if (manifest.row_count > 1 && manifest.byte_count > REPORTING_ROW_CHUNK_MAX_BYTES) {
|
|
119
|
+
throw new ReportingRowEncodingError("MANIFEST_MISMATCH", `chunk ${index} exceeds the byte limit`);
|
|
120
|
+
}
|
|
121
|
+
nextOrdinal += manifest.row_count;
|
|
122
|
+
});
|
|
123
|
+
if (nextOrdinal !== expected.rowCount) {
|
|
124
|
+
throw new ReportingRowEncodingError("MANIFEST_MISMATCH", "chunk manifests do not cover row_count");
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function verifyReportingRowChunkV1(manifest, bytes) {
|
|
128
|
+
const buffer = toBuffer(bytes);
|
|
129
|
+
if (buffer.byteLength !== manifest.byte_count || sha256Hex(buffer) !== manifest.sha256) {
|
|
130
|
+
throw new ReportingRowEncodingError("CHUNK_INTEGRITY_FAILED", `chunk ${manifest.chunk_index} digest mismatch`);
|
|
131
|
+
}
|
|
132
|
+
manifest.segments.forEach((segment, index) => {
|
|
133
|
+
verifySegment(manifest, index, buffer.subarray(segment.byte_offset, segment.byte_offset + segment.byte_count));
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function decodeVerifiedReportingRowSegmentsV1(manifest, segmentRange, bytes) {
|
|
137
|
+
const [from, to] = segmentRange;
|
|
138
|
+
if (!Number.isInteger(from) || !Number.isInteger(to) || from < 0 || to < from || to >= manifest.segments.length) {
|
|
139
|
+
throw new ReportingRowEncodingError("MANIFEST_MISMATCH", "segment range is outside the chunk");
|
|
140
|
+
}
|
|
141
|
+
const buffer = toBuffer(bytes);
|
|
142
|
+
const base = manifest.segments[from].byte_offset;
|
|
143
|
+
const end = manifest.segments[to].byte_offset + manifest.segments[to].byte_count;
|
|
144
|
+
if (buffer.byteLength !== end - base) {
|
|
145
|
+
throw new ReportingRowEncodingError("CHUNK_INTEGRITY_FAILED", "segment range byte length mismatch");
|
|
146
|
+
}
|
|
147
|
+
for (let index = from; index <= to; index += 1) {
|
|
148
|
+
const segment = manifest.segments[index];
|
|
149
|
+
verifySegment(
|
|
150
|
+
manifest,
|
|
151
|
+
index,
|
|
152
|
+
buffer.subarray(segment.byte_offset - base, segment.byte_offset - base + segment.byte_count)
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
return splitLines(buffer).map((line) => JSON.parse(line.toString("utf8")));
|
|
156
|
+
}
|
|
157
|
+
function createReportingRevisionEnvelopeHasherV1(envelope) {
|
|
158
|
+
const prefix = Buffer.from(
|
|
159
|
+
`{"control_totals":${canonicalize(envelope.control_totals)},"reporting_revision_id":${canonicalize(
|
|
160
|
+
envelope.reporting_revision_id
|
|
161
|
+
)},"reporting_rows":[`,
|
|
162
|
+
"utf8"
|
|
163
|
+
);
|
|
164
|
+
const suffix = Buffer.from(`],"row_count":${canonicalize(envelope.row_count)}}`, "utf8");
|
|
165
|
+
return createJoinedRowsHasher(prefix, suffix, envelope.row_count);
|
|
166
|
+
}
|
|
167
|
+
function reportingRevisionEnvelopeDigestV1(envelope, chunks) {
|
|
168
|
+
const hasher = createReportingRevisionEnvelopeHasherV1(envelope);
|
|
169
|
+
for (const chunk of chunks) hasher.update(chunk);
|
|
170
|
+
return hasher.digest();
|
|
171
|
+
}
|
|
172
|
+
function createReportingRowsOnlyHasherV1(rowCount) {
|
|
173
|
+
return createJoinedRowsHasher(Buffer.from("[", "utf8"), Buffer.from("]", "utf8"), rowCount);
|
|
174
|
+
}
|
|
175
|
+
function assertReportingRevisionEnvelopeV1(envelope, chunks, expected) {
|
|
176
|
+
const actual = reportingRevisionEnvelopeDigestV1(envelope, chunks);
|
|
177
|
+
if (actual.sha256 !== expected.sha256.toLowerCase() || expected.byteCount !== void 0 && actual.byteCount !== expected.byteCount) {
|
|
178
|
+
throw new ReportingRowEncodingError("ENVELOPE_INTEGRITY_FAILED", "revision content binding mismatch");
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function buildChunk(chunkIndex, firstOrdinal, lines) {
|
|
182
|
+
const segments = [];
|
|
183
|
+
let offset = 0;
|
|
184
|
+
for (let start = 0; start < lines.length; start += REPORTING_ROW_SEGMENT_MAX_ROWS) {
|
|
185
|
+
const segmentLines = lines.slice(start, start + REPORTING_ROW_SEGMENT_MAX_ROWS);
|
|
186
|
+
const segmentBytes = Buffer.concat(segmentLines);
|
|
187
|
+
segments.push({
|
|
188
|
+
first_ordinal: firstOrdinal + start,
|
|
189
|
+
row_count: segmentLines.length,
|
|
190
|
+
byte_offset: offset,
|
|
191
|
+
byte_count: segmentBytes.byteLength,
|
|
192
|
+
sha256: sha256Hex(segmentBytes)
|
|
193
|
+
});
|
|
194
|
+
offset += segmentBytes.byteLength;
|
|
195
|
+
}
|
|
196
|
+
const bytes = Buffer.concat(lines);
|
|
197
|
+
return {
|
|
198
|
+
manifest: {
|
|
199
|
+
chunk_index: chunkIndex,
|
|
200
|
+
first_ordinal: firstOrdinal,
|
|
201
|
+
row_count: lines.length,
|
|
202
|
+
byte_count: bytes.byteLength,
|
|
203
|
+
sha256: sha256Hex(bytes),
|
|
204
|
+
segments
|
|
205
|
+
},
|
|
206
|
+
bytes
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function verifySegment(manifest, index, bytes) {
|
|
210
|
+
const segment = manifest.segments[index];
|
|
211
|
+
if (bytes.byteLength !== segment.byte_count || sha256Hex(bytes) !== segment.sha256) {
|
|
212
|
+
throw new ReportingRowEncodingError(
|
|
213
|
+
"CHUNK_INTEGRITY_FAILED",
|
|
214
|
+
`chunk ${manifest.chunk_index} segment ${index} digest mismatch`
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
let lines = 0;
|
|
218
|
+
for (const byte of bytes) if (byte === NEWLINE) lines += 1;
|
|
219
|
+
if (lines !== segment.row_count || bytes[bytes.byteLength - 1] !== NEWLINE) {
|
|
220
|
+
throw new ReportingRowEncodingError(
|
|
221
|
+
"CHUNK_INTEGRITY_FAILED",
|
|
222
|
+
`chunk ${manifest.chunk_index} segment ${index} line count mismatch`
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function createJoinedRowsHasher(prefix, suffix, expectedRows) {
|
|
227
|
+
const hash = createHash("sha256").update(prefix);
|
|
228
|
+
let byteCount = prefix.byteLength;
|
|
229
|
+
let rows = 0;
|
|
230
|
+
let finished = false;
|
|
231
|
+
return {
|
|
232
|
+
update(chunkBytes) {
|
|
233
|
+
if (finished) throw new Error("Reporting row hasher already finished");
|
|
234
|
+
const buffer = toBuffer(chunkBytes);
|
|
235
|
+
if (buffer.byteLength > 0 && buffer[buffer.byteLength - 1] !== NEWLINE) {
|
|
236
|
+
throw new ReportingRowEncodingError("CHUNK_INTEGRITY_FAILED", "chunk does not end at a row boundary");
|
|
237
|
+
}
|
|
238
|
+
for (const line of splitLines(buffer)) {
|
|
239
|
+
if (rows > 0) {
|
|
240
|
+
hash.update(COMMA);
|
|
241
|
+
byteCount += 1;
|
|
242
|
+
}
|
|
243
|
+
hash.update(line);
|
|
244
|
+
byteCount += line.byteLength;
|
|
245
|
+
rows += 1;
|
|
246
|
+
}
|
|
247
|
+
},
|
|
248
|
+
digest() {
|
|
249
|
+
if (finished) throw new Error("Reporting row hasher already finished");
|
|
250
|
+
finished = true;
|
|
251
|
+
if (rows !== expectedRows) {
|
|
252
|
+
throw new ReportingRowEncodingError("ENVELOPE_INTEGRITY_FAILED", "row count does not match the header");
|
|
253
|
+
}
|
|
254
|
+
hash.update(suffix);
|
|
255
|
+
return { sha256: hash.digest("hex"), byteCount: byteCount + suffix.byteLength };
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function splitLines(buffer) {
|
|
260
|
+
const lines = [];
|
|
261
|
+
let start = 0;
|
|
262
|
+
for (let index = 0; index < buffer.byteLength; index += 1) {
|
|
263
|
+
if (buffer[index] === NEWLINE) {
|
|
264
|
+
lines.push(buffer.subarray(start, index));
|
|
265
|
+
start = index + 1;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (start !== buffer.byteLength) {
|
|
269
|
+
throw new ReportingRowEncodingError("CHUNK_INTEGRITY_FAILED", "trailing bytes after the last row");
|
|
270
|
+
}
|
|
271
|
+
return lines;
|
|
272
|
+
}
|
|
273
|
+
function assertPortableNumbers(value, ordinal) {
|
|
274
|
+
if (typeof value === "number") {
|
|
275
|
+
if (!Number.isFinite(value) || Number.isInteger(value) && !Number.isSafeInteger(value)) {
|
|
276
|
+
throw new ReportingRowEncodingError(
|
|
277
|
+
"INVALID_ROW",
|
|
278
|
+
`row ${ordinal} contains a number outside the portable range; encode it as a string`
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
if (Array.isArray(value)) {
|
|
284
|
+
for (const item of value) assertPortableNumbers(item, ordinal);
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
if (value && typeof value === "object") {
|
|
288
|
+
for (const item of Object.values(value)) assertPortableNumbers(item, ordinal);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function toBuffer(bytes) {
|
|
292
|
+
return Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
293
|
+
}
|
|
294
|
+
function sha256Hex(value) {
|
|
295
|
+
return createHash("sha256").update(value).digest("hex");
|
|
296
|
+
}
|
|
297
|
+
export {
|
|
298
|
+
REPORTING_ROW_CHUNK_MAX_BYTES,
|
|
299
|
+
REPORTING_ROW_CHUNK_MAX_ROWS,
|
|
300
|
+
REPORTING_ROW_CHUNK_MAX_SEGMENTS,
|
|
301
|
+
REPORTING_ROW_ENCODING_V1,
|
|
302
|
+
REPORTING_ROW_SEGMENT_MAX_ROWS,
|
|
303
|
+
ReportingRowEncodingError,
|
|
304
|
+
assertReportingRevisionEnvelopeV1,
|
|
305
|
+
canonicalReportingRowV1,
|
|
306
|
+
createReportingRevisionEnvelopeHasherV1,
|
|
307
|
+
createReportingRowsOnlyHasherV1,
|
|
308
|
+
decodeVerifiedReportingRowSegmentsV1,
|
|
309
|
+
encodeReportingRowsV1,
|
|
310
|
+
isReportingRowEncodingError,
|
|
311
|
+
reportingRevisionEnvelopeDigestV1,
|
|
312
|
+
reportingRowManifestSha256V1,
|
|
313
|
+
verifyReportingRowChunkV1,
|
|
314
|
+
verifyReportingRowManifestsV1
|
|
315
|
+
};
|
|
@@ -198,6 +198,21 @@ export interface ReportingLedgerAdjustmentV1 {
|
|
|
198
198
|
}
|
|
199
199
|
export type ReportingLedgerRevisionSnapshotV1 = Omit<ReportingLedgerRevisionV1, 'rows'>;
|
|
200
200
|
export type ReportingLedgerRevisionMetadataV1 = Omit<ReportingLedgerRevisionV1, 'rows'>;
|
|
201
|
+
export type ReportingLedgerAdjustmentMetadataV1 = Omit<ReportingLedgerAdjustmentV1, 'rows'>;
|
|
202
|
+
export interface ReportingRevisionRowsReadV1 {
|
|
203
|
+
reporting_revision_id: string;
|
|
204
|
+
account_id: string;
|
|
205
|
+
/** Zero-based ordinal of the first row to return. */
|
|
206
|
+
offset: number;
|
|
207
|
+
/** Maximum rows to return; at least 1. */
|
|
208
|
+
limit: number;
|
|
209
|
+
signal?: AbortSignal;
|
|
210
|
+
}
|
|
211
|
+
export interface ReportingRevisionRowsPageV1 {
|
|
212
|
+
rows: Record<string, unknown>[];
|
|
213
|
+
/** Total rows in the revision. */
|
|
214
|
+
total: number;
|
|
215
|
+
}
|
|
201
216
|
export type ReportingLedgerAdjustmentSnapshotV1 = Omit<ReportingLedgerAdjustmentV1, 'rows'>;
|
|
202
217
|
export interface ReportingLedgerConsumerStatusV1 {
|
|
203
218
|
consumerStatusId: string;
|
|
@@ -761,12 +776,34 @@ export interface ReportingLedgerStore {
|
|
|
761
776
|
}>;
|
|
762
777
|
/** Returns an exact row-bearing revision only when it belongs to the resolved account. */
|
|
763
778
|
getRevision(reporting_revision_id: string, account_id: string): Promise<ReportingLedgerRevisionV1 | null>;
|
|
779
|
+
/**
|
|
780
|
+
* Optional row-free counterpart of `getRevision`, scoped to the resolved
|
|
781
|
+
* account. Exact-read handlers prefer it so they never load every row to
|
|
782
|
+
* serve one page.
|
|
783
|
+
*/
|
|
784
|
+
getRevisionMetadata?(reporting_revision_id: string, account_id: string): Promise<ReportingLedgerRevisionMetadataV1 | null>;
|
|
785
|
+
/**
|
|
786
|
+
* Optional: one page of a revision's rows in ordinal order, only when the
|
|
787
|
+
* revision belongs to the resolved account. `total` is the revision's row
|
|
788
|
+
* count. Stores that keep rows outside the revision document verify every
|
|
789
|
+
* row they return against the committed binding before returning it.
|
|
790
|
+
*/
|
|
791
|
+
readRevisionRows?(input: ReportingRevisionRowsReadV1): Promise<ReportingRevisionRowsPageV1 | null>;
|
|
764
792
|
listRevisions(reporting_obligation_id: string): Promise<ReportingLedgerRevisionV1[]>;
|
|
793
|
+
/**
|
|
794
|
+
* Optional: every retained revision for one obligation without
|
|
795
|
+
* materializing rows. The producer, lifecycle reconciler and status ingest
|
|
796
|
+
* prefer it and otherwise fall back to `listRevisions` with rows dropped.
|
|
797
|
+
* When `account_id` is supplied, only that account's revisions are returned.
|
|
798
|
+
*/
|
|
799
|
+
listRevisionMetadata?(reporting_obligation_id: string, account_id?: string): Promise<ReportingLedgerRevisionMetadataV1[]>;
|
|
765
800
|
commitAdjustment(adjustment: ReportingLedgerAdjustmentV1, lease: ReportingLedgerLeaseV1): Promise<{
|
|
766
801
|
inserted: boolean;
|
|
767
802
|
value: ReportingLedgerAdjustmentV1;
|
|
768
803
|
}>;
|
|
769
804
|
listAdjustments(reporting_obligation_id: string): Promise<ReportingLedgerAdjustmentV1[]>;
|
|
805
|
+
/** Optional row-free counterpart of `listAdjustments`, preferred when present. */
|
|
806
|
+
listAdjustmentMetadata?(reporting_obligation_id: string): Promise<ReportingLedgerAdjustmentMetadataV1[]>;
|
|
770
807
|
putConsumerStatus(status: ReportingLedgerConsumerStatusV1): Promise<{
|
|
771
808
|
inserted: boolean;
|
|
772
809
|
value: ReportingLedgerConsumerStatusV1;
|
|
@@ -198,6 +198,21 @@ export interface ReportingLedgerAdjustmentV1 {
|
|
|
198
198
|
}
|
|
199
199
|
export type ReportingLedgerRevisionSnapshotV1 = Omit<ReportingLedgerRevisionV1, 'rows'>;
|
|
200
200
|
export type ReportingLedgerRevisionMetadataV1 = Omit<ReportingLedgerRevisionV1, 'rows'>;
|
|
201
|
+
export type ReportingLedgerAdjustmentMetadataV1 = Omit<ReportingLedgerAdjustmentV1, 'rows'>;
|
|
202
|
+
export interface ReportingRevisionRowsReadV1 {
|
|
203
|
+
reporting_revision_id: string;
|
|
204
|
+
account_id: string;
|
|
205
|
+
/** Zero-based ordinal of the first row to return. */
|
|
206
|
+
offset: number;
|
|
207
|
+
/** Maximum rows to return; at least 1. */
|
|
208
|
+
limit: number;
|
|
209
|
+
signal?: AbortSignal;
|
|
210
|
+
}
|
|
211
|
+
export interface ReportingRevisionRowsPageV1 {
|
|
212
|
+
rows: Record<string, unknown>[];
|
|
213
|
+
/** Total rows in the revision. */
|
|
214
|
+
total: number;
|
|
215
|
+
}
|
|
201
216
|
export type ReportingLedgerAdjustmentSnapshotV1 = Omit<ReportingLedgerAdjustmentV1, 'rows'>;
|
|
202
217
|
export interface ReportingLedgerConsumerStatusV1 {
|
|
203
218
|
consumerStatusId: string;
|
|
@@ -761,12 +776,34 @@ export interface ReportingLedgerStore {
|
|
|
761
776
|
}>;
|
|
762
777
|
/** Returns an exact row-bearing revision only when it belongs to the resolved account. */
|
|
763
778
|
getRevision(reporting_revision_id: string, account_id: string): Promise<ReportingLedgerRevisionV1 | null>;
|
|
779
|
+
/**
|
|
780
|
+
* Optional row-free counterpart of `getRevision`, scoped to the resolved
|
|
781
|
+
* account. Exact-read handlers prefer it so they never load every row to
|
|
782
|
+
* serve one page.
|
|
783
|
+
*/
|
|
784
|
+
getRevisionMetadata?(reporting_revision_id: string, account_id: string): Promise<ReportingLedgerRevisionMetadataV1 | null>;
|
|
785
|
+
/**
|
|
786
|
+
* Optional: one page of a revision's rows in ordinal order, only when the
|
|
787
|
+
* revision belongs to the resolved account. `total` is the revision's row
|
|
788
|
+
* count. Stores that keep rows outside the revision document verify every
|
|
789
|
+
* row they return against the committed binding before returning it.
|
|
790
|
+
*/
|
|
791
|
+
readRevisionRows?(input: ReportingRevisionRowsReadV1): Promise<ReportingRevisionRowsPageV1 | null>;
|
|
764
792
|
listRevisions(reporting_obligation_id: string): Promise<ReportingLedgerRevisionV1[]>;
|
|
793
|
+
/**
|
|
794
|
+
* Optional: every retained revision for one obligation without
|
|
795
|
+
* materializing rows. The producer, lifecycle reconciler and status ingest
|
|
796
|
+
* prefer it and otherwise fall back to `listRevisions` with rows dropped.
|
|
797
|
+
* When `account_id` is supplied, only that account's revisions are returned.
|
|
798
|
+
*/
|
|
799
|
+
listRevisionMetadata?(reporting_obligation_id: string, account_id?: string): Promise<ReportingLedgerRevisionMetadataV1[]>;
|
|
765
800
|
commitAdjustment(adjustment: ReportingLedgerAdjustmentV1, lease: ReportingLedgerLeaseV1): Promise<{
|
|
766
801
|
inserted: boolean;
|
|
767
802
|
value: ReportingLedgerAdjustmentV1;
|
|
768
803
|
}>;
|
|
769
804
|
listAdjustments(reporting_obligation_id: string): Promise<ReportingLedgerAdjustmentV1[]>;
|
|
805
|
+
/** Optional row-free counterpart of `listAdjustments`, preferred when present. */
|
|
806
|
+
listAdjustmentMetadata?(reporting_obligation_id: string): Promise<ReportingLedgerAdjustmentMetadataV1[]>;
|
|
770
807
|
putConsumerStatus(status: ReportingLedgerConsumerStatusV1): Promise<{
|
|
771
808
|
inserted: boolean;
|
|
772
809
|
value: ReportingLedgerConsumerStatusV1;
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
"source_sha": "4e553ad955f83b49c7d221ab5c3ff78237ad02e3",
|
|
5
5
|
"source_tarball_sha256": "580656d6466ef9f0d1119985e6726c2efea718dc671e2ad30957fcb2fd54af0f",
|
|
6
6
|
"upstream_adcp_version": "2.5.3",
|
|
7
|
-
"synced_at": "2026-10-
|
|
7
|
+
"synced_at": "2026-10-08T19:53:54.089Z"
|
|
8
8
|
}
|
|
@@ -197,7 +197,7 @@ export interface UpstreamTrafficQueryResult {
|
|
|
197
197
|
*/
|
|
198
198
|
export declare function runValidations(validations: StoryboardValidation[], context: ValidationContext): ValidationResult[];
|
|
199
199
|
/** Capability semver emitted in run summaries and used for advisory expiry. */
|
|
200
|
-
export declare const RUNNER_CAPABILITY_VERSION = "15.
|
|
200
|
+
export declare const RUNNER_CAPABILITY_VERSION = "15.4.0";
|
|
201
201
|
/** True when a failed validation contributes to the owning step's grade. */
|
|
202
202
|
export declare function validationFailsStep(result: ValidationResult): boolean;
|
|
203
203
|
/**
|
|
@@ -197,7 +197,7 @@ export interface UpstreamTrafficQueryResult {
|
|
|
197
197
|
*/
|
|
198
198
|
export declare function runValidations(validations: StoryboardValidation[], context: ValidationContext): ValidationResult[];
|
|
199
199
|
/** Capability semver emitted in run summaries and used for advisory expiry. */
|
|
200
|
-
export declare const RUNNER_CAPABILITY_VERSION = "15.
|
|
200
|
+
export declare const RUNNER_CAPABILITY_VERSION = "15.4.0";
|
|
201
201
|
/** True when a failed validation contributes to the owning step's grade. */
|
|
202
202
|
export declare function validationFailsStep(result: ValidationResult): boolean;
|
|
203
203
|
/**
|
package/dist/lib/version.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AdCP SDK library version
|
|
3
3
|
*/
|
|
4
|
-
export declare const LIBRARY_VERSION = "15.
|
|
4
|
+
export declare const LIBRARY_VERSION = "15.4.0";
|
|
5
5
|
/**
|
|
6
6
|
* AdCP specification version this library is built for
|
|
7
7
|
*/
|
|
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
|
|
|
33
33
|
* Full version information
|
|
34
34
|
*/
|
|
35
35
|
export declare const VERSION_INFO: {
|
|
36
|
-
readonly library: "15.
|
|
36
|
+
readonly library: "15.4.0";
|
|
37
37
|
readonly adcp: "3.2.3";
|
|
38
38
|
readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.2.1", "3.2", "3.2.2", "3.2.3"];
|
|
39
|
-
readonly generatedAt: "2026-10-
|
|
39
|
+
readonly generatedAt: "2026-10-08T17:53:59.048Z";
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
42
42
|
* Get the AdCP specification version this library is built for
|
package/dist/lib/version.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AdCP SDK library version
|
|
3
3
|
*/
|
|
4
|
-
export declare const LIBRARY_VERSION = "15.
|
|
4
|
+
export declare const LIBRARY_VERSION = "15.4.0";
|
|
5
5
|
/**
|
|
6
6
|
* AdCP specification version this library is built for
|
|
7
7
|
*/
|
|
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
|
|
|
33
33
|
* Full version information
|
|
34
34
|
*/
|
|
35
35
|
export declare const VERSION_INFO: {
|
|
36
|
-
readonly library: "15.
|
|
36
|
+
readonly library: "15.4.0";
|
|
37
37
|
readonly adcp: "3.2.3";
|
|
38
38
|
readonly compatibleVersions: readonly ["v2.5", "v2.6", "v3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.2.1", "3.2", "3.2.2", "3.2.3"];
|
|
39
|
-
readonly generatedAt: "2026-10-
|
|
39
|
+
readonly generatedAt: "2026-10-08T17:53:59.048Z";
|
|
40
40
|
};
|
|
41
41
|
/**
|
|
42
42
|
* Get the AdCP specification version this library is built for
|
package/dist/lib/version.js
CHANGED
|
@@ -31,7 +31,7 @@ __export(version_exports, {
|
|
|
31
31
|
toReleasePrecisionVersion: () => toReleasePrecisionVersion
|
|
32
32
|
});
|
|
33
33
|
module.exports = __toCommonJS(version_exports);
|
|
34
|
-
const LIBRARY_VERSION = "15.
|
|
34
|
+
const LIBRARY_VERSION = "15.4.0";
|
|
35
35
|
const ADCP_VERSION = "3.2.3";
|
|
36
36
|
const ADCP_MAJOR_VERSION = 3;
|
|
37
37
|
const COMPATIBLE_ADCP_VERSIONS = [
|
|
@@ -97,10 +97,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
|
|
|
97
97
|
"3.2.3"
|
|
98
98
|
];
|
|
99
99
|
const VERSION_INFO = {
|
|
100
|
-
library: "15.
|
|
100
|
+
library: "15.4.0",
|
|
101
101
|
adcp: "3.2.3",
|
|
102
102
|
compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
|
|
103
|
-
generatedAt: "2026-10-
|
|
103
|
+
generatedAt: "2026-10-08T17:53:59.048Z"
|
|
104
104
|
};
|
|
105
105
|
function getAdcpVersion() {
|
|
106
106
|
return ADCP_VERSION;
|
package/dist/lib/version.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const LIBRARY_VERSION = "15.
|
|
1
|
+
const LIBRARY_VERSION = "15.4.0";
|
|
2
2
|
const ADCP_VERSION = "3.2.3";
|
|
3
3
|
const ADCP_MAJOR_VERSION = 3;
|
|
4
4
|
const COMPATIBLE_ADCP_VERSIONS = [
|
|
@@ -64,10 +64,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
|
|
|
64
64
|
"3.2.3"
|
|
65
65
|
];
|
|
66
66
|
const VERSION_INFO = {
|
|
67
|
-
library: "15.
|
|
67
|
+
library: "15.4.0",
|
|
68
68
|
adcp: "3.2.3",
|
|
69
69
|
compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
|
|
70
|
-
generatedAt: "2026-10-
|
|
70
|
+
generatedAt: "2026-10-08T17:53:59.048Z"
|
|
71
71
|
};
|
|
72
72
|
function getAdcpVersion() {
|
|
73
73
|
return ADCP_VERSION;
|
package/docs/TYPE-SUMMARY.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# AdCP Type Summary
|
|
2
2
|
|
|
3
3
|
> Generated at: 2026-10-08
|
|
4
|
-
> @adcp/sdk v15.
|
|
4
|
+
> @adcp/sdk v15.4.0
|
|
5
5
|
|
|
6
6
|
Curated reference of the types that matter for using the AdCP client. For full generated types see `src/lib/types/tools.generated.ts` and `src/lib/types/core.generated.ts`.
|
|
7
7
|
|
|
@@ -57,6 +57,7 @@ interface TransportOptions {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
interface TaskOptions {
|
|
60
|
+
skipStatusHandlers?: boolean; // Skip inline completion handlers, including continuations
|
|
60
61
|
timeout?: number; // Absolute whole-task deadline
|
|
61
62
|
signal?: AbortSignal; // Caller cancellation
|
|
62
63
|
// Direct A2A mutation route, bound to authenticated principal + account scope.
|
|
@@ -39,6 +39,45 @@ the reporting webhook schema. A caller-provided reporting URL must always bring
|
|
|
39
39
|
its own complete authentication block; the client never pairs `webhookSecret`
|
|
40
40
|
with a caller-controlled endpoint.
|
|
41
41
|
|
|
42
|
+
## Inline completion handlers
|
|
43
|
+
|
|
44
|
+
Configured status handlers also run inline when a task call returns a successful
|
|
45
|
+
completed result. By default, an inline handler error rejects that call. For a
|
|
46
|
+
forwarding call whose caller will process the returned result, skip the inline
|
|
47
|
+
handler for that call:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
const result = await agent.syncCreatives(params, undefined, { skipStatusHandlers: true });
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The option follows submitted waits and deferred resumes, including stored
|
|
54
|
+
continuations resumed after restart. Independently delivered webhook handlers
|
|
55
|
+
still run; `skipStatusHandlers` does not disable webhook registration or delivery.
|
|
56
|
+
|
|
57
|
+
To keep successful results when inline post-processing fails, opt in at client
|
|
58
|
+
construction:
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
const agent = new SingleAgentClient(sellerConfig, {
|
|
62
|
+
handlers: {
|
|
63
|
+
onSyncCreativesStatusChange: recordCreativeResults,
|
|
64
|
+
},
|
|
65
|
+
isolateStatusHandlerErrors: true,
|
|
66
|
+
onStatusHandlerError: async (error, { handlerName, metadata }) => {
|
|
67
|
+
await recordLocalFailure(error, handlerName, metadata.task_id);
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Isolation returns the completed `TaskResult` and allows settlement acknowledgement.
|
|
73
|
+
The SDK adds a warning to `debug_logs` without including the handler's error text.
|
|
74
|
+
The observer receives the original error and completion metadata, so keep secrets
|
|
75
|
+
out of application logs. Observer errors add a warning and do not reject the task.
|
|
76
|
+
The observer is awaited; keep its work bounded so it cannot stall local completion.
|
|
77
|
+
Cancellation, response validation, settlement acknowledgement errors, and webhook
|
|
78
|
+
error handling retain their existing behavior. With isolation disabled, durable
|
|
79
|
+
handler failures remain retryable without redispatching the seller operation.
|
|
80
|
+
|
|
42
81
|
## Wire Payload
|
|
43
82
|
|
|
44
83
|
The default RFC 9421 registration has no `authentication` block:
|
package/docs/llms.txt
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Ad Context Protocol (AdCP)
|
|
2
2
|
|
|
3
3
|
> Generated at: 2026-10-08
|
|
4
|
-
> Library: @adcp/sdk v15.
|
|
4
|
+
> Library: @adcp/sdk v15.4.0
|
|
5
5
|
> AdCP major version: 3
|
|
6
6
|
> Canonical URL: https://adcontextprotocol.github.io/adcp-client/llms.txt
|
|
7
7
|
> Note: the `Library` stamp reflects the package.json version at doc-generation time. The narrative below describes the surface that lands on the next-published minor — including any 6.7 helpers documented here ahead of the release tag.
|
|
@@ -11,8 +11,8 @@ below as the publication/deployment gate.
|
|
|
11
11
|
|
|
12
12
|
| Fact | Value |
|
|
13
13
|
| --- | --- |
|
|
14
|
-
| Exact npm package | `@adcp/sdk@15.
|
|
15
|
-
| npm integrity | registry-derived after publication; run `npm view @adcp/sdk@15.
|
|
14
|
+
| Exact npm package | `@adcp/sdk@15.4.0` |
|
|
15
|
+
| npm integrity | registry-derived after publication; run `npm view @adcp/sdk@15.4.0 dist.integrity` |
|
|
16
16
|
| Node.js runtime | `^20.19.0 || >=22.12.0` |
|
|
17
17
|
| Default AdCP wire release | `3.2.3` |
|
|
18
18
|
| Maintained wire releases | `v2.5`, `v2.6`, `v3`, `3.0.0`, `3.0`, `3.0.1`, `3.0.2`, `3.0.3`, `3.0.4`, `3.0.5`, `3.0.6`, `3.0.7`, `3.0.8`, `3.0.9`, `3.0.10`, `3.0.11`, `3.0.12`, `3.0.13`, `3.0.14`, `3.0.15`, `3.0.16`, `3.0.17`, `3.0.18`, `3.0.19`, `3.0.20`, `3.0.21`, `3.0.22`, `3.0.23`, `3.0.24`, `3.0.25`, `3.1.0`, `3.1`, `3.1.1`, `3.1.2`, `3.1.3`, `3.1.4`, `3.1.5`, `3.1.6`, `3.1.7`, `3.1.8`, `3.1.9`, `3.1.10`, `3.1.11`, `3.1.12`, `3.1.13`, `3.1.14`, `3.1.15`, `3.1.16`, `3.1.17`, `3.1.18`, `3.1.19`, `3.1.20`, `3.1.21`, `3.1.22`, `3.1.23`, `3.1.24`, `3.2.1`, `3.2`, `3.2.2`, `3.2.3` |
|
|
@@ -21,8 +21,8 @@ below as the publication/deployment gate.
|
|
|
21
21
|
Install exact production inputs rather than a moving range or dist-tag:
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
npm install --save-exact '@adcp/sdk@15.
|
|
25
|
-
npm view '@adcp/sdk@15.
|
|
24
|
+
npm install --save-exact '@adcp/sdk@15.4.0'
|
|
25
|
+
npm view '@adcp/sdk@15.4.0' dist.integrity
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
### Required and optional peers
|