@opengeni/contracts 2.2.0-canary.0 → 2.5.0-canary.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.
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  /**
3
3
  * Explicit user-directed durable write ("remember X for this workspace").
4
4
  *
5
- * The lane is the Company Brain area the content belongs to:
5
+ * The lane is the Agent Knowledge area the content belongs to:
6
6
  * - `preference`: a Ways-of-working preference (how agents should act);
7
7
  * - `instruction_policy`: a mandatory workspace rule ("always"/"never");
8
8
  * - `knowledge`: a company/product/people fact.
@@ -120,10 +120,11 @@ export declare const RememberActivationSummary: z.ZodDiscriminatedUnion<[z.ZodOb
120
120
  destination: z.ZodLiteral<"knowledge">;
121
121
  receiptId: z.ZodString;
122
122
  claimId: z.ZodString;
123
+ memoryId: z.ZodString;
123
124
  approvalReviewId: z.ZodString;
124
125
  effectiveAt: z.ZodNullable<z.ZodString>;
125
126
  authorityKind: z.ZodLiteral<"human_confirmed">;
126
- undo: z.ZodLiteral<"knowledge_review">;
127
+ undo: z.ZodLiteral<"memory_management">;
127
128
  }, z.core.$strip>], "destination">;
128
129
  export type RememberActivationSummary = z.infer<typeof RememberActivationSummary>;
129
130
  export declare const RememberReceipt: z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -205,10 +206,11 @@ export declare const RememberReceipt: z.ZodDiscriminatedUnion<[z.ZodObject<{
205
206
  destination: z.ZodLiteral<"knowledge">;
206
207
  receiptId: z.ZodString;
207
208
  claimId: z.ZodString;
209
+ memoryId: z.ZodString;
208
210
  approvalReviewId: z.ZodString;
209
211
  effectiveAt: z.ZodNullable<z.ZodString>;
210
212
  authorityKind: z.ZodLiteral<"human_confirmed">;
211
- undo: z.ZodLiteral<"knowledge_review">;
213
+ undo: z.ZodLiteral<"memory_management">;
212
214
  }, z.core.$strip>], "destination">;
213
215
  }, z.core.$strip>, z.ZodObject<{
214
216
  status: z.ZodLiteral<"confirmation_required">;
@@ -322,10 +324,11 @@ export declare const RememberConfirmReceipt: z.ZodObject<{
322
324
  destination: z.ZodLiteral<"knowledge">;
323
325
  receiptId: z.ZodString;
324
326
  claimId: z.ZodString;
327
+ memoryId: z.ZodString;
325
328
  approvalReviewId: z.ZodString;
326
329
  effectiveAt: z.ZodNullable<z.ZodString>;
327
330
  authorityKind: z.ZodLiteral<"human_confirmed">;
328
- undo: z.ZodLiteral<"knowledge_review">;
331
+ undo: z.ZodLiteral<"memory_management">;
329
332
  }, z.core.$strip>], "destination">;
330
333
  }, z.core.$strip>;
331
334
  export type RememberConfirmReceipt = z.infer<typeof RememberConfirmReceipt>;
@@ -0,0 +1,23 @@
1
+ /** Human-authored session titles keep the existing public API ceiling. */
2
+ export declare const SESSION_TITLE_MAX_CHARACTERS = 200;
3
+ /**
4
+ * Automatic titles are intentionally much shorter than the manual rename
5
+ * ceiling. This is measured in grapheme clusters so emoji and combining text
6
+ * are never split into malformed display strings.
7
+ */
8
+ export declare const AUTOMATIC_SESSION_TITLE_MAX_GRAPHEMES = 80;
9
+ /**
10
+ * Safe durable title used until semantic generation succeeds. It contains no
11
+ * user prompt bytes, so provider failure/offline operation cannot leak a
12
+ * credential or leave a raw prompt prefix in navigation surfaces.
13
+ */
14
+ export declare const AUTOMATIC_SESSION_TITLE_FALLBACK = "New conversation";
15
+ /**
16
+ * Normalize a model/system-authored title before it reaches durable session
17
+ * metadata. Human renames intentionally do not use this path.
18
+ *
19
+ * Returns null when the candidate is empty, only boilerplate, or appears to
20
+ * contain a credential/opaque prompt value. Callers should retain the current
21
+ * title (normally {@link AUTOMATIC_SESSION_TITLE_FALLBACK}) in that case.
22
+ */
23
+ export declare function normalizeAutomaticSessionTitle(value: string): string | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/contracts",
3
- "version": "2.2.0-canary.0",
3
+ "version": "2.5.0-canary.0",
4
4
  "description": "Shared zod schemas and wire-contract types for the OpenGeni API.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -15,8 +15,11 @@
