@opengeni/contracts 0.40.0 → 0.50.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 (148) hide show
  1. package/dist/atlassian.d.ts +278 -0
  2. package/dist/atlassian.js +57 -0
  3. package/dist/atlassian.js.map +1 -0
  4. package/dist/canonical-human-identities.d.ts +157 -0
  5. package/dist/canonical-human-identities.js +23 -0
  6. package/dist/canonical-human-identities.js.map +1 -0
  7. package/dist/{chunk-7JZMI22I.js → chunk-5UDNP7AO.js} +34 -2
  8. package/dist/chunk-5UDNP7AO.js.map +1 -0
  9. package/dist/chunk-BVGIYW7D.js +11 -0
  10. package/dist/chunk-BVGIYW7D.js.map +1 -0
  11. package/dist/chunk-CADSX6UN.js +1145 -0
  12. package/dist/chunk-CADSX6UN.js.map +1 -0
  13. package/dist/chunk-CM6BMECR.js +24 -0
  14. package/dist/chunk-CM6BMECR.js.map +1 -0
  15. package/dist/chunk-D2HKF2EF.js +1460 -0
  16. package/dist/chunk-D2HKF2EF.js.map +1 -0
  17. package/dist/chunk-JBCIY7QD.js +194 -0
  18. package/dist/chunk-JBCIY7QD.js.map +1 -0
  19. package/dist/chunk-JUFK3T4Q.js +80 -0
  20. package/dist/chunk-JUFK3T4Q.js.map +1 -0
  21. package/dist/chunk-LSB7GRLG.js +779 -0
  22. package/dist/chunk-LSB7GRLG.js.map +1 -0
  23. package/dist/chunk-LW7OH6CS.js +382 -0
  24. package/dist/chunk-LW7OH6CS.js.map +1 -0
  25. package/dist/chunk-M5ZGRVIQ.js +719 -0
  26. package/dist/chunk-M5ZGRVIQ.js.map +1 -0
  27. package/dist/chunk-MYBZRDTY.js +340 -0
  28. package/dist/chunk-MYBZRDTY.js.map +1 -0
  29. package/dist/chunk-Q6A7XT2N.js +16734 -0
  30. package/dist/chunk-Q6A7XT2N.js.map +1 -0
  31. package/dist/chunk-RIY7GYQS.js +1204 -0
  32. package/dist/chunk-RIY7GYQS.js.map +1 -0
  33. package/dist/chunk-TZ6YEYN4.js +386 -0
  34. package/dist/chunk-TZ6YEYN4.js.map +1 -0
  35. package/dist/chunk-Y3MLSLB4.js +392 -0
  36. package/dist/chunk-Y3MLSLB4.js.map +1 -0
  37. package/dist/chunk-YRKRZ6OF.js +134 -0
  38. package/dist/chunk-YRKRZ6OF.js.map +1 -0
  39. package/dist/codex-provider-account-authority.d.ts +23 -0
  40. package/dist/codex-provider-account-authority.js +23 -0
  41. package/dist/codex-provider-account-authority.js.map +1 -0
  42. package/dist/company-profile.d.ts +629 -0
  43. package/dist/document-artifact-commands.d.ts +282 -0
  44. package/dist/document-artifact-commands.js +54 -0
  45. package/dist/document-artifact-commands.js.map +1 -0
  46. package/dist/document-artifact-query.d.ts +2 -0
  47. package/dist/document-artifact-query.js +54 -0
  48. package/dist/document-artifact-query.js.map +1 -0
  49. package/dist/editable-artifact-binary.d.ts +56 -0
  50. package/dist/editable-artifact-causal-frontier.d.ts +12 -0
  51. package/dist/editable-artifact-causal-frontier.js +18 -0
  52. package/dist/editable-artifact-causal-frontier.js.map +1 -0
  53. package/dist/editable-artifact-codec-registry.d.ts +48 -0
  54. package/dist/editable-artifact-codec-registry.js +20 -0
  55. package/dist/editable-artifact-codec-registry.js.map +1 -0
  56. package/dist/editable-artifact-committed-transaction.d.ts +35 -0
  57. package/dist/editable-artifact-committed-transaction.js +19 -0
  58. package/dist/editable-artifact-committed-transaction.js.map +1 -0
  59. package/dist/editable-artifact-live.d.ts +276 -0
  60. package/dist/editable-artifact-live.js +907 -0
  61. package/dist/editable-artifact-live.js.map +1 -0
  62. package/dist/editable-artifact-serialized-commit.d.ts +53 -0
  63. package/dist/editable-artifact-serialized-commit.js +26 -0
  64. package/dist/editable-artifact-serialized-commit.js.map +1 -0
  65. package/dist/editable-artifact-versions.d.ts +6 -0
  66. package/dist/editable-artifact-versions.js +11 -0
  67. package/dist/editable-artifact-versions.js.map +1 -0
  68. package/dist/editable-artifacts.d.ts +46 -0
  69. package/dist/editable-artifacts.js +236 -0
  70. package/dist/editable-artifacts.js.map +1 -0
  71. package/dist/event-preview.d.ts +1 -1
  72. package/dist/google-drive.d.ts +114 -2
  73. package/dist/google-drive.js +72 -14
  74. package/dist/google-drive.js.map +1 -1
  75. package/dist/image-generation.d.ts +70 -0
  76. package/dist/index.d.ts +5661 -166
  77. package/dist/index.js +1438 -21
  78. package/dist/interaction.d.ts +8290 -0
  79. package/dist/knowledge.d.ts +543 -0
  80. package/dist/memory-slack-delivery.d.ts +397 -0
  81. package/dist/presentation-artifact-commands.d.ts +349 -0
  82. package/dist/presentation-artifact-commands.js +66 -0
  83. package/dist/presentation-artifact-commands.js.map +1 -0
  84. package/dist/presentation-artifact-query.d.ts +2 -0
  85. package/dist/presentation-artifact-query.js +66 -0
  86. package/dist/presentation-artifact-query.js.map +1 -0
  87. package/dist/retained-output.d.ts +24 -0
  88. package/dist/sandbox-snapshots.d.ts +9 -0
  89. package/dist/scoped-knowledge.d.ts +14 -13
  90. package/dist/slack-bot-scopes.d.ts +4 -0
  91. package/dist/slack-bot-scopes.js +3 -1
  92. package/dist/slack-task-policy.d.ts +294 -0
  93. package/dist/spreadsheet-artifact-commands.d.ts +101 -0
  94. package/dist/spreadsheet-artifact-commands.js +27 -0
  95. package/dist/spreadsheet-artifact-commands.js.map +1 -0
  96. package/dist/spreadsheet-artifact-date.d.ts +4 -0
  97. package/dist/spreadsheet-artifact-query.d.ts +120 -0
  98. package/dist/spreadsheet-artifact-query.js +48 -0
  99. package/dist/spreadsheet-artifact-query.js.map +1 -0
  100. package/dist/task-notes.d.ts +128 -0
  101. package/dist/tool-catalog.d.ts +576 -0
  102. package/dist/video-generation.d.ts +580 -0
  103. package/dist/video-generation.js +59 -0
  104. package/dist/video-generation.js.map +1 -0
  105. package/dist/workspace-learning-policy.d.ts +208 -0
  106. package/dist/xai-provider-account-authority.d.ts +23 -0
  107. package/dist/xai-provider-account-authority.js +9 -0
  108. package/dist/xai-provider-account-authority.js.map +1 -0
  109. package/package.json +73 -1
  110. package/src/artifacts.ts +1 -1
  111. package/src/atlassian.ts +160 -0
  112. package/src/canonical-human-identities.ts +93 -0
  113. package/src/codex-provider-account-authority.ts +37 -0
  114. package/src/company-profile.ts +306 -0
  115. package/src/document-artifact-commands.ts +1709 -0
  116. package/src/document-artifact-query.ts +2 -0
  117. package/src/editable-artifact-binary.ts +396 -0
  118. package/src/editable-artifact-causal-frontier.ts +154 -0
  119. package/src/editable-artifact-codec-registry.ts +261 -0
  120. package/src/editable-artifact-committed-transaction.ts +478 -0
  121. package/src/editable-artifact-live.ts +1379 -0
  122. package/src/editable-artifact-serialized-commit.ts +494 -0
  123. package/src/editable-artifact-versions.ts +8 -0
  124. package/src/editable-artifacts.ts +473 -0
  125. package/src/google-drive.ts +68 -15
  126. package/src/image-generation.ts +106 -0
  127. package/src/index.ts +2920 -326
  128. package/src/interaction.ts +3173 -0
  129. package/src/knowledge.ts +207 -0
  130. package/src/memory-slack-delivery.ts +183 -0
  131. package/src/presentation-artifact-commands.ts +2035 -0
  132. package/src/presentation-artifact-query.ts +2 -0
  133. package/src/retained-output.ts +149 -2
  134. package/src/sandbox-snapshots.ts +28 -1
  135. package/src/scoped-knowledge.ts +18 -4
  136. package/src/slack-bot-scopes.ts +34 -1
  137. package/src/slack-task-policy.ts +215 -0
  138. package/src/spreadsheet-artifact-commands.ts +999 -0
  139. package/src/spreadsheet-artifact-date.ts +21 -0
  140. package/src/spreadsheet-artifact-query.ts +1411 -0
  141. package/src/task-notes.ts +92 -0
  142. package/src/tool-catalog.ts +334 -0
  143. package/src/video-generation.ts +431 -0
  144. package/src/workspace-learning-policy.ts +233 -0
  145. package/src/xai-provider-account-authority.ts +37 -0
  146. package/dist/chunk-5HR2GPSC.js +0 -11031
  147. package/dist/chunk-5HR2GPSC.js.map +0 -1
  148. package/dist/chunk-7JZMI22I.js.map +0 -1
