@opengeni/sdk 0.46.0 → 0.52.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.
Files changed (103) hide show
  1. package/README.md +94 -2
  2. package/dist/artifact-client.d.ts +20 -2
  3. package/dist/artifacts.d.ts +4 -0
  4. package/dist/artifacts.js +11 -0
  5. package/dist/artifacts.js.map +1 -0
  6. package/dist/chunk-FHI4DFIG.js +128 -0
  7. package/dist/chunk-FHI4DFIG.js.map +1 -0
  8. package/dist/chunk-FRJFNDIR.js +218 -0
  9. package/dist/chunk-FRJFNDIR.js.map +1 -0
  10. package/dist/{chunk-QKV5OCLJ.js → chunk-ILQZR5N6.js} +1380 -595
  11. package/dist/chunk-ILQZR5N6.js.map +1 -0
  12. package/dist/chunk-MZWTWOX6.js +661 -0
  13. package/dist/chunk-MZWTWOX6.js.map +1 -0
  14. package/dist/chunk-VWE2QIVO.js +1162 -0
  15. package/dist/chunk-VWE2QIVO.js.map +1 -0
  16. package/dist/chunk-VYCTL62C.js +230 -0
  17. package/dist/chunk-VYCTL62C.js.map +1 -0
  18. package/dist/client.d.ts +176 -20
  19. package/dist/codex-realtime-controller.d.ts +6 -6
  20. package/dist/codex-realtime-lifecycle.d.ts +1 -1
  21. package/dist/codex-realtime-v3.d.ts +3 -3
  22. package/dist/codex-realtime.d.ts +1 -1
  23. package/dist/company-profile.d.ts +100 -0
  24. package/dist/core.d.ts +5 -5
  25. package/dist/core.js +9 -4
  26. package/dist/desktop.d.ts +1 -1
  27. package/dist/editable-artifact-resources.d.ts +96 -0
  28. package/dist/editable-artifacts/browser-session.d.ts +35 -0
  29. package/dist/editable-artifacts/controller.d.ts +60 -0
  30. package/dist/editable-artifacts/errors.d.ts +23 -0
  31. package/dist/editable-artifacts/http-live-transport.d.ts +46 -0
  32. package/dist/editable-artifacts/index.d.ts +19 -0
  33. package/dist/editable-artifacts/pool.d.ts +15 -0
  34. package/dist/editable-artifacts/session.d.ts +96 -0
  35. package/dist/editable-artifacts/storage.d.ts +72 -0
  36. package/dist/editable-artifacts/types.d.ts +416 -0
  37. package/dist/editable-artifacts/worker/browser-client.d.ts +80 -0
  38. package/dist/editable-artifacts/worker/browser-entry.d.ts +6 -0
  39. package/dist/editable-artifacts/worker/kernel-adapter.d.ts +45 -0
  40. package/dist/editable-artifacts/worker/rpc-protocol.d.ts +92 -0
  41. package/dist/editable-artifacts/worker/runtime.d.ts +66 -0
  42. package/dist/editable-artifacts/worker/wire-codec.d.ts +52 -0
  43. package/dist/editable-artifacts-worker.d.ts +8 -0
  44. package/dist/editable-artifacts-worker.js +1708 -0
  45. package/dist/editable-artifacts-worker.js.map +1 -0
  46. package/dist/editable-artifacts.d.ts +6 -0
  47. package/dist/editable-artifacts.js +5954 -0
  48. package/dist/editable-artifacts.js.map +1 -0
  49. package/dist/gateway-realtime-transport.d.ts +1 -1
  50. package/dist/index.d.ts +41 -35
  51. package/dist/index.js +104 -68
  52. package/dist/index.js.map +1 -1
  53. package/dist/interaction.d.ts +885 -0
  54. package/dist/interaction.js +55 -0
  55. package/dist/interaction.js.map +1 -0
  56. package/dist/memory-slack-client.d.ts +13 -0
  57. package/dist/memory-slack-delivery.d.ts +99 -0
  58. package/dist/memory-slack.d.ts +4 -0
  59. package/dist/memory-slack.js +44 -0
  60. package/dist/memory-slack.js.map +1 -0
  61. package/dist/proxy.d.ts +3 -3
  62. package/dist/realtime.d.ts +12 -12
  63. package/dist/retained-artifacts.d.ts +12 -0
  64. package/dist/stream.d.ts +16 -1
  65. package/dist/terminal.d.ts +1 -1
  66. package/dist/transcription.d.ts +2 -2
  67. package/dist/types.d.ts +1203 -23
  68. package/dist/workspace-control-stream.d.ts +2 -2
  69. package/dist/workspace-state.d.ts +1 -1
  70. package/package.json +29 -3
  71. package/src/artifact-client.ts +129 -0
  72. package/src/artifacts.ts +17 -0
  73. package/src/client.ts +1801 -206
  74. package/src/company-profile.ts +92 -0
  75. package/src/editable-artifact-resources.ts +119 -0
  76. package/src/editable-artifacts/browser-session.ts +176 -0
  77. package/src/editable-artifacts/controller.ts +2632 -0
  78. package/src/editable-artifacts/errors.ts +52 -0
  79. package/src/editable-artifacts/http-live-transport.ts +1449 -0
  80. package/src/editable-artifacts/index.ts +175 -0
  81. package/src/editable-artifacts/pool.ts +81 -0
  82. package/src/editable-artifacts/session.ts +778 -0
  83. package/src/editable-artifacts/storage.ts +1718 -0
  84. package/src/editable-artifacts/types.ts +499 -0
  85. package/src/editable-artifacts/worker/browser-client.ts +1167 -0
  86. package/src/editable-artifacts/worker/browser-entry.ts +57 -0
  87. package/src/editable-artifacts/worker/kernel-adapter.ts +1039 -0
  88. package/src/editable-artifacts/worker/rpc-protocol.ts +622 -0
  89. package/src/editable-artifacts/worker/runtime.ts +1204 -0
  90. package/src/editable-artifacts/worker/wire-codec.ts +852 -0
  91. package/src/editable-artifacts-worker.ts +8 -0
  92. package/src/editable-artifacts.ts +6 -0
  93. package/src/index.ts +194 -0
  94. package/src/interaction.ts +1830 -0
  95. package/src/memory-slack-client.ts +71 -0
  96. package/src/memory-slack-delivery.ts +128 -0
  97. package/src/memory-slack.ts +19 -0
  98. package/src/retained-artifacts.ts +326 -0
  99. package/src/stream.ts +102 -4
  100. package/src/transcription.ts +2 -2
  101. package/src/types.ts +1430 -33
  102. package/src/workspace-control-stream.ts +15 -5
  103. package/dist/chunk-QKV5OCLJ.js.map +0 -1