15
15
  * retrieved on demand behind the exact attempt's retrieval handle. Its length
16
16
  * is therefore retrieval cost, not standing prompt cost, which is why it gets
17
17
  * more room rather than less.
18
- * - A company profile is the largest always-on surface: every field is
19
- * mandatory prompt context in every session across the whole organization.
18
+ * - Organization identity and mission are always-on context for root sessions
19
+ * across the whole organization. Historical company-profile list fields stay
20
+ * in the storage contract for compatibility; nonempty values on an already-
21
+ * active historical revision remain composed with an explicit compatibility
22
+ * label until an organization owner replaces the profile.
20
23
  * - Knowledge is retrieval evidence and never joins the always-composed prefix.
21
24
  *
22
25
  * These caps deliberately bind only agent-authored writes. The human-facing
@@ -38,10 +41,10 @@ export const AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS = 1_200;
38
41
  /** `identity` and `mission`: a couple of sentences, not a positioning document. */
39
42
  export const AGENT_AUTHORED_COMPANY_PROFILE_SCALAR_MAX_CHARS = 400;
40
43
 
41
- /** One product, customer, goal, or constraint: a phrase or a single sentence. */
44
+ /** Legacy company-profile list entry bound; retained for stored-revision compatibility. */
42
45
  export const AGENT_AUTHORED_COMPANY_PROFILE_ENTRY_MAX_CHARS = 200;
43
46
 
44
- /** Whole canonical profile, mandatory in every session across the organization. */
47
+ /** Whole canonical compatibility profile; current agent tools submit only identity and mission. */
45
48
  export const AGENT_AUTHORED_COMPANY_PROFILE_CONTENT_MAX_UTF8_BYTES = 4_096;
46
49
 
47
50
  export const AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_TOO_LONG_MESSAGE =
@@ -51,19 +54,17 @@ export const AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_TOO_LONG_MESSAGE =
51
54
  "imperative, no numbered procedure. Split unrelated rules into separate entries.";
52
55
 
53
56
  export const AGENT_AUTHORED_PREFERENCE_CONTENT_TOO_LONG_MESSAGE =
54
- "A workspace preference is durable Company Brain content that agents retrieve on demand, so its length is " +
57
+ "A Skill is durable Agent Knowledge that agents retrieve on demand, so its length is " +
55
58
  "retrieval cost rather than standing prompt cost: only its short title and description are composed into " +
56
59
  `every session prompt. Keep it under ${AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS} characters: state the ` +
57
60
  "preference plainly, no numbered procedure and no examples. Put procedure in a Document or Skill and " +
58
61
  "reference it instead.";
59
62
 
60
63
  export const AGENT_AUTHORED_COMPANY_PROFILE_TOO_LONG_MESSAGE =
61
- "Every company-profile field is mandatory prompt context in every session across the organization. Keep " +
62
- `identity and mission under ${AGENT_AUTHORED_COMPANY_PROFILE_SCALAR_MAX_CHARS} characters each, each list ` +
63
- `entry under ${AGENT_AUTHORED_COMPANY_PROFILE_ENTRY_MAX_CHARS}, and the whole profile under ` +
64
- `${AGENT_AUTHORED_COMPANY_PROFILE_CONTENT_MAX_UTF8_BYTES} UTF-8 bytes: one concise statement per field, no ` +
65
- "numbered procedure and no marketing copy. Longer source material belongs in organization Documents and is " +
66
- "retrieved as evidence.";
64
+ "Organization identity and mission are mandatory prompt context in every root session across the " +
65
+ `organization. Keep each under ${AGENT_AUTHORED_COMPANY_PROFILE_SCALAR_MAX_CHARS} characters: one concise ` +
66
+ "descriptive statement, no products, customers, goals, constraints, procedure, or marketing copy. Those " +
67
+ "details belong in organization Documents and are retrieved as evidence when relevant.";
67
68
 
68
69
  /**
69
70
  * Lane-agnostic guidance for the one `remember` content field, whose schema
@@ -110,9 +110,9 @@ export type CompanyProfileContent = z.infer<typeof CompanyProfileContent>;
110
110
  /**
111
111
  * The same profile, bounded for an **agent** author. The human `account:admin`
112
112
  * route keeps `CompanyProfileContent` and its wider limits; this is the shape
113
- * the first-party `company_profile_propose` tool accepts, because the profile is
114
- * the largest always-on prompt surface in the product and a model left to its
115
- * own judgement fills every field to the ceiling.
113
+ * persisted by the first-party `company_profile_propose` tool. The current tool
114
+ * accepts only identity and mission and writes empty compatibility lists, but
115
+ * the validator must still read historical revisions without rewriting them.
116
116
  */
