@opengeni/contracts 0.44.1 → 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 (49) hide show
  1. package/dist/atlassian.js +10 -8
  2. package/dist/canonical-human-identities.d.ts +157 -0
  3. package/dist/canonical-human-identities.js +23 -0
  4. package/dist/canonical-human-identities.js.map +1 -0
  5. package/dist/chunk-CM6BMECR.js +24 -0
  6. package/dist/chunk-CM6BMECR.js.map +1 -0
  7. package/dist/{chunk-FJBG5E4O.js → chunk-JBCIY7QD.js} +12 -12
  8. package/dist/chunk-JUFK3T4Q.js +80 -0
  9. package/dist/chunk-JUFK3T4Q.js.map +1 -0
  10. package/dist/{chunk-H5BVCZKF.js → chunk-LW7OH6CS.js} +2 -2
  11. package/dist/{chunk-52SGB2QO.js → chunk-M5ZGRVIQ.js} +37 -6
  12. package/dist/chunk-M5ZGRVIQ.js.map +1 -0
  13. package/dist/{chunk-VA22KRHS.js → chunk-Q6A7XT2N.js} +6371 -4814
  14. package/dist/chunk-Q6A7XT2N.js.map +1 -0
  15. package/dist/codex-provider-account-authority.d.ts +23 -0
  16. package/dist/codex-provider-account-authority.js +23 -0
  17. package/dist/codex-provider-account-authority.js.map +1 -0
  18. package/dist/editable-artifact-codec-registry.js +5 -5
  19. package/dist/editable-artifact-live.js +3 -3
  20. package/dist/editable-artifact-serialized-commit.js +4 -4
  21. package/dist/editable-artifacts.js +27 -27
  22. package/dist/google-drive.js +11 -9
  23. package/dist/google-drive.js.map +1 -1
  24. package/dist/index.d.ts +1318 -128
  25. package/dist/index.js +400 -80
  26. package/dist/interaction.d.ts +1415 -20
  27. package/dist/knowledge.d.ts +543 -0
  28. package/dist/slack-task-policy.d.ts +294 -0
  29. package/dist/task-notes.d.ts +128 -0
  30. package/dist/video-generation.d.ts +48 -0
  31. package/dist/video-generation.js +9 -1
  32. package/dist/xai-provider-account-authority.d.ts +23 -0
  33. package/dist/xai-provider-account-authority.js +9 -0
  34. package/dist/xai-provider-account-authority.js.map +1 -0
  35. package/package.json +13 -1
  36. package/src/artifacts.ts +1 -1
  37. package/src/canonical-human-identities.ts +93 -0
  38. package/src/codex-provider-account-authority.ts +37 -0
  39. package/src/index.ts +731 -138
  40. package/src/interaction.ts +886 -5
  41. package/src/knowledge.ts +207 -0
  42. package/src/slack-task-policy.ts +215 -0
  43. package/src/task-notes.ts +92 -0
  44. package/src/video-generation.ts +43 -6
  45. package/src/xai-provider-account-authority.ts +37 -0
  46. package/dist/chunk-52SGB2QO.js.map +0 -1
  47. package/dist/chunk-VA22KRHS.js.map +0 -1
  48. /package/dist/{chunk-FJBG5E4O.js.map → chunk-JBCIY7QD.js.map} +0 -0
  49. /package/dist/{chunk-H5BVCZKF.js.map → chunk-LW7OH6CS.js.map} +0 -0