@@ -0,0 +1,473 @@
1
+ import { sha256 } from "@noble/hashes/sha256";
2
+ import { bytesToHex } from "@noble/hashes/utils";
3
+
4
+ export * from "./spreadsheet-artifact-commands";
5
+ export * from "./spreadsheet-artifact-query";
6
+ export * from "./editable-artifact-causal-frontier";
7
+ export * from "./document-artifact-commands";
8
+ export * from "./presentation-artifact-commands";
9
+ export * from "./editable-artifact-codec-registry";
10
+
11
+ export const EDITABLE_ARTIFACT_INTENT_VERSION = 1 as const;
12
+ export const EDITABLE_ARTIFACT_INTENT_MAX_BYTES = 5 * 1024 * 1024;
13
+ export const EDITABLE_ARTIFACT_COMMAND_MAX_BYTES = 4 * 1024 * 1024;
14
+ export const EDITABLE_ARTIFACT_KERNEL_VERSION_MAX_BYTES = 512;
15
+ /** Largest durable snapshot every supported browser/WASM client can open. */
16
+ export const EDITABLE_ARTIFACT_PRODUCT_MAX_SNAPSHOT_BYTES = 64 * 1024 * 1024;
17
+ export const EDITABLE_ARTIFACT_INTENT_MAX_CAUSAL_ACTORS = 1_024;
18
+ export const EDITABLE_ARTIFACT_INTENT_MAX_UNDO_TARGETS = 10_000;
19
+
20
+ const MAGIC = new TextEncoder().encode("OGATX001");
21
+ const textEncoder = new TextEncoder();
22
+ const textDecoder = new TextDecoder("utf-8", { fatal: true });
23
+ const STABLE_ID = /^[0-9a-f]{32}$/u;
24
+ const REPLICA_ID = /^[0-9a-f]{16}$/u;
25
+ const CLIENT_TRANSACTION_ID = /^[A-Za-z0-9._:-]{1,200}$/u;
26
+ const REQUEST_HASH = /^sha256:[0-9a-f]{64}$/u;
27
+
28
+ export type EditableArtifactCausalEntry = Readonly<{
29
+ replicaId: string;
30
+ counter: number;
31
+ }>;
32
+
33
+ /**
34
+ * Exact client-authored mutation identity. Scope and actor authority are
35
+ * deliberately absent: the server derives them and binds them in the
36
+ * idempotency lookup tuple instead of trusting client bytes.
37
+ */
38
+ export type EditableArtifactMutationIntent = Readonly<{
39
+ envelopeVersion: typeof EDITABLE_ARTIFACT_INTENT_VERSION;
40
+ protocolVersion: number;
41
+ modelSchemaVersion: number;
42
+ commandProtocolVersion: number;
43
+ artifactId: string;
44
+ clientTransactionId: string;
45
+ replicaId: string;
46
+ replicaCounter: number;
47
+ previousLocalTransactionId: string | null;
48
+ observedHeadSequence: number;
49
+ causalBase: readonly EditableArtifactCausalEntry[];
50
+ selectiveUndoOperationIds: readonly string[];
51
+ commandBytes: Uint8Array;
52
+ }>;
53
+
54
+ export function encodeEditableArtifactMutationIntent(
55
+ input: EditableArtifactMutationIntent,
56
+ ): Uint8Array {
57
+ // The writer owns the emitted bytes, so a second eager copy of a potentially
58
+ // multi-megabyte command block would add no safety.
59
+ const intent = normalizeIntent(input, false);
60
+ const writer = new BinaryWriter(EDITABLE_ARTIFACT_INTENT_MAX_BYTES);
61
+ writer.bytes(MAGIC);
62
+ writer.u16(intent.envelopeVersion);
63
+ writer.u16(intent.protocolVersion);
64
+ writer.u16(intent.modelSchemaVersion);
65
+ writer.u16(intent.commandProtocolVersion);
66
+ writer.string(intent.artifactId);
67
+ writer.string(intent.clientTransactionId);
68
+ writer.string(intent.replicaId);
69
+ writer.u64(intent.replicaCounter);
70
+ writer.u8(intent.previousLocalTransactionId === null ? 0 : 1);
71
+ if (intent.previousLocalTransactionId !== null) {
72
+ writer.string(intent.previousLocalTransactionId);
73
+ }
74
+ writer.u64(intent.observedHeadSequence);
75
+ writer.u16(intent.causalBase.length);
76
+ for (const entry of intent.causalBase) {
77
+ writer.string(entry.replicaId);
78
+ writer.u64(entry.counter);
79
+ }
80
+ writer.u16(intent.selectiveUndoOperationIds.length);
81
+ for (const operationId of intent.selectiveUndoOperationIds) writer.string(operationId);
82
+ writer.byteBlock(intent.commandBytes);
83
+ return writer.finish();
84
+ }
85
+
86
+ export function decodeEditableArtifactMutationIntent(
87
+ bytes: Uint8Array,
88
+ ): EditableArtifactMutationIntent {
89
+ return parseEditableArtifactMutationIntent(bytes, true);
90
+ }
91
+
92
+ function parseEditableArtifactMutationIntent(
93
+ bytes: Uint8Array,
94
+ copyCommandBytes: boolean,
95
+ ): EditableArtifactMutationIntent {
96
+ if (!(bytes instanceof Uint8Array)) throw new TypeError("intent bytes must be a Uint8Array");
97
+ if (bytes.byteLength > EDITABLE_ARTIFACT_INTENT_MAX_BYTES) {
98
+ throw new RangeError("editable artifact intent exceeds its byte limit");
99
+ }
100
+ const reader = new BinaryReader(bytes);
101
+ const magic = reader.bytes(MAGIC.byteLength);
102
+ if (!equalBytes(magic, MAGIC)) throw new TypeError("invalid editable artifact intent magic");
103
+ const envelopeVersion = reader.u16();
104
+ if (envelopeVersion !== EDITABLE_ARTIFACT_INTENT_VERSION) {
105
+ throw new TypeError(`unsupported editable artifact intent version: ${envelopeVersion}`);
106
+ }
107
+ const protocolVersion = reader.u16();
108
+ const modelSchemaVersion = reader.u16();
109
+ const commandProtocolVersion = reader.u16();
110
+ const artifactId = reader.string();
111
+ const clientTransactionId = reader.string();
112
+ const replicaId = reader.string();
113
+ const replicaCounter = reader.u64();
114
+ const predecessorFlag = reader.u8();
115
+ if (predecessorFlag > 1) throw new TypeError("invalid predecessor presence flag");
116
+ const previousLocalTransactionId = predecessorFlag === 1 ? reader.string() : null;
117
+ const observedHeadSequence = reader.u64();
118
+ const causalCount = reader.u16();
119
+ if (causalCount > EDITABLE_ARTIFACT_INTENT_MAX_CAUSAL_ACTORS) {
120
+ throw new RangeError("editable artifact causal base exceeds its actor limit");
121
+ }
122
+ const causalBase: EditableArtifactCausalEntry[] = [];
123
+ let previousReplicaId = "";
124
+ for (let index = 0; index < causalCount; index += 1) {
125
+ const causalReplicaId = reader.string();
126
+ if (causalReplicaId <= previousReplicaId) {
127
+ throw new TypeError("causal base replica ids must be unique and canonically sorted");
128
+ }
129
+ previousReplicaId = causalReplicaId;
130
+ causalBase.push(Object.freeze({ replicaId: causalReplicaId, counter: reader.u64() }));
131
+ }
132
+ const undoCount = reader.u16();
133
+ if (undoCount > EDITABLE_ARTIFACT_INTENT_MAX_UNDO_TARGETS) {
134
+ throw new RangeError("editable artifact undo targets exceed their limit");
135
+ }
136
+ const selectiveUndoOperationIds: string[] = [];
137
+ let previousOperationId = "";
138
+ for (let index = 0; index < undoCount; index += 1) {
139
+ const operationId = reader.string();
140
+ if (operationId <= previousOperationId) {
141
+ throw new TypeError("undo operation ids must be unique and canonically sorted");
142
+ }
143
+ previousOperationId = operationId;
144
+ selectiveUndoOperationIds.push(operationId);
145
+ }
146
+ const commandBytes = reader.byteBlock(EDITABLE_ARTIFACT_COMMAND_MAX_BYTES);
147
+ reader.done();
148
+ return normalizeIntent(
149
+ {
150
+ envelopeVersion: EDITABLE_ARTIFACT_INTENT_VERSION,
151
+ protocolVersion,
152
+ modelSchemaVersion,
153
+ commandProtocolVersion,
154
+ artifactId,
155
+ clientTransactionId,
156
+ replicaId,
157
+ replicaCounter,
158
+ previousLocalTransactionId,
159
+ observedHeadSequence,
160
+ causalBase,
161
+ selectiveUndoOperationIds,
162
+ commandBytes,
163
+ },
164
+ copyCommandBytes,
165
+ );
166
+ }
167
+
168
+ export function hashEditableArtifactMutationIntentBytes(bytes: Uint8Array): string {
169
+ // Decode first so noncanonical or malformed bytes can never acquire a valid
170
+ // application-level request hash merely because SHA-256 accepts any bytes.
171
+ parseEditableArtifactMutationIntent(bytes, false);
172
+ return `sha256:${bytesToHex(sha256(bytes))}`;
173
+ }
174
+
175
+ export function hashEditableArtifactMutationIntent(intent: EditableArtifactMutationIntent): {
176
+ bytes: Uint8Array;
177
+ requestHash: string;
178
+ } {
179
+ const bytes = encodeEditableArtifactMutationIntent(intent);
180
+ return { bytes, requestHash: `sha256:${bytesToHex(sha256(bytes))}` };
181
+ }
182
+
183
+ export function assertEditableArtifactRequestHash(value: string): string {
184
+ if (!REQUEST_HASH.test(value)) {
185
+ throw new TypeError("editable artifact request hash must be canonical sha256 text");
186
+ }
187
+ return value;
188
+ }
189
+
190
+ function normalizeIntent(
191
+ input: EditableArtifactMutationIntent,
192
+ copyCommandBytes = true,
193
+ ): EditableArtifactMutationIntent {
194
+ if (!isPlainRecord(input)) throw new TypeError("editable artifact intent must be a plain record");
195
+ if (input.envelopeVersion !== EDITABLE_ARTIFACT_INTENT_VERSION) {
196
+ throw new TypeError("editable artifact intent envelope version must be 1");
197
+ }
198
+ const protocolVersion = positiveU16(input.protocolVersion, "protocolVersion");
199
+ const modelSchemaVersion = positiveU16(input.modelSchemaVersion, "modelSchemaVersion");
200
+ const commandProtocolVersion = positiveU16(
201
+ input.commandProtocolVersion,
202
+ "commandProtocolVersion",
203
+ );
204
+ const artifactId = stableId(input.artifactId, "artifactId");
205
+ const clientTransactionId = portableTransactionId(
206
+ input.clientTransactionId,
207
+ "clientTransactionId",
208
+ );
209
+ const replicaId = replicaIdentity(input.replicaId, "replicaId");
210
+ const replicaCounter = positiveSafeInteger(input.replicaCounter, "replicaCounter");
211
+ const previousLocalTransactionId =
212
+ input.previousLocalTransactionId === null
213
+ ? null
214
+ : portableTransactionId(input.previousLocalTransactionId, "previousLocalTransactionId");
215
+ const observedHeadSequence = nonnegativeSafeInteger(
216
+ input.observedHeadSequence,
217
+ "observedHeadSequence",
218
+ );
219
+ if (!Array.isArray(input.causalBase)) throw new TypeError("causalBase must be an array");
220
+ if (input.causalBase.length > EDITABLE_ARTIFACT_INTENT_MAX_CAUSAL_ACTORS) {
221
+ throw new RangeError("editable artifact causal base exceeds its actor limit");
222
+ }
223
+ const causalByReplica = new Map<string, number>();
224
+ for (const entry of input.causalBase) {
225
+ if (!isPlainRecord(entry)) throw new TypeError("causal entries must be plain records");
226
+ const causalReplicaId = replicaIdentity(entry.replicaId, "causal replicaId");
227
+ if (causalByReplica.has(causalReplicaId)) throw new TypeError("duplicate causal replicaId");
228
+ causalByReplica.set(
229
+ causalReplicaId,
230
+ positiveSafeInteger(entry.counter, `causal counter for ${causalReplicaId}`),
231
+ );
232
+ }
233
+ const causalBase = [...causalByReplica]
234
+ .sort(([left], [right]) => compareCodeUnits(left, right))
235
+ .map(([causalReplicaId, counter]) => Object.freeze({ replicaId: causalReplicaId, counter }));
236
+ if (!Array.isArray(input.selectiveUndoOperationIds)) {
237
+ throw new TypeError("selectiveUndoOperationIds must be an array");
238
+ }
239
+ if (input.selectiveUndoOperationIds.length > EDITABLE_ARTIFACT_INTENT_MAX_UNDO_TARGETS) {
240
+ throw new RangeError("editable artifact undo targets exceed their limit");
241
+ }
242
+ const undoSet = new Set<string>();
243
+ for (const value of input.selectiveUndoOperationIds) {
244
+ const operationId = stableId(value, "selective undo operation id");
245
+ if (undoSet.has(operationId)) throw new TypeError("duplicate selective undo operation id");
246
+ undoSet.add(operationId);
247
+ }
248
+ const selectiveUndoOperationIds = [...undoSet].sort(compareCodeUnits);
249
+ if (!(input.commandBytes instanceof Uint8Array)) {
250
+ throw new TypeError("commandBytes must be a Uint8Array");
251
+ }
252
+ if (input.commandBytes.byteLength < 1) throw new TypeError("commandBytes must not be empty");
253
+ if (input.commandBytes.byteLength > EDITABLE_ARTIFACT_COMMAND_MAX_BYTES) {
254
+ throw new RangeError("commandBytes exceeds its byte limit");
255
+ }
256
+ return Object.freeze({
257
+ envelopeVersion: EDITABLE_ARTIFACT_INTENT_VERSION,
258
+ protocolVersion,
259
+ modelSchemaVersion,
260
+ commandProtocolVersion,
261
+ artifactId,
262
+ clientTransactionId,
263
+ replicaId,
264
+ replicaCounter,
265
+ previousLocalTransactionId,
266
+ observedHeadSequence,
267
+ causalBase: Object.freeze(causalBase),
268
+ selectiveUndoOperationIds: Object.freeze(selectiveUndoOperationIds),
269
+ commandBytes: copyCommandBytes ? input.commandBytes.slice() : input.commandBytes,
270
+ });
271
+ }
272
+
273
+ function isPlainRecord(value: unknown): value is Record<string, unknown> {
274
+ return (
275
+ typeof value === "object" && value !== null && Object.getPrototypeOf(value) === Object.prototype
276
+ );
277
+ }
278
+
279
+ function stableId(value: unknown, label: string): string {
280
+ if (typeof value !== "string" || !STABLE_ID.test(value) || /^0+$/u.test(value)) {
281
+ throw new TypeError(`${label} must be nonzero fixed-width lowercase hexadecimal text`);
282
+ }
283
+ return value;
284
+ }
285
+
286
+ function replicaIdentity(value: unknown, label: string): string {
287
+ if (typeof value !== "string" || !REPLICA_ID.test(value) || /^0+$/u.test(value)) {
288
+ throw new TypeError(`${label} must be nonzero 64-bit lowercase hexadecimal text`);
289
+ }
290
+ return value;
291
+ }
292
+
293
+ function portableTransactionId(value: unknown, label: string): string {
294
+ if (typeof value !== "string" || !CLIENT_TRANSACTION_ID.test(value)) {
295
+ throw new TypeError(`${label} must contain 1-200 portable identifier characters`);
296
+ }
297
+ return value;
298
+ }
299
+
300
+ function positiveU16(value: unknown, label: string): number {
301
+ if (!Number.isInteger(value) || (value as number) < 1 || (value as number) > 0xffff) {
302
+ throw new TypeError(`${label} must be a positive 16-bit integer`);
303
+ }
304
+ return value as number;
305
+ }
306
+
307
+ function positiveSafeInteger(value: unknown, label: string): number {
308
+ if (!Number.isSafeInteger(value) || (value as number) < 1) {
309
+ throw new TypeError(`${label} must be a positive safe integer`);
310
+ }
311
+ return value as number;
312
+ }
313
+
314
+ function nonnegativeSafeInteger(value: unknown, label: string): number {
315
+ if (!Number.isSafeInteger(value) || (value as number) < 0) {
316
+ throw new TypeError(`${label} must be a nonnegative safe integer`);
317
+ }
318
+ return value as number;
319
+ }
320
+
321
+ function compareCodeUnits(left: string, right: string): number {
322
+ return left < right ? -1 : left > right ? 1 : 0;
323
+ }
324
+
325
+ function equalBytes(left: Uint8Array, right: Uint8Array): boolean {
326
+ return (
327
+ left.byteLength === right.byteLength && left.every((value, index) => value === right[index])
328
+ );
329
+ }
330
+
331
+ class BinaryWriter {
332
+ private buffer = new Uint8Array(1_024);
333
+ private length = 0;
334
+
335
+ constructor(private readonly maximum: number) {}
336
+
337
+ u8(value: number): void {
338
+ this.ensure(1);
339
+ this.buffer[this.length++] = value;
340
+ }
341
+
342
+ u16(value: number): void {
343
+ this.ensure(2);
344
+ this.buffer[this.length++] = value & 0xff;
345
+ this.buffer[this.length++] = (value >>> 8) & 0xff;
346
+ }
347
+
348
+ u32(value: number): void {
349
+ this.ensure(4);
350
+ for (let offset = 0; offset < 4; offset += 1) {
351
+ this.buffer[this.length++] = Math.floor(value / 2 ** (offset * 8)) & 0xff;
352
+ }
353
+ }
354
+
355
+ u64(value: number): void {
356
+ if (!Number.isSafeInteger(value) || value < 0) throw new TypeError("u64 must be safe");
357
+ this.ensure(8);
358
+ let remaining = BigInt(value);
359
+ for (let offset = 0; offset < 8; offset += 1) {
360
+ this.buffer[this.length++] = Number(remaining & 0xffn);
361
+ remaining >>= 8n;
362
+ }
363
+ }
364
+
365
+ string(value: string): void {
366
+ const bytes = textEncoder.encode(value);
367
+ if (bytes.byteLength > 0xffff) throw new RangeError("intent string exceeds 65535 bytes");
368
+ this.u16(bytes.byteLength);
369
+ this.bytes(bytes);
370
+ }
371
+
372
+ byteBlock(value: Uint8Array): void {
373
+ this.u32(value.byteLength);
374
+ this.bytes(value);
375
+ }
376
+
377
+ bytes(value: Uint8Array): void {
378
+ this.ensure(value.byteLength);
379
+ this.buffer.set(value, this.length);
380
+ this.length += value.byteLength;
381
+ }
382
+
383
+ finish(): Uint8Array {
384
+ return this.buffer.slice(0, this.length);
385
+ }
386
+
387
+ private ensure(additional: number): void {
388
+ const needed = this.length + additional;
389
+ if (!Number.isSafeInteger(needed) || needed > this.maximum) {
390
+ throw new RangeError("editable artifact intent exceeds its byte limit");
391
+ }
392
+ if (needed <= this.buffer.byteLength) return;
393
+ let size = this.buffer.byteLength;
394
+ while (size < needed) size = Math.min(this.maximum, size * 2);
395
+ const next = new Uint8Array(size);
396
+ next.set(this.buffer.subarray(0, this.length));
397
+ this.buffer = next;
398
+ }
399
+ }
400
+
401
+ class BinaryReader {
402
+ private offset = 0;
403
+
404
+ constructor(private readonly input: Uint8Array) {}
405
+
406
+ u8(): number {
407
+ this.require(1);
408
+ return this.input[this.offset++]!;
409
+ }
410
+
411
+ u16(): number {
412
+ this.require(2);
413
+ const value = this.input[this.offset]! | (this.input[this.offset + 1]! << 8);
414
+ this.offset += 2;
415
+ return value;
416
+ }
417
+
418
+ u32(): number {
419
+ this.require(4);
420
+ const value =
421
+ this.input[this.offset]! +
422
+ this.input[this.offset + 1]! * 2 ** 8 +
423
+ this.input[this.offset + 2]! * 2 ** 16 +
424
+ this.input[this.offset + 3]! * 2 ** 24;
425
+ this.offset += 4;
426
+ return value;
427
+ }
428
+
429
+ u64(): number {
430
+ this.require(8);
431
+ let value = 0n;
432
+ for (let offset = 0; offset < 8; offset += 1) {
433
+ value |= BigInt(this.input[this.offset + offset]!) << BigInt(offset * 8);
434
+ }
435
+ this.offset += 8;
436
+ if (value > BigInt(Number.MAX_SAFE_INTEGER)) throw new RangeError("u64 exceeds safe integer");
437
+ return Number(value);
438
+ }
439
+
440
+ string(): string {
441
+ return textDecoder.decode(this.bytes(this.u16()));
442
+ }
443
+
444
+ byteBlock(maximum: number): Uint8Array {
445
+ const length = this.u32();
446
+ if (length < 1) throw new TypeError("commandBytes must not be empty");
447
+ if (length > maximum) throw new RangeError("commandBytes exceeds its byte limit");
448
+ return this.bytes(length);
449
+ }
450
+
451
+ bytes(length: number): Uint8Array {
452
+ this.require(length);
453
+ const output = this.input.subarray(this.offset, this.offset + length);
454
+ this.offset += length;
455
+ return output;
456
+ }
457
+
458
+ done(): void {
459
+ if (this.offset !== this.input.byteLength) {
460
+ throw new TypeError("editable artifact intent contains trailing bytes");
461
+ }
462
+ }
463
+
464
+ private require(length: number): void {
465
+ if (
466
+ !Number.isSafeInteger(length) ||
467
+ length < 0 ||
468
+ this.offset + length > this.input.byteLength
469
+ ) {
470
+ throw new TypeError("truncated editable artifact intent");
471
+ }
472
+ }
473
+ }
@@ -13,8 +13,10 @@ export const GOOGLE_DRIVE_METADATA_READONLY_SCOPE =
13
13
  "https://www.googleapis.com/auth/drive.metadata.readonly" as const;
