@opengeni/contracts 0.39.0 → 0.44.1
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/atlassian.d.ts +278 -0
- package/dist/atlassian.js +55 -0
- package/dist/atlassian.js.map +1 -0
- package/dist/chunk-52SGB2QO.js +688 -0
- package/dist/chunk-52SGB2QO.js.map +1 -0
- package/dist/{chunk-7JZMI22I.js → chunk-5UDNP7AO.js} +34 -2
- package/dist/chunk-5UDNP7AO.js.map +1 -0
- package/dist/chunk-BVGIYW7D.js +11 -0
- package/dist/chunk-BVGIYW7D.js.map +1 -0
- package/dist/chunk-CADSX6UN.js +1145 -0
- package/dist/chunk-CADSX6UN.js.map +1 -0
- package/dist/chunk-D2HKF2EF.js +1460 -0
- package/dist/chunk-D2HKF2EF.js.map +1 -0
- package/dist/chunk-FJBG5E4O.js +194 -0
- package/dist/chunk-FJBG5E4O.js.map +1 -0
- package/dist/chunk-H5BVCZKF.js +382 -0
- package/dist/chunk-H5BVCZKF.js.map +1 -0
- package/dist/chunk-LSB7GRLG.js +779 -0
- package/dist/chunk-LSB7GRLG.js.map +1 -0
- package/dist/chunk-MYBZRDTY.js +340 -0
- package/dist/chunk-MYBZRDTY.js.map +1 -0
- package/dist/chunk-RIY7GYQS.js +1204 -0
- package/dist/chunk-RIY7GYQS.js.map +1 -0
- package/dist/chunk-TZ6YEYN4.js +386 -0
- package/dist/chunk-TZ6YEYN4.js.map +1 -0
- package/dist/chunk-VA22KRHS.js +15177 -0
- package/dist/chunk-VA22KRHS.js.map +1 -0
- package/dist/chunk-Y3MLSLB4.js +392 -0
- package/dist/chunk-Y3MLSLB4.js.map +1 -0
- package/dist/chunk-YRKRZ6OF.js +134 -0
- package/dist/chunk-YRKRZ6OF.js.map +1 -0
- package/dist/company-profile.d.ts +629 -0
- package/dist/document-artifact-commands.d.ts +282 -0
- package/dist/document-artifact-commands.js +54 -0
- package/dist/document-artifact-commands.js.map +1 -0
- package/dist/document-artifact-query.d.ts +2 -0
- package/dist/document-artifact-query.js +54 -0
- package/dist/document-artifact-query.js.map +1 -0
- package/dist/editable-artifact-binary.d.ts +56 -0
- package/dist/editable-artifact-causal-frontier.d.ts +12 -0
- package/dist/editable-artifact-causal-frontier.js +18 -0
- package/dist/editable-artifact-causal-frontier.js.map +1 -0
- package/dist/editable-artifact-codec-registry.d.ts +48 -0
- package/dist/editable-artifact-codec-registry.js +20 -0
- package/dist/editable-artifact-codec-registry.js.map +1 -0
- package/dist/editable-artifact-committed-transaction.d.ts +35 -0
- package/dist/editable-artifact-committed-transaction.js +19 -0
- package/dist/editable-artifact-committed-transaction.js.map +1 -0
- package/dist/editable-artifact-live.d.ts +276 -0
- package/dist/editable-artifact-live.js +907 -0
- package/dist/editable-artifact-live.js.map +1 -0
- package/dist/editable-artifact-serialized-commit.d.ts +53 -0
- package/dist/editable-artifact-serialized-commit.js +26 -0
- package/dist/editable-artifact-serialized-commit.js.map +1 -0
- package/dist/editable-artifact-versions.d.ts +6 -0
- package/dist/editable-artifact-versions.js +11 -0
- package/dist/editable-artifact-versions.js.map +1 -0
- package/dist/editable-artifacts.d.ts +46 -0
- package/dist/editable-artifacts.js +236 -0
- package/dist/editable-artifacts.js.map +1 -0
- package/dist/event-preview.d.ts +7 -7
- package/dist/google-drive.d.ts +114 -2
- package/dist/google-drive.js +70 -14
- package/dist/google-drive.js.map +1 -1
- package/dist/image-generation.d.ts +70 -0
- package/dist/index.d.ts +5180 -329
- package/dist/index.js +1173 -40
- package/dist/interaction.d.ts +6895 -0
- package/dist/mcp-receipts.d.ts +96 -0
- package/dist/memory-slack-delivery.d.ts +397 -0
- package/dist/presentation-artifact-commands.d.ts +349 -0
- package/dist/presentation-artifact-commands.js +66 -0
- package/dist/presentation-artifact-commands.js.map +1 -0
- package/dist/presentation-artifact-query.d.ts +2 -0
- package/dist/presentation-artifact-query.js +66 -0
- package/dist/presentation-artifact-query.js.map +1 -0
- package/dist/retained-output.d.ts +83 -6
- package/dist/sandbox-snapshots.d.ts +9 -0
- package/dist/scoped-knowledge.d.ts +14 -13
- package/dist/slack-bot-scopes.d.ts +4 -0
- package/dist/slack-bot-scopes.js +3 -1
- package/dist/spreadsheet-artifact-commands.d.ts +101 -0
- package/dist/spreadsheet-artifact-commands.js +27 -0
- package/dist/spreadsheet-artifact-commands.js.map +1 -0
- package/dist/spreadsheet-artifact-date.d.ts +4 -0
- package/dist/spreadsheet-artifact-query.d.ts +120 -0
- package/dist/spreadsheet-artifact-query.js +48 -0
- package/dist/spreadsheet-artifact-query.js.map +1 -0
- package/dist/tool-catalog.d.ts +576 -0
- package/dist/video-generation.d.ts +532 -0
- package/dist/video-generation.js +51 -0
- package/dist/video-generation.js.map +1 -0
- package/dist/workspace-learning-policy.d.ts +208 -0
- package/package.json +61 -1
- package/src/atlassian.ts +160 -0
- package/src/company-profile.ts +306 -0
- package/src/document-artifact-commands.ts +1709 -0
- package/src/document-artifact-query.ts +2 -0
- package/src/editable-artifact-binary.ts +396 -0
- package/src/editable-artifact-causal-frontier.ts +154 -0
- package/src/editable-artifact-codec-registry.ts +261 -0
- package/src/editable-artifact-committed-transaction.ts +478 -0
- package/src/editable-artifact-live.ts +1379 -0
- package/src/editable-artifact-serialized-commit.ts +494 -0
- package/src/editable-artifact-versions.ts +8 -0
- package/src/editable-artifacts.ts +473 -0
- package/src/event-preview.ts +6 -6
- package/src/google-drive.ts +68 -15
- package/src/image-generation.ts +106 -0
- package/src/index.ts +2535 -282
- package/src/interaction.ts +2292 -0
- package/src/mcp-receipts.ts +281 -0
- package/src/memory-slack-delivery.ts +183 -0
- package/src/presentation-artifact-commands.ts +2035 -0
- package/src/presentation-artifact-query.ts +2 -0
- package/src/retained-output.ts +248 -8
- package/src/sandbox-snapshots.ts +28 -1
- package/src/scoped-knowledge.ts +18 -4
- package/src/slack-bot-scopes.ts +34 -1
- package/src/spreadsheet-artifact-commands.ts +999 -0
- package/src/spreadsheet-artifact-date.ts +21 -0
- package/src/spreadsheet-artifact-query.ts +1411 -0
- package/src/tool-catalog.ts +334 -0
- package/src/video-generation.ts +394 -0
- package/src/workspace-learning-policy.ts +233 -0
- package/dist/chunk-7JZMI22I.js.map +0 -1
- package/dist/chunk-PCTCJEAF.js +0 -10799
- package/dist/chunk-PCTCJEAF.js.map +0 -1
- package/dist/secret-redaction.d.ts +0 -40
- package/src/secret-redaction.ts +0 -364
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
const TEXT_ENCODER = new TextEncoder();
|
|
2
|
+
const TEXT_DECODER = new TextDecoder("utf-8", { fatal: true });
|
|
3
|
+
const FNV_OFFSET = 0xcbf29ce484222325n;
|
|
4
|
+
const FNV_PRIME = 0x100000001b3n;
|
|
5
|
+
const SAFE_INTEGER = BigInt(Number.MAX_SAFE_INTEGER);
|
|
6
|
+
const STABLE_ID = /^[0-9a-f]{32}$/u;
|
|
7
|
+
|
|
8
|
+
export const EDITABLE_ARTIFACT_BINARY_HEADER_BYTES = 24;
|
|
9
|
+
export const EDITABLE_ARTIFACT_BINARY_CHECKSUM_BYTES = 8;
|
|
10
|
+
|
|
11
|
+
export function strictUtf8(value: string, label: string): Uint8Array {
|
|
12
|
+
if (typeof value !== "string") throw new TypeError(`${label} must be a string`);
|
|
13
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
14
|
+
const code = value.charCodeAt(index);
|
|
15
|
+
if (code >= 0xd800 && code <= 0xdbff) {
|
|
16
|
+
const next = value.charCodeAt(index + 1);
|
|
17
|
+
if (next < 0xdc00 || next > 0xdfff) {
|
|
18
|
+
throw new TypeError(`${label} contains an unpaired surrogate`);
|
|
19
|
+
}
|
|
20
|
+
index += 1;
|
|
21
|
+
} else if (code >= 0xdc00 && code <= 0xdfff) {
|
|
22
|
+
throw new TypeError(`${label} contains an unpaired surrogate`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return TEXT_ENCODER.encode(value);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function decodeUtf8(bytes: Uint8Array, label: string): string {
|
|
29
|
+
try {
|
|
30
|
+
return TEXT_DECODER.decode(bytes);
|
|
31
|
+
} catch {
|
|
32
|
+
throw new TypeError(`${label} is not valid UTF-8`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function canonicalStableId(value: string, label: string): string {
|
|
37
|
+
if (!STABLE_ID.test(value)) {
|
|
38
|
+
throw new TypeError(`${label} must be a lowercase 128-bit hexadecimal id`);
|
|
39
|
+
}
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function allocatedStableId(value: string, label: string): string {
|
|
44
|
+
canonicalStableId(value, label);
|
|
45
|
+
if (value.slice(0, 16) === "0000000000000000" || value.slice(16) === "0000000000000000") {
|
|
46
|
+
throw new TypeError(`${label} must have nonzero namespace and counter`);
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function positiveSafeInteger(value: number, label: string): number {
|
|
52
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
53
|
+
throw new TypeError(`${label} must be a positive safe integer`);
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function nonnegativeSafeInteger(value: number, label: string): number {
|
|
59
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
60
|
+
throw new TypeError(`${label} must be a nonnegative safe integer`);
|
|
61
|
+
}
|
|
62
|
+
return value;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function boundedU32(value: number, label: string, maximum = 0xffff_ffff): number {
|
|
66
|
+
if (!Number.isInteger(value) || value < 0 || value > maximum) {
|
|
67
|
+
throw new RangeError(`${label} is outside its unsigned 32-bit bound`);
|
|
68
|
+
}
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function canonicalNumber(value: number, label: string): number {
|
|
73
|
+
if (!Number.isFinite(value) || Object.is(value, -0)) {
|
|
74
|
+
throw new TypeError(`${label} must be finite and must not be negative zero`);
|
|
75
|
+
}
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function fnv1a64(bytes: Uint8Array): bigint {
|
|
80
|
+
let hash = FNV_OFFSET;
|
|
81
|
+
for (const byte of bytes) {
|
|
82
|
+
hash ^= BigInt(byte);
|
|
83
|
+
hash = BigInt.asUintN(64, hash * FNV_PRIME);
|
|
84
|
+
}
|
|
85
|
+
return hash;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function equalBytes(left: Uint8Array, right: Uint8Array): boolean {
|
|
89
|
+
return left.byteLength === right.byteLength && left.every((byte, index) => byte === right[index]);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export class ArtifactBinaryWriter {
|
|
93
|
+
readonly #maximum: number;
|
|
94
|
+
#bytes: Uint8Array;
|
|
95
|
+
#view: DataView;
|
|
96
|
+
#length = 0;
|
|
97
|
+
|
|
98
|
+
constructor(maximum: number) {
|
|
99
|
+
this.#maximum = nonnegativeSafeInteger(maximum, "binary writer maximum");
|
|
100
|
+
this.#bytes = new Uint8Array(Math.min(Math.max(maximum, 32), 1024));
|
|
101
|
+
this.#view = new DataView(this.#bytes.buffer);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
get length(): number {
|
|
105
|
+
return this.#length;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
view(): Uint8Array {
|
|
109
|
+
return this.#bytes.subarray(0, this.#length);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
finish(): Uint8Array {
|
|
113
|
+
return this.#bytes.slice(0, this.#length);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#reserve(additional: number): void {
|
|
117
|
+
const next = this.#length + additional;
|
|
118
|
+
if (!Number.isSafeInteger(next) || next > this.#maximum) {
|
|
119
|
+
throw new RangeError("editable artifact binary payload exceeds its byte limit");
|
|
120
|
+
}
|
|
121
|
+
if (next <= this.#bytes.byteLength) return;
|
|
122
|
+
let capacity = this.#bytes.byteLength;
|
|
123
|
+
while (capacity < next) capacity = Math.min(this.#maximum, Math.max(next, capacity * 2));
|
|
124
|
+
const grown = new Uint8Array(capacity);
|
|
125
|
+
grown.set(this.#bytes.subarray(0, this.#length));
|
|
126
|
+
this.#bytes = grown;
|
|
127
|
+
this.#view = new DataView(grown.buffer);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
bytes(value: Uint8Array): void {
|
|
131
|
+
this.#reserve(value.byteLength);
|
|
132
|
+
this.#bytes.set(value, this.#length);
|
|
133
|
+
this.#length += value.byteLength;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
u8(value: number): void {
|
|
137
|
+
boundedU32(value, "u8", 0xff);
|
|
138
|
+
this.#reserve(1);
|
|
139
|
+
this.#view.setUint8(this.#length, value);
|
|
140
|
+
this.#length += 1;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
bool(value: boolean): void {
|
|
144
|
+
if (typeof value !== "boolean") throw new TypeError("boolean value is invalid");
|
|
145
|
+
this.u8(value ? 1 : 0);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
u16(value: number): void {
|
|
149
|
+
boundedU32(value, "u16", 0xffff);
|
|
150
|
+
this.#reserve(2);
|
|
151
|
+
this.#view.setUint16(this.#length, value, true);
|
|
152
|
+
this.#length += 2;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
u32(value: number): void {
|
|
156
|
+
boundedU32(value, "u32");
|
|
157
|
+
this.#reserve(4);
|
|
158
|
+
this.#view.setUint32(this.#length, value, true);
|
|
159
|
+
this.#length += 4;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
i32(value: number): void {
|
|
163
|
+
if (!Number.isInteger(value) || value < -0x8000_0000 || value > 0x7fff_ffff) {
|
|
164
|
+
throw new RangeError("i32 value is outside its bound");
|
|
165
|
+
}
|
|
166
|
+
this.#reserve(4);
|
|
167
|
+
this.#view.setInt32(this.#length, value, true);
|
|
168
|
+
this.#length += 4;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
u64(value: bigint | number): void {
|
|
172
|
+
const encoded =
|
|
173
|
+
typeof value === "number" ? BigInt(nonnegativeSafeInteger(value, "u64")) : value;
|
|
174
|
+
if (encoded < 0n || encoded > 0xffff_ffff_ffff_ffffn)
|
|
175
|
+
throw new RangeError("u64 value is outside its bound");
|
|
176
|
+
this.#reserve(8);
|
|
177
|
+
this.#view.setBigUint64(this.#length, encoded, true);
|
|
178
|
+
this.#length += 8;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
i64(value: bigint | number): void {
|
|
182
|
+
const encoded =
|
|
183
|
+
typeof value === "number"
|
|
184
|
+
? BigInt(
|
|
185
|
+
Number.isSafeInteger(value)
|
|
186
|
+
? value
|
|
187
|
+
: (() => {
|
|
188
|
+
throw new TypeError("i64 number must be safe");
|
|
189
|
+
})(),
|
|
190
|
+
)
|
|
191
|
+
: value;
|
|
192
|
+
if (encoded < -0x8000_0000_0000_0000n || encoded > 0x7fff_ffff_ffff_ffffn) {
|
|
193
|
+
throw new RangeError("i64 value is outside its bound");
|
|
194
|
+
}
|
|
195
|
+
this.#reserve(8);
|
|
196
|
+
this.#view.setBigInt64(this.#length, encoded, true);
|
|
197
|
+
this.#length += 8;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
f64(value: number, label = "number"): void {
|
|
201
|
+
canonicalNumber(value, label);
|
|
202
|
+
this.#reserve(8);
|
|
203
|
+
this.#view.setFloat64(this.#length, value, true);
|
|
204
|
+
this.#length += 8;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
count(value: number, maximum: number, label: string): void {
|
|
208
|
+
if (!Number.isInteger(value) || value < 0 || value > maximum) {
|
|
209
|
+
throw new RangeError(`${label} exceeds its collection bound`);
|
|
210
|
+
}
|
|
211
|
+
this.u32(value);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
string(value: string, maximum: number, label: string): void {
|
|
215
|
+
const bytes = strictUtf8(value, label);
|
|
216
|
+
if (bytes.byteLength > maximum) throw new RangeError(`${label} exceeds its byte limit`);
|
|
217
|
+
this.u32(bytes.byteLength);
|
|
218
|
+
this.bytes(bytes);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
stableId(value: string, label: string, requireAllocated = false): void {
|
|
222
|
+
(requireAllocated ? allocatedStableId : canonicalStableId)(value, label);
|
|
223
|
+
this.u64(BigInt(`0x${value.slice(16)}`));
|
|
224
|
+
this.u64(BigInt(`0x${value.slice(0, 16)}`));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export class ArtifactBinaryReader {
|
|
229
|
+
readonly #bytes: Uint8Array;
|
|
230
|
+
readonly #view: DataView;
|
|
231
|
+
#offset = 0;
|
|
232
|
+
|
|
233
|
+
constructor(bytes: Uint8Array) {
|
|
234
|
+
if (!(bytes instanceof Uint8Array)) throw new TypeError("binary input must be a Uint8Array");
|
|
235
|
+
this.#bytes = bytes;
|
|
236
|
+
this.#view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
get remaining(): number {
|
|
240
|
+
return this.#bytes.byteLength - this.#offset;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
done(message = "editable artifact binary payload contains trailing bytes"): void {
|
|
244
|
+
if (this.remaining !== 0) throw new TypeError(message);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
bytes(length: number): Uint8Array {
|
|
248
|
+
if (!Number.isSafeInteger(length) || length < 0 || length > this.remaining) {
|
|
249
|
+
throw new TypeError("truncated editable artifact binary payload");
|
|
250
|
+
}
|
|
251
|
+
const value = this.#bytes.subarray(this.#offset, this.#offset + length);
|
|
252
|
+
this.#offset += length;
|
|
253
|
+
return value;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
u8(): number {
|
|
257
|
+
return this.bytes(1)[0]!;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
bool(label = "boolean"): boolean {
|
|
261
|
+
const value = this.u8();
|
|
262
|
+
if (value > 1) throw new TypeError(`invalid ${label}`);
|
|
263
|
+
return value === 1;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
u16(): number {
|
|
267
|
+
const offset = this.#offset;
|
|
268
|
+
this.bytes(2);
|
|
269
|
+
return this.#view.getUint16(offset, true);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
u32(): number {
|
|
273
|
+
const offset = this.#offset;
|
|
274
|
+
this.bytes(4);
|
|
275
|
+
return this.#view.getUint32(offset, true);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
i32(): number {
|
|
279
|
+
const offset = this.#offset;
|
|
280
|
+
this.bytes(4);
|
|
281
|
+
return this.#view.getInt32(offset, true);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
u64BigInt(): bigint {
|
|
285
|
+
const offset = this.#offset;
|
|
286
|
+
this.bytes(8);
|
|
287
|
+
return this.#view.getBigUint64(offset, true);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
u64Safe(label: string): number {
|
|
291
|
+
const value = this.u64BigInt();
|
|
292
|
+
if (value > SAFE_INTEGER) throw new RangeError(`${label} exceeds the JavaScript-safe bound`);
|
|
293
|
+
return Number(value);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
i64BigInt(): bigint {
|
|
297
|
+
const offset = this.#offset;
|
|
298
|
+
this.bytes(8);
|
|
299
|
+
return this.#view.getBigInt64(offset, true);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
i64Safe(label: string): number {
|
|
303
|
+
const value = this.i64BigInt();
|
|
304
|
+
if (value < -SAFE_INTEGER || value > SAFE_INTEGER)
|
|
305
|
+
throw new RangeError(`${label} exceeds the JavaScript-safe bound`);
|
|
306
|
+
return Number(value);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
f64(label: string): number {
|
|
310
|
+
const offset = this.#offset;
|
|
311
|
+
this.bytes(8);
|
|
312
|
+
return canonicalNumber(this.#view.getFloat64(offset, true), label);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
count(maximum: number, label: string, minimumBytes = 0): number {
|
|
316
|
+
const value = this.u32();
|
|
317
|
+
if (value > maximum) throw new RangeError(`${label} exceeds its collection bound`);
|
|
318
|
+
if (minimumBytes > 0 && value > Math.floor(this.remaining / minimumBytes)) {
|
|
319
|
+
throw new TypeError("truncated editable artifact binary payload");
|
|
320
|
+
}
|
|
321
|
+
return value;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
string(maximum: number, label: string): string {
|
|
325
|
+
const length = this.count(maximum, label, 1);
|
|
326
|
+
return decodeUtf8(this.bytes(length), label);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
stableId(label: string, requireAllocated = false): string {
|
|
330
|
+
const counter = this.u64BigInt().toString(16).padStart(16, "0");
|
|
331
|
+
const namespace = this.u64BigInt().toString(16).padStart(16, "0");
|
|
332
|
+
const value = `${namespace}${counter}`;
|
|
333
|
+
return (requireAllocated ? allocatedStableId : canonicalStableId)(value, label);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export function encodeCountedEnvelope(
|
|
338
|
+
magic: string,
|
|
339
|
+
version: number,
|
|
340
|
+
count: number,
|
|
341
|
+
payload: Uint8Array,
|
|
342
|
+
maximum: number,
|
|
343
|
+
): Uint8Array {
|
|
344
|
+
if (strictUtf8(magic, "envelope magic").byteLength !== 8)
|
|
345
|
+
throw new TypeError("envelope magic must be eight bytes");
|
|
346
|
+
const output = new ArtifactBinaryWriter(maximum);
|
|
347
|
+
output.bytes(strictUtf8(magic, "envelope magic"));
|
|
348
|
+
output.u16(version);
|
|
349
|
+
output.u16(0);
|
|
350
|
+
output.u32(count);
|
|
351
|
+
output.u64(BigInt(payload.byteLength));
|
|
352
|
+
output.bytes(payload);
|
|
353
|
+
output.u64(fnv1a64(output.view()));
|
|
354
|
+
return output.finish();
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export function decodeCountedEnvelope(
|
|
358
|
+
bytes: Uint8Array,
|
|
359
|
+
magic: string,
|
|
360
|
+
version: number,
|
|
361
|
+
maximum: number,
|
|
362
|
+
maxCount: number,
|
|
363
|
+
): { count: number; payload: Uint8Array } {
|
|
364
|
+
if (!(bytes instanceof Uint8Array)) throw new TypeError("envelope bytes must be a Uint8Array");
|
|
365
|
+
if (bytes.byteLength > maximum)
|
|
366
|
+
throw new RangeError("editable artifact envelope exceeds its byte limit");
|
|
367
|
+
if (
|
|
368
|
+
bytes.byteLength <
|
|
369
|
+
EDITABLE_ARTIFACT_BINARY_HEADER_BYTES + EDITABLE_ARTIFACT_BINARY_CHECKSUM_BYTES
|
|
370
|
+
) {
|
|
371
|
+
throw new TypeError("truncated editable artifact envelope");
|
|
372
|
+
}
|
|
373
|
+
const reader = new ArtifactBinaryReader(bytes);
|
|
374
|
+
if (!equalBytes(reader.bytes(8), strictUtf8(magic, "envelope magic")))
|
|
375
|
+
throw new TypeError("invalid editable artifact envelope magic");
|
|
376
|
+
const actualVersion = reader.u16();
|
|
377
|
+
if (actualVersion !== version)
|
|
378
|
+
throw new TypeError(`unsupported editable artifact envelope version: ${actualVersion}`);
|
|
379
|
+
if (reader.u16() !== 0)
|
|
380
|
+
throw new TypeError("reserved editable artifact envelope flags must be zero");
|
|
381
|
+
const count = reader.u32();
|
|
382
|
+
if (count > maxCount) throw new RangeError("editable artifact envelope count exceeds its limit");
|
|
383
|
+
const payloadLength = reader.u64Safe("editable artifact payload length");
|
|
384
|
+
const expected =
|
|
385
|
+
EDITABLE_ARTIFACT_BINARY_HEADER_BYTES + payloadLength + EDITABLE_ARTIFACT_BINARY_CHECKSUM_BYTES;
|
|
386
|
+
if (bytes.byteLength < expected) throw new TypeError("truncated editable artifact envelope");
|
|
387
|
+
if (bytes.byteLength > expected)
|
|
388
|
+
throw new TypeError("editable artifact envelope contains trailing bytes");
|
|
389
|
+
const payload = reader.bytes(payloadLength);
|
|
390
|
+
const checksum = reader.u64BigInt();
|
|
391
|
+
reader.done();
|
|
392
|
+
if (checksum !== fnv1a64(bytes.subarray(0, -EDITABLE_ARTIFACT_BINARY_CHECKSUM_BYTES))) {
|
|
393
|
+
throw new TypeError("editable artifact envelope checksum does not match");
|
|
394
|
+
}
|
|
395
|
+
return { count, payload };
|
|
396
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ArtifactBinaryReader,
|
|
3
|
+
ArtifactBinaryWriter,
|
|
4
|
+
equalBytes,
|
|
5
|
+
fnv1a64,
|
|
6
|
+
positiveSafeInteger,
|
|
7
|
+
strictUtf8,
|
|
8
|
+
} from "./editable-artifact-binary";
|
|
9
|
+
|
|
10
|
+
export const EDITABLE_ARTIFACT_CAUSAL_FRONTIER_VERSION = 1 as const;
|
|
11
|
+
/** Exact effective Rust OGACF001 bound (`MAX_INTENT_CAUSAL_ACTORS`). */
|
|
12
|
+
export const EDITABLE_ARTIFACT_CAUSAL_FRONTIER_MAX_REPLICAS = 1_024;
|
|
13
|
+
export const EDITABLE_ARTIFACT_CAUSAL_FRONTIER_MAX_BYTES =
|
|
14
|
+
8 + 2 + 2 + 4 + EDITABLE_ARTIFACT_CAUSAL_FRONTIER_MAX_REPLICAS * 16 + 8;
|
|
15
|
+
|
|
16
|
+
const MAGIC = strictUtf8("OGACF001", "causal frontier magic");
|
|
17
|
+
const REPLICA_ID = /^[0-9a-f]{16}$/u;
|
|
18
|
+
const HEADER_BYTES = 16;
|
|
19
|
+
const CHECKSUM_BYTES = 8;
|
|
20
|
+
|
|
21
|
+
export type EditableArtifactCausalFrontierEntry = Readonly<{
|
|
22
|
+
replicaId: string;
|
|
23
|
+
counter: number;
|
|
24
|
+
}>;
|
|
25
|
+
|
|
26
|
+
export type EditableArtifactCausalFrontier = readonly EditableArtifactCausalFrontierEntry[];
|
|
27
|
+
|
|
28
|
+
export function encodeEditableArtifactCausalFrontier(
|
|
29
|
+
frontier: EditableArtifactCausalFrontier,
|
|
30
|
+
): Uint8Array {
|
|
31
|
+
const entries = normalizeFrontier(frontier);
|
|
32
|
+
const writer = new ArtifactBinaryWriter(EDITABLE_ARTIFACT_CAUSAL_FRONTIER_MAX_BYTES);
|
|
33
|
+
writer.bytes(MAGIC);
|
|
34
|
+
writer.u16(EDITABLE_ARTIFACT_CAUSAL_FRONTIER_VERSION);
|
|
35
|
+
writer.u16(0);
|
|
36
|
+
writer.u32(entries.length);
|
|
37
|
+
for (const entry of entries) {
|
|
38
|
+
writer.u64(BigInt(`0x${entry.replicaId}`));
|
|
39
|
+
writer.u64(entry.counter);
|
|
40
|
+
}
|
|
41
|
+
writer.u64(fnv1a64(writer.view()));
|
|
42
|
+
return writer.finish();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function decodeEditableArtifactCausalFrontier(
|
|
46
|
+
bytes: Uint8Array,
|
|
47
|
+
): EditableArtifactCausalFrontier {
|
|
48
|
+
if (!(bytes instanceof Uint8Array))
|
|
49
|
+
throw new TypeError("causal frontier bytes must be a Uint8Array");
|
|
50
|
+
if (bytes.byteLength > EDITABLE_ARTIFACT_CAUSAL_FRONTIER_MAX_BYTES) {
|
|
51
|
+
throw new RangeError("causal frontier exceeds its byte limit");
|
|
52
|
+
}
|
|
53
|
+
if (bytes.byteLength < HEADER_BYTES + CHECKSUM_BYTES) {
|
|
54
|
+
throw new TypeError("truncated causal frontier");
|
|
55
|
+
}
|
|
56
|
+
const reader = new ArtifactBinaryReader(bytes);
|
|
57
|
+
if (!equalBytes(reader.bytes(8), MAGIC)) throw new TypeError("invalid causal frontier magic");
|
|
58
|
+
const version = reader.u16();
|
|
59
|
+
if (version !== EDITABLE_ARTIFACT_CAUSAL_FRONTIER_VERSION) {
|
|
60
|
+
throw new TypeError(`unsupported causal frontier version: ${version}`);
|
|
61
|
+
}
|
|
62
|
+
if (reader.u16() !== 0) throw new TypeError("reserved causal frontier flags must be zero");
|
|
63
|
+
const count = reader.u32();
|
|
64
|
+
if (count > EDITABLE_ARTIFACT_CAUSAL_FRONTIER_MAX_REPLICAS) {
|
|
65
|
+
throw new RangeError("causal frontier exceeds its replica limit");
|
|
66
|
+
}
|
|
67
|
+
const expected = HEADER_BYTES + count * 16 + CHECKSUM_BYTES;
|
|
68
|
+
if (bytes.byteLength < expected) throw new TypeError("truncated causal frontier");
|
|
69
|
+
if (bytes.byteLength > expected) throw new TypeError("causal frontier contains trailing bytes");
|
|
70
|
+
if (fnv1a64(bytes.subarray(0, -CHECKSUM_BYTES)) !== readU64At(bytes, expected - CHECKSUM_BYTES)) {
|
|
71
|
+
throw new TypeError("causal frontier checksum does not match");
|
|
72
|
+
}
|
|
73
|
+
const entries: EditableArtifactCausalFrontierEntry[] = [];
|
|
74
|
+
let previous = 0n;
|
|
75
|
+
for (let index = 0; index < count; index += 1) {
|
|
76
|
+
const replica = reader.u64BigInt();
|
|
77
|
+
const counter = reader.u64Safe("causal frontier counter");
|
|
78
|
+
if (replica === 0n || replica <= previous || counter === 0) {
|
|
79
|
+
throw new TypeError("causal frontier entries must be nonzero and strictly ordered");
|
|
80
|
+
}
|
|
81
|
+
previous = replica;
|
|
82
|
+
entries.push(
|
|
83
|
+
Object.freeze({
|
|
84
|
+
replicaId: replica.toString(16).padStart(16, "0"),
|
|
85
|
+
counter,
|
|
86
|
+
}),
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
reader.u64BigInt();
|
|
90
|
+
reader.done();
|
|
91
|
+
return Object.freeze(entries);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function assertCanonicalEditableArtifactCausalFrontierBytes(bytes: Uint8Array): void {
|
|
95
|
+
const decoded = decodeEditableArtifactCausalFrontier(bytes);
|
|
96
|
+
if (!equalBytes(bytes, encodeEditableArtifactCausalFrontier(decoded))) {
|
|
97
|
+
throw new TypeError("causal frontier is not canonically encoded");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function normalizeFrontier(
|
|
102
|
+
frontier: EditableArtifactCausalFrontier,
|
|
103
|
+
): EditableArtifactCausalFrontier {
|
|
104
|
+
if (!Array.isArray(frontier)) throw new TypeError("causal frontier must be an array");
|
|
105
|
+
if (frontier.length > EDITABLE_ARTIFACT_CAUSAL_FRONTIER_MAX_REPLICAS) {
|
|
106
|
+
throw new RangeError("causal frontier exceeds its replica limit");
|
|
107
|
+
}
|
|
108
|
+
let previous = "";
|
|
109
|
+
const entries: EditableArtifactCausalFrontierEntry[] = [];
|
|
110
|
+
for (const entry of frontier) {
|
|
111
|
+
if (
|
|
112
|
+
typeof entry !== "object" ||
|
|
113
|
+
entry === null ||
|
|
114
|
+
Array.isArray(entry) ||
|
|
115
|
+
(Object.getPrototypeOf(entry) !== Object.prototype && Object.getPrototypeOf(entry) !== null)
|
|
116
|
+
) {
|
|
117
|
+
throw new TypeError("causal frontier entries must be records");
|
|
118
|
+
}
|
|
119
|
+
const keys = Reflect.ownKeys(entry);
|
|
120
|
+
if (
|
|
121
|
+
keys.length !== 2 ||
|
|
122
|
+
keys.some((key) => typeof key !== "string") ||
|
|
123
|
+
!(keys as string[]).includes("counter") ||
|
|
124
|
+
!(keys as string[]).includes("replicaId")
|
|
125
|
+
) {
|
|
126
|
+
throw new TypeError("causal frontier entry fields must be exactly counter and replicaId");
|
|
127
|
+
}
|
|
128
|
+
for (const key of keys as string[]) {
|
|
129
|
+
const descriptor = Object.getOwnPropertyDescriptor(entry, key);
|
|
130
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
131
|
+
throw new TypeError("causal frontier entries must contain enumerable data properties");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (!REPLICA_ID.test(entry.replicaId) || entry.replicaId === "0000000000000000") {
|
|
135
|
+
throw new TypeError("causal frontier replicaId must be canonical nonzero lowercase hex");
|
|
136
|
+
}
|
|
137
|
+
if (entry.replicaId <= previous) {
|
|
138
|
+
throw new TypeError("causal frontier replica ids must be unique and strictly ordered");
|
|
139
|
+
}
|
|
140
|
+
previous = entry.replicaId;
|
|
141
|
+
entries.push(
|
|
142
|
+
Object.freeze({
|
|
143
|
+
replicaId: entry.replicaId,
|
|
144
|
+
counter: positiveSafeInteger(entry.counter, "causal frontier counter"),
|
|
145
|
+
}),
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
return Object.freeze(entries);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function readU64At(bytes: Uint8Array, offset: number): bigint {
|
|
152
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
153
|
+
return view.getBigUint64(offset, true);
|
|
154
|
+
}
|