@opengeni/api-router 0.26.1 → 0.30.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 (87) hide show
  1. package/dist/app.d.ts +1 -0
  2. package/dist/app.js +5 -3
  3. package/dist/auth/canonical-human-session-admission.d.ts +27 -0
  4. package/dist/browser-auth-broker.d.ts +20 -0
  5. package/dist/browser-controller-authority.d.ts +19 -1
  6. package/dist/browser-network-route.d.ts +8 -0
  7. package/dist/{chunk-JIKNR5YL.js → chunk-2PQMSRCB.js} +15518 -6863
  8. package/dist/chunk-2PQMSRCB.js.map +1 -0
  9. package/dist/controller-data-plane.d.ts +12 -0
  10. package/dist/http/auth.d.ts +1 -1
  11. package/dist/http/sse.d.ts +18 -1
  12. package/dist/index.js +1 -1
  13. package/dist/integrations/api-integrations.d.ts +2 -2
  14. package/dist/integrations/fiken.d.ts +233 -0
  15. package/dist/integrations/google-drive.d.ts +6 -6
  16. package/dist/integrations/provider-oauth.d.ts +0 -2
  17. package/dist/integrations/slack-bot.d.ts +171 -1
  18. package/dist/integrations/slack-interactions.d.ts +17 -5
  19. package/dist/interaction-holder-heartbeat.d.ts +17 -0
  20. package/dist/interaction-metrics.d.ts +11 -0
  21. package/dist/mcp/server.d.ts +3 -2
  22. package/dist/model-catalog.d.ts +1 -0
  23. package/dist/routes/canonical-human-identities.d.ts +3 -0
  24. package/dist/routes/channels.d.ts +3 -0
  25. package/dist/routes/integration-facets.d.ts +3 -0
  26. package/dist/routes/interaction-resources.d.ts +5 -0
  27. package/dist/routes/organization-memberships.d.ts +3 -0
  28. package/dist/routes/sessions.d.ts +2 -1
  29. package/dist/routes/slack-task-policy.d.ts +3 -0
  30. package/dist/routes/supergrok.d.ts +3 -0
  31. package/dist/sandbox/channel-a.d.ts +8 -1
  32. package/dist/sandbox/machines.d.ts +2 -2
  33. package/dist/sandbox/viewer.d.ts +3 -1
  34. package/dist/slack-reaction-files.d.ts +27 -0
  35. package/dist/transcription/providers/xai-subscription.d.ts +8 -0
  36. package/dist/xai-realtime.d.ts +26 -0
  37. package/dist/xai-subscription-auth.d.ts +23 -0
  38. package/package.json +17 -16
  39. package/src/app.ts +352 -49
  40. package/src/auth/canonical-human-session-admission.ts +116 -0
  41. package/src/auth/managed-auth.ts +101 -0
  42. package/src/browser-auth-broker.ts +155 -0
  43. package/src/browser-controller-authority.ts +50 -1
  44. package/src/browser-network-route.ts +34 -0
  45. package/src/controller-data-plane.ts +35 -0
  46. package/src/http/auth.ts +27 -9
  47. package/src/http/sse.ts +229 -5
  48. package/src/integrations/api-integrations.ts +57 -42
  49. package/src/integrations/fiken.ts +1230 -0
  50. package/src/integrations/google-drive.ts +31 -26
  51. package/src/integrations/provider-oauth.ts +70 -91
  52. package/src/integrations/slack-bot.ts +638 -9
  53. package/src/integrations/slack-interactions.ts +1583 -73
  54. package/src/interaction-holder-heartbeat.ts +95 -0
  55. package/src/interaction-metrics.ts +159 -0
  56. package/src/mcp/documents.ts +115 -6
  57. package/src/mcp/server.ts +865 -242
  58. package/src/model-catalog.ts +19 -6
  59. package/src/routes/api-integrations.ts +32 -29
  60. package/src/routes/browser-identities.ts +24 -0
  61. package/src/routes/browser-sessions.ts +2122 -183
  62. package/src/routes/canonical-human-identities.ts +156 -0
  63. package/src/routes/channels.ts +90 -0
  64. package/src/routes/computer-sessions.ts +441 -86
  65. package/src/routes/connections.ts +141 -4
  66. package/src/routes/{integration-features.ts → integration-facets.ts} +63 -63
  67. package/src/routes/interaction-resources.ts +595 -0
  68. package/src/routes/organization-memberships.ts +53 -0
  69. package/src/routes/plugins.ts +2 -1
  70. package/src/routes/sessions.ts +419 -43
  71. package/src/routes/skills.ts +92 -10
  72. package/src/routes/slack-task-policy.ts +115 -0
  73. package/src/routes/supergrok.ts +717 -0
  74. package/src/routes/transcription-recordings.ts +9 -2
  75. package/src/routes/transcriptions.ts +2 -1
  76. package/src/routes/video-generation.ts +34 -4
  77. package/src/routes/workspaces.ts +22 -4
  78. package/src/sandbox/channel-a.ts +29 -2
  79. package/src/sandbox/machines.ts +5 -5
  80. package/src/sandbox/viewer.ts +10 -3
  81. package/src/slack-reaction-files.ts +181 -0
  82. package/src/transcription/providers/xai-subscription.ts +110 -0
  83. package/src/transcription/service.ts +17 -2
  84. package/src/xai-realtime.ts +216 -0
  85. package/src/xai-subscription-auth.ts +132 -0
  86. package/dist/chunk-JIKNR5YL.js.map +0 -1
  87. package/dist/routes/integration-features.d.ts +0 -3