14
14
  export const GOOGLE_DRIVE_READONLY_SCOPE =
15
15
  "https://www.googleapis.com/auth/drive.readonly" as const;
16
+ /** Stable serialized role retained for existing connection rows; not product-facing copy. */
16
17
  export const GOOGLE_DRIVE_CREDENTIAL_ROLE = "google_drive_metadata" as const;
17
- export const GOOGLE_DRIVE_CREDENTIAL_LABEL = "Google Drive metadata browser" as const;
18
+ export const GOOGLE_DRIVE_CREDENTIAL_LABEL = "Google Drive read-only source sync" as const;
19
+ export const GOOGLE_DRIVE_LEGACY_CREDENTIAL_LABEL = "Google Drive metadata browser" as const;
18
20
 
19
21
  export const GoogleDriveOAuthCapability = z.enum([
20
22
  "picker_file_read",
@@ -139,6 +141,8 @@ export const GoogleDriveSelectedSource = z.object({
139
141
  /** @deprecated Missing destinations resolve to the current workspace boundary. */
140
142
  targetScope: GoogleDriveTargetScope.optional(),
141
143
  syncCadence: GoogleDriveSyncCadence.default("hourly"),
144
+ syncEnabled: z.boolean().default(false),
145
+ configGeneration: z.number().int().positive().default(1),
142
146
  readPolicy: GoogleDriveReadPolicy.default("allow"),
143
147
  selectedAt: z.string().datetime({ offset: true }),
144
148
  });
@@ -147,7 +151,10 @@ export type GoogleDriveSelectedSource = z.infer<typeof GoogleDriveSelectedSource
147
151
  export const GoogleDriveConnectionMetadata = z
148
152
  .object({
149
153
  credentialRole: z.literal(GOOGLE_DRIVE_CREDENTIAL_ROLE),
150
- credentialLabel: z.literal(GOOGLE_DRIVE_CREDENTIAL_LABEL),
154
+ credentialLabel: z.union([
155
+ z.literal(GOOGLE_DRIVE_CREDENTIAL_LABEL),
156
+ z.literal(GOOGLE_DRIVE_LEGACY_CREDENTIAL_LABEL),
157
+ ]),
151
158
  googlePermissionId: z.string().min(1).max(256),
152
159
  googleEmail: z.string().email().max(320),
153
160
  googleDisplayName: z.string().min(1).max(512).nullable(),
@@ -207,28 +214,74 @@ export const GoogleDriveBrowseResponse = z.object({
207
214
  });
208
215
  export type GoogleDriveBrowseResponse = z.infer<typeof GoogleDriveBrowseResponse>;
209
216
 
217
+ const GoogleDriveSourceSelection = z
218
+ .array(
219
+ GoogleDriveBrowseItem.pick({
220
+ id: true,
221
+ name: true,
222
+ mimeType: true,
223
+ driveId: true,
224
+ }),
225
+ )
226
+ .max(100)
227
+ .refine((sources) => new Set(sources.map((source) => source.id)).size === sources.length, {
228
+ message: "Google Drive sources must be unique",
229
+ });
230
+
210
231
  export const SaveGoogleDriveSourceRequest = z
211
232
  .object({
212
- sources: z
213
- .array(
214
- GoogleDriveBrowseItem.pick({
215
- id: true,
216
- name: true,
217
- mimeType: true,
218
- driveId: true,
219
- }),
220
- )
221
- .max(100)
222
- .refine((sources) => new Set(sources.map((source) => source.id)).size === sources.length, {
223
- message: "Google Drive sources must be unique",
224
- }),
233
+ sources: GoogleDriveSourceSelection,
225
234
  destination: ConnectorDocumentDestinationSelection.optional(),
226
235
  /** @deprecated Legacy requests are accepted but resolve to workspace authority. */
227
236
  targetScope: GoogleDriveTargetScope.optional(),
228
237
  syncCadence: GoogleDriveSyncCadence.default("hourly"),
238
+ syncEnabled: z.boolean().default(false),
229
239
  readPolicy: GoogleDriveReadPolicy.default("allow"),
230
240
  })
231
241
  .refine((request) => request.destination !== undefined || request.targetScope !== undefined, {
232
242
  message: "Google Drive document destination is required",
233
243
  });
234
244
  export type SaveGoogleDriveSourceRequest = z.infer<typeof SaveGoogleDriveSourceRequest>;
245
+
246
+ export const GoogleDriveKnowledgeSourceItem = z.object({
247
+ id: z.string().min(1).max(512),
248
+ name: z.string().min(1).max(1024),
249
+ mimeType: z.string().min(1).max(256),
250
+ driveId: z.string().min(1).max(512).optional(),
251
+ sourceKind: z.enum(["my_drive", "shared_drive", "folder"]),
252
+ includeDescendants: z.boolean(),
253
+ });
254
+ export type GoogleDriveKnowledgeSourceItem = z.infer<typeof GoogleDriveKnowledgeSourceItem>;
255
+
256
+ export const GoogleDriveKnowledgeSourceDestination = z.object({
257
+ authorityKind: z.enum(["organization", "workspace", "personal"]),
258
+ authorityAccountId: z.string().min(1).max(128),
259
+ authorityWorkspaceId: z.string().min(1).max(128).optional(),
260
+ authoritySubjectId: z.string().min(1).max(512).optional(),
261
+ collectionId: z.string().min(1).max(512).optional(),
262
+ });
263
+ export type GoogleDriveKnowledgeSourceDestination = z.infer<
264
+ typeof GoogleDriveKnowledgeSourceDestination
265
+ >;
266
+
267
+ export const GoogleDriveKnowledgeSourceConfig = z.object({
268
+ sources: z.array(GoogleDriveKnowledgeSourceItem).min(1).max(100),
269
+ destination: GoogleDriveKnowledgeSourceDestination,
270
+ syncCadence: GoogleDriveSyncCadence,
271
+ readPolicy: GoogleDriveReadPolicy,
272
+ });
273
+ export type GoogleDriveKnowledgeSourceConfig = z.infer<typeof GoogleDriveKnowledgeSourceConfig>;
274
+
275
+ export const SaveGoogleDriveIntegrationSourceRequest = z.intersection(
276
+ SaveGoogleDriveSourceRequest,
277
+ z.object({
278
+ sources: GoogleDriveSourceSelection.refine((sources) => sources.length > 0, {
279
+ message: "At least one Google Drive source is required",
280
+ }),
281
+ expectedVersion: z.number().int().positive().optional(),
282
+ idempotencyKey: z.string().uuid(),
283
+ }),
284
+ );
285
+ export type SaveGoogleDriveIntegrationSourceRequest = z.infer<
286
+ typeof SaveGoogleDriveIntegrationSourceRequest
287
+ >;
@@ -0,0 +1,106 @@
1
+ import { z } from "zod";
2
+ import { RETAINED_OUTPUT_MAX_PAGE_BYTES, RetainedArtifactReferenceSchema } from "./retained-output";
3
+
4
+ // Codex accepts five references, while the current Gateway GPT Image 2 route
5
+ // accepts four. Keep the provider-neutral tool at the reliable shared limit.
6
+ export const IMAGE_GENERATION_MAX_REFERENCES = 4;
7
+
8
+ const WorkspaceImagePathSchema = z
9
+ .string()
10
+ .max(512)
11
+ // Keep the provider-visible pattern within the portable JSON Schema regex
12
+ // subset. Codex rejects lookaround before inference.
13
+ .regex(/^\/workspace\/.+$/)
14
+ // Path traversal remains an exact runtime validation concern. Zod does not
15
+ // project custom refinements into JSON Schema, so this preserves the guard
16
+ // without sending unsupported regex syntax to model providers.
17
+ .refine((path) => path.split("/").every((segment) => segment !== "." && segment !== ".."), {
18
+ message: "Sandbox image paths cannot contain dot segments",
19
+ });
20
+
21
+ /** One ordered, workspace-owned input used to guide or edit an image. */
22
+ export const ImageGenerationReferenceSchema = z.discriminatedUnion("kind", [
23
+ z
24
+ .object({
25
+ kind: z.literal("sandbox_path"),
26
+ path: WorkspaceImagePathSchema,
27
+ })
28
+ .strict(),
29
+ z
30
+ .object({
31
+ kind: z.literal("file"),
32
+ fileId: z.string().uuid(),
33
+ })
34
+ .strict(),
35
+ z
36
+ .object({
37
+ kind: z.literal("artifact"),
38
+ artifactId: z.string().uuid(),
39
+ })
40
+ .strict(),
41
+ ]);
42
+ export type ImageGenerationReference = z.infer<typeof ImageGenerationReferenceSchema>;
43
+
44
+ /** Provider-neutral minimum shared by native and adapter-backed image tools. */
45
+ export const GenerateImageToolInput = z
46
+ .object({
47
+ prompt: z.string().trim().min(1).max(32_000),
48
+ references: z
49
+ .array(ImageGenerationReferenceSchema)
50
+ .max(IMAGE_GENERATION_MAX_REFERENCES)
51
+ .optional()
52
+ .default([]),
53
+ })
54
+ .strict();
55
+ export type GenerateImageToolInput = z.infer<typeof GenerateImageToolInput>;
56
+
57
+ /** Closed durable result shared by native and adapter-backed image tools. */
58
+ export const GeneratedImageReceiptSchema = z
59
+ .object({
60
+ type: z.literal("generated_image"),
61
+ artifact: RetainedArtifactReferenceSchema,
62
+ sandboxPath: z
63
+ .string()
64
+ .max(256)
65
+ .regex(
66
+ /^\/workspace\/generated-images\/generated-image-[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.(png|jpg|webp)$/,
67
+ ),
68
+ })
69
+ .strict()
70
+ .superRefine((value, ctx) => {
71
+ if (value.artifact.kind !== "generated_image") {
72
+ ctx.addIssue({
73
+ code: "custom",
74
+ path: ["artifact", "kind"],
75
+ message: "generated-image receipt requires a generated-image artifact",
76
+ });
77
+ return;
78
+ }
79
+ if (value.artifact.retrieval.maxRangeBytes !== RETAINED_OUTPUT_MAX_PAGE_BYTES) {
80
+ ctx.addIssue({
81
+ code: "custom",
82
+ path: ["artifact", "retrieval", "maxRangeBytes"],
83
+ message: "generated-image receipt requires the canonical range size",
84
+ });
85
+ }
86
+ const extension =
87
+ value.artifact.contentType === "image/png"
88
+ ? "png"
89
+ : value.artifact.contentType === "image/jpeg"
90
+ ? "jpg"
91
+ : value.artifact.contentType === "image/webp"
92
+ ? "webp"
93
+ : null;
94
+ if (
95
+ extension === null ||
96
+ value.sandboxPath !==
97
+ `/workspace/generated-images/generated-image-${value.artifact.artifactId}.${extension}`
98
+ ) {
99
+ ctx.addIssue({
100
+ code: "custom",
101
+ path: ["sandboxPath"],
102
+ message: "generated-image sandbox path does not match its artifact",
103
+ });
104
+ }
105
+ });
106
+ export type GeneratedImageReceipt = z.infer<typeof GeneratedImageReceiptSchema>;