@@ -0,0 +1,622 @@
1
+ const FRAME_MAGIC = new Uint8Array([0x4f, 0x47, 0x41, 0x57, 0x52, 0x50, 0x43, 0x31]); // OGAWRPC1
2
+ const FRAME_HEADER_BYTES = 36;
3
+ const FRAME_VERSION = 1;
4
+ const DEFAULT_MAX_METADATA_BYTES = 1024 * 1024;
5
+ const DEFAULT_MAX_SEGMENT_BYTES = 128 * 1024 * 1024;
6
+ const DEFAULT_MAX_TOTAL_SEGMENT_BYTES = 512 * 1024 * 1024;
7
+ const DEFAULT_MAX_SEGMENTS = 4_096;
8
+
9
+ export const enum ArtifactWorkerRpcKind {
10
+ Initialize = 1,
11
+ Reset = 2,
12
+ LoadSnapshot = 3,
13
+ ApplyRecovered = 4,
14
+ ReconcileCommitted = 5,
15
+ ReplacePending = 6,
16
+ AuthorPending = 7,
17
+ Cancel = 8,
18
+ Dispose = 9,
19
+ QuerySpreadsheet = 10,
20
+ Response = 128,
21
+ Error = 129,
22
+ }
23
+
24
+ export type ArtifactWorkerRpcMessage = {
25
+ frame: ArrayBuffer;
26
+ segments: ArrayBuffer[];
27
+ };
28
+
29
+ export type ArtifactWorkerRpcLimits = {
30
+ maxMetadataBytes: number;
31
+ maxSegmentBytes: number;
32
+ maxTotalSegmentBytes: number;
33
+ maxSegments: number;
34
+ };
35
+
36
+ export type DecodedArtifactWorkerRpcFrame = {
37
+ kind: ArtifactWorkerRpcKind;
38
+ generation: number;
39
+ requestId: number;
40
+ flags: number;
41
+ metadata: Uint8Array;
42
+ segments: Uint8Array[];
43
+ };
44
+
45
+ export const DEFAULT_ARTIFACT_WORKER_RPC_LIMITS: Readonly<ArtifactWorkerRpcLimits> = Object.freeze({
46
+ maxMetadataBytes: DEFAULT_MAX_METADATA_BYTES,
47
+ maxSegmentBytes: DEFAULT_MAX_SEGMENT_BYTES,
48
+ maxTotalSegmentBytes: DEFAULT_MAX_TOTAL_SEGMENT_BYTES,
49
+ maxSegments: DEFAULT_MAX_SEGMENTS,
50
+ });
51
+
52
+ export class ArtifactWorkerProtocolError extends Error {
53
+ readonly code: string;
54
+
55
+ constructor(code: string, message: string, options?: { cause?: unknown }) {
56
+ super(message, options?.cause === undefined ? undefined : { cause: options.cause });
57
+ this.name = "ArtifactWorkerProtocolError";
58
+ this.code = code;
59
+ }
60
+ }
61
+
62
+ export function encodeArtifactWorkerRpcMessage(input: {
63
+ kind: ArtifactWorkerRpcKind;
64
+ generation: number;
65
+ requestId: number;
66
+ flags?: number;
67
+ metadata?: Uint8Array;
68
+ /** Every buffer must already be exclusively owned by this message. */
69
+ segments?: ArrayBuffer[];
70
+ limits?: Readonly<ArtifactWorkerRpcLimits>;
71
+ }): ArtifactWorkerRpcMessage {
72
+ const limits = validateLimits(input.limits ?? DEFAULT_ARTIFACT_WORKER_RPC_LIMITS);
73
+ const generation = unsignedInt(input.generation, "generation");
74
+ const requestId = unsignedInt(input.requestId, "requestId");
75
+ if (generation === 0 || requestId === 0) {
76
+ throw protocolError("invalid_number", "generation and requestId must be nonzero");
77
+ }
78
+ const flags = unsignedInt(input.flags ?? 0, "flags");
79
+ const kind = unsignedShort(input.kind, "kind");
80
+ if (!isKnownKind(kind)) throw protocolError("unknown_kind", `unknown RPC kind ${kind}`);
81
+ const metadata = input.metadata ?? new Uint8Array();
82
+ if (!(metadata instanceof Uint8Array))
83
+ throw protocolError("invalid_frame", "metadata must be bytes");
84
+ if (metadata.byteLength > limits.maxMetadataBytes) {
85
+ throw protocolError("metadata_too_large", "RPC metadata exceeds its configured byte limit");
86
+ }
87
+ const segments = input.segments ?? [];
88
+ if (
89
+ !Array.isArray(segments) ||
90
+ segments.length > limits.maxSegments ||
91
+ segments.length > 0xffff
92
+ ) {
93
+ throw protocolError("segments_too_large", "RPC segment count exceeds its configured limit");
94
+ }
95
+ let totalSegmentBytes = 0;
96
+ const uniqueSegments = new Set<ArrayBuffer>();
97
+ for (const segment of segments) {
98
+ if (!(segment instanceof ArrayBuffer)) {
99
+ throw protocolError("invalid_segment", "RPC segments must be transferable ArrayBuffers");
100
+ }
101
+ if (segment.byteLength > limits.maxSegmentBytes) {
102
+ throw protocolError("segment_too_large", "RPC segment exceeds its configured byte limit");
103
+ }
104
+ if (uniqueSegments.has(segment)) {
105
+ throw protocolError("invalid_segment", "RPC segments must not alias one transferable buffer");
106
+ }
107
+ uniqueSegments.add(segment);
108
+ totalSegmentBytes = checkedAdd(totalSegmentBytes, segment.byteLength, "RPC segment bytes");
109
+ if (totalSegmentBytes > limits.maxTotalSegmentBytes) {
110
+ throw protocolError("segments_too_large", "RPC segments exceed their aggregate byte limit");
111
+ }
112
+ }
113
+
114
+ const segmentTableBytes = checkedMultiply(segments.length, 4, "RPC segment table");
115
+ const frameBytes = checkedAdd(
116
+ checkedAdd(FRAME_HEADER_BYTES, metadata.byteLength, "RPC frame"),
117
+ segmentTableBytes,
118
+ "RPC frame",
119
+ );
120
+ const frame = new Uint8Array(frameBytes);
121
+ const view = new DataView(frame.buffer);
122
+ frame.set(FRAME_MAGIC, 0);
123
+ view.setUint16(8, FRAME_VERSION, true);
124
+ view.setUint16(10, kind, true);
125
+ view.setUint32(12, generation, true);
126
+ view.setUint32(16, requestId, true);
127
+ view.setUint32(20, flags, true);
128
+ view.setUint32(24, metadata.byteLength, true);
129
+ view.setUint16(28, segments.length, true);
130
+ view.setUint16(30, 0, true);
131
+ view.setUint32(32, 0, true);
132
+ frame.set(metadata, FRAME_HEADER_BYTES);
133
+ let offset = FRAME_HEADER_BYTES + metadata.byteLength;
134
+ for (const segment of segments) {
135
+ view.setUint32(offset, segment.byteLength, true);
136
+ offset += 4;
137
+ }
138
+ view.setUint32(32, checksum32(frame), true);
139
+ return { frame: frame.buffer, segments };
140
+ }
141
+
142
+ export function decodeArtifactWorkerRpcMessage(
143
+ input: unknown,
144
+ limitsInput: Readonly<ArtifactWorkerRpcLimits> = DEFAULT_ARTIFACT_WORKER_RPC_LIMITS,
145
+ ): DecodedArtifactWorkerRpcFrame {
146
+ const limits = validateLimits(limitsInput);
147
+ if (!isPlainRecord(input)) throw protocolError("invalid_frame", "RPC message must be a record");
148
+ const keys = Object.keys(input);
149
+ if (keys.length !== 2 || !keys.includes("frame") || !keys.includes("segments")) {
150
+ throw protocolError("invalid_frame", "RPC message contains unknown or missing fields");
151
+ }
152
+ const frameBuffer = dataProperty(input, "frame");
153
+ const rawSegments = dataProperty(input, "segments");
154
+ if (!(frameBuffer instanceof ArrayBuffer)) {
155
+ throw protocolError("invalid_frame", "RPC frame must be a transferable ArrayBuffer");
156
+ }
157
+ if (!Array.isArray(rawSegments))
158
+ throw protocolError("invalid_frame", "RPC segments must be an array");
159
+ if (frameBuffer.byteLength < FRAME_HEADER_BYTES)
160
+ throw protocolError("truncated", "RPC frame is truncated");
161
+ if (
162
+ frameBuffer.byteLength >
163
+ FRAME_HEADER_BYTES + limits.maxMetadataBytes + limits.maxSegments * 4
164
+ ) {
165
+ throw protocolError("metadata_too_large", "RPC frame exceeds its configured byte limit");
166
+ }
167
+ const frame = new Uint8Array(frameBuffer);
168
+ for (let index = 0; index < FRAME_MAGIC.length; index += 1) {
169
+ if (frame[index] !== FRAME_MAGIC[index])
170
+ throw protocolError("bad_magic", "invalid RPC frame magic");
171
+ }
172
+ const view = new DataView(frameBuffer);
173
+ const version = view.getUint16(8, true);
174
+ if (version !== FRAME_VERSION) {
175
+ throw protocolError("unsupported_version", `unsupported RPC frame version ${version}`);
176
+ }
177
+ const kind = view.getUint16(10, true);
178
+ if (!isKnownKind(kind)) throw protocolError("unknown_kind", `unknown RPC kind ${kind}`);
179
+ const generation = view.getUint32(12, true);
180
+ const requestId = view.getUint32(16, true);
181
+ if (generation === 0 || requestId === 0) {
182
+ throw protocolError("noncanonical", "generation and requestId must be nonzero");
183
+ }
184
+ const flags = view.getUint32(20, true);
185
+ const metadataBytes = view.getUint32(24, true);
186
+ const segmentCount = view.getUint16(28, true);
187
+ if (view.getUint16(30, true) !== 0) {
188
+ throw protocolError("noncanonical", "reserved RPC frame bits are set");
189
+ }
190
+ if (metadataBytes > limits.maxMetadataBytes) {
191
+ throw protocolError("metadata_too_large", "RPC metadata exceeds its configured byte limit");
192
+ }
193
+ if (segmentCount > limits.maxSegments || rawSegments.length !== segmentCount) {
194
+ throw protocolError("invalid_segment", "RPC segment count does not match its frame");
195
+ }
196
+ const expectedFrameBytes = checkedAdd(
197
+ checkedAdd(FRAME_HEADER_BYTES, metadataBytes, "RPC frame"),
198
+ checkedMultiply(segmentCount, 4, "RPC segment table"),
199
+ "RPC frame",
200
+ );
201
+ if (frame.byteLength !== expectedFrameBytes) {
202
+ throw protocolError("trailing_bytes", "RPC frame has a truncated or trailing payload");
203
+ }
204
+ const expectedChecksum = view.getUint32(32, true);
205
+ view.setUint32(32, 0, true);
206
+ const actualChecksum = checksum32(frame);
207
+ view.setUint32(32, expectedChecksum, true);
208
+ if (expectedChecksum !== actualChecksum) {
209
+ throw protocolError("checksum_mismatch", "RPC frame checksum does not match");
210
+ }
211
+ const segments: Uint8Array[] = [];
212
+ const uniqueBuffers = new Set<ArrayBuffer>([frameBuffer]);
213
+ let totalSegmentBytes = 0;
214
+ let tableOffset = FRAME_HEADER_BYTES + metadataBytes;
215
+ for (let index = 0; index < segmentCount; index += 1) {
216
+ const expectedBytes = view.getUint32(tableOffset, true);
217
+ tableOffset += 4;
218
+ const segment = rawSegments[index];
219
+ if (!(segment instanceof ArrayBuffer) || segment.byteLength !== expectedBytes) {
220
+ throw protocolError(
221
+ "invalid_segment",
222
+ `RPC segment ${index} does not match its declared length`,
223
+ );
224
+ }
225
+ if (uniqueBuffers.has(segment)) {
226
+ throw protocolError("invalid_segment", "RPC frame and segments must use distinct buffers");
227
+ }
228
+ uniqueBuffers.add(segment);
229
+ if (segment.byteLength > limits.maxSegmentBytes) {
230
+ throw protocolError("segment_too_large", `RPC segment ${index} exceeds its configured limit`);
231
+ }
232
+ totalSegmentBytes = checkedAdd(totalSegmentBytes, segment.byteLength, "RPC segment bytes");
233
+ if (totalSegmentBytes > limits.maxTotalSegmentBytes) {
234
+ throw protocolError("segments_too_large", "RPC segments exceed their aggregate byte limit");
235
+ }
236
+ segments.push(new Uint8Array(segment));
237
+ }
238
+ return {
239
+ kind: kind as ArtifactWorkerRpcKind,
240
+ generation,
241
+ requestId,
242
+ flags,
243
+ metadata: frame.slice(FRAME_HEADER_BYTES, FRAME_HEADER_BYTES + metadataBytes),
244
+ segments,
245
+ };
246
+ }
247
+
248
+ export function transferListForArtifactWorkerRpcMessage(
249
+ message: ArtifactWorkerRpcMessage,
250
+ ): Transferable[] {
251
+ return [message.frame, ...message.segments];
252
+ }
253
+
254
+ /** Creates a private transferable copy; transferring never detaches caller-owned bytes. */
255
+ export function ownedTransferBuffer(bytes: Uint8Array): ArrayBuffer {
256
+ if (!(bytes instanceof Uint8Array))
257
+ throw protocolError("invalid_segment", "expected byte segment");
258
+ return bytes.slice().buffer;
259
+ }
260
+
261
+ export class ArtifactWorkerBinaryWriter {
262
+ private readonly chunks: Uint8Array[] = [];
263
+ private size = 0;
264
+
265
+ constructor(private readonly maximumBytes = DEFAULT_MAX_METADATA_BYTES) {
266
+ positiveSafeInteger(maximumBytes, "maximumBytes");
267
+ }
268
+
269
+ u8(value: number): this {
270
+ unsignedByte(value, "u8");
271
+ return this.append(new Uint8Array([value]));
272
+ }
273
+
274
+ u16(value: number): this {
275
+ unsignedShort(value, "u16");
276
+ const bytes = new Uint8Array(2);
277
+ new DataView(bytes.buffer).setUint16(0, value, true);
278
+ return this.append(bytes);
279
+ }
280
+
281
+ u32(value: number): this {
282
+ unsignedInt(value, "u32");
283
+ const bytes = new Uint8Array(4);
284
+ new DataView(bytes.buffer).setUint32(0, value, true);
285
+ return this.append(bytes);
286
+ }
287
+
288
+ safeUint(value: number): this {
289
+ nonNegativeSafeInteger(value, "safeUint");
290
+ const bytes = new Uint8Array(8);
291
+ new DataView(bytes.buffer).setBigUint64(0, BigInt(value), true);
292
+ return this.append(bytes);
293
+ }
294
+
295
+ f64(value: number): this {
296
+ if (!Number.isFinite(value)) throw protocolError("invalid_number", "f64 must be finite");
297
+ const bytes = new Uint8Array(8);
298
+ new DataView(bytes.buffer).setFloat64(0, value, true);
299
+ return this.append(bytes);
300
+ }
301
+
302
+ string(value: string, maximumBytes = 256 * 1024): this {
303
+ if (typeof value !== "string") throw protocolError("invalid_string", "expected a string");
304
+ if (!isWellFormedUnicode(value)) {
305
+ throw protocolError("invalid_string", "string contains an unpaired UTF-16 surrogate");
306
+ }
307
+ const bytes = new TextEncoder().encode(value);
308
+ if (bytes.byteLength > maximumBytes)
309
+ throw protocolError("string_too_large", "string exceeds its byte limit");
310
+ this.u32(bytes.byteLength);
311
+ return this.append(bytes);
312
+ }
313
+
314
+ optionalString(value: string | null, maximumBytes = 256 * 1024): this {
315
+ this.u8(value === null ? 0 : 1);
316
+ if (value !== null) this.string(value, maximumBytes);
317
+ return this;
318
+ }
319
+
320
+ frontier(
321
+ value: readonly Readonly<{ replicaId: string; counter: number }>[],
322
+ maximumActors = 1_024,
323
+ ): this {
324
+ const entries = validateFrontier(value, maximumActors);
325
+ this.u32(entries.length);
326
+ for (const [actor, counter] of entries) {
327
+ this.string(actor, 256);
328
+ this.safeUint(counter);
329
+ }
330
+ return this;
331
+ }
332
+
333
+ finish(): Uint8Array {
334
+ const output = new Uint8Array(this.size);
335
+ let offset = 0;
336
+ for (const chunk of this.chunks) {
337
+ output.set(chunk, offset);
338
+ offset += chunk.byteLength;
339
+ }
340
+ return output;
341
+ }
342
+
343
+ private append(bytes: Uint8Array): this {
344
+ this.size = checkedAdd(this.size, bytes.byteLength, "binary metadata");
345
+ if (this.size > this.maximumBytes) {
346
+ throw protocolError("metadata_too_large", "binary metadata exceeds its configured limit");
347
+ }
348
+ this.chunks.push(bytes);
349
+ return this;
350
+ }
351
+ }
352
+
353
+ export class ArtifactWorkerBinaryReader {
354
+ private readonly view: DataView;
355
+ private offset = 0;
356
+
357
+ constructor(private readonly bytes: Uint8Array) {
358
+ if (!(bytes instanceof Uint8Array))
359
+ throw protocolError("invalid_frame", "metadata must be bytes");
360
+ this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
361
+ }
362
+
363
+ u8(): number {
364
+ this.require(1);
365
+ const value = this.view.getUint8(this.offset);
366
+ this.offset += 1;
367
+ return value;
368
+ }
369
+
370
+ u16(): number {
371
+ this.require(2);
372
+ const value = this.view.getUint16(this.offset, true);
373
+ this.offset += 2;
374
+ return value;
375
+ }
376
+
377
+ u32(): number {
378
+ this.require(4);
379
+ const value = this.view.getUint32(this.offset, true);
380
+ this.offset += 4;
381
+ return value;
382
+ }
383
+
384
+ safeUint(): number {
385
+ this.require(8);
386
+ const value = this.view.getBigUint64(this.offset, true);
387
+ this.offset += 8;
388
+ if (value > BigInt(Number.MAX_SAFE_INTEGER)) {
389
+ throw protocolError("invalid_number", "RPC unsigned integer exceeds JavaScript safe range");
390
+ }
391
+ return Number(value);
392
+ }
393
+
394
+ f64(): number {
395
+ this.require(8);
396
+ const value = this.view.getFloat64(this.offset, true);
397
+ this.offset += 8;
398
+ if (!Number.isFinite(value)) throw protocolError("invalid_number", "non-finite RPC number");
399
+ return value;
400
+ }
401
+
402
+ string(maximumBytes = 256 * 1024): string {
403
+ const length = this.u32();
404
+ if (length > maximumBytes)
405
+ throw protocolError("string_too_large", "RPC string exceeds its byte limit");
406
+ this.require(length);
407
+ const bytes = this.bytes.subarray(this.offset, this.offset + length);
408
+ this.offset += length;
409
+ try {
410
+ return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
411
+ } catch (error) {
412
+ throw protocolError("invalid_utf8", "RPC string is not valid UTF-8", error);
413
+ }
414
+ }
415
+
416
+ optionalString(maximumBytes = 256 * 1024): string | null {
417
+ const present = this.u8();
418
+ if (present === 0) return null;
419
+ if (present !== 1) throw protocolError("noncanonical", "invalid optional-string tag");
420
+ return this.string(maximumBytes);
421
+ }
422
+
423
+ frontier(maximumActors = 1_024): readonly Readonly<{ replicaId: string; counter: number }>[] {
424
+ const count = this.u32();
425
+ if (count > maximumActors)
426
+ throw protocolError("frontier_too_large", "causal frontier exceeds its actor limit");
427
+ const entries: Array<Readonly<{ replicaId: string; counter: number }>> = [];
428
+ let previous = "";
429
+ for (let index = 0; index < count; index += 1) {
430
+ const actor = this.string(256);
431
+ if (!actor || (index > 0 && compareCodeUnits(previous, actor) >= 0)) {
432
+ throw protocolError(
433
+ "noncanonical",
434
+ "causal frontier actors must be unique and code-unit sorted",
435
+ );
436
+ }
437
+ const counter = this.safeUint();
438
+ entries.push(Object.freeze({ replicaId: actor, counter }));
439
+ previous = actor;
440
+ }
441
+ return Object.freeze(entries);
442
+ }
443
+
444
+ done(): void {
445
+ if (this.offset !== this.bytes.byteLength) {
446
+ throw protocolError("trailing_bytes", "RPC metadata contains trailing bytes");
447
+ }
448
+ }
449
+
450
+ remaining(): number {
451
+ return this.bytes.byteLength - this.offset;
452
+ }
453
+
454
+ private require(length: number): void {
455
+ if (length < 0 || this.offset + length > this.bytes.byteLength) {
456
+ throw protocolError("truncated", "RPC metadata is truncated");
457
+ }
458
+ }
459
+ }
460
+
461
+ function validateFrontier(
462
+ value: readonly Readonly<{ replicaId: string; counter: number }>[],
463
+ maximumActors: number,
464
+ ): Array<readonly [string, number]> {
465
+ if (!Array.isArray(value))
466
+ throw protocolError("invalid_frontier", "causal frontier must be an array");
467
+ const entries: Array<readonly [string, number]> = [];
468
+ for (const entry of value) {
469
+ if (!isPlainRecord(entry))
470
+ throw protocolError("invalid_frontier", "causal frontier entry is invalid");
471
+ const keys = Object.keys(entry);
472
+ if (keys.length !== 2 || !keys.includes("replicaId") || !keys.includes("counter")) {
473
+ throw protocolError("invalid_frontier", "causal frontier entry has unknown fields");
474
+ }
475
+ const actor = dataProperty(entry, "replicaId");
476
+ const counter = dataProperty(entry, "counter");
477
+ if (typeof actor !== "string" || typeof counter !== "number") {
478
+ throw protocolError("invalid_frontier", "causal frontier entry has invalid fields");
479
+ }
480
+ entries.push([actor, counter]);
481
+ }
482
+ if (entries.length > maximumActors) {
483
+ throw protocolError("frontier_too_large", "causal frontier exceeds its actor limit");
484
+ }
485
+ for (const [actor, counter] of entries) {
486
+ if (!actor || new TextEncoder().encode(actor).byteLength > 256) {
487
+ throw protocolError("invalid_frontier", "causal frontier actor is invalid");
488
+ }
489
+ nonNegativeSafeInteger(counter, `causal frontier counter for ${actor}`);
490
+ }
491
+ const sorted = entries.slice().sort(([left], [right]) => compareCodeUnits(left, right));
492
+ for (let index = 0; index < entries.length; index += 1) {
493
+ if (entries[index]![0] !== sorted[index]![0]) {
494
+ throw protocolError("noncanonical", "causal frontier must already be code-unit sorted");
495
+ }
496
+ if (index > 0 && entries[index - 1]![0] === entries[index]![0]) {
497
+ throw protocolError("noncanonical", "causal frontier contains a duplicate replica");
498
+ }
499
+ }
500
+ return entries;
501
+ }
502
+
503
+ function validateLimits(input: Readonly<ArtifactWorkerRpcLimits>): ArtifactWorkerRpcLimits {
504
+ const limits = {
505
+ maxMetadataBytes: positiveSafeInteger(input.maxMetadataBytes, "maxMetadataBytes"),
506
+ maxSegmentBytes: positiveSafeInteger(input.maxSegmentBytes, "maxSegmentBytes"),
507
+ maxTotalSegmentBytes: positiveSafeInteger(input.maxTotalSegmentBytes, "maxTotalSegmentBytes"),
508
+ maxSegments: positiveSafeInteger(input.maxSegments, "maxSegments"),
509
+ };
510
+ if (limits.maxSegments > 0xffff) {
511
+ throw protocolError("invalid_limit", "maxSegments exceeds the frame encoding limit");
512
+ }
513
+ return limits;
514
+ }
515
+
516
+ function isKnownKind(kind: number): boolean {
517
+ return (
518
+ (kind >= ArtifactWorkerRpcKind.Initialize && kind <= ArtifactWorkerRpcKind.QuerySpreadsheet) ||
519
+ kind === ArtifactWorkerRpcKind.Response ||
520
+ kind === ArtifactWorkerRpcKind.Error
521
+ );
522
+ }
523
+
524
+ function checksum32(bytes: Uint8Array): number {
525
+ let hash = 0x811c9dc5;
526
+ for (const byte of bytes) {
527
+ hash ^= byte;
528
+ hash = Math.imul(hash, 0x01000193) >>> 0;
529
+ }
530
+ return hash;
531
+ }
532
+
533
+ function compareCodeUnits(left: string, right: string): number {
534
+ return left < right ? -1 : left > right ? 1 : 0;
535
+ }
536
+
537
+ function isWellFormedUnicode(value: string): boolean {
538
+ for (let index = 0; index < value.length; index += 1) {
539
+ const code = value.charCodeAt(index);
540
+ if (code >= 0xd800 && code <= 0xdbff) {
541
+ const following = value.charCodeAt(index + 1);
542
+ if (!(following >= 0xdc00 && following <= 0xdfff)) return false;
543
+ index += 1;
544
+ } else if (code >= 0xdc00 && code <= 0xdfff) {
545
+ return false;
546
+ }
547
+ }
548
+ return true;
549
+ }
550
+
551
+ function isPlainRecord(value: unknown): value is Record<string, unknown> {
552
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
553
+ const prototype = Object.getPrototypeOf(value);
554
+ return prototype === Object.prototype || prototype === null;
555
+ }
556
+
557
+ function dataProperty(record: Record<string, unknown>, key: string): unknown {
558
+ const descriptor = Object.getOwnPropertyDescriptor(record, key);
559
+ if (!descriptor || !("value" in descriptor)) {
560
+ throw protocolError("invalid_frame", `RPC ${key} must be a data property`);
561
+ }
562
+ return descriptor.value;
563
+ }
564
+
565
+ function unsignedByte(value: number, label: string): number {
566
+ if (!Number.isInteger(value) || value < 0 || value > 0xff) {
567
+ throw protocolError("invalid_number", `${label} must be an unsigned byte`);
568
+ }
569
+ return value;
570
+ }
571
+
572
+ function unsignedShort(value: number, label: string): number {
573
+ if (!Number.isInteger(value) || value < 0 || value > 0xffff) {
574
+ throw protocolError("invalid_number", `${label} must be an unsigned 16-bit integer`);
575
+ }
576
+ return value;
577
+ }
578
+
579
+ function unsignedInt(value: number, label: string): number {
580
+ if (!Number.isInteger(value) || value < 0 || value > 0xffffffff) {
581
+ throw protocolError("invalid_number", `${label} must be an unsigned 32-bit integer`);
582
+ }
583
+ return value;
584
+ }
585
+
586
+ function positiveSafeInteger(value: number, label: string): number {
587
+ if (!Number.isSafeInteger(value) || value <= 0) {
588
+ throw protocolError("invalid_limit", `${label} must be a positive safe integer`);
589
+ }
590
+ return value;
591
+ }
592
+
593
+ function nonNegativeSafeInteger(value: number, label: string): number {
594
+ if (!Number.isSafeInteger(value) || value < 0) {
595
+ throw protocolError("invalid_number", `${label} must be a non-negative safe integer`);
596
+ }
597
+ return value;
598
+ }
599
+
600
+ function checkedAdd(left: number, right: number, label: string): number {
601
+ const result = left + right;
602
+ if (!Number.isSafeInteger(result)) throw protocolError("size_overflow", `${label} overflow`);
603
+ return result;
604
+ }
605
+
606
+ function checkedMultiply(left: number, right: number, label: string): number {
607
+ const result = left * right;
608
+ if (!Number.isSafeInteger(result)) throw protocolError("size_overflow", `${label} overflow`);
609
+ return result;
610
+ }
611
+
612
+ function protocolError(
613
+ code: string,
614
+ message: string,
615
+ cause?: unknown,
616
+ ): ArtifactWorkerProtocolError {
617
+ return new ArtifactWorkerProtocolError(
618
+ code,
619
+ message,
620
+ cause === undefined ? undefined : { cause },
621
+ );
622
+ }