@@ -0,0 +1,12 @@
1
+ /** Prefer a lease-fenced controller endpoint for the idempotent create path.
2
+ * Only a transport-class failure invalidates the cache and provisions once;
3
+ * semantic failures belong to the caller and must never be replayed. */
4
+ export declare function withCachedController<C, T>(options: {
5
+ cachedUrl: string | null;
6
+ createCachedClient: (url: string) => C;
7
+ prepareCachedClient?: (client: C) => Promise<void>;
8
+ invalidateCachedUrl: () => Promise<unknown>;
9
+ provisionClient: () => Promise<C>;
10
+ use: (client: C) => Promise<T>;
11
+ }): Promise<T>;
12
+ export declare function isRetryableControllerTransport(error: unknown): boolean;
@@ -1,3 +1,3 @@
1
- import type { Settings } from "@opengeni/config";
1
+ import { type Settings } from "@opengeni/config";
2
2
  import type { MiddlewareHandler } from "hono";
3
3
  export declare function requireAccessKey(settings: Settings): MiddlewareHandler;
@@ -1,4 +1,4 @@
1
- import type { SessionEvent } from "@opengeni/contracts";
1
+ import { type SessionEvent } from "@opengeni/contracts";
2
2
  import { type Database } from "@opengeni/db";
3
3
  import { type EventBus } from "@opengeni/events";
4
4
  import type { Observability } from "@opengeni/observability";
