@opengeni/sdk 0.48.0 → 0.57.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.
Files changed (122) hide show
  1. package/README.md +147 -1
  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-V5F253OG.js → chunk-GU6JF75T.js} +6 -3
  7. package/dist/chunk-GU6JF75T.js.map +1 -0
  8. package/dist/chunk-HJ3HHUT5.js +222 -0
  9. package/dist/chunk-HJ3HHUT5.js.map +1 -0
  10. package/dist/{chunk-KIHGPM7H.js → chunk-JDLDDRNE.js} +20 -14
  11. package/dist/chunk-JDLDDRNE.js.map +1 -0
  12. package/dist/chunk-JRPFWI6T.js +128 -0
  13. package/dist/chunk-JRPFWI6T.js.map +1 -0
  14. package/dist/{chunk-MBGBLVUV.js → chunk-PKQ377ED.js} +1725 -555
  15. package/dist/chunk-PKQ377ED.js.map +1 -0
  16. package/dist/chunk-ST5DDKJP.js +987 -0
  17. package/dist/chunk-ST5DDKJP.js.map +1 -0
  18. package/dist/chunk-VWE2QIVO.js +1162 -0
  19. package/dist/chunk-VWE2QIVO.js.map +1 -0
  20. package/dist/chunk-VYCTL62C.js +230 -0
  21. package/dist/chunk-VYCTL62C.js.map +1 -0
  22. package/dist/{chunk-DXDL7EEW.js → chunk-YKZME56C.js} +197 -113
  23. package/dist/chunk-YKZME56C.js.map +1 -0
  24. package/dist/client.d.ts +240 -16
  25. package/dist/codex-realtime-controller.d.ts +9 -6
  26. package/dist/codex-realtime-controller.js +2 -2
  27. package/dist/codex-realtime-lifecycle.d.ts +1 -1
  28. package/dist/codex-realtime-v3.d.ts +3 -3
  29. package/dist/codex-realtime.d.ts +1 -1
  30. package/dist/company-profile.d.ts +100 -0
  31. package/dist/core.d.ts +5 -5
  32. package/dist/core.js +10 -5
  33. package/dist/desktop.d.ts +9 -1
  34. package/dist/editable-artifact-resources.d.ts +96 -0
  35. package/dist/editable-artifacts/browser-session.d.ts +35 -0
  36. package/dist/editable-artifacts/controller.d.ts +60 -0
  37. package/dist/editable-artifacts/errors.d.ts +23 -0
  38. package/dist/editable-artifacts/http-live-transport.d.ts +46 -0
  39. package/dist/editable-artifacts/index.d.ts +19 -0
  40. package/dist/editable-artifacts/pool.d.ts +15 -0
  41. package/dist/editable-artifacts/session.d.ts +96 -0
  42. package/dist/editable-artifacts/storage.d.ts +72 -0
  43. package/dist/editable-artifacts/types.d.ts +416 -0
  44. package/dist/editable-artifacts/worker/browser-client.d.ts +80 -0
  45. package/dist/editable-artifacts/worker/browser-entry.d.ts +6 -0
  46. package/dist/editable-artifacts/worker/kernel-adapter.d.ts +45 -0
  47. package/dist/editable-artifacts/worker/rpc-protocol.d.ts +92 -0
  48. package/dist/editable-artifacts/worker/runtime.d.ts +66 -0
  49. package/dist/editable-artifacts/worker/wire-codec.d.ts +52 -0
  50. package/dist/editable-artifacts-worker.d.ts +8 -0
  51. package/dist/editable-artifacts-worker.js +1708 -0
  52. package/dist/editable-artifacts-worker.js.map +1 -0
  53. package/dist/editable-artifacts.d.ts +6 -0
  54. package/dist/editable-artifacts.js +5954 -0
  55. package/dist/editable-artifacts.js.map +1 -0
  56. package/dist/gateway-realtime-transport.d.ts +2 -1
  57. package/dist/gateway-realtime-transport.js +5 -3
  58. package/dist/index.d.ts +45 -35
  59. package/dist/index.js +134 -64
  60. package/dist/index.js.map +1 -1
  61. package/dist/interaction-revision-stream.d.ts +11 -0
  62. package/dist/interaction.d.ts +1484 -0
  63. package/dist/interaction.js +81 -0
  64. package/dist/interaction.js.map +1 -0
  65. package/dist/memory-slack-client.d.ts +13 -0
  66. package/dist/memory-slack-delivery.d.ts +99 -0
  67. package/dist/memory-slack.d.ts +4 -0
  68. package/dist/memory-slack.js +44 -0
  69. package/dist/memory-slack.js.map +1 -0
  70. package/dist/proxy.d.ts +3 -3
  71. package/dist/realtime.d.ts +14 -14
  72. package/dist/realtime.js +11 -7
  73. package/dist/realtime.js.map +1 -1
  74. package/dist/retained-artifacts.d.ts +12 -0
  75. package/dist/stream.d.ts +1 -1
  76. package/dist/terminal.d.ts +1 -1
  77. package/dist/types.d.ts +1347 -34
  78. package/dist/workspace-control-stream.d.ts +2 -2
  79. package/dist/workspace-live-stream.d.ts +14 -0
  80. package/dist/workspace-state.d.ts +1 -1
  81. package/package.json +29 -3
  82. package/src/artifact-client.ts +129 -0
  83. package/src/artifacts.ts +17 -0
  84. package/src/client.ts +3022 -910
  85. package/src/codex-realtime-controller.ts +25 -7
  86. package/src/codex-realtime-lifecycle.ts +1 -0
  87. package/src/company-profile.ts +92 -0
  88. package/src/desktop.ts +11 -1
  89. package/src/editable-artifact-resources.ts +119 -0
  90. package/src/editable-artifacts/browser-session.ts +176 -0
  91. package/src/editable-artifacts/controller.ts +2632 -0
  92. package/src/editable-artifacts/errors.ts +52 -0
  93. package/src/editable-artifacts/http-live-transport.ts +1449 -0
  94. package/src/editable-artifacts/index.ts +175 -0
  95. package/src/editable-artifacts/pool.ts +81 -0
  96. package/src/editable-artifacts/session.ts +778 -0
  97. package/src/editable-artifacts/storage.ts +1718 -0
  98. package/src/editable-artifacts/types.ts +499 -0
  99. package/src/editable-artifacts/worker/browser-client.ts +1167 -0
  100. package/src/editable-artifacts/worker/browser-entry.ts +57 -0
  101. package/src/editable-artifacts/worker/kernel-adapter.ts +1039 -0
  102. package/src/editable-artifacts/worker/rpc-protocol.ts +622 -0
  103. package/src/editable-artifacts/worker/runtime.ts +1204 -0
  104. package/src/editable-artifacts/worker/wire-codec.ts +852 -0
  105. package/src/editable-artifacts-worker.ts +8 -0
  106. package/src/editable-artifacts.ts +6 -0
  107. package/src/errors.ts +16 -2
  108. package/src/gateway-realtime-transport.ts +252 -109
  109. package/src/index.ts +215 -1
  110. package/src/interaction-revision-stream.ts +117 -0
  111. package/src/interaction.ts +2874 -0
  112. package/src/memory-slack-client.ts +71 -0
  113. package/src/memory-slack-delivery.ts +128 -0
  114. package/src/memory-slack.ts +19 -0
  115. package/src/realtime.ts +14 -4
  116. package/src/retained-artifacts.ts +326 -0
  117. package/src/types.ts +1636 -52
  118. package/src/workspace-live-stream.ts +137 -0
  119. package/dist/chunk-DXDL7EEW.js.map +0 -1
  120. package/dist/chunk-KIHGPM7H.js.map +0 -1
  121. package/dist/chunk-MBGBLVUV.js.map +0 -1
  122. package/dist/chunk-V5F253OG.js.map +0 -1
