@opengeni/sdk 0.25.0 → 0.26.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.
package/src/errors.ts CHANGED
@@ -2,33 +2,97 @@
2
2
  export class OpenGeniApiError extends Error {
3
3
  readonly status: number;
4
4
  readonly code: string | undefined;
5
+ readonly retryable: boolean;
6
+ readonly correlationId: string | undefined;
7
+ /** True only when an uncontrolled transport failed after a mutation may have been accepted. */
8
+ readonly outcomeUnknown: boolean;
5
9
  readonly body: string;
6
10
 
7
- constructor(status: number, body: string) {
11
+ constructor(
12
+ status: number,
13
+ body: string,
14
+ options: {
15
+ code?: string | undefined;
16
+ retryable?: boolean | undefined;
17
+ correlationId?: string | undefined;
18
+ outcomeUnknown?: boolean | undefined;
19
+ displayMessage?: string | undefined;
20
+ mutation?: boolean | undefined;
21
+ } = {},
22
+ ) {
8
23
  const decoded = decodeApiErrorBody(body);
9
- super(`OpenGeni API ${status}: ${decoded.message ?? (body || "(empty body)")}`);
24
+ const correlationId = decoded?.requestId ?? boundedCorrelationId(options.correlationId);
25
+ const gatewayFailure = status >= 502 && status <= 504;
26
+ const fromResponse = options.mutation !== undefined;
27
+ const message = decoded?.message ?? (fromResponse ? "Request failed." : body || "(empty body)");
28
+ const displayMessage =
29
+ options.displayMessage ??
30
+ (gatewayFailure && fromResponse
31
+ ? "OpenGeni is temporarily unavailable — retry."
32
+ : `OpenGeni API ${status}: ${message}`);
33
+ super(correlationId ? `${displayMessage} Reference: ${correlationId}.` : displayMessage);
10
34
  this.name = "OpenGeniApiError";
11
35
  this.status = status;
12
- this.code = decoded.code;
13
- this.body = body;
36
+ this.code =
37
+ options.code ??
38
+ decoded?.code ??
39
+ (gatewayFailure && fromResponse ? "upstream_unavailable" : undefined);
40
+ this.retryable = options.retryable ?? decoded?.retryable ?? retryableApiStatus(status);
41
+ this.correlationId = correlationId;
42
+ this.outcomeUnknown =
43
+ options.outcomeUnknown ?? (gatewayFailure && !!options.mutation && !decoded);
44
+ this.body = !fromResponse || decoded ? body : "";
14
45
  }
15
46
  }
16
47
 
17
- function decodeApiErrorBody(body: string): { code?: string; message?: string } {
18
- if (!body) return {};
48
+ function decodeApiErrorBody(body: string): {
49
+ code: string | undefined;
50
+ message: string | undefined;
51
+ requestId: string | undefined;
52
+ retryable: boolean | undefined;
53
+ } | null {
54
+ if (!body) return null;
19
55
  try {
20
56
  const decoded: unknown = JSON.parse(body);
21
- if (!decoded || typeof decoded !== "object" || Array.isArray(decoded)) return {};
57
+ if (!decoded || typeof decoded !== "object" || Array.isArray(decoded)) return null;
22
58
  const record = decoded as Record<string, unknown>;
59
+ const nested =
60
+ record.error && typeof record.error === "object" && !Array.isArray(record.error)
61
+ ? (record.error as Record<string, unknown>)
62
+ : record;
63
+ const code = boundedApiField(nested.code);
64
+ const message = boundedApiField(nested.message);
65
+ const requestId = boundedCorrelationId(nested.requestId);
66
+ const retryable = typeof nested.retryable === "boolean" ? nested.retryable : undefined;
67
+ if (!code && !message && !requestId && retryable === undefined) return null;
23
68
  return {
24
- ...(typeof record.code === "string" && record.code ? { code: record.code } : {}),
25
- ...(typeof record.message === "string" && record.message ? { message: record.message } : {}),
69
+ code,
70
+ message,
71
+ requestId,
72
+ retryable,
26
73
  };
27
74
  } catch {
28
- return {};
75
+ return null;
29
76
  }
30
77
  }
31
78
 
79
+ function boundedApiField(value: unknown): string | undefined {
80
+ if (typeof value !== "string") return;
81
+ const bytes = new TextEncoder().encode(value);
82
+ return bytes.byteLength <= 512 ? value : new TextDecoder().decode(bytes.slice(0, 512));
83
+ }
84
+
85
+ function retryableApiStatus(status: number): boolean {
86
+ return status === 408 || status === 409 || status === 425 || status === 429 || status >= 500;
87
+ }
88
+
89
+ function boundedCorrelationId(value: unknown): string | undefined {
90
+ if (typeof value !== "string" || value.length > 128 || !/^[\w.:-]+$/.test(value)) {
91
+ return;
92
+ }
93
+ return value;
94
+ }
95
+
32
96
  /** A short-lived session-list snapshot cursor can no longer be continued. */
33
97
  export class OpenGeniSessionListCursorError extends OpenGeniApiError {}
34
98
 
@@ -67,14 +131,6 @@ export function isAbortError(error: unknown): boolean {
67
131
  * permanent and surface to the caller instead.
68
132
  */
69
133
  export function isRetryableStreamError(error: unknown): boolean {
70
- if (error instanceof OpenGeniApiError) {
71
- return (
72
- error.status === 408 ||
73
- error.status === 409 ||
74
- error.status === 425 ||
75
- error.status === 429 ||
76
- error.status >= 500
77
- );
78
- }
134
+ if (error instanceof OpenGeniApiError) return error.retryable;
79
135
  return error instanceof TypeError;
80
136
  }
package/src/index.ts CHANGED
@@ -53,6 +53,29 @@ export type {
53
53
  } from "./stream";
54
54
  export { streamWorkspaceControlEvents } from "./workspace-control-stream";
55
55
  export type { WorkspaceControlStreamTransport } from "./workspace-control-stream";
56
+ export { normalizeWorkspaceInstructionPolicyRoleKey } from "./workspace-instruction-policies";
57
+ export type {
58
+ ActivateWorkspaceInstructionPolicyRequest,
59
+ CreateWorkspaceInstructionPolicyDraftRequest,
60
+ ImportLegacyWorkspaceInstructionPolicyDraftRequest,
61
+ RollbackWorkspaceInstructionPolicyRequest,
62
+ WorkspaceInstructionPolicyActivationEvent,
63
+ WorkspaceInstructionPolicyActivationResponse,
64
+ WorkspaceInstructionPolicyActivationType,
65
+ WorkspaceInstructionPolicyConflictResponse,
66
+ WorkspaceInstructionPolicyDiffRequest,
67
+ WorkspaceInstructionPolicyDiffResponse,
68
+ WorkspaceInstructionPolicyDraftProvenanceSource,
69
+ WorkspaceInstructionPolicyHead,
70
+ WorkspaceInstructionPolicyKind,
71
+ WorkspaceInstructionPolicyListOptions,
72
+ WorkspaceInstructionPolicyListResponse,
73
+ WorkspaceInstructionPolicyProvenanceSource,
74
+ WorkspaceInstructionPolicyRevision,
75
+ WorkspaceInstructionPolicyRevisionIdentity,
76
+ WorkspaceInstructionPolicyScope,
77
+ WorkspaceInstructionPolicyTarget,
78
+ } from "./workspace-instruction-policies";
56
79
  export {
57
80
  DEFAULT_WORKSPACE_TRANSCRIPTION_POLICY,
58
81
  authorizeTranscriptionAdapter,
@@ -86,6 +109,7 @@ export {
86
109
  KNOWN_USAGE_EVENT_TYPES,
87
110
  OPENGENI_API_CONTRACT_HEADER,
88
111
  OPENGENI_API_CONTRACT_REVISION,
112
+ OPENGENI_CORRELATION_HEADER,
89
113
  RETAINED_OUTPUT_DEFAULT_PAGE_BYTES,
90
114
  RETAINED_OUTPUT_MAX_PAGE_BYTES,
91
115
  SESSION_EVENT_TYPES,
@@ -167,6 +191,7 @@ export type {
167
191
  CreateApiKeyRequest,
168
192
  CreateApiKeyResponse,
169
193
  CreateCapabilityCatalogItemRequest,
194
+ ConnectOpenGeniSlackBotRequest,
170
195
  CreateConnectionRequest,
171
196
  CreateCheckoutRequest,
172
197
  CreateCheckoutResponse,
@@ -175,6 +200,7 @@ export type {
175
200
  CreateFileUploadResponse,
176
201
  CreateGitHubAppManifestRequest,
177
202
  CreateGitHubAppManifestResponse,
203
+ CreateKnowledgeDropRequest,
178
204
  CreateKnowledgeMemoryRequest,
179
205
  CreateScheduledTaskRequest,
180
206
  CreateSessionRequest,
@@ -184,11 +210,15 @@ export type {
184
210
  DiscoverMcpCapabilitiesResponse,
185
211
  Document,
186
212
  DocumentBase,
213
+ DocumentCuration,
214
+ DocumentCurationStatus,
187
215
  DocumentSearchMode,
188
216
  DocumentSearchRequest,
189
217
  DocumentSearchResponse,
190
218
  DocumentSearchResult,
191
219
  DocumentStatus,
220
+ DocumentVisibility,
221
+ MoveDocumentRequest,
192
222
  EnableCapabilityRequest,
193
223
  EnablePackRequest,
194
224
  Entitlements,
@@ -206,7 +236,9 @@ export type {
206
236
  FileUploadData,
207
237
  GetPackResponse,
208
238
  GitHubAppInfo,
239
+ GitHubBindingStatus,
209
240
  GitHubInstallationBinding,
241
+ GitHubInstallationLifecycle,
210
242
  GitHubRepositoriesResponse,
211
243
  GitHubRepository,
212
244
  GitHubRepositoryScope,
@@ -411,6 +443,7 @@ export type {
411
443
  UpdateSessionMcpApprovalPolicyResponse,
412
444
  UpdateSessionPinRequest,
413
445
  UpdateSessionRequest,
446
+ UpdateSessionToolPolicyRequest,
414
447
  UpdateVariableSetRequest,
415
448
  UpdateWorkspaceEnvironmentRequest,
416
449
  UpdateWorkspaceMemberRequest,
package/src/types.ts CHANGED
@@ -276,6 +276,18 @@ export type SessionToolPolicy = {
276
276
  inheritedFromSessionId: string | null;
277
277
  };
278
278
 
279
+ export type UpdateSessionToolPolicyRequest =
280
+ | {
281
+ mode: "workspace_default";
282
+ expectedVersion: number;
283
+ }
284
+ | {
285
+ /** Omitted for compatibility with the original explicit-only API. */
286
+ mode?: "explicit" | undefined;
287
+ tools: ToolRef[];
288
+ expectedVersion: number;
289
+ };
290
+
279
291
  export type SessionEffectiveToolPolicy = {
280
292
  mode: SessionToolPolicy["mode"];
281
293
  inheritedFromSessionId: string | null;
@@ -377,6 +389,8 @@ export type ConnectionMetadata = {
377
389
  lastUsedAt: string | null;
378
390
  lastError: string | null;
379
391
  version: number;
392
+ verifiedInstallAt?: string | null;
393
+ verifiedInstallVersion?: number | null;
380
394
  metadata: Record<string, unknown>;
381
395
  createdBySubjectId: string | null;
382
396
  updatedBySubjectId: string | null;
@@ -394,6 +408,13 @@ export type CreateConnectionRequest = {
394
408
  metadata?: Record<string, unknown> | undefined;
395
409
  };
396
410
 
411
+ export type ConnectOpenGeniSlackBotRequest = {
412
+ /** Write-only Slack bot token. It is never returned by the API. */
413
+ token: string;
414
+ /** Existing OpenGeni Slack bot connection to reinstall in place. */
415
+ connectionId?: string | undefined;
416
+ };
417
+
397
418
  export type UpdateConnectionRequest = {
398
419
  providerDomain?: string | undefined;
399
420
  subjectId?: string | null | undefined;
@@ -472,6 +493,7 @@ export type Session = {
472
493
  resources: ResourceRef[];
473
494
  tools: ToolRef[];
474
495
  toolPolicy?: SessionToolPolicy | undefined;
496
+ toolPolicyVersion?: number | undefined;
475
497
  effectiveToolPolicy?: SessionEffectiveToolPolicy | undefined;
476
498
  metadata: Record<string, unknown>;
477
499
  /** Frozen creator fact; later turns carry their own independent initiator. */
@@ -762,6 +784,7 @@ export const SESSION_EVENT_TYPES = [
762
784
  "terminal.pty.exited",
763
785
  "session.title_set",
764
786
  "session.mcp.approval_policy.updated",
787
+ "session.tool_policy.updated",
765
788
  // Multi-account Codex (P1): the session's inference account changed.
766
789
  "codex.account.switched",
767
790
  // credential allocator metadata-only per-turn credential selection audit.
@@ -1492,6 +1515,7 @@ export type ScheduledTaskAgentConfig = {
1492
1515
  resources: ResourceRef[];
1493
1516
  tools: ToolRef[];
1494
1517
  metadata: Record<string, unknown>;
1518
+ slackBotConnectionId?: string | undefined;
1495
1519
  model?: string | undefined;
1496
1520
  reasoningEffort?: ReasoningEffort | undefined;
1497
1521
  sandboxBackend?: SandboxBackend | undefined;
@@ -1993,6 +2017,8 @@ export type ClientAuthConfig =
1993
2017
  // parity suite. The SDK has no runtime dependency on the Zod contracts package.
1994
2018
  export const OPENGENI_API_CONTRACT_REVISION = "2026-07-turn-instructions-v1" as const;
1995
2019
  export const OPENGENI_API_CONTRACT_HEADER = "x-opengeni-api-contract" as const;
2020
+ /** Bounded request/response identifier shared by browser, ingress, and API diagnostics. */
2021
+ export const OPENGENI_CORRELATION_HEADER = "x-opengeni-correlation-id" as const;
1996
2022
 
1997
2023
  /**
1998
2024
  * Public, unauthenticated-by-default client bootstrap config returned by
@@ -2324,6 +2350,8 @@ export type NewSessionDraft = {
2324
2350
  text: string;
2325
2351
  resources: ResourceRef[];
2326
2352
  tools: ToolRef[];
2353
+ /** False inherits the workspace-default MCP policy; true preserves an explicit array. */
2354
+ toolsProvided: boolean;
2327
2355
  model: string;
2328
2356
  reasoningEffort: ReasoningEffort;
2329
2357
  options: NewSessionDraftOptions;
@@ -2470,6 +2498,7 @@ export type ScheduledTaskAgentConfigInput = {
2470
2498
  resources?: ResourceRef[] | undefined;
2471
2499
  tools?: ToolRef[] | undefined;
2472
2500
  metadata?: Record<string, unknown> | undefined;
2501
+ slackBotConnectionId?: string | undefined;
2473
2502
  model?: string | undefined;
2474
2503
  reasoningEffort?: ReasoningEffort | undefined;
2475
2504
  sandboxBackend?: SandboxBackend | undefined;
@@ -2823,6 +2852,19 @@ export type KnowledgeSourceKind =
2823
2852
  | "other";
2824
2853
  export type DocumentSearchMode = "hybrid" | "vector" | "keyword";
2825
2854
 
2855
+ export type DocumentVisibility = "workspace" | "private";
2856
+
2857
+ export type DocumentCurationStatus = "none" | "pending" | "suggested" | "auto_filed" | "failed";
2858
+
2859
+ export type DocumentCuration = {
2860
+ suggestedBaseId: string | null;
2861
+ suggestedBaseName: string | null;
2862
+ confidence: number;
2863
+ reason: string | null;
2864
+ originalTitle: string | null;
2865
+ model: string | null;
2866
+ };
2867
+
2826
2868
  export type DocumentBase = {
2827
2869
  id: string;
2828
2870
  workspaceId: string;
@@ -2851,6 +2893,13 @@ export type Document = {
2851
2893
  sourceUpdatedAt: string | null;
2852
2894
  sourceVersion: string | null;
2853
2895
  aclTags: string[];
2896
+ visibility: DocumentVisibility;
2897
+ createdBy: string | null;
2898
+ agentAccess: boolean;
2899
+ summary: string | null;
2900
+ topics: string[];
2901
+ curationStatus: DocumentCurationStatus;
2902
+ curation: DocumentCuration | null;
2854
2903
  createdAt: string;
2855
2904
  updatedAt: string;
2856
2905
  };
@@ -2897,6 +2946,21 @@ export type AddDocumentRequest = {
2897
2946
  sourceUpdatedAt?: string | undefined;
2898
2947
  sourceVersion?: string | undefined;
2899
2948
  aclTags?: string[] | undefined;
2949
+ visibility?: DocumentVisibility | undefined;
2950
+ agentAccess?: boolean | undefined;
2951
+ };
2952
+
2953
+ export type CreateKnowledgeDropRequest = {
2954
+ text?: string | undefined;
2955
+ fileId?: string | undefined;
2956
+ filename?: string | undefined;
2957
+ title?: string | undefined;
2958
+ visibility?: DocumentVisibility | undefined;
2959
+ agentAccess?: boolean | undefined;
2960
+ };
2961
+
2962
+ export type MoveDocumentRequest = {
2963
+ targetBaseId?: string | undefined;
2900
2964
  };
2901
2965
 
2902
2966
  export type DocumentSearchRequest = {
@@ -3333,10 +3397,16 @@ export type GitHubRepository = {
3333
3397
 
3334
3398
  export type GitHubRepositoryScope = "all" | "selected";
3335
3399
 
3400
+ export type GitHubBindingStatus = "disabled" | "unbound" | "bound";
3401
+
3402
+ export type GitHubInstallationLifecycle = "active" | "suspended" | "deleted" | "unverified";
3403
+
3336
3404
  export type GitHubInstallationBinding = {
3337
3405
  installationId: number;
3406
+ githubAccountId: number | null;
3338
3407
  accountLogin: string | null;
3339
3408
  accountType: string | null;
3409
+ lifecycle: GitHubInstallationLifecycle;
3340
3410
  repositoryScope: GitHubRepositoryScope;
3341
3411
  repositoryCount: number;
3342
3412
  createdAt: string;
@@ -3345,12 +3415,14 @@ export type GitHubInstallationBinding = {
3345
3415
 
3346
3416
  export type GitHubAppInfo = {
3347
3417
  configured: boolean;
3418
+ /** Truthful workspace binding state; server App credentials alone are not a binding. */
3419
+ status: GitHubBindingStatus;
3348
3420
  appId: string | null;
3349
3421
  clientId: string | null;
3350
3422
  appSlug: string | null;
3351
- /** Reserved compatibility field; null while new installation binding is disabled. */
3423
+ /** Fresh GitHub-controlled installation/configuration consent entry point. */
3352
3424
  installUrl: string | null;
3353
- /** Reserved compatibility field; null while new installation binding is disabled. */
3425
+ /** Compatibility alias for installUrl; no repository-admin chooser is exposed. */
3354
3426
  linkUrl: string | null;
3355
3427
  /** Installation bindings owned independently by this workspace. */
3356
3428
  installations: GitHubInstallationBinding[];
@@ -0,0 +1,124 @@
1
+ export type WorkspaceInstructionPolicyKind = "charter" | "policy";
2
+ export type WorkspaceInstructionPolicyScope = "global" | "role";
3
+ export type WorkspaceInstructionPolicyProvenanceSource =
4
+ | "human"
5
+ | "onboarding"
6
+ | "knowledge_proposal"
7
+ | "legacy_import";
8
+ export type WorkspaceInstructionPolicyDraftProvenanceSource = Exclude<
9
+ WorkspaceInstructionPolicyProvenanceSource,
10
+ "legacy_import"
11
+ >;
12
+ export type WorkspaceInstructionPolicyActivationType = "activate" | "rollback";
13
+
14
+ export function normalizeWorkspaceInstructionPolicyRoleKey(value: string): string {
15
+ return value.normalize("NFKC").trim().toLowerCase().replace(/\s+/gu, "-").replace(/-+/g, "-");
16
+ }
17
+
18
+ export type WorkspaceInstructionPolicyTarget = {
19
+ kind: WorkspaceInstructionPolicyKind;
20
+ scope: WorkspaceInstructionPolicyScope;
21
+ roleKey: string | null;
22
+ };
23
+
24
+ export type WorkspaceInstructionPolicyRevisionIdentity = {
25
+ id: string;
26
+ revision: number;
27
+ contentHash: string;
28
+ };
29
+
30
+ export type WorkspaceInstructionPolicyRevision = WorkspaceInstructionPolicyRevisionIdentity &
31
+ WorkspaceInstructionPolicyTarget & {
32
+ accountId: string;
33
+ workspaceId: string;
34
+ content: string;
35
+ provenance: {
36
+ source: WorkspaceInstructionPolicyProvenanceSource;
37
+ sourceId: string | null;
38
+ };
39
+ supersedesRevisionId: string | null;
40
+ createdBySubjectId: string;
41
+ createdAt: string;
42
+ };
43
+
44
+ export type WorkspaceInstructionPolicyHead = WorkspaceInstructionPolicyTarget & {
45
+ workspaceId: string;
46
+ revisionId: string;
47
+ revision: number;
48
+ contentHash: string;
49
+ activationVersion: number;
50
+ activatedAt: string;
51
+ };
52
+
53
+ export type WorkspaceInstructionPolicyActivationEvent = WorkspaceInstructionPolicyTarget & {
54
+ id: string;
55
+ accountId: string;
56
+ workspaceId: string;
57
+ type: WorkspaceInstructionPolicyActivationType;
58
+ activationVersion: number;
59
+ oldRevision: WorkspaceInstructionPolicyRevisionIdentity | null;
60
+ newRevision: WorkspaceInstructionPolicyRevisionIdentity;
61
+ actorSubjectId: string;
62
+ reason: string;
63
+ createdAt: string;
64
+ };
65
+
66
+ export type CreateWorkspaceInstructionPolicyDraftRequest = WorkspaceInstructionPolicyTarget & {
67
+ content: string;
68
+ provenanceSource?: WorkspaceInstructionPolicyDraftProvenanceSource;
69
+ provenanceSourceId?: string | null;
70
+ supersedesRevisionId?: string | null;
71
+ };
72
+
73
+ export type ImportLegacyWorkspaceInstructionPolicyDraftRequest = {
74
+ supersedesRevisionId?: string | null;
75
+ };
76
+
77
+ export type WorkspaceInstructionPolicyListOptions = {
78
+ kind?: WorkspaceInstructionPolicyKind;
79
+ scope?: WorkspaceInstructionPolicyScope;
80
+ roleKey?: string;
81
+ afterRevision?: number;
82
+ limit?: number;
83
+ };
84
+
85
+ export type WorkspaceInstructionPolicyListResponse = {
86
+ revisions: WorkspaceInstructionPolicyRevision[];
87
+ activeHeads: WorkspaceInstructionPolicyHead[];
88
+ activationEvents: WorkspaceInstructionPolicyActivationEvent[];
89
+ nextAfterRevision: number | null;
90
+ };
91
+
92
+ export type WorkspaceInstructionPolicyDiffRequest = {
93
+ fromRevisionId: string;
94
+ toRevisionId: string;
95
+ };
96
+
97
+ export type WorkspaceInstructionPolicyDiffResponse = {
98
+ from: WorkspaceInstructionPolicyRevision;
99
+ to: WorkspaceInstructionPolicyRevision;
100
+ format: "unified";
101
+ diff: string;
102
+ };
103
+
104
+ export type ActivateWorkspaceInstructionPolicyRequest = {
105
+ expectedCurrentRevisionId: string | null;
106
+ reason: string;
107
+ };
108
+
109
+ export type RollbackWorkspaceInstructionPolicyRequest = {
110
+ targetRevisionId: string;
111
+ expectedCurrentRevisionId: string;
112
+ reason: string;
113
+ };
114
+
115
+ export type WorkspaceInstructionPolicyActivationResponse = {
116
+ head: WorkspaceInstructionPolicyHead;
117
+ event: WorkspaceInstructionPolicyActivationEvent;
118
+ };
119
+
120
+ export type WorkspaceInstructionPolicyConflictResponse = {
121
+ code: "WORKSPACE_INSTRUCTION_POLICY_CONFLICT";
122
+ message: string;
123
+ currentHead: WorkspaceInstructionPolicyHead | null;
124
+ };