@@ -58,6 +58,23 @@ export declare function createLatestWinsDelivery<T extends {
58
58
  export declare function sseSessionStream(db: Database, bus: EventBus, workspaceId: string, sessionId: string, after: number, signal: AbortSignal, options?: SessionSseDeliveryOptions): Promise<Response>;
59
59
  export declare function replaySessionEvents(loadPage: (after: number, limit: number) => Promise<SessionEvent[]>, send: (event: SessionEvent) => Promise<void>, after: number, pageSize?: number): Promise<void>;
60
60
  export declare function sseWorkspaceControlStream(db: Database, bus: EventBus, workspaceId: string, after: number, signal: AbortSignal, options?: SseDeliveryOptions): Promise<Response>;
61
+ export type WorkspaceInteractionSseOptions = SseDeliveryOptions & {
62
+ pollIntervalMs?: number | undefined;
63
+ };
64
+ /**
65
+ * One HTTP connection for the two workspace-wide invalidation domains used by
66
+ * every visible OpenGeni surface. Keeping these as separate HTTP/1 streams
67
+ * consumes all six per-origin browser connections with only two windows and
68
+ * starves ordinary mutations/terminal grants. The durable cursors remain
69
+ * independent; this function only multiplexes their already-bounded SSE frames.
70
+ */
71
+ export declare function sseWorkspaceLiveStream(db: Database, bus: EventBus, accountId: string, workspaceId: string, controlAfter: number, interactionAfter: number, signal: AbortSignal, options?: WorkspaceInteractionSseOptions): Promise<Response>;
72
+ /**
73
+ * Latest-wins interaction invalidation stream. The durable truth is one
74
+ * monotonic workspace row, not an ever-growing event log. Each poll reads only
75
+ * that row; reconnect immediately projects the newest revision after `after`.
76
+ */
77
+ export declare function sseWorkspaceInteractionRevisionStream(db: Database, accountId: string, workspaceId: string, after: number, signal: AbortSignal, options?: WorkspaceInteractionSseOptions): Promise<Response>;
61
78
  export type SseDeliveryOptions = {
62
79
  maxQueuedBytes?: number;
63
80
  stallTimeoutMs?: number;
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  createOpenGeniSlackBotInteractionClient,
5
5
  startSlackInteractionPump,
6
6
  startTemporalScheduleCleanupPump
7
- } from "./chunk-JIKNR5YL.js";
7
+ } from "./chunk-2PQMSRCB.js";
8
8
 
9
9
  // src/index.ts
