@opengeni/api-router 0.23.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.
- package/dist/app.d.ts +3 -2
- package/dist/app.js +5 -3
- package/dist/auth/canonical-human-session-admission.d.ts +27 -0
- package/dist/browser-auth-broker.d.ts +20 -0
- package/dist/browser-controller-authority.d.ts +61 -0
- package/dist/browser-network-route.d.ts +8 -0
- package/dist/browser-state-authority.d.ts +27 -0
- package/dist/{chunk-T4T2PGU4.js → chunk-2PQMSRCB.js} +37891 -17463
- package/dist/chunk-2PQMSRCB.js.map +1 -0
- package/dist/codemode.d.ts +23 -0
- package/dist/controller-data-plane.d.ts +12 -0
- package/dist/editable-artifact-live-hints.d.ts +11 -0
- package/dist/editable-artifact-native-kernel.d.ts +37 -0
- package/dist/editable-artifact-office-import.d.ts +22 -0
- package/dist/editable-artifact-production.d.ts +29 -0
- package/dist/editable-artifact-websocket.d.ts +49 -0
- package/dist/editable-artifact-workspace-files.d.ts +23 -0
- package/dist/github-browser-flow.d.ts +6 -0
- package/dist/http/auth.d.ts +1 -1
- package/dist/http/cors.d.ts +1 -0
- package/dist/http/sse.d.ts +18 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1796 -22
- package/dist/index.js.map +1 -1
- package/dist/integrations/api-integrations.d.ts +24 -0
- package/dist/integrations/atlassian.d.ts +176 -0
- package/dist/integrations/fiken.d.ts +233 -0
- package/dist/integrations/github-skill-source.d.ts +5 -0
- package/dist/integrations/google-drive.d.ts +85 -0
- package/dist/integrations/oauth-client.d.ts +22 -1
- package/dist/integrations/provider-oauth.d.ts +17 -0
- package/dist/integrations/slack-bot.d.ts +175 -1
- package/dist/integrations/slack-interactions.d.ts +24 -6
- package/dist/integrations/social-api.d.ts +2 -1
- package/dist/interaction-holder-heartbeat.d.ts +17 -0
- package/dist/interaction-metrics.d.ts +11 -0
- package/dist/mcp/editable-artifact-query-schema.d.ts +4 -0
- package/dist/mcp/editable-artifacts.d.ts +13 -0
- package/dist/mcp/scheduled-task-view.d.ts +168 -0
- package/dist/mcp/server.d.ts +16 -4
- package/dist/memory-slack-delivery.d.ts +9 -0
- package/dist/model-catalog.d.ts +1 -0
- package/dist/routes/api-integrations.d.ts +8 -0
- package/dist/routes/browser-identities.d.ts +5 -0
- package/dist/routes/browser-sessions.d.ts +6 -0
- package/dist/routes/canonical-human-identities.d.ts +3 -0
- package/dist/routes/channels.d.ts +3 -0
- package/dist/routes/company-profile.d.ts +3 -0
- package/dist/routes/computer-sessions.d.ts +6 -0
- package/dist/routes/editable-artifacts.d.ts +44 -0
- package/dist/routes/integration-facets.d.ts +3 -0
- package/dist/routes/interaction-resources.d.ts +5 -0
- package/dist/routes/memory-slack-publications.d.ts +6 -0
- package/dist/routes/organization-memberships.d.ts +3 -0
- package/dist/routes/plugins.d.ts +8 -0
- package/dist/routes/sessions.d.ts +18 -2
- package/dist/routes/skills.d.ts +6 -0
- package/dist/routes/slack-task-policy.d.ts +3 -0
- package/dist/routes/supergrok.d.ts +3 -0
- package/dist/routes/video-generation.d.ts +3 -0
- package/dist/sandbox/channel-a.d.ts +62 -2
- package/dist/sandbox/machines.d.ts +2 -2
- package/dist/sandbox/metrics-ingestion.d.ts +6 -1
- package/dist/sandbox/viewer.d.ts +7 -3
- package/dist/slack-reaction-files.d.ts +27 -0
- package/dist/temporal-schedule-cleanup.d.ts +26 -0
- package/dist/transcription/providers/xai-subscription.d.ts +8 -0
- package/dist/xai-realtime.d.ts +26 -0
- package/dist/xai-subscription-auth.d.ts +23 -0
- package/package.json +20 -14
- package/src/app.ts +604 -64
- package/src/auth/canonical-human-session-admission.ts +116 -0
- package/src/auth/managed-auth.ts +101 -0
- package/src/browser-auth-broker.ts +155 -0
- package/src/browser-controller-authority.ts +186 -0
- package/src/browser-network-route.ts +34 -0
- package/src/browser-state-authority.ts +236 -0
- package/src/codemode.ts +186 -0
- package/src/controller-data-plane.ts +35 -0
- package/src/editable-artifact-live-hints.ts +64 -0
- package/src/editable-artifact-native-kernel.ts +659 -0
- package/src/editable-artifact-office-import.ts +230 -0
- package/src/editable-artifact-production.ts +419 -0
- package/src/editable-artifact-websocket.ts +311 -0
- package/src/editable-artifact-workspace-files.ts +186 -0
- package/src/github-browser-flow.ts +35 -6
- package/src/http/auth.ts +29 -9
- package/src/http/cors.ts +3 -0
- package/src/http/sse.ts +229 -5
- package/src/index.ts +119 -20
- package/src/integrations/api-integrations.ts +365 -0
- package/src/integrations/atlassian.ts +1621 -0
- package/src/integrations/fiken.ts +1230 -0
- package/src/integrations/github-skill-source.ts +142 -0
- package/src/integrations/google-drive.ts +1005 -64
- package/src/integrations/oauth-client.ts +123 -33
- package/src/integrations/provider-oauth.ts +756 -0
- package/src/integrations/slack-bot.ts +669 -11
- package/src/integrations/slack-interactions.ts +2063 -93
- package/src/integrations/social-api.ts +11 -0
- package/src/interaction-holder-heartbeat.ts +95 -0
- package/src/interaction-metrics.ts +159 -0
- package/src/mcp/documents.ts +146 -6
- package/src/mcp/editable-artifact-query-schema.ts +236 -0
- package/src/mcp/editable-artifacts.ts +448 -0
- package/src/mcp/scheduled-task-view.ts +34 -0
- package/src/mcp/server.ts +1756 -355
- package/src/memory-slack-delivery.ts +209 -0
- package/src/model-catalog.ts +19 -6
- package/src/routes/api-integrations.ts +410 -0
- package/src/routes/browser-identities.ts +160 -0
- package/src/routes/browser-sessions.ts +4482 -0
- package/src/routes/canonical-human-identities.ts +156 -0
- package/src/routes/channels.ts +90 -0
- package/src/routes/company-profile.ts +255 -0
- package/src/routes/computer-sessions.ts +1602 -0
- package/src/routes/connections.ts +421 -99
- package/src/routes/documents.ts +22 -3
- package/src/routes/editable-artifacts.ts +1159 -0
- package/src/routes/files.ts +106 -4
- package/src/routes/github.ts +18 -2
- package/src/routes/install.ts +7 -1
- package/src/routes/integration-facets.ts +258 -0
- package/src/routes/interaction-resources.ts +595 -0
- package/src/routes/memory-slack-publications.ts +216 -0
- package/src/routes/organization-memberships.ts +53 -0
- package/src/routes/packs.ts +437 -7
- package/src/routes/plugins.ts +752 -0
- package/src/routes/rigs.ts +77 -20
- package/src/routes/scheduled-tasks.ts +67 -40
- package/src/routes/sessions.ts +830 -278
- package/src/routes/skills.ts +256 -0
- package/src/routes/slack-task-policy.ts +115 -0
- package/src/routes/supergrok.ts +717 -0
- package/src/routes/transcription-recordings.ts +9 -2
- package/src/routes/transcriptions.ts +2 -1
- package/src/routes/video-generation.ts +162 -0
- package/src/routes/workspaces.ts +68 -28
- package/src/sandbox/channel-a.ts +750 -116
- package/src/sandbox/machines.ts +5 -5
- package/src/sandbox/metrics-ingestion.ts +121 -3
- package/src/sandbox/rematerialize.ts +35 -47
- package/src/sandbox/viewer.ts +39 -12
- package/src/slack-reaction-files.ts +181 -0
- package/src/temporal-schedule-cleanup.ts +135 -0
- package/src/transcription/providers/xai-subscription.ts +110 -0
- package/src/transcription/service.ts +17 -2
- package/src/xai-realtime.ts +216 -0
- package/src/xai-subscription-auth.ts +132 -0
- package/dist/chunk-T4T2PGU4.js.map +0 -1
- package/dist/mcp/toolspace.d.ts +0 -71
- package/src/mcp/toolspace.ts +0 -1190
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MemorySlackPublication,
|
|
3
|
+
MemorySlackPublicationActionRequest,
|
|
4
|
+
MemorySlackPublicationConfigurationResponse,
|
|
5
|
+
MemorySlackPublicationHistoryResponse,
|
|
6
|
+
SlackPublicationChannelListResponse,
|
|
7
|
+
UpdateMemorySlackPublicationConfigurationRequest,
|
|
8
|
+
type MemorySlackPublication as MemorySlackPublicationRecord,
|
|
9
|
+
} from "@opengeni/contracts";
|
|
10
|
+
import {
|
|
11
|
+
actOnMemorySlackPublication,
|
|
12
|
+
createMemorySlackPublicationConfiguration,
|
|
13
|
+
listMemorySlackPublicationConfigurations,
|
|
14
|
+
listMemorySlackPublications,
|
|
15
|
+
MemorySlackPublicationRevisionConflictError,
|
|
16
|
+
recordAuditEvent,
|
|
17
|
+
} from "@opengeni/db";
|
|
18
|
+
import {
|
|
19
|
+
openGeniSlackBotMetadata,
|
|
20
|
+
requireAccessGrant,
|
|
21
|
+
sanitizeSlackPublicationText,
|
|
22
|
+
validateOpenGeniSlackBotConnectionSelection,
|
|
23
|
+
type ApiRouteDeps,
|
|
24
|
+
} from "@opengeni/core";
|
|
25
|
+
import type { Hono } from "hono";
|
|
26
|
+
import { HTTPException } from "hono/http-exception";
|
|
27
|
+
import { createOpenGeniSlackBotInteractionClient } from "../integrations/slack-bot";
|
|
28
|
+
|
|
29
|
+
export function registerMemorySlackPublicationRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
30
|
+
const base = "/v1/workspaces/:workspaceId/memory-slack-publications";
|
|
31
|
+
|
|
32
|
+
app.get(`${base}/configuration`, async (c) => {
|
|
33
|
+
const workspaceId = c.req.param("workspaceId");
|
|
34
|
+
await requireAccessGrant(c, deps, workspaceId, "workspace:read");
|
|
35
|
+
const history = await listMemorySlackPublicationConfigurations(deps.db, workspaceId, 25);
|
|
36
|
+
c.header("cache-control", "private, no-store");
|
|
37
|
+
return c.json(
|
|
38
|
+
MemorySlackPublicationConfigurationResponse.parse({
|
|
39
|
+
current: history[0] ?? null,
|
|
40
|
+
history,
|
|
41
|
+
}),
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
app.put(`${base}/configuration`, async (c) => {
|
|
46
|
+
const workspaceId = c.req.param("workspaceId");
|
|
47
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
|
|
48
|
+
const payload = UpdateMemorySlackPublicationConfigurationRequest.parse(await c.req.json());
|
|
49
|
+
let slackTeamId: string | null = null;
|
|
50
|
+
let channelName = payload.slackChannelName;
|
|
51
|
+
if (payload.connectionId || payload.slackChannelId) {
|
|
52
|
+
if (!payload.connectionId || !payload.slackChannelId) {
|
|
53
|
+
throw new HTTPException(400, {
|
|
54
|
+
message: "connectionId and slackChannelId must be configured together",
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const connection = await validateOpenGeniSlackBotConnectionSelection(
|
|
58
|
+
deps.db,
|
|
59
|
+
grant,
|
|
60
|
+
workspaceId,
|
|
61
|
+
payload.connectionId,
|
|
62
|
+
);
|
|
63
|
+
const metadata = openGeniSlackBotMetadata(connection.metadata);
|
|
64
|
+
if (!metadata) {
|
|
65
|
+
throw new HTTPException(422, { message: "Slack bot installation metadata is invalid" });
|
|
66
|
+
}
|
|
67
|
+
const client = await createOpenGeniSlackBotInteractionClient(deps, {
|
|
68
|
+
accountId: grant.accountId,
|
|
69
|
+
workspaceId,
|
|
70
|
+
connectionId: connection.id,
|
|
71
|
+
subjectId: grant.subjectId,
|
|
72
|
+
});
|
|
73
|
+
const channel = await client.verifyChannelAccess(payload.slackChannelId);
|
|
74
|
+
if (
|
|
75
|
+
channel.isShared ||
|
|
76
|
+
channel.isExternallyShared ||
|
|
77
|
+
channel.isOrgShared ||
|
|
78
|
+
channel.isArchived
|
|
79
|
+
) {
|
|
80
|
+
throw new HTTPException(422, {
|
|
81
|
+
message: "Slack publication requires an active, non-shared bot-member channel",
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
slackTeamId = metadata.slackTeamId;
|
|
85
|
+
channelName = channel.name ?? payload.slackChannelName;
|
|
86
|
+
}
|
|
87
|
+
try {
|
|
88
|
+
const configuration = await createMemorySlackPublicationConfiguration(deps.db, {
|
|
89
|
+
accountId: grant.accountId,
|
|
90
|
+
workspaceId,
|
|
91
|
+
expectedRevision: payload.expectedRevision,
|
|
92
|
+
enabled: payload.enabled,
|
|
93
|
+
connectionId: payload.connectionId,
|
|
94
|
+
slackTeamId,
|
|
95
|
+
slackChannelId: payload.slackChannelId,
|
|
96
|
+
slackChannelName: channelName,
|
|
97
|
+
autoImportances: payload.autoImportances,
|
|
98
|
+
reviewImportances: payload.reviewImportances,
|
|
99
|
+
subjectId: grant.subjectId,
|
|
100
|
+
});
|
|
101
|
+
await recordAuditEvent(deps.db, {
|
|
102
|
+
accountId: grant.accountId,
|
|
103
|
+
workspaceId,
|
|
104
|
+
subjectId: grant.subjectId,
|
|
105
|
+
action: "memory_slack_publication.configuration.created",
|
|
106
|
+
targetType: "memory_slack_publication_configuration",
|
|
107
|
+
targetId: configuration.id,
|
|
108
|
+
metadata: {
|
|
109
|
+
revision: configuration.revision,
|
|
110
|
+
enabled: configuration.enabled,
|
|
111
|
+
connectionId: configuration.connectionId,
|
|
112
|
+
slackTeamId: configuration.slackTeamId,
|
|
113
|
+
slackChannelId: configuration.slackChannelId,
|
|
114
|
+
autoImportances: configuration.autoImportances,
|
|
115
|
+
reviewImportances: configuration.reviewImportances,
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
return c.json(configuration);
|
|
119
|
+
} catch (error) {
|
|
120
|
+
if (error instanceof MemorySlackPublicationRevisionConflictError) {
|
|
121
|
+
throw new HTTPException(409, {
|
|
122
|
+
message: `configuration revision conflict; current revision is ${error.currentRevision}`,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
app.get(`${base}/channels`, async (c) => {
|
|
130
|
+
const workspaceId = c.req.param("workspaceId");
|
|
131
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
|
|
132
|
+
const connectionId = c.req.query("connectionId");
|
|
133
|
+
if (!connectionId) throw new HTTPException(400, { message: "connectionId is required" });
|
|
134
|
+
await validateOpenGeniSlackBotConnectionSelection(deps.db, grant, workspaceId, connectionId);
|
|
135
|
+
const client = await createOpenGeniSlackBotInteractionClient(deps, {
|
|
136
|
+
accountId: grant.accountId,
|
|
137
|
+
workspaceId,
|
|
138
|
+
connectionId,
|
|
139
|
+
subjectId: grant.subjectId,
|
|
140
|
+
});
|
|
141
|
+
const result = await client.listChannels({
|
|
142
|
+
limit: 200,
|
|
143
|
+
...(c.req.query("cursor") ? { cursor: c.req.query("cursor")! } : {}),
|
|
144
|
+
});
|
|
145
|
+
return c.json(
|
|
146
|
+
SlackPublicationChannelListResponse.parse({
|
|
147
|
+
channels: result.channels
|
|
148
|
+
.filter(
|
|
149
|
+
(channel) =>
|
|
150
|
+
channel.isMember &&
|
|
151
|
+
!channel.isArchived &&
|
|
152
|
+
!channel.isShared &&
|
|
153
|
+
!channel.isExternallyShared &&
|
|
154
|
+
!channel.isOrgShared,
|
|
155
|
+
)
|
|
156
|
+
.map((channel) => ({
|
|
157
|
+
id: channel.id,
|
|
158
|
+
name: channel.name,
|
|
159
|
+
isPrivate: channel.isPrivate,
|
|
160
|
+
})),
|
|
161
|
+
nextCursor: result.nextCursor || null,
|
|
162
|
+
}),
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
app.get(base, async (c) => {
|
|
167
|
+
const workspaceId = c.req.param("workspaceId");
|
|
168
|
+
await requireAccessGrant(c, deps, workspaceId, "workspace:read");
|
|
169
|
+
const publications = await listMemorySlackPublications(deps.db, workspaceId, { limit: 50 });
|
|
170
|
+
c.header("cache-control", "private, no-store");
|
|
171
|
+
return c.json(
|
|
172
|
+
MemorySlackPublicationHistoryResponse.parse({
|
|
173
|
+
publications: publications.map(sanitizeMemorySlackPublicationHistory),
|
|
174
|
+
nextCursor: null,
|
|
175
|
+
}),
|
|
176
|
+
);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
app.post(`${base}/:publicationId/action`, async (c) => {
|
|
180
|
+
const workspaceId = c.req.param("workspaceId");
|
|
181
|
+
const grant = await requireAccessGrant(c, deps, workspaceId, "workspace:admin");
|
|
182
|
+
const payload = MemorySlackPublicationActionRequest.parse(await c.req.json());
|
|
183
|
+
const publication = await actOnMemorySlackPublication(deps.db, {
|
|
184
|
+
workspaceId,
|
|
185
|
+
publicationId: c.req.param("publicationId"),
|
|
186
|
+
expectedState: payload.expectedState,
|
|
187
|
+
action: payload.action,
|
|
188
|
+
subjectId: grant.subjectId,
|
|
189
|
+
});
|
|
190
|
+
if (!publication) {
|
|
191
|
+
throw new HTTPException(409, { message: "publication state changed or action is invalid" });
|
|
192
|
+
}
|
|
193
|
+
await recordAuditEvent(deps.db, {
|
|
194
|
+
accountId: grant.accountId,
|
|
195
|
+
workspaceId,
|
|
196
|
+
subjectId: grant.subjectId,
|
|
197
|
+
action: `memory_slack_publication.${payload.action}`,
|
|
198
|
+
targetType: "memory_slack_publication",
|
|
199
|
+
targetId: publication.id,
|
|
200
|
+
metadata: {
|
|
201
|
+
expectedState: payload.expectedState,
|
|
202
|
+
resultState: publication.state,
|
|
203
|
+
operationId: publication.receipts.at(-1)?.operationId ?? null,
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
return c.json(MemorySlackPublication.parse(sanitizeMemorySlackPublicationHistory(publication)));
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** Defensively protects legacy rows without rewriting their durable projection. */
|
|
211
|
+
export function sanitizeMemorySlackPublicationHistory(
|
|
212
|
+
publication: MemorySlackPublicationRecord,
|
|
213
|
+
): MemorySlackPublicationRecord {
|
|
214
|
+
const summary = sanitizeSlackPublicationText(publication.summary);
|
|
215
|
+
return summary === publication.summary ? publication : { ...publication, summary };
|
|
216
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { ListManagedOrganizationMembershipsResponse } from "@opengeni/contracts";
|
|
2
|
+
import { getManagedSession, type ApiRouteDeps } from "@opengeni/core";
|
|
3
|
+
import {
|
|
4
|
+
ensureManagedAccessForUserWithOrganizationMemberships,
|
|
5
|
+
nestedPostgresSqlState,
|
|
6
|
+
} from "@opengeni/db";
|
|
7
|
+
import type { Hono } from "hono";
|
|
8
|
+
import { HTTPException } from "hono/http-exception";
|
|
9
|
+
|
|
10
|
+
export function registerOrganizationMembershipRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
11
|
+
app.get("/v1/organization-memberships", async (context) => {
|
|
12
|
+
if (
|
|
13
|
+
deps.settings.productAccessMode !== "managed" ||
|
|
14
|
+
!deps.managedAuth ||
|
|
15
|
+
!context.req.header("cookie") ||
|
|
16
|
+
context.req.header("authorization")
|
|
17
|
+
) {
|
|
18
|
+
throw new HTTPException(401, {
|
|
19
|
+
message: "managed human session required",
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const session = await getManagedSession(context, deps.managedAuth, {
|
|
24
|
+
db: deps.db,
|
|
25
|
+
});
|
|
26
|
+
if (!session?.user) {
|
|
27
|
+
throw new HTTPException(401, {
|
|
28
|
+
message: "managed human session required",
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let result;
|
|
33
|
+
try {
|
|
34
|
+
result = await ensureManagedAccessForUserWithOrganizationMemberships(deps.db, {
|
|
35
|
+
userId: session.user.id,
|
|
36
|
+
email: session.user.email,
|
|
37
|
+
name: session.user.name,
|
|
38
|
+
});
|
|
39
|
+
} catch (error) {
|
|
40
|
+
if (nestedPostgresSqlState(error) === "42501") {
|
|
41
|
+
throw new HTTPException(403, {
|
|
42
|
+
message: "organization membership is not active",
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
return context.json(
|
|
48
|
+
ListManagedOrganizationMembershipsResponse.parse({
|
|
49
|
+
memberships: result.organizationMemberships,
|
|
50
|
+
}),
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
}
|