117
117
  export const AgentAuthoredCompanyProfileContent = CompanyProfileContent.superRefine(
118
118
  (value, context) => {
package/src/index.ts CHANGED
@@ -30,6 +30,7 @@ export * from "./tool-result-spill";
30
30
  export * from "./interaction";
31
31
  export * from "./sandbox-file-artifacts";
32
32
  export * from "./permissions";
33
+ export * from "./session-titles";
33
34
 
34
35
  export {
35
36
  CreateWorkspaceArtifactRequest,
@@ -1459,6 +1460,7 @@ export const SessionTenancyBlocker = z.enum([
1459
1460
  export type SessionTenancyBlocker = z.infer<typeof SessionTenancyBlocker>;
1460
1461
 
1461
1462
  export const SESSION_OPERATION_KEY_MAX_CHARS = 256;
1463
+ export const MAX_SELECTED_VARIABLE_SETS = 25;
1462
1464
  const SessionTenancyIdempotencyKey = z.string().trim().min(1).max(SESSION_OPERATION_KEY_MAX_CHARS);
1463
1465
 
1464
1466
  export const UpdateSessionVisibilityRequest = z
@@ -1505,6 +1507,10 @@ export const ForkSessionRequest = z
1505
1507
  idempotencyKey: SessionTenancyIdempotencyKey,
1506
1508
  visibility: SessionVisibility,
1507
1509
  workspaceSharedAcknowledged: z.boolean(),
1510
+ // Optional fresh-session runtime setup. Omission preserves the historical
1511
+ // content-only fork; explicit null/[] creates a rigless, set-free restart.
1512
+ rigId: z.string().uuid().nullable().optional(),
1513
+ variableSetIds: z.array(z.string().uuid()).max(MAX_SELECTED_VARIABLE_SETS).optional(),
1508
1514
  })
1509
1515
  .strict()
1510
1516
  .superRefine((value, context) => {
@@ -1515,6 +1521,16 @@ export const ForkSessionRequest = z
1515
1521
  message: "workspaceSharedAcknowledged must be false for a private destination",
1516
1522
  });
1517
1523
  }
1524
+ if (
1525
+ value.variableSetIds &&
1526
+ new Set(value.variableSetIds).size !== value.variableSetIds.length
1527
+ ) {
1528
+ context.addIssue({
1529
+ code: "custom",
1530
+ path: ["variableSetIds"],
1531
+ message: "variableSetIds must not contain duplicates",
1532
+ });
1533
+ }
1518
1534
  });
1519
1535
  export type ForkSessionRequest = z.infer<typeof ForkSessionRequest>;
1520
1536
 