@@ -123,6 +123,12 @@ export type CodexRealtimeControllerClient = {
123
123
  request: GatewayRealtimeConnectRequest,
124
124
  options?: { signal?: AbortSignal | undefined },
125
125
  ): Promise<GatewayRealtimeConnectResponse>;
126
+ negotiateXaiSubscriptionRealtime?(
127
+ workspaceId: string,
128
+ sessionId: string,
129
+ request: GatewayRealtimeConnectRequest,
130
+ options?: { signal?: AbortSignal | undefined },
131
+ ): Promise<GatewayRealtimeConnectResponse>;
126
132
  activateCodexRealtimeConnection(
127
133
  workspaceId: string,
128
134
  sessionId: string,
@@ -149,7 +155,9 @@ export type CodexRealtimeOwnerStorage = Pick<Storage, "getItem" | "setItem" | "r
149
155
 
150
156
  /** Canonical browser-owner storage namespace for a public realtime model. */
151
157
  export function sessionRealtimeOwnerStorageNamespace(model: SessionRealtimeModel): string {
152
- return model === "gpt-live-1-boulder-alpha" ? "codex-realtime-owner" : "gateway-realtime-owner";
158
+ if (model === "gpt-live-1-boulder-alpha") return "codex-realtime-owner";
159
+ if (model === "supergrok/grok-voice-think-fast-2.0") return "xai-realtime-owner";
160
+ return "gateway-realtime-owner";
153
161
  }
154
162
 
155
163
  /** Canonical browser-owner storage key shared by the SDK controller and React facade. */
@@ -454,16 +462,26 @@ export function createCodexRealtimeController(
454
462
  publish({ microphone: "active" });
455
463
  return acquired;
456
464
  } catch (error) {
457
- if (error instanceof CodexRealtimeMicrophoneError) {
458
- const kind = error.code === "permission_denied" ? "permission_failure" : "device_failure";
465
+ const microphoneError =
466
+ error instanceof CodexRealtimeMicrophoneError
467
+ ? error
468
+ : signal.aborted && state.microphone === "acquiring"
469
+ ? new CodexRealtimeMicrophoneError(
470
+ "acquisition_failed",
471
+ "Microphone did not become available before voice startup timed out",
472
+ )
473
+ : null;
474
+ if (microphoneError) {
475
+ const kind =
476
+ microphoneError.code === "permission_denied" ? "permission_failure" : "device_failure";
459
477
  publish({
460
- microphone: error.code,
478
+ microphone: microphoneError.code,
461
479
  status: state.mode?.state === "active" ? "recovering" : "error",
462
- diagnostic: diagnostic(kind, error.message, true),
463
- error: error.message,
480
+ diagnostic: diagnostic(kind, microphoneError.message, true),
481
+ error: microphoneError.message,
464
482
  });
465
483
  }
466
- throw error;
484
+ throw microphoneError ?? error;
467
485
  }
468
486
  };
469
487
 
@@ -66,6 +66,7 @@ export function projectSessionRealtimeLifecycle(
66
66
 
67
67
  function realtimeModel(value: unknown): SessionRealtimeModel | null {
68
68
  return value === "gpt-live-1-boulder-alpha" ||
69
+ value === "supergrok/grok-voice-think-fast-2.0" ||
69
70
  value === "opengeni-gateway/openai/gpt-realtime-2.1" ||
70
71
  value === "opengeni-gateway/openai/gpt-realtime-mini" ||
71
72
  value === "opengeni-gateway/xai/grok-voice-think-fast-2.0" ||
@@ -0,0 +1,92 @@
1
+ export const COMPANY_PROFILE_SCALAR_MAX_CHARS = 2_048;
2
+ export const COMPANY_PROFILE_ENTRY_MAX_CHARS = 1_024;
3
+ export const COMPANY_PROFILE_ENTRY_MAX_COUNT = 16;
4
+
5
+ export type CompanyProfileEntry = { key: string; content: string };
6
+ export type CompanyProfileContent = {
7
+ identity: string | null;
8
+ mission: string | null;
9
+ products: CompanyProfileEntry[];
10
+ customers: CompanyProfileEntry[];
11
+ goals: CompanyProfileEntry[];
12
+ constraints: CompanyProfileEntry[];
13
+ };
14
+ export type CompanyProfileRevisionIdentity = {
15
+ id: string;
16
+ revision: number;
17
+ contentHash: string;
18
+ };
19
+ export type CompanyProfileRevision = CompanyProfileRevisionIdentity & {
20
+ operationId: string;
21
+ accountId: string;
22
+ intent: "active" | "proposal";
23
+ profile: CompanyProfileContent;
24
+ provenance: { source: "human" | "durable_learning" | "migration"; sourceId: string | null };
25
+ supersedesRevisionId: string | null;
26
+ createdBySubjectId: string;
27
+ createdAt: string;
28
+ };
29
+ export type CompanyProfileHead = {
30
+ accountId: string;
31
+ revisionId: string;
32
+ revision: number;
33
+ contentHash: string;
34
+ activationVersion: number;
35
+ activatedAt: string;
36
+ };
37
+ export type CompanyProfileActivationEvent = {
38
+ id: string;
39
+ operationId: string;
40
+ accountId: string;
41
+ type: "activate" | "rollback";
42
+ activationVersion: number;
43
+ oldRevision: CompanyProfileRevisionIdentity | null;
44
+ newRevision: CompanyProfileRevisionIdentity | null;
45
+ actorSubjectId: string;
46
+ reason: string;
47
+ createdAt: string;
48
+ };
49
+ export type CompanyProfileListOptions = { afterRevision?: number; limit?: number };
50
+ export type CompanyProfileListResponse = {
51
+ current: CompanyProfileHead | null;
52
+ activeRevision: CompanyProfileRevision | null;
53
+ revisions: CompanyProfileRevision[];
54
+ activationEvents: CompanyProfileActivationEvent[];
55
+ nextAfterRevision: number | null;
56
+ };
57
+ export type UpdateCompanyProfileRequest = {
58
+ operationId?: string;
59
+ profile: CompanyProfileContent;
60
+ expectedCurrentRevisionId: string | null;
61
+ expectedActivationVersion: number;
62
+ reason: string;
63
+ };
64
+ export type ActivateCompanyProfileRevisionRequest = {
65
+ operationId?: string;
66
+ expectedCurrentRevisionId: string | null;
67
+ expectedActivationVersion: number;
68
+ reason: string;
69
+ };
70
+ export type RollbackCompanyProfileRequest = {
71
+ operationId?: string;
72
+ targetRevisionId: string;
73
+ expectedCurrentRevisionId: string;
74
+ expectedActivationVersion: number;
75
+ reason: string;
76
+ };
77
+ export type CompanyProfileMutationResponse = {
78
+ revision: CompanyProfileRevision | null;
79
+ head: CompanyProfileHead | null;
80
+ event: CompanyProfileActivationEvent | null;
81
+ };
82
+ export type CompanyProfileDiffRequest = { fromRevisionId: string; toRevisionId: string };
83
+ export type CompanyProfileDiffResponse = {
84
+ from: CompanyProfileRevision;
85
+ to: CompanyProfileRevision;
86
+ format: "unified_json";
87
+ diff: string;
88
+ };
89
+
90
+ export function normalizeCompanyProfileStableKey(value: string): string {
91
+ return value.normalize("NFKC").trim().toLowerCase().replace(/\s+/gu, "-").replace(/-+/g, "-");
92
+ }
package/src/desktop.ts CHANGED
@@ -71,13 +71,23 @@ export interface DesktopRfbLike {
71
71
  type: "connect" | "disconnect" | "securityfailure",
72
72
  cb: (e?: unknown) => void,
73
73
  ) => void;
74
+ /** Send clipboard text over the already-open RFB connection. */
75
+ clipboardPasteFrom?(text: string): void;
76
+ /** Send one RFB key event. A missing `down` emits a complete key press. */
77
+ sendKey?(keysym: number, code: string, down?: boolean): void;
78
+ /** Focus or release the RFB keyboard sink without reconnecting. */
79
+ focus?(options?: FocusOptions): void;
80
+ blur?(): void;
74
81
  disconnect(): void;
75
82
  }
76
83
 
77
84
  export type DesktopRfbFactory = (
78
85
  target: HTMLElement,
79
86
  url: string,
80
- opts: { credentials?: { password?: string | undefined } | undefined },
87
+ opts: {
88
+ credentials?: { password?: string | undefined } | undefined;
89
+ wsProtocols?: string[] | undefined;
90
+ },
81
91
  ) => DesktopRfbLike;
82
92
 
83
93
  export type DesktopConnectionState =
@@ -0,0 +1,119 @@
1
+ import type { OpenGeniRequestOptions } from "./client";
2
+ import type { EditableArtifactModality } from "./editable-artifacts/types";
3
+
4
+ /** Durable metadata returned by the editable-artifact product API. */
5
+ export type EditableArtifactResource = Readonly<{
6
+ id: string;
7
+ modality: EditableArtifactModality;
8
+ title: string;
9
+ lifecycle: "active" | "archived";
10
+ headSequence: number;
11
+ stateHash: string;
12
+ createdAt: string;
13
+ updatedAt: string;
14
+ }>;
15
+
16
+ export type EditableArtifactListResource = Readonly<{
17
+ artifacts: readonly EditableArtifactResource[];
18
+ }>;
19
+
20
+ export type CreateEditableArtifactResourceRequest = Readonly<{
21
+ /** Stable across transport retries; conflicting reuse is rejected. */
22
+ idempotencyKey: string;
23
+ /** Exact writer replica that will open the first live editing session. */
24
+ replicaId: string;
25
+ modality: EditableArtifactModality;
26
+ title: string;
27
+ }>;
28
+
29
+ export type ImportEditableArtifactResourceRequest = Readonly<{
30
+ idempotencyKey: string;
31
+ replicaId: string;
32
+ modality: EditableArtifactModality;
33
+ title: string;
34
+ sourceFileId: string;
35
+ }>;
36
+
37
+ export type ReadEditableArtifactResourceOptions = OpenGeniRequestOptions &
38
+ Readonly<{
39
+ /** Writer/read replica used to mint artifact-scoped authority. */
40
+ replicaId: string;
41
+ }>;
42
+
43
+ export type ListSessionEditableArtifactResourcesOptions = OpenGeniRequestOptions &
44
+ Readonly<{
45
+ replicaId: string;
46
+ }>;
47
+
48
+ export type EditableArtifactMaterializationFormat =
49
+ | "xlsx"
50
+ | "pptx"
51
+ | "docx"
52
+ | "pdf"
53
+ | "png"
54
+ | "webp";
55
+
56
+ export type EditableArtifactPinnedVersionResource = Readonly<{
57
+ id: string;
58
+ artifactId: string;
59
+ modality: EditableArtifactModality;
60
+ snapshotId: string;
61
+ headSequence: number;
62
+ causalFrontier: readonly Readonly<{ replicaId: string; counter: number }>[] | null;
63
+ nativeRevision: number | null;
64
+ stateHash: string;
65
+ name: string;
66
+ pinned: true;
67
+ createdAt: string;
68
+ replayed: boolean;
69
+ }>;
70
+
71
+ export type PinEditableArtifactVersionRequest = Readonly<{
72
+ replicaId: string;
73
+ idempotencyKey: string;
74
+ name: string;
75
+ }>;
76
+
77
+ export type EditableArtifactMaterializationResultResource = Readonly<{
78
+ id: string;
79
+ byteSize: number;
80
+ contentHash: string;
81
+ mimeType:
82
+ | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
83
+ | "application/vnd.openxmlformats-officedocument.presentationml.presentation"
84
+ | "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
85
+ | "application/pdf"
86
+ | "image/png"
87
+ | "image/webp";
88
+ verifiedAt: string;
89
+ createdAt: string;
90
+ }>;
91
+
92
+ export type EditableArtifactMaterializationJobResource = Readonly<{
93
+ id: string;
94
+ artifactId: string;
95
+ versionId: string;
96
+ inputSnapshotId: string;
97
+ targetHeadSequence: number;
98
+ stateHash: string;
99
+ format: EditableArtifactMaterializationFormat;
100
+ state: "pending" | "running" | "succeeded" | "failed";
101
+ attemptCount: number;
102
+ errorCode: string | null;
103
+ createdAt: string;
104
+ startedAt: string | null;
105
+ completedAt: string | null;
106
+ result: EditableArtifactMaterializationResultResource | null;
107
+ replayed?: boolean;
108
+ }>;
109
+
110
+ export type CreateEditableArtifactMaterializationRequest = Readonly<{
111
+ replicaId: string;
112
+ idempotencyKey: string;
113
+ versionId: string;
114
+ format: EditableArtifactMaterializationFormat;
115
+ options?: Readonly<Record<string, unknown>>;
116
+ }>;
117
+
118
+ export type ReadEditableArtifactMaterializationOptions = OpenGeniRequestOptions &
119
+ Readonly<{ replicaId: string }>;
@@ -0,0 +1,176 @@
1
+ import { DOCUMENT_ARTIFACT_COMMAND_VERSION } from "@opengeni/contracts/document-artifact-commands";
2
+ import { PRESENTATION_ARTIFACT_COMMAND_VERSION } from "@opengeni/contracts/presentation-artifact-commands";
3
+ import { SPREADSHEET_ARTIFACT_COMMAND_VERSION } from "@opengeni/contracts/spreadsheet-artifact-commands";
4
+
5
+ import type { EditableArtifactCacheAuthority } from "./controller";
6
+ import {
7
+ createEditableArtifactHttpLiveTransport,
8
+ type CreateEditableArtifactHttpLiveTransportOptions,
9
+ } from "./http-live-transport";
10
+ import { createEditableArtifactSession, type EditableArtifactSession } from "./session";
11
+ import type { EditableArtifactStoragePort } from "./storage";
12
+ import type { EditableArtifactModality } from "./types";
13
+ import {
14
+ createBrowserEditableArtifactWorkerKernel,
15
+ type CreateBrowserEditableArtifactWorkerKernelOptions,
16
+ } from "./worker/browser-client";
17
+
18
+ export type EditableArtifactBrowserRuntime = Omit<
19
+ CreateBrowserEditableArtifactWorkerKernelOptions,
20
+ "modality" | "kernelVersion" | "protocolVersion" | "modelSchemaVersion" | "commandVersion"
21
+ > &
22
+ Readonly<{
23
+ /** Exact native/WASM build identity admitted by the API. */
24
+ kernelVersion: string;
25
+ modelSchemaVersion: number;
26
+ protocolVersion?: number;
27
+ commandVersion: number;
28
+ }>;
29
+
30
+ export type CreateBrowserEditableArtifactSessionOptions = Readonly<{
31
+ baseUrl: string | URL;
32
+ workspaceId: string;
33
+ artifact: Readonly<{ id: string; modality: EditableArtifactModality }>;
34
+ /** Exact login/grant partition; rotate authorizationEpoch on authority changes. */
35
+ storageAuthority: EditableArtifactCacheAuthority;
36
+ runtime: EditableArtifactBrowserRuntime;
37
+ transport?: Omit<
38
+ CreateEditableArtifactHttpLiveTransportOptions,
39
+ "baseUrl" | "workspaceId" | "protocolVersion" | "kernelVersion" | "modelSchemaVersion"
40
+ >;
41
+ storage?: EditableArtifactStoragePort;
42
+ /** Reuse the replica used to create the artifact when opening it immediately. */
43
+ replicaId?: string;
44
+ }>;
45
+
46
+ /**
47
+ * One production browser composition point: verified WASM Worker, durable WAL,
48
+ * authenticated HTTP/WebSocket transport, replay, and modality projections.
49
+ */
50
+ export function createBrowserEditableArtifactSession(
51
+ options: CreateBrowserEditableArtifactSessionOptions,
52
+ ): EditableArtifactSession {
53
+ const baseUrl = canonicalBaseUrl(options.baseUrl);
54
+ const workspaceId = boundedIdentity(options.workspaceId, "workspaceId");
55
+ assertCacheAuthority(options.storageAuthority, baseUrl, workspaceId);
56
+ const protocolVersion = positiveVersion(options.runtime.protocolVersion ?? 1, "protocolVersion");
57
+ const modelSchemaVersion = positiveVersion(
58
+ options.runtime.modelSchemaVersion,
59
+ "modelSchemaVersion",
60
+ );
61
+ const kernelVersion = boundedIdentity(options.runtime.kernelVersion, "kernelVersion", 512);
62
+ const commandVersion = positiveVersion(options.runtime.commandVersion, "commandVersion");
63
+ const expectedCommandVersion = commandVersionFor(options.artifact.modality);
64
+ if (commandVersion !== expectedCommandVersion) {
65
+ throw new TypeError(
66
+ `commandVersion ${commandVersion} is incompatible with ${options.artifact.modality} ${expectedCommandVersion}`,
67
+ );
68
+ }
69
+ const {
70
+ kernelVersion: _kernelVersion,
71
+ modelSchemaVersion: _modelSchemaVersion,
72
+ protocolVersion: _protocolVersion,
73
+ commandVersion: _commandVersion,
74
+ ...workerOptions
75
+ } = options.runtime;
76
+ const worker = createBrowserEditableArtifactWorkerKernel({
77
+ ...workerOptions,
78
+ modality: options.artifact.modality,
79
+ kernelVersion,
80
+ protocolVersion,
81
+ modelSchemaVersion,
82
+ commandVersion,
83
+ });
84
+ const replicaId = options.replicaId;
85
+ try {
86
+ const transport = createEditableArtifactHttpLiveTransport({
87
+ ...options.transport,
88
+ baseUrl,
89
+ workspaceId,
90
+ protocolVersion,
91
+ kernelVersion,
92
+ modelSchemaVersion,
93
+ });
94
+ return createEditableArtifactSession({
95
+ artifactId: options.artifact.id,
96
+ modality: options.artifact.modality,
97
+ storageAuthority: options.storageAuthority,
98
+ transport,
99
+ worker,
100
+ ...(options.storage ? { storage: options.storage } : {}),
101
+ kernelVersion,
102
+ modelSchemaVersion,
103
+ commandVersion,
104
+ protocolVersion,
105
+ ...(replicaId ? { writerReplicaIdFactory: () => replicaId } : {}),
106
+ ownsWorker: true,
107
+ });
108
+ } catch (error) {
109
+ void worker.dispose().catch(() => undefined);
110
+ throw error;
111
+ }
112
+ }
113
+
114
+ /** Generates the portable 64-bit nonzero replica identity used by create/open. */
115
+ export function createEditableArtifactReplicaId(): string {
116
+ for (;;) {
117
+ const value = [...crypto.getRandomValues(new Uint8Array(8))]
118
+ .map((byte) => byte.toString(16).padStart(2, "0"))
119
+ .join("");
120
+ if (value !== "0000000000000000") return value;
121
+ }
122
+ }
123
+
124
+ function commandVersionFor(modality: EditableArtifactModality): number {
125
+ switch (modality) {
126
+ case "spreadsheet":
127
+ return SPREADSHEET_ARTIFACT_COMMAND_VERSION;
128
+ case "document":
129
+ return DOCUMENT_ARTIFACT_COMMAND_VERSION;
130
+ case "presentation":
131
+ return PRESENTATION_ARTIFACT_COMMAND_VERSION;
132
+ }
133
+ }
134
+
135
+ function canonicalBaseUrl(value: string | URL): URL {
136
+ const url = new URL(value);
137
+ if (url.username || url.password || url.search || url.hash) {
138
+ throw new TypeError("baseUrl must not contain credentials, query, or fragment");
139
+ }
140
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
141
+ throw new TypeError("baseUrl must use HTTP or HTTPS");
142
+ }
143
+ return url;
144
+ }
145
+
146
+ function assertCacheAuthority(
147
+ authority: EditableArtifactCacheAuthority,
148
+ baseUrl: URL,
149
+ workspaceId: string,
150
+ ): void {
151
+ if (new URL(authority.deploymentOrigin).origin !== baseUrl.origin) {
152
+ throw new TypeError("storageAuthority deployment origin does not match baseUrl");
153
+ }
154
+ if (authority.workspaceId !== workspaceId) {
155
+ throw new TypeError("storageAuthority workspace does not match workspaceId");
156
+ }
157
+ }
158
+
159
+ function boundedIdentity(value: string, label: string, maximum = 256): string {
160
+ if (
161
+ typeof value !== "string" ||
162
+ value.length === 0 ||
163
+ value.trim() !== value ||
164
+ new TextEncoder().encode(value).byteLength > maximum
165
+ ) {
166
+ throw new TypeError(`${label} is malformed`);
167
+ }
168
+ return value;
169
+ }
170
+
171
+ function positiveVersion(value: number, label: string): number {
172
+ if (!Number.isSafeInteger(value) || value < 1 || value > 65_535) {
173
+ throw new TypeError(`${label} must be a positive 16-bit integer`);
174
+ }
175
+ return value;
176
+ }