10
10
  import {
@@ -1,5 +1,5 @@
1
1
  import { type IntegrationCredentialResolver, type IntegrationInvocationAuthority, type IntegrationTransport } from "@opengeni/capabilities";
2
- import { ApiIntegrationPreview, type ApiIntegrationSource } from "@opengeni/contracts";
2
+ import { ApiIntegrationPreview, type IntegrationSource } from "@opengeni/contracts";
3
3
  import type { StoredApiIntegrationRevision } from "@opengeni/db";
4
4
  export type ApiIntegrationConnectionDescriptor = {
5
5
  id: string;
@@ -16,7 +16,7 @@ export type ResolvedApiIntegrationPreview = {
16
16
  authScheme: Record<string, unknown>;
17
17
  };
18
18
  export declare function resolveApiIntegrationPreview(input: {
19
- source: ApiIntegrationSource;
19
+ source: IntegrationSource;
20
20
  connection: ApiIntegrationConnectionDescriptor | null;
21
21
  transport: IntegrationTransport;
22
22
  credentialResolver?: IntegrationCredentialResolver;
@@ -0,0 +1,233 @@
1
+ import type { ApiRouteDeps } from "@opengeni/core";
2
+ import type { Settings } from "@opengeni/config";
3
+ import { FikenOAuthStartResponse, type AccessGrant, type ConnectionMetadata, type FikenCompanySummary, type FikenConnectionMetadata, type FikenOAuthStartRequest } from "@opengeni/contracts";
4
+ import { type Database } from "@opengeni/db";
5
+ import { type FetchLike } from "@opengeni/network";
6
+ import { HTTPException } from "hono/http-exception";
7
+ export type FikenOperation = "companies.list" | "contacts.list" | "contact.create" | "products.list" | "invoices.list" | "invoice.get" | "invoice_draft.create" | "bank_accounts.list" | "purchases.list" | "sales.list";
8
+ export declare class FikenProviderError extends Error {
9
+ readonly code: string;
10
+ readonly status: number | null;
11
+ constructor(code: string, status?: number | null, providerMessage?: string | null);
12
+ }
13
+ export declare class FikenCredentialVerificationError extends HTTPException {
14
+ constructor(message: string);
15
+ }
16
+ export type FikenPage = {
17
+ page: number;
18
+ pageSize: number;
19
+ pageCount: number | null;
20
+ resultCount: number | null;
21
+ };
22
+ type FikenContext = {
23
+ accountId: string;
24
+ workspaceId: string;
25
+ subjectId: string | null;
26
+ sessionId: string | null;
27
+ };
28
+ /**
29
+ * Validates a pasted Fiken personal API token before it enters encrypted
30
+ * storage, and discovers the companies it can act on. The companies list is
31
+ * the connection's bounded metadata; company slugs are re-validated by Fiken
32
+ * itself on every later call.
33
+ */
34
+ export declare function verifyFikenApiToken(token: string, fetchImpl?: FetchLike): Promise<{
35
+ companies: FikenCompanySummary[];
36
+ }>;
37
+ export declare function fikenCredentialBundle(token: string): Record<string, unknown>;
38
+ export declare function resolveFikenConnectionForTool(input: {
39
+ db: Database;
40
+ grant: AccessGrant;
41
+ sessionId: string | null;
42
+ requestedConnectionId?: string;
43
+ }): Promise<{
44
+ connection: ConnectionMetadata;
45
+ metadata: FikenConnectionMetadata;
46
+ context: FikenContext;
47
+ }>;
48
+ export type FikenListInput = {
49
+ companySlug?: string | undefined;
50
+ page?: number | undefined;
51
+ pageSize?: number | undefined;
52
+ };
53
+ export declare class FikenClient {
54
+ private readonly db;
55
+ private readonly settings;
56
+ private readonly connection;
57
+ private readonly metadata;
58
+ private readonly context;
59
+ private readonly fetchImpl;
60
+ private readonly resolveCredential;
61
+ constructor(db: Database, settings: Settings, connection: ConnectionMetadata, metadata: FikenConnectionMetadata, context: FikenContext, fetchImpl?: FetchLike);
62
+ listCompanies(input?: {
63
+ page?: number;
64
+ pageSize?: number;
65
+ }): Promise<{
66
+ companies: Record<string, unknown>[];
67
+ page: FikenPage | null;
68
+ }>;
69
+ listContacts(input: FikenListInput & {
70
+ name?: string | undefined;
71
+ email?: string | undefined;
72
+ organizationNumber?: string | undefined;
73
+ customer?: boolean | undefined;
74
+ supplier?: boolean | undefined;
75
+ inactive?: boolean | undefined;
76
+ }): Promise<{
77
+ companySlug: string;
78
+ contacts: Record<string, unknown>[];
79
+ page: FikenPage | null;
80
+ }>;
81
+ createContact(input: {
82
+ companySlug?: string | undefined;
83
+ name: string;
84
+ email?: string | undefined;
85
+ organizationNumber?: string | undefined;
86
+ phoneNumber?: string | undefined;
87
+ customer?: boolean | undefined;
88
+ supplier?: boolean | undefined;
89
+ }): Promise<{
90
+ companySlug: string;
91
+ contactId: number;
92
+ receipt: {
93
+ credentialRole: "fiken_api_token";
94
+ credentialLabel: "Fiken API token";
95
+ connectionId: string;
96
+ operation: FikenOperation;
97
+ operationId?: string;
98
+ };
99
+ }>;
100
+ listProducts(input: FikenListInput & {
101
+ name?: string | undefined;
102
+ active?: boolean | undefined;
103
+ }): Promise<{
104
+ companySlug: string;
105
+ products: Record<string, unknown>[];
106
+ page: FikenPage | null;
107
+ }>;
108
+ listInvoices(input: FikenListInput & {
109
+ issueDateGe?: string | undefined;
110
+ issueDateLe?: string | undefined;
111
+ customerId?: number | undefined;
112
+ settled?: boolean | undefined;
113
+ invoiceNumber?: string | undefined;
114
+ }): Promise<{
115
+ companySlug: string;
116
+ invoices: Record<string, unknown>[];
117
+ page: FikenPage | null;
118
+ }>;
119
+ getInvoice(input: {
120
+ companySlug?: string | undefined;
121
+ invoiceId: number;
122
+ }): Promise<{
123
+ companySlug: string;
124
+ invoice: Record<string, unknown> | null;
125
+ }>;
126
+ createInvoiceDraft(input: {
127
+ companySlug?: string | undefined;
128
+ operationId: string;
129
+ customerId: number;
130
+ daysUntilDueDate: number;
131
+ invoiceText?: string | undefined;
132
+ yourReference?: string | undefined;
133
+ ourReference?: string | undefined;
134
+ currency?: string | undefined;
135
+ bankAccountNumber?: string | undefined;
136
+ lines: Array<{
137
+ description?: string | undefined;
138
+ productId?: number | undefined;
139
+ unitPriceCents?: number | undefined;
140
+ vatType?: string | undefined;
141
+ quantity: number;
142
+ discountPercent?: number | undefined;
143
+ incomeAccount?: string | undefined;
144
+ comment?: string | undefined;
145
+ }>;
146
+ }): Promise<{
147
+ companySlug: string;
148
+ draftId: number | null;
149
+ draft: Record<string, unknown>;
150
+ alreadyExisted: boolean;
151
+ receipt: {
152
+ credentialRole: "fiken_api_token";
153
+ credentialLabel: "Fiken API token";
154
+ connectionId: string;
155
+ operation: FikenOperation;
156
+ operationId?: string;
157
+ };
158
+ } | {
159
+ draft?: never;
160
+ companySlug: string;
161
+ draftId: number;
162
+ alreadyExisted: boolean;
163
+ receipt: {
164
+ credentialRole: "fiken_api_token";
165
+ credentialLabel: "Fiken API token";
166
+ connectionId: string;
167
+ operation: FikenOperation;
168
+ operationId?: string;
169
+ };
170
+ }>;
171
+ listBankAccounts(input: FikenListInput & {
172
+ inactive?: boolean | undefined;
173
+ }): Promise<{
174
+ companySlug: string;
175
+ bankAccounts: Record<string, unknown>[];
176
+ page: FikenPage | null;
177
+ }>;
178
+ listPurchases(input: FikenListInput & {
179
+ dateGe?: string | undefined;
180
+ dateLe?: string | undefined;
181
+ paid?: boolean | undefined;
182
+ }): Promise<{
183
+ companySlug: string;
184
+ purchases: Record<string, unknown>[];
185
+ page: FikenPage | null;
186
+ }>;
187
+ listSales(input: FikenListInput & {
188
+ dateGe?: string | undefined;
189
+ dateLe?: string | undefined;
190
+ settled?: boolean | undefined;
191
+ }): Promise<{
192
+ companySlug: string;
193
+ sales: Record<string, unknown>[];
194
+ page: FikenPage | null;
195
+ }>;
196
+ /**
197
+ * The company scope for a call: an explicit slug wins, then the connection's
198
+ * configured default, then the only verified company. Ambiguity is an error
199
+ * that lists the available slugs instead of guessing.
200
+ */
201
+ private companySlugFor;
202
+ private request;
203
+ private readResponse;
204
+ private markNeedsReauth;
205
+ private headersFor;
206
+ private receipt;
207
+ private recordAudit;
208
+ }
209
+ export declare function createFikenClient(deps: {
210
+ db: Database;
211
+ settings: Settings;
212
+ fikenFetch?: typeof fetch;
213
+ }, resolved: Awaited<ReturnType<typeof resolveFikenConnectionForTool>>): FikenClient;
214
+ export declare class FikenOAuthCallbackError extends Error {
215
+ readonly reason: string;
216
+ constructor(reason: string);
217
+ }
218
+ export declare function startFikenOAuth(deps: ApiRouteDeps, input: {
219
+ accountId: string;
220
+ workspaceId: string;
221
+ subjectId: string;
222
+ requestUrl: string;
223
+ payload: FikenOAuthStartRequest;
224
+ }): Promise<FikenOAuthStartResponse>;
225
+ export declare function completeFikenOAuthCallback(deps: ApiRouteDeps, input: {
226
+ code?: string | undefined;
227
+ state?: string | undefined;
228
+ error?: string | undefined;
229
+ requestUrl: string;
230
+ }): Promise<{
231
+ redirectTo: string;
232
+ }>;
233
+ export {};
@@ -1,6 +1,6 @@
1
1
  import type { AccessGrant, ScheduledTask } from "@opengeni/contracts";
2
2
  import { GoogleDriveOAuthStartResponse, type GoogleDriveDisconnectRequest, type GoogleDriveLifecycleActionRequest, type GoogleDriveOAuthStartRequest } from "@opengeni/contracts/google-drive";
3
- import { IntegrationFeatureMutationResult } from "@opengeni/contracts";
3
+ import { IntegrationFacetMutationResult } from "@opengeni/contracts";
4
4
  import type { ApiRouteDeps } from "@opengeni/core";
5
5
  import { getConnectionMetadata } from "@opengeni/db";
6
6
  export declare function wakeGoogleDriveSourcesFromWorkspaceEvent(deps: ApiRouteDeps, input: {
@@ -95,12 +95,12 @@ export declare function browseGoogleDrive(deps: ApiRouteDeps, input: {
95
95
  nextPageToken: string | null;
96
96
  incompleteSearch: boolean;
97
97
  }>;
98
- export declare function browseGoogleDriveIntegrationSource(deps: ApiRouteDeps, input: {
98
+ export declare function browseGoogleDriveFacetSource(deps: ApiRouteDeps, input: {
99
99
  workspaceId: string;
100
100
  subjectId: string;
101
101
  capabilityId: string;
102
102
  instanceKey: string;
103
- featureKey: string;
103
+ facetKey: string;
104
104
  parentId: string;
105
105
  pageToken?: string | undefined;
106
106
  }): Promise<{
@@ -150,18 +150,18 @@ export declare function browseGoogleDriveIntegrationSource(deps: ApiRouteDeps, i
150
150
  nextPageToken: string | null;
151
151
  incompleteSearch: boolean;
152
152
  }>;
153
- export declare function saveGoogleDriveIntegrationSource(deps: ApiRouteDeps, input: {
153
+ export declare function saveGoogleDriveFacetSource(deps: ApiRouteDeps, input: {
154
154
  accountId: string;
155
155
  workspaceId: string;
156
156
  subjectId: string;
157
157
  capabilityId: string;
158
158
  instanceKey: string;
159
- featureKey: string;
159
+ facetKey: string;
160
160
  payload: unknown;
161
161
  canManageOrganizationDestination: boolean;
162
162
  canManageWorkspaceDestination: boolean;
163
163
  canManagePersonalDestination: boolean;
164
- }): Promise<IntegrationFeatureMutationResult>;
164
+ }): Promise<IntegrationFacetMutationResult>;
165
165
  export declare function saveGoogleDriveSource(deps: ApiRouteDeps, input: {
166
166
  accountId: string;
167
167
  workspaceId: string;
@@ -1,4 +1,3 @@
1
- import { type Settings } from "@opengeni/config";
2
1
  import { OAuthStartResponse, type ApiIntegrationOAuthStartRequest } from "@opengeni/contracts";
3
2
  import { type ApiRouteDeps } from "@opengeni/core";
4
3
  export declare function startApiIntegrationProviderOAuth(deps: ApiRouteDeps, input: {
@@ -16,4 +15,3 @@ export declare function completeApiIntegrationProviderOAuth(deps: ApiRouteDeps,
16
15
  }): Promise<{
17
16
  redirectTo: string;
18
17
  }>;
19
- export declare function isApiIntegrationProviderOAuthState(value: string | undefined, settings: Settings): boolean;