@@ -1546,6 +1562,7 @@ export type ManagedAccount = z.infer<typeof ManagedAccount>;
1546
1562
  export const Workspace = z.object({
1547
1563
  id: z.string().uuid(),
1548
1564
  accountId: z.string().uuid(),
1565
+ kind: z.enum(["personal", "shared"]),
1549
1566
  name: z.string(),
1550
1567
  slug: z.string().nullable(),
1551
1568
  externalSource: z.string().nullable(),
@@ -1998,6 +2015,43 @@ export const SlackReactionChannelListResponse = z.object({
1998
2015
  });
1999
2016
  export type SlackReactionChannelListResponse = z.infer<typeof SlackReactionChannelListResponse>;
2000
2017
 
2018
+ /** Where one Slack channel starts work. */
2019
+ export const SlackChannelRoute = z.object({
2020
+ slackChannelId: z.string().min(1).max(64),
2021
+ targetWorkspaceId: z.string().uuid(),
2022
+ // Unbounded like `Workspace.name` itself: a cap here would reject a row the
2023
+ // database happily holds.
2024
+ targetWorkspaceName: z.string().min(1).nullable(),
2025
+ source: z.enum(["picker", "admin"]),
2026
+ updatedAt: z.string(),
2027
+ });
2028
+ export type SlackChannelRoute = z.infer<typeof SlackChannelRoute>;
2029
+
2030
+ export const SlackChannelRouteListResponse = z.object({
2031
+ /** Every stored route. Bounded in practice by the channels the bot is in. */
2032
+ routes: z.array(SlackChannelRoute),
2033
+ /**
2034
+ * Whether routing is switched on for this deployment. With it off the stored
2035
+ * routes are inert, so the surface says so instead of implying they apply.
2036
+ */
2037
+ routingEnabled: z.boolean(),
2038
+ });
2039
+ export type SlackChannelRouteListResponse = z.infer<typeof SlackChannelRouteListResponse>;
2040
+
2041
+ export const UpdateSlackChannelRoutesRequest = z.object({
2042
+ connectionId: z.string().uuid(),
2043
+ routes: z
2044
+ .array(
2045
+ z.object({
2046
+ slackChannelId: z.string().min(1).max(64),
2047
+ /** Null clears the route, so the channel asks once again. */
2048
+ targetWorkspaceId: z.string().uuid().nullable(),
2049
+ }),
2050
+ )
2051
+ .max(200),
2052
+ });
2053
+ export type UpdateSlackChannelRoutesRequest = z.infer<typeof UpdateSlackChannelRoutesRequest>;
2054
+
2001
2055
  export const DEFAULT_WORKSPACE_SLACK_REACTION_SUMMON_SETTINGS = {
2002
2056
  enabled: false,
2003
2057
  emoji: "genie",
@@ -3102,7 +3156,7 @@ export const ModelContextContributionSource = z.enum([
3102
3156
  ]);
3103
3157
  export type ModelContextContributionSource = z.infer<typeof ModelContextContributionSource>;
3104
3158
 
3105
- /** Content-free per-call summary of model-visible Company Brain material. */
3159
+ /** Content-free per-call summary of model-visible Agent Knowledge material. */
3106
3160
  export const ModelContextContributionSummary = z
3107
3161
  .object({
3108
3162
  source: ModelContextContributionSource,
@@ -4914,11 +4968,113 @@ export const DocumentDefaultCollectionBackfill = z.object({
4914
4968
  });
4915
4969
  export type DocumentDefaultCollectionBackfill = z.infer<typeof DocumentDefaultCollectionBackfill>;
4916
4970
 
4971
+ export const DocumentDefaultCollectionBackfillRunAudit = DocumentDefaultCollectionBackfill.omit({
4972
+ operationId: true,
4973
+ }).extend({
4974
+ actorSubjectId: z.string().min(1),
4975
+ startedAt: z.string().datetime({ offset: true }),
4976
+ updatedAt: z.string().datetime({ offset: true }),
4977
+ });
4978
+ export type DocumentDefaultCollectionBackfillRunAudit = z.infer<
4979
+ typeof DocumentDefaultCollectionBackfillRunAudit
4980
+ >;
4981
+
4982
+ export const DocumentDefaultCollectionBackfillOperationAudit = z.object({
4983
+ operationId: z.string().uuid(),
4984
+ result: DocumentDefaultCollectionBackfill,
4985
+ createdAt: z.string().datetime({ offset: true }),
4986
+ });
4987
+ export type DocumentDefaultCollectionBackfillOperationAudit = z.infer<
4988
+ typeof DocumentDefaultCollectionBackfillOperationAudit
4989
+ >;
4990
+
4991
+ export const DocumentDefaultCollectionBackfillReceiptAudit = z.object({
4992
+ workspaceId: z.string().uuid(),
4993
+ baseId: z.string().uuid(),
4994
+ outcome: z.enum(["created", "adopted"]),
4995
+ createdAt: z.string().datetime({ offset: true }),
4996
+ });
4997
+ export type DocumentDefaultCollectionBackfillReceiptAudit = z.infer<
4998
+ typeof DocumentDefaultCollectionBackfillReceiptAudit
4999
+ >;
5000
+
5001
+ export const ListDocumentMigrationAuditQuery = ListDocumentAuthorityReclassificationsQuery;
5002
+ export type ListDocumentMigrationAuditQuery = z.infer<typeof ListDocumentMigrationAuditQuery>;
5003
+
5004
+ export const ListDocumentDefaultCollectionBackfillRunsResponse = z.object({
5005
+ runs: z.array(DocumentDefaultCollectionBackfillRunAudit),
5006
+ hasMore: z.boolean(),
5007
+ nextCursor: z.string().max(DOCUMENT_AUTHORITY_RECLASSIFICATION_CURSOR_MAX_CHARS).nullable(),
5008
+ });
5009
+ export type ListDocumentDefaultCollectionBackfillRunsResponse = z.infer<
5010
+ typeof ListDocumentDefaultCollectionBackfillRunsResponse
5011
+ >;
5012
+
5013
+ export const GetDocumentDefaultCollectionBackfillAuditQuery = z.object({
5014
+ limit: z.coerce
5015
+ .number()
5016
+ .int()
5017
+ .positive()
5018
+ .max(DOCUMENT_AUTHORITY_RECLASSIFICATION_LIST_MAX_LIMIT)
5019
+ .default(DOCUMENT_AUTHORITY_RECLASSIFICATION_LIST_DEFAULT_LIMIT),
5020
+ operationCursor: z
5021
+ .string()
5022
+ .min(1)
5023
+ .max(DOCUMENT_AUTHORITY_RECLASSIFICATION_CURSOR_MAX_CHARS)
5024
+ .optional(),
5025
+ receiptCursor: z
5026
+ .string()
5027
+ .min(1)
5028
+ .max(DOCUMENT_AUTHORITY_RECLASSIFICATION_CURSOR_MAX_CHARS)
5029
+ .optional(),
5030
+ });
5031
+ export type GetDocumentDefaultCollectionBackfillAuditQuery = z.infer<
5032
+ typeof GetDocumentDefaultCollectionBackfillAuditQuery
5033
+ >;
5034
+
5035
+ export const DocumentDefaultCollectionBackfillAudit = z.object({
5036
+ run: DocumentDefaultCollectionBackfillRunAudit,
5037
+ operations: z.array(DocumentDefaultCollectionBackfillOperationAudit),
5038
+ receipts: z.array(DocumentDefaultCollectionBackfillReceiptAudit),
5039
+ operationsHasMore: z.boolean(),
5040
+ operationsNextCursor: z
5041
+ .string()
5042
+ .max(DOCUMENT_AUTHORITY_RECLASSIFICATION_CURSOR_MAX_CHARS)
5043
+ .nullable(),
5044
+ receiptsHasMore: z.boolean(),
5045
+ receiptsNextCursor: z
5046
+ .string()
5047
+ .max(DOCUMENT_AUTHORITY_RECLASSIFICATION_CURSOR_MAX_CHARS)
5048
+ .nullable(),
5049
+ });
5050
+ export type DocumentDefaultCollectionBackfillAudit = z.infer<
5051
+ typeof DocumentDefaultCollectionBackfillAudit
5052
+ >;
5053
+
5054
+ export const OrganizationDocumentAuthorityReclassification =
5055
+ DocumentAuthorityReclassification.extend({
5056
+ actorSubjectId: z.string().min(1),
5057
+ requestWorkspaceId: z.string().uuid(),
5058
+ });
5059
+ export type OrganizationDocumentAuthorityReclassification = z.infer<
5060
+ typeof OrganizationDocumentAuthorityReclassification
5061
+ >;
5062
+
5063
+ export const ListOrganizationDocumentAuthorityReclassificationsResponse = z.object({
5064
+ receipts: z.array(OrganizationDocumentAuthorityReclassification),
5065
+ hasMore: z.boolean(),
5066
+ nextCursor: z.string().max(DOCUMENT_AUTHORITY_RECLASSIFICATION_CURSOR_MAX_CHARS).nullable(),
5067
+ });
5068
+ export type ListOrganizationDocumentAuthorityReclassificationsResponse = z.infer<
5069
+ typeof ListOrganizationDocumentAuthorityReclassificationsResponse
5070
+ >;
5071
+
4917
5072
  export const DocumentSearchRequest = z.object({
4918
5073
  query: z.string().min(1),
4919
5074
  baseIds: z.array(z.string().uuid()).optional(),
4920
5075
  mode: DocumentSearchMode.optional(),
4921
5076
  sourceKinds: z.array(KnowledgeSourceKind).optional(),
5077
+ authorityKinds: z.array(DocumentAuthorityKind).max(3).optional(),
4922
5078
  aclTags: z.array(z.string().min(1)).optional(),
4923
5079
  limit: z.number().int().positive().max(50).default(5),
4924
5080
  });
@@ -5707,6 +5863,22 @@ export const UpdateSessionRequest = z.object({
5707
5863
  });
5708
5864
  export type UpdateSessionRequest = z.infer<typeof UpdateSessionRequest>;
5709
5865
 
5866
+ export const UpdateSessionVariableSetsRequest = z
5867
+ .object({
5868
+ variableSetIds: z.array(z.string().uuid()).max(MAX_SELECTED_VARIABLE_SETS),
5869
+ })
5870
+ .strict()
5871
+ .superRefine((value, context) => {
5872
+ if (new Set(value.variableSetIds).size !== value.variableSetIds.length) {
5873
+ context.addIssue({
5874
+ code: z.ZodIssueCode.custom,
5875
+ path: ["variableSetIds"],
5876
+ message: "variableSetIds must not contain duplicates",
5877
+ });
5878
+ }
5879
+ });
5880
+ export type UpdateSessionVariableSetsRequest = z.infer<typeof UpdateSessionVariableSetsRequest>;
5881
+
5710
5882
  /**
5711
5883
  * Replace the complete durable session tool policy, or explicitly opt back in
5712
5884
  * to current workspace defaults. MCP servers and individual OpenGeni tools
@@ -6224,6 +6396,7 @@ export const SessionAuthorizationOperation = z.enum([
6224
6396
  "session.human_input.write",
6225
6397
  "session.title.write",
6226
6398
  "session.channel.write",
6399
+ "session.variable_sets.write",
6227
6400
  "session.mcp.approval_policy.write",
6228
6401
  "session.tool_policy.write",
6229
6402
  "session.goal.read",
@@ -6833,12 +7006,13 @@ export type SubmitComposerDraftRequest = z.infer<typeof SubmitComposerDraftReque
6833
7006
  * deliberately narrower than CreateSessionRequest: idempotency/event keys and
6834
7007
  * credential-bearing MCP server inputs are per-attempt data, never draft state.
6835
7008
  */
6836
- export const NewSessionDraftOptions = z.object({
7009
+ export const NewSessionDraftOptions = withVariableSetIdAlias({
6837
7010
  visibility: SessionVisibility.optional(),
6838
7011
  sandboxBackend: SandboxBackend.optional(),
6839
7012
  targetSandboxId: z.string().uuid().optional(),
6840
7013
  workingDir: z.string().min(1).optional(),
6841
7014
  variableSetId: z.string().uuid().optional(),
7015
+ variableSetIds: z.array(z.string().uuid()).max(MAX_SELECTED_VARIABLE_SETS).optional(),
6842
7016
  rigId: z.string().uuid().optional(),
6843
7017
  goal: GoalSpec.optional(),
6844
7018
  firstPartyMcpPermissions: z.array(Permission).optional(),
@@ -7482,17 +7656,49 @@ function withVariableSetIdAlias<T extends z.ZodRawShape>(
7482
7656
  shape: T,
7483
7657
  options: { rejectKeys?: readonly string[] } = {},
7484
7658
  ) {
7485
- return z.preprocess((input) => {
7486
- if (!input || typeof input !== "object" || Array.isArray(input)) {
7487
- return input;
7488
- }
7489
- const record = input as Record<string, unknown>;
7490
- if (options.rejectKeys?.some((key) => Object.hasOwn(record, key))) return null;
7491
- if (record.variableSetId !== undefined || record.environmentId === undefined) {
7492
- return record;
7493
- }
7494
- return { ...record, variableSetId: record.environmentId };
7495
- }, z.object(shape));
7659
+ return z.preprocess(
7660
+ (input) => {
7661
+ if (!input || typeof input !== "object" || Array.isArray(input)) {
7662
+ return input;
7663
+ }
7664
+ const record = input as Record<string, unknown>;
7665
+ if (options.rejectKeys?.some((key) => Object.hasOwn(record, key))) return null;
7666
+ const aliased =
7667
+ record.variableSetId !== undefined || record.environmentId === undefined
7668
+ ? record
7669
+ : { ...record, variableSetId: record.environmentId };
7670
+ if (aliased.variableSetIds === undefined && aliased.variableSetId !== undefined) {
7671
+ return {
7672
+ ...aliased,
7673
+ variableSetIds: aliased.variableSetId === null ? [] : [aliased.variableSetId],
7674
+ };
7675
+ }
7676
+ return aliased;
7677
+ },
7678
+ z.object(shape).superRefine((value, context) => {
7679
+ const record = value as Record<string, unknown>;
7680
+ if (!Array.isArray(record.variableSetIds)) return;
7681
+ if (new Set(record.variableSetIds).size !== record.variableSetIds.length) {
7682
+ context.addIssue({
7683
+ code: z.ZodIssueCode.custom,
7684
+ path: ["variableSetIds"],
7685
+ message: "variableSetIds must not contain duplicates",
7686
+ });
7687
+ }
7688
+ if (record.variableSetId === undefined) return;
7689
+ const expected =
7690
+ record.variableSetIds.length > 0
7691
+ ? record.variableSetIds[record.variableSetIds.length - 1]
7692
+ : null;
7693
+ if (record.variableSetId !== expected) {
7694
+ context.addIssue({
7695
+ code: z.ZodIssueCode.custom,
7696
+ path: ["variableSetId"],
7697
+ message: "variableSetId must match the last variableSetIds entry",
7698
+ });
7699
+ }
7700
+ }),
7701
+ );
7496
7702
  }
7497
7703
 
7498
7704
  // Generic variable-set reads remain metadata-only. Exact plaintext has one
@@ -7781,6 +7987,7 @@ export const RigChangeVerification = z
7781
7987
  startedAt: z.string().optional(),
7782
7988
  finishedAt: z.string().optional(),
7783
7989
  log: z.string().optional(),
7990
+ platformCheckResults: z.array(RigCheckResult).optional(),
7784
7991
  checkResults: z.array(RigCheckResult).optional(),
7785
7992
  })
7786
7993
  .passthrough();
@@ -7807,7 +8014,12 @@ export const CreateRigRequest = z.object({
7807
8014
  name: z.string().min(1).max(120),
7808
8015
  description: z.string().max(2000).optional(),
7809
8016
  // Initial (version 1) content, inline.
7810
- image: z.string().max(1024).optional(),
8017
+ // Explicit Rig base images are temporarily disabled. Rigs always compose on
8018
+ // the deployment-owned platform sandbox image so Computer, Browser, Terminal,
8019
+ // and the stock runtime cannot be replaced by a user definition. Keep an
8020
+ // explicit never-field instead of silently stripping `image` from older
8021
+ // clients: callers must receive a validation error and remove the override.
8022
+ image: z.never().optional(),
7811
8023
  setupScript: z.string().max(131072).optional(),
7812
8024
  checks: z.array(RigCheck).max(100).default([]),
7813
8025
  credentialHooks: z.array(z.string().min(1).max(200)).max(50).default([]),
@@ -7874,7 +8086,10 @@ export type RigSetupAppendPayload = z.infer<typeof RigSetupAppendPayload>;
7874
8086
  // definition_edit: the full next-version content (all fields optional; unset
7875
8087
  // fields inherit from the base version at promote time).
7876
8088
  export const RigDefinitionEditPayload = z.object({
7877
- image: z.string().max(1024).nullish(),
8089
+ // See CreateRigRequest.image. Historical RigVersion.image values remain on
8090
+ // the read model for compatibility, but no new definition may set or clear
8091
+ // one through the public write contract.
8092
+ image: z.never().optional(),
7878
8093
  setupScript: z.string().max(131072).nullish(),
7879
8094
  checks: z.array(RigCheck).max(100).optional(),
7880
8095
  credentialHooks: z.array(z.string().min(1).max(200)).max(50).optional(),
@@ -8449,6 +8664,17 @@ export const ScheduledTaskRunAcceptedExecution = /* @__PURE__ */ z
8449
8664
  .array(z.string().min(1).max(256))
8450
8665
  .max(SCHEDULED_TASK_TOOL_MAX_COUNT),
8451
8666
  toolPolicyVersion: z.number().int().nonnegative(),
8667
+ variableSets: z
8668
+ .array(
8669
+ z
8670
+ .object({
8671
+ id: z.string().uuid(),
8672
+ generation: z.number().int().positive(),
8673
+ })
8674
+ .strict(),
8675
+ )
8676
+ .max(MAX_SELECTED_VARIABLE_SETS)
8677
+ .default([]),
8452
8678
  variableSetId: z.string().uuid().nullable(),
8453
8679
  variableSetGeneration: z.number().int().positive().nullable(),
8454
8680
  rigId: z.string().uuid().nullable(),
@@ -9460,7 +9686,11 @@ export const OPENGENI_PR_REVIEW_SESSION_ROLE = "pull_request_review" as const;
9460
9686
  export const PrReviewProvider = GitCredentialProvider;
9461
9687
  export type PrReviewProvider = z.infer<typeof PrReviewProvider>;
9462
9688
 
9463
- export const PrReviewCredentialKind = /* @__PURE__ */ z.enum(["github_app", "provider_token"]);
9689
+ export const PrReviewCredentialKind = /* @__PURE__ */ z.enum([
9690
+ "github_app",
9691
+ "managed_github_app",
9692
+ "provider_token",
9693
+ ]);
9464
9694
  export type PrReviewCredentialKind = z.infer<typeof PrReviewCredentialKind>;
9465
9695
 
9466
9696
  export const PrReviewWebhookAuthKind = /* @__PURE__ */ z.enum([
@@ -9581,6 +9811,9 @@ export const PrReviewAppRegistration = /* @__PURE__ */ (() =>
9581
9811
  provider: PrReviewProvider,
9582
9812
  providerBaseUrl: z.string().url(),
9583
9813
  appId: z.string().nullable(),
9814
+ installationId: z.string().nullable(),
9815
+ providerAccountLogin: z.string().nullable(),
9816
+ providerAccountType: z.enum(["User", "Organization"]).nullable(),
9584
9817
  credentialKind: PrReviewCredentialKind,
9585
9818
  hasCredential: z.boolean(),
9586
9819
  accessTokenExpiresAt: z.string().nullable(),
@@ -9595,6 +9828,27 @@ export const PrReviewAppRegistration = /* @__PURE__ */ (() =>
9595
9828
  }))();
9596
9829
  export type PrReviewAppRegistration = z.infer<typeof PrReviewAppRegistration>;
9597
9830
 
9831
+ export const PrReviewManagedGitHubInstallation = /* @__PURE__ */ (() =>
9832
+ z.object({
9833
+ registrationId: z.string().uuid(),
9834
+ installationId: z.string(),
9835
+ accountLogin: z.string().nullable(),
9836
+ configureUrl: z.string().url().nullable(),
9837
+ repositoryCount: z.number().int().nonnegative(),
9838
+ }))();
9839
+ export type PrReviewManagedGitHubInstallation = z.infer<typeof PrReviewManagedGitHubInstallation>;
9840
+
9841
+ export const PrReviewManagedGitHubSetup = /* @__PURE__ */ (() =>
9842
+ z.object({
9843
+ configured: z.boolean(),
9844
+ status: z.enum(["unavailable", "not_connected", "connected"]),
9845
+ appName: z.literal("OpenGeni Lens"),
9846
+ connectUrl: z.string().url().nullable(),
9847
+ installations: z.array(PrReviewManagedGitHubInstallation),
9848
+ missing: z.array(z.string()),
9849
+ }))();
9850
+ export type PrReviewManagedGitHubSetup = z.infer<typeof PrReviewManagedGitHubSetup>;
9851
+
9598
9852
  export const CreatePrReviewRepositoryBindingRequest = /* @__PURE__ */ (() =>
9599
9853
  z
9600
9854
  .object({
@@ -11281,6 +11535,9 @@ export const Session = z.object({
11281
11535
  // The explicit connected-machine project root selected for this session.
11282
11536
  // Null means the enrolled agent's launch workspace root.
11283
11537
  workingDir: z.string().nullable().default(null),
11538
+ // Ordered low-to-high precedence. The legacy singular aliases below expose
11539
+ // the final (highest-precedence) entry for older clients.
11540
+ variableSetIds: z.array(z.string().uuid()).max(MAX_SELECTED_VARIABLE_SETS).default([]),
11284
11541
  variableSetId: z.string().uuid().nullable().default(null),
11285
11542
  /** @deprecated use variableSetId */
11286
11543
  environmentId: z.string().uuid().nullable().default(null),
@@ -11498,6 +11755,8 @@ export type SessionLineageResponse = z.infer<typeof SessionLineageResponse>;
11498
11755
 
11499
11756
  export const SessionEventType = z.enum([
11500
11757
  "session.created",
11758
+ "session.variable_sets.updated",
11759
+ "session.runtime.configured",
11501
11760
  "session.personal_resources.attached",
11502
11761
  "session.visibility.changed",
11503
11762
  // Defensive read/transport projection for a malformed or historically
@@ -13750,8 +14009,10 @@ export const CreateSessionRequest = withVariableSetIdAlias(
13750
14009
  // plane has no authenticated home-directory fact. Only valid WITH
13751
14010
  // targetSandboxId; omitted selects the reported root.
13752
14011
  workingDir: z.string().min(1).optional(),
13753
- // Variable set attachment is fixed at session creation; follow-up
13754
- // user.message events cannot switch or add one.
14012
+ // Ordered low-to-high precedence. A legacy singular selection is normalized
14013
+ // into one entry by withVariableSetIdAlias; when both are present the
14014
+ // singular value must match the final (highest-precedence) entry.
14015
+ variableSetIds: z.array(z.string().uuid()).max(MAX_SELECTED_VARIABLE_SETS).optional(),
13755
14016
  variableSetId: z.string().uuid().optional(),
13756
14017
  environmentId: z.string().uuid().optional(),
13757
14018
  // The rig to bind this session to (M3). Its ACTIVE version is resolved and
@@ -15443,7 +15704,8 @@ export type WorkspaceModelCatalogResponse = z.infer<typeof WorkspaceModelCatalog
15443
15704
  * that rollout boundary. Mutating clients send this value in
15444
15705
  * `x-opengeni-api-contract`; the API rejects any other value before routing.
15445
15706
  */
15446
- export const OPENGENI_API_CONTRACT_REVISION = "2026-08-atomic-session-fork-visibility-v1" as const;
15707
+ export const OPENGENI_API_CONTRACT_REVISION =
15708
+ "2026-08-personal-only-organization-setup-v1" as const;
15447
15709
  export const OPENGENI_API_CONTRACT_HEADER = "x-opengeni-api-contract" as const;
15448
15710
  /** Bounded request/response identifier shared by browser, ingress, and API diagnostics. */
15449
15711
  export const OPENGENI_CORRELATION_HEADER = "x-opengeni-correlation-id" as const;
package/src/knowledge.ts CHANGED
@@ -119,6 +119,7 @@ export const KnowledgeSearchRequest = z
119
119
  baseIds: z.array(z.string().uuid()).max(50).optional(),
120
120
  mode: z.enum(["hybrid", "vector", "keyword"]).optional(),
121
121
  sourceKinds: z.array(KnowledgeSource.shape.kind).max(8).optional(),
122
+ authorityKinds: z.array(KnowledgeAuthority.shape.kind).max(3).optional(),
122
123
  aclTags: z
123
124
  .array(boundedUtf8(KNOWLEDGE_TOPIC_MAX_BYTES).pipe(z.string().min(1)))
124
125
  .max(64)