@@ -0,0 +1,207 @@
1
+ import { z } from "zod";
2
+
3
+ export const KNOWLEDGE_BROWSE_CURSOR_MAX_CHARS = 1_024;
4
+ export const KNOWLEDGE_BROWSE_DEFAULT_LIMIT = 20;
5
+ export const KNOWLEDGE_BROWSE_MAX_LIMIT = 50;
6
+ export const KNOWLEDGE_TITLE_MAX_BYTES = 1_024;
7
+ export const KNOWLEDGE_BODY_MAX_BYTES = 16 * 1_024;
8
+ export const KNOWLEDGE_SUMMARY_MAX_BYTES = 4 * 1_024;
9
+ export const KNOWLEDGE_TOPIC_MAX_BYTES = 256;
10
+ export const KNOWLEDGE_TOPICS_MAX_ITEMS = 32;
11
+ export const KNOWLEDGE_METADATA_MAX_BYTES = 8 * 1_024;
12
+ export const KNOWLEDGE_METADATA_MAX_ITEMS = 64;
13
+ export const KNOWLEDGE_METADATA_MAX_DEPTH = 4;
14
+ export const KNOWLEDGE_SOURCE_STRING_MAX_BYTES = 2_048;
15
+ export const KNOWLEDGE_SOURCE_URI_MAX_BYTES = 8_192;
16
+
17
+ const utf8Bytes = (value: string): number => new TextEncoder().encode(value).byteLength;
18
+ const boundedUtf8 = (maxBytes: number) =>
19
+ z.string().superRefine((value, ctx) => {
20
+ if (utf8Bytes(value) > maxBytes) {
21
+ ctx.addIssue({
22
+ code: z.ZodIssueCode.custom,
23
+ message: `must be at most ${maxBytes} UTF-8 bytes`,
24
+ });
25
+ }
26
+ });
27
+
28
+ function boundedJson(value: unknown): boolean {
29
+ let items = 0;
30
+ let valid = true;
31
+ const visit = (candidate: unknown, depth: number): void => {
32
+ if (!valid || ++items > KNOWLEDGE_METADATA_MAX_ITEMS || depth > KNOWLEDGE_METADATA_MAX_DEPTH) {
33
+ valid = false;
34
+ return;
35
+ }
36
+ if (
37
+ candidate === null ||
38
+ typeof candidate === "boolean" ||
39
+ (typeof candidate === "number" && Number.isFinite(candidate))
40
+ ) {
41
+ return;
42
+ }
43
+ if (typeof candidate === "string") {
44
+ if (utf8Bytes(candidate) > KNOWLEDGE_SOURCE_STRING_MAX_BYTES) valid = false;
45
+ return;
46
+ }
47
+ if (Array.isArray(candidate)) {
48
+ for (const item of candidate) visit(item, depth + 1);
49
+ return;
50
+ }
51
+ if (typeof candidate === "object") {
52
+ for (const [key, item] of Object.entries(candidate as Record<string, unknown>)) {
53
+ if (utf8Bytes(key) > KNOWLEDGE_TOPIC_MAX_BYTES) valid = false;
54
+ visit(item, depth + 1);
55
+ }
56
+ return;
57
+ }
58
+ valid = false;
59
+ };
60
+ visit(value, 0);
61
+ if (!valid) return false;
62
+ try {
63
+ return utf8Bytes(JSON.stringify(value)) <= KNOWLEDGE_METADATA_MAX_BYTES;
64
+ } catch {
65
+ return false;
66
+ }
67
+ }
68
+
69
+ export const KnowledgeRecordId = z
70
+ .string()
71
+ .regex(
72
+ /^(document|document_chunk):[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu,
73
+ );
74
+ export type KnowledgeRecordId = z.infer<typeof KnowledgeRecordId>;
75
+
76
+ export const KnowledgeRecordKind = z.enum(["document", "document_chunk"]);
77
+ export type KnowledgeRecordKind = z.infer<typeof KnowledgeRecordKind>;
78
+
79
+ export const KnowledgeAuthority = z.object({
80
+ kind: z.enum(["organization", "workspace", "personal"]),
81
+ });
82
+ export type KnowledgeAuthority = z.infer<typeof KnowledgeAuthority>;
83
+
84
+ export const KnowledgeSource = z.object({
85
+ kind: z.enum([
86
+ "manual_upload",
87
+ "meeting_transcript",
88
+ "repository",
89
+ "email",
90
+ "chat",
91
+ "document",
92
+ "web",
93
+ "other",
94
+ ]),
95
+ uri: boundedUtf8(KNOWLEDGE_SOURCE_URI_MAX_BYTES).pipe(z.string().min(1)).nullable(),
96
+ externalId: boundedUtf8(KNOWLEDGE_SOURCE_STRING_MAX_BYTES).nullable(),
97
+ title: boundedUtf8(KNOWLEDGE_SOURCE_STRING_MAX_BYTES).nullable(),
98
+ author: boundedUtf8(KNOWLEDGE_SOURCE_STRING_MAX_BYTES).nullable(),
99
+ createdAt: z.string().nullable(),
100
+ updatedAt: z.string().nullable(),
101
+ version: boundedUtf8(KNOWLEDGE_SOURCE_STRING_MAX_BYTES).nullable(),
102
+ });
103
+ export type KnowledgeSource = z.infer<typeof KnowledgeSource>;
104
+
105
+ export const KnowledgeLinkTarget = z.discriminatedUnion("kind", [
106
+ z.object({
107
+ kind: z.literal("knowledge"),
108
+ id: KnowledgeRecordId,
109
+ }),
110
+ z.object({
111
+ kind: z.literal("external"),
112
+ uri: boundedUtf8(KNOWLEDGE_SOURCE_URI_MAX_BYTES).pipe(z.string().min(1)),
113
+ }),
114
+ ]);
115
+ export type KnowledgeLinkTarget = z.infer<typeof KnowledgeLinkTarget>;
116
+
117
+ export const KnowledgeLink = z.object({
118
+ relation: z.enum(["parent", "contents", "previous", "next", "source"]),
119
+ target: KnowledgeLinkTarget,
120
+ });
121
+ export type KnowledgeLink = z.infer<typeof KnowledgeLink>;
122
+
123
+ /**
124
+ * Permission-safe agent projection over one flexible knowledge record. Scope,
125
+ * provenance, lifecycle, and stable identity are strict. The body and metadata
126
+ * stay source-shaped so varied company knowledge does not require one rigid
127
+ * taxonomy. Personal subject ids and inaccessible linked-record metadata are
128
+ * deliberately absent.
129
+ */
130
+ export const KnowledgeRecord = z.object({
131
+ id: KnowledgeRecordId,
132
+ kind: KnowledgeRecordKind,
133
+ title: boundedUtf8(KNOWLEDGE_TITLE_MAX_BYTES),
134
+ content: z.object({
135
+ format: z.literal("markdown"),
136
+ body: boundedUtf8(KNOWLEDGE_BODY_MAX_BYTES).nullable(),
137
+ summary: boundedUtf8(KNOWLEDGE_SUMMARY_MAX_BYTES).nullable(),
138
+ topics: z.array(boundedUtf8(KNOWLEDGE_TOPIC_MAX_BYTES)).max(KNOWLEDGE_TOPICS_MAX_ITEMS),
139
+ metadata: z.record(z.string(), z.unknown()).refine(boundedJson, {
140
+ message: "knowledge metadata exceeds its JSON projection boundary",
141
+ }),
142
+ }),
143
+ authority: KnowledgeAuthority,
144
+ provenance: z.object({
145
+ source: KnowledgeSource,
146
+ indexedAt: z.string(),
147
+ }),
148
+ lifecycle: z.object({
149
+ state: z.literal("active"),
150
+ updatedAt: z.string(),
151
+ }),
152
+ quality: z.object({
153
+ trust: z.literal("sourced"),
154
+ freshnessAt: z.string(),
155
+ conflict: z.literal("not_evaluated"),
156
+ correction: z.literal("current_source_version"),
157
+ }),
158
+ links: z.array(KnowledgeLink).max(8),
159
+ projection: z.object({
160
+ truncated: z.boolean(),
161
+ fields: z
162
+ .array(
163
+ z.enum([
164
+ "title",
165
+ "content.body",
166
+ "content.summary",
167
+ "content.topics",
168
+ "content.metadata",
169
+ "provenance.source.uri",
170
+ "provenance.source.externalId",
171
+ "provenance.source.title",
172
+ "provenance.source.author",
173
+ "provenance.source.version",
174
+ ]),
175
+ )
176
+ .max(10),
177
+ }),
178
+ });
179
+ export type KnowledgeRecord = z.infer<typeof KnowledgeRecord>;
180
+
181
+ export const KnowledgeSearchResult = z.object({
182
+ record: KnowledgeRecord,
183
+ retrieval: z.object({
184
+ score: z.number(),
185
+ matchType: z.enum(["hybrid", "vector", "keyword"]),
186
+ vectorScore: z.number().nullable(),
187
+ keywordScore: z.number().nullable(),
188
+ }),
189
+ });
190
+ export type KnowledgeSearchResult = z.infer<typeof KnowledgeSearchResult>;
191
+
192
+ export const KnowledgeSearchResponse = z.object({
193
+ results: z.array(KnowledgeSearchResult),
194
+ });
195
+ export type KnowledgeSearchResponse = z.infer<typeof KnowledgeSearchResponse>;
196
+
197
+ export const KnowledgeGetResponse = z.object({
198
+ record: KnowledgeRecord,
199
+ });
200
+ export type KnowledgeGetResponse = z.infer<typeof KnowledgeGetResponse>;
201
+
202
+ export const KnowledgeBrowseResponse = z.object({
203
+ records: z.array(KnowledgeRecord),
204
+ nextCursor: z.string().min(1).max(KNOWLEDGE_BROWSE_CURSOR_MAX_CHARS).nullable(),
205
+ hasMore: z.boolean(),
206
+ });
207
+ export type KnowledgeBrowseResponse = z.infer<typeof KnowledgeBrowseResponse>;
@@ -0,0 +1,215 @@
1
+ import { z } from "zod";
2
+
3
+ export const SLACK_TASK_POLICY_ID_MAX_CHARS = 128;
4
+ export const SLACK_TASK_POLICY_REASON_MAX_CHARS = 4_096;
5
+ export const SLACK_TASK_POLICY_MAX_IDS = 256;
6
+
7
+ const SlackOpaqueId = z.string().min(1).max(SLACK_TASK_POLICY_ID_MAX_CHARS);
8
+
9
+ export const SlackSharedConversationMode = z.enum(["deny", "private_handoff"]);
10
+ export type SlackSharedConversationMode = z.infer<typeof SlackSharedConversationMode>;
11
+
12
+ export const SlackResultPublicationMode = z.enum(["never", "approval_required", "allow"]);
13
+ export type SlackResultPublicationMode = z.infer<typeof SlackResultPublicationMode>;
14
+
15
+ function uniqueSortedIds(values: string[]): string[] {
16
+ return [...new Set(values)].sort();
17
+ }
18
+
19
+ export const SlackTaskPolicyContent = z
20
+ .object({
21
+ allowedTeamIds: z
22
+ .array(SlackOpaqueId)
23
+ .max(SLACK_TASK_POLICY_MAX_IDS)
24
+ .transform(uniqueSortedIds),
25
+ allowedConversationIds: z
26
+ .array(SlackOpaqueId)
27
+ .max(SLACK_TASK_POLICY_MAX_IDS)
28
+ .transform(uniqueSortedIds),
29
+ allowGuestInitiators: z.boolean(),
30
+ allowExternalInitiators: z.boolean(),
31
+ allowMpim: z.boolean(),
32
+ sharedConversationMode: SlackSharedConversationMode,
33
+ resultPublicationMode: SlackResultPublicationMode,
34
+ })
35
+ .strict();
36
+ export type SlackTaskPolicyContent = z.infer<typeof SlackTaskPolicyContent>;
37
+
38
+ export const DEFAULT_SLACK_TASK_POLICY: SlackTaskPolicyContent = Object.freeze({
39
+ allowedTeamIds: [],
40
+ allowedConversationIds: [],
41
+ allowGuestInitiators: false,
42
+ allowExternalInitiators: false,
43
+ allowMpim: false,
44
+ sharedConversationMode: "deny",
45
+ resultPublicationMode: "never",
46
+ });
47
+
48
+ export function canonicalizeSlackTaskPolicy(value: SlackTaskPolicyContent): SlackTaskPolicyContent {
49
+ const parsed = SlackTaskPolicyContent.parse(value);
50
+ return {
51
+ allowedTeamIds: parsed.allowedTeamIds,
52
+ allowedConversationIds: parsed.allowedConversationIds,
53
+ allowGuestInitiators: parsed.allowGuestInitiators,
54
+ allowExternalInitiators: parsed.allowExternalInitiators,
55
+ allowMpim: parsed.allowMpim,
56
+ sharedConversationMode: parsed.sharedConversationMode,
57
+ resultPublicationMode: parsed.resultPublicationMode,
58
+ };
59
+ }
60
+
61
+ export const SlackTaskPolicyRevisionIdentity = z.object({
62
+ id: z.string().uuid(),
63
+ revision: z.number().int().positive(),
64
+ policyHash: z.string().regex(/^[0-9a-f]{64}$/),
65
+ });
66
+ export type SlackTaskPolicyRevisionIdentity = z.infer<typeof SlackTaskPolicyRevisionIdentity>;
67
+
68
+ export const SlackTaskPolicyRevision = SlackTaskPolicyRevisionIdentity.extend({
69
+ operationId: z.string().uuid(),
70
+ accountId: z.string().uuid(),
71
+ workspaceId: z.string().uuid(),
72
+ policy: SlackTaskPolicyContent,
73
+ supersedesRevisionId: z.string().uuid().nullable(),
74
+ createdBySubjectId: z.string().min(1).max(1_024),
75
+ createdAt: z.string().datetime(),
76
+ });
77
+ export type SlackTaskPolicyRevision = z.infer<typeof SlackTaskPolicyRevision>;
78
+
79
+ export const SlackTaskPolicyHead = z.object({
80
+ accountId: z.string().uuid(),
81
+ workspaceId: z.string().uuid(),
82
+ revisionId: z.string().uuid(),
83
+ revision: z.number().int().positive(),
84
+ policyHash: z.string().regex(/^[0-9a-f]{64}$/),
85
+ activationVersion: z.number().int().positive(),
86
+ activatedAt: z.string().datetime(),
87
+ });
88
+ export type SlackTaskPolicyHead = z.infer<typeof SlackTaskPolicyHead>;
89
+
90
+ export const SlackTaskPolicyActivationEvent = z.object({
91
+ id: z.string().uuid(),
92
+ operationId: z.string().uuid(),
93
+ accountId: z.string().uuid(),
94
+ workspaceId: z.string().uuid(),
95
+ activationVersion: z.number().int().positive(),
96
+ oldRevision: SlackTaskPolicyRevisionIdentity.nullable(),
97
+ newRevision: SlackTaskPolicyRevisionIdentity,
98
+ actorSubjectId: z.string().min(1).max(1_024),
99
+ reason: z.string().min(1).max(SLACK_TASK_POLICY_REASON_MAX_CHARS),
100
+ createdAt: z.string().datetime(),
101
+ });
102
+ export type SlackTaskPolicyActivationEvent = z.infer<typeof SlackTaskPolicyActivationEvent>;
103
+
104
+ export const SlackTaskPolicyListResponse = z.object({
105
+ current: SlackTaskPolicyHead.nullable(),
106
+ activeRevision: SlackTaskPolicyRevision.nullable(),
107
+ revisions: z.array(SlackTaskPolicyRevision),
108
+ activationEvents: z.array(SlackTaskPolicyActivationEvent),
109
+ });
110
+ export type SlackTaskPolicyListResponse = z.infer<typeof SlackTaskPolicyListResponse>;
111
+
112
+ export const UpdateSlackTaskPolicyRequest = z.object({
113
+ operationId: z.string().uuid().optional(),
114
+ policy: SlackTaskPolicyContent,
115
+ expectedCurrentRevisionId: z.string().uuid().nullable(),
116
+ expectedActivationVersion: z.number().int().nonnegative(),
117
+ reason: z.string().trim().min(1).max(SLACK_TASK_POLICY_REASON_MAX_CHARS),
118
+ });
119
+ export type UpdateSlackTaskPolicyRequest = z.infer<typeof UpdateSlackTaskPolicyRequest>;
120
+
121
+ export const SlackTaskPolicyMutationResponse = z.object({
122
+ revision: SlackTaskPolicyRevision,
123
+ head: SlackTaskPolicyHead,
124
+ event: SlackTaskPolicyActivationEvent,
125
+ });
126
+ export type SlackTaskPolicyMutationResponse = z.infer<typeof SlackTaskPolicyMutationResponse>;
127
+
128
+ export type SlackTaskPolicyConversationFacts = Readonly<{
129
+ installationTeamId: string;
130
+ conversationId: string;
131
+ contextTeamId: string | null;
132
+ connectedTeamIds: readonly string[] | null;
133
+ sharedTeamIds: readonly string[] | null;
134
+ isShared: boolean;
135
+ isExternallyShared: boolean;
136
+ isOrgShared: boolean;
137
+ isPendingExternallyShared: boolean;
138
+ isMpim: boolean;
139
+ }>;
140
+
141
+ export type SlackTaskPolicyInitiatorFacts = Readonly<{
142
+ teamId: string | null;
143
+ isGuest: boolean | null;
144
+ isExternal: boolean | null;
145
+ }>;
146
+
147
+ export type SlackTaskPolicyDecision = Readonly<{
148
+ disposition: "ordinary" | "deny" | "private_handoff";
149
+ publication: SlackResultPublicationMode;
150
+ reason:
151
+ | "ordinary_conversation"
152
+ | "policy_missing"
153
+ | "conversation_not_allowed"
154
+ | "team_not_allowed"
155
+ | "ambiguous_shared_facts"
156
+ | "mpim_not_allowed"
157
+ | "guest_not_allowed"
158
+ | "external_not_allowed"
159
+ | "allowed";
160
+ }>;
161
+
162
+ export function evaluateSlackTaskPolicy(input: {
163
+ policy: SlackTaskPolicyContent | null;
164
+ conversation: SlackTaskPolicyConversationFacts;
165
+ initiator: SlackTaskPolicyInitiatorFacts;
166
+ }): SlackTaskPolicyDecision {
167
+ const { conversation, initiator } = input;
168
+ const governed =
169
+ conversation.isShared ||
170
+ conversation.isExternallyShared ||
171
+ conversation.isOrgShared ||
172
+ conversation.isPendingExternallyShared ||
173
+ conversation.isMpim;
174
+ if (!governed) {
175
+ return { disposition: "ordinary", publication: "allow", reason: "ordinary_conversation" };
176
+ }
177
+ if (!input.policy) return { disposition: "deny", publication: "never", reason: "policy_missing" };
178
+ const policy = canonicalizeSlackTaskPolicy(input.policy);
179
+ if (!policy.allowedConversationIds.includes(conversation.conversationId)) {
180
+ return { disposition: "deny", publication: "never", reason: "conversation_not_allowed" };
181
+ }
182
+ if (conversation.isMpim && !policy.allowMpim) {
183
+ return { disposition: "deny", publication: "never", reason: "mpim_not_allowed" };
184
+ }
185
+ if (initiator.isGuest === null || initiator.isExternal === null || initiator.teamId === null) {
186
+ return { disposition: "deny", publication: "never", reason: "ambiguous_shared_facts" };
187
+ }
188
+ if (initiator.isGuest && !policy.allowGuestInitiators) {
189
+ return { disposition: "deny", publication: "never", reason: "guest_not_allowed" };
190
+ }
191
+ if (initiator.isExternal && !policy.allowExternalInitiators) {
192
+ return { disposition: "deny", publication: "never", reason: "external_not_allowed" };
193
+ }
194
+ const teams = [
195
+ conversation.installationTeamId,
196
+ conversation.contextTeamId,
197
+ initiator.teamId,
198
+ ...(conversation.connectedTeamIds ?? []),
199
+ ...(conversation.sharedTeamIds ?? []),
200
+ ];
201
+ if (conversation.connectedTeamIds === null || conversation.sharedTeamIds === null) {
202
+ return { disposition: "deny", publication: "never", reason: "ambiguous_shared_facts" };
203
+ }
204
+ if (teams.some((teamId) => teamId === null || !policy.allowedTeamIds.includes(teamId))) {
205
+ return { disposition: "deny", publication: "never", reason: "team_not_allowed" };
206
+ }
207
+ if (policy.sharedConversationMode === "deny") {
208
+ return { disposition: "deny", publication: "never", reason: "allowed" };
209
+ }
210
+ return {
211
+ disposition: "private_handoff",
212
+ publication: policy.resultPublicationMode,
213
+ reason: "allowed",
214
+ };
215
+ }
@@ -0,0 +1,92 @@
1
+ import { z } from "zod";
2
+
3
+ export const TASK_NOTE_TEXT_MAX_BYTES = 4_096;
4
+ export const TASK_NOTE_REASON_MAX_BYTES = 2_048;
5
+ export const TASK_NOTE_MAX_LIFETIME_DAYS = 30;
6
+ export const TASK_NOTE_ACTIVE_RECORD_CAP = 500;
7
+ export const TASK_NOTE_LIST_DEFAULT_LIMIT = 10;
8
+ export const TASK_NOTE_LIST_MAX_LIMIT = 20;
9
+ export const TASK_NOTE_LIST_RESPONSE_MAX_BYTES = 96 * 1_024;
10
+
11
+ const utf8Bytes = (value: string): number => new TextEncoder().encode(value).byteLength;
12
+
13
+ export function boundedTaskNoteText(maxBytes: number, label: string) {
14
+ return z
15
+ .string()
16
+ .min(1)
17
+ .superRefine((value, ctx) => {
18
+ if (value !== value.trim()) {
19
+ ctx.addIssue({
20
+ code: z.ZodIssueCode.custom,
21
+ message: `${label} must not have leading or trailing whitespace`,
22
+ });
23
+ }
24
+ if (utf8Bytes(value) > maxBytes) {
25
+ ctx.addIssue({
26
+ code: z.ZodIssueCode.custom,
27
+ message: `${label} must be at most ${maxBytes} UTF-8 bytes`,
28
+ });
29
+ }
30
+ });
31
+ }
32
+
33
+ export const TaskNoteText = boundedTaskNoteText(TASK_NOTE_TEXT_MAX_BYTES, "task note text");
34
+ export const TaskNoteReason = boundedTaskNoteText(
35
+ TASK_NOTE_REASON_MAX_BYTES,
36
+ "task note archive reason",
37
+ );
38
+
39
+ export const TaskNoteKind = z.enum([
40
+ "finding",
41
+ "decision",
42
+ "blocker",
43
+ "ownership",
44
+ "artifact",
45
+ "handoff",
46
+ ]);
47
+ export type TaskNoteKind = z.infer<typeof TaskNoteKind>;
48
+
49
+ export const TaskNoteStatus = z.enum(["active", "archived"]);
50
+ export type TaskNoteStatus = z.infer<typeof TaskNoteStatus>;
51
+
52
+ export const TaskNoteActorKind = z.enum(["human", "service"]);
53
+ export type TaskNoteActorKind = z.infer<typeof TaskNoteActorKind>;
54
+
55
+ export const TaskNote = z.object({
56
+ id: z.string().uuid(),
57
+ rootSessionId: z.string().uuid(),
58
+ kind: TaskNoteKind,
59
+ text: TaskNoteText,
60
+ status: TaskNoteStatus,
61
+ version: z.number().int().positive(),
62
+ expiresAt: z.string().datetime({ offset: true }),
63
+ createdAt: z.string().datetime({ offset: true }),
64
+ updatedAt: z.string().datetime({ offset: true }),
65
+ archivedAt: z.string().datetime({ offset: true }).nullable(),
66
+ provenance: z.object({
67
+ actorKind: TaskNoteActorKind,
68
+ sourceSessionId: z.string().uuid(),
69
+ sourceTurnId: z.string().uuid(),
70
+ }),
71
+ });
72
+ export type TaskNote = z.infer<typeof TaskNote>;
73
+
74
+ export const TaskNoteMutationResult = z.object({
75
+ note: TaskNote,
76
+ replayed: z.boolean(),
77
+ });
78
+ export type TaskNoteMutationResult = z.infer<typeof TaskNoteMutationResult>;
79
+
80
+ export const TaskNoteListResponse = z
81
+ .object({
82
+ notes: z.array(TaskNote).max(TASK_NOTE_LIST_MAX_LIMIT),
83
+ })
84
+ .superRefine((value, ctx) => {
85
+ if (utf8Bytes(JSON.stringify(value)) > TASK_NOTE_LIST_RESPONSE_MAX_BYTES) {
86
+ ctx.addIssue({
87
+ code: z.ZodIssueCode.custom,
88
+ message: `task note list response must be at most ${TASK_NOTE_LIST_RESPONSE_MAX_BYTES} UTF-8 bytes`,
89
+ });
90
+ }
91
+ });
92
+ export type TaskNoteListResponse = z.infer<typeof TaskNoteListResponse>;
@@ -7,6 +7,7 @@ import {
7
7
 
8
8
  export const VIDEO_GENERATION_SCHEMA_VERSION = 1 as const;
9
9
  export const SEEDANCE_2_5_MODEL_ID = "bytedance/seedance-2.5" as const;
10
+ export const GROK_IMAGINE_VIDEO_1_5_MODEL_ID = "xai/grok-imagine-video-1.5" as const;
10
11
 
11
12
  export const VideoGenerationSourceMode = z.enum([
12
13
  "text",
@@ -20,7 +21,11 @@ export type VideoGenerationSourceMode = z.infer<typeof VideoGenerationSourceMode
20
21
  export const VideoGenerationResolution = z.enum(["480p", "720p"]);
21
22
  export type VideoGenerationResolution = z.infer<typeof VideoGenerationResolution>;
22
23
 
23
- export const VideoGenerationFundingSource = z.enum(["opengeni_credits", "workspace_gateway"]);
24
+ export const VideoGenerationFundingSource = z.enum([
25
+ "opengeni_credits",
26
+ "workspace_gateway",
27
+ "supergrok_subscription",
28
+ ]);
24
29
  export type VideoGenerationFundingSource = z.infer<typeof VideoGenerationFundingSource>;
25
30
 
26
31
  export const VideoGenerationAspectRatio = z.enum([
@@ -131,7 +136,11 @@ export const VideoGenerationCapabilities = z
131
136
  .superRefine((value, ctx) => {
132
137
  const ids = new Set(value.models.map((model) => model.modelId));
133
138
  if (ids.size !== value.models.length) {
134
- ctx.addIssue({ code: "custom", path: ["models"], message: "model ids must be unique" });
139
+ ctx.addIssue({
140
+ code: "custom",
141
+ path: ["models"],
142
+ message: "model ids must be unique",
143
+ });
135
144
  }
136
145
  if (!ids.has(value.defaultModelId)) {
137
146
  ctx.addIssue({
@@ -205,21 +214,22 @@ export const WorkspaceVideoGenerationSettings = z
205
214
  .object({
206
215
  schemaVersion: z.literal(VIDEO_GENERATION_SCHEMA_VERSION),
207
216
  policy: VideoGenerationPolicy,
208
- fundingOptions: z.array(VideoGenerationFundingOption).length(2),
217
+ fundingOptions: z.array(VideoGenerationFundingOption).length(3),
209
218
  availableModels: z.array(VideoGenerationModelCapability).max(16),
210
219
  capabilities: VideoGenerationCapabilities.nullable(),
211
220
  })
212
221
  .strict()
213
222
  .superRefine((value, ctx) => {
214
223
  if (
215
- new Set(value.fundingOptions.map((option) => option.source)).size !== 2 ||
224
+ new Set(value.fundingOptions.map((option) => option.source)).size !== 3 ||
216
225
  !value.fundingOptions.some((option) => option.source === "opengeni_credits") ||
217
- !value.fundingOptions.some((option) => option.source === "workspace_gateway")
226
+ !value.fundingOptions.some((option) => option.source === "workspace_gateway") ||
227
+ !value.fundingOptions.some((option) => option.source === "supergrok_subscription")
218
228
  ) {
219
229
  ctx.addIssue({
220
230
  code: "custom",
221
231
  path: ["fundingOptions"],
222
- message: "both funding sources must be described exactly once",
232
+ message: "all funding sources must be described exactly once",
223
233
  });
224
234
  }
225
235
  const selected = value.fundingOptions.find(
@@ -250,6 +260,33 @@ export const VideoGenerationAcceptedReceipt = z
250
260
  .strict();
251
261
  export type VideoGenerationAcceptedReceipt = z.infer<typeof VideoGenerationAcceptedReceipt>;
252
262
 
263
+ export const VideoGenerationRejectedCode = z.enum([
264
+ "invalid_reference_path",
265
+ "reference_not_stable",
266
+ "reference_too_large",
267
+ "reference_media_type_mismatch",
268
+ "unsupported_reference_media",
269
+ ]);
270
+ export type VideoGenerationRejectedCode = z.infer<typeof VideoGenerationRejectedCode>;
271
+
272
+ /** Deterministic pre-admission rejection: no provider request or durable operation was created. */
273
+ export const VideoGenerationRejectedResult = z
274
+ .object({
275
+ schemaVersion: z.literal(VIDEO_GENERATION_SCHEMA_VERSION),
276
+ status: z.literal("rejected"),
277
+ code: VideoGenerationRejectedCode,
278
+ message: z.string().min(1).max(512),
279
+ operationCreated: z.literal(false),
280
+ })
281
+ .strict();
282
+ export type VideoGenerationRejectedResult = z.infer<typeof VideoGenerationRejectedResult>;
283
+
284
+ export const VideoGenerationToolResult = z.discriminatedUnion("status", [
285
+ VideoGenerationAcceptedReceipt,
286
+ VideoGenerationRejectedResult,
287
+ ]);
288
+ export type VideoGenerationToolResult = z.infer<typeof VideoGenerationToolResult>;
289
+
253
290
  export const GeneratedVideoFacts = z
254
291
  .object({
255
292
  durationSeconds: z.number().positive().max(120),
@@ -0,0 +1,37 @@
1
+ import { z } from "zod";
2
+
3
+ const PositiveSafeInteger = z.number().int().positive().max(Number.MAX_SAFE_INTEGER);
4
+
5
+ /**
6
+ * Opaque authority frozen at an xAI provider-account acceptance boundary.
7
+ *
8
+ * This snapshot deliberately carries no organization, membership, credential,
9
+ * provider-account, subject, label, quota, token, or plan identity. User scope
10
+ * becomes executable only after exact live database revalidation against the
11
+ * separately stored causal subject and xAI subscription authority row.
12
+ */
13
+ export const XaiProviderAccountAuthoritySnapshotV1 = z.discriminatedUnion("scope", [
14
+ z
15
+ .object({
16
+ version: z.literal(1),
17
+ scope: z.literal("workspace"),
18
+ })
19
+ .strict(),
20
+ z
21
+ .object({
22
+ version: z.literal(1),
23
+ scope: z.literal("user"),
24
+ authorityGeneration: PositiveSafeInteger,
25
+ })
26
+ .strict(),
27
+ ]);
28
+
29
+ export type XaiProviderAccountAuthoritySnapshotV1 = z.infer<
30
+ typeof XaiProviderAccountAuthoritySnapshotV1
31
+ >;
32
+
33
+ /** Explicit compatibility value for workspace-default accepted work. */
34
+ export const WORKSPACE_XAI_PROVIDER_ACCOUNT_AUTHORITY_SNAPSHOT_V1 = {
35
+ version: 1,
36
+ scope: "workspace",
37
+ } as const satisfies XaiProviderAccountAuthoritySnapshotV1;