@opengeni/api-router 0.23.1 → 0.26.1

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 (107) hide show
  1. package/dist/app.d.ts +2 -2
  2. package/dist/app.js +1 -1
  3. package/dist/browser-controller-authority.d.ts +43 -0
  4. package/dist/browser-state-authority.d.ts +27 -0
  5. package/dist/{chunk-T4T2PGU4.js → chunk-JIKNR5YL.js} +26181 -14408
  6. package/dist/chunk-JIKNR5YL.js.map +1 -0
  7. package/dist/codemode.d.ts +23 -0
  8. package/dist/editable-artifact-live-hints.d.ts +11 -0
  9. package/dist/editable-artifact-native-kernel.d.ts +37 -0
  10. package/dist/editable-artifact-office-import.d.ts +22 -0
  11. package/dist/editable-artifact-production.d.ts +29 -0
  12. package/dist/editable-artifact-websocket.d.ts +49 -0
  13. package/dist/editable-artifact-workspace-files.d.ts +23 -0
  14. package/dist/github-browser-flow.d.ts +6 -0
  15. package/dist/http/cors.d.ts +1 -0
  16. package/dist/index.d.ts +3 -2
  17. package/dist/index.js +1796 -22
  18. package/dist/index.js.map +1 -1
  19. package/dist/integrations/api-integrations.d.ts +24 -0
  20. package/dist/integrations/atlassian.d.ts +176 -0
  21. package/dist/integrations/github-skill-source.d.ts +5 -0
  22. package/dist/integrations/google-drive.d.ts +85 -0
  23. package/dist/integrations/oauth-client.d.ts +22 -1
  24. package/dist/integrations/provider-oauth.d.ts +19 -0
  25. package/dist/integrations/slack-bot.d.ts +4 -0
  26. package/dist/integrations/slack-interactions.d.ts +8 -2
  27. package/dist/integrations/social-api.d.ts +2 -1
  28. package/dist/mcp/editable-artifact-query-schema.d.ts +4 -0
  29. package/dist/mcp/editable-artifacts.d.ts +13 -0
  30. package/dist/mcp/scheduled-task-view.d.ts +168 -0
  31. package/dist/mcp/server.d.ts +14 -3
  32. package/dist/memory-slack-delivery.d.ts +9 -0
  33. package/dist/routes/api-integrations.d.ts +8 -0
  34. package/dist/routes/browser-identities.d.ts +5 -0
  35. package/dist/routes/browser-sessions.d.ts +6 -0
  36. package/dist/routes/company-profile.d.ts +3 -0
  37. package/dist/routes/computer-sessions.d.ts +6 -0
  38. package/dist/routes/editable-artifacts.d.ts +44 -0
  39. package/dist/routes/integration-features.d.ts +3 -0
  40. package/dist/routes/memory-slack-publications.d.ts +6 -0
  41. package/dist/routes/plugins.d.ts +8 -0
  42. package/dist/routes/sessions.d.ts +17 -2
  43. package/dist/routes/skills.d.ts +6 -0
  44. package/dist/routes/video-generation.d.ts +3 -0
  45. package/dist/sandbox/channel-a.d.ts +55 -2
  46. package/dist/sandbox/metrics-ingestion.d.ts +6 -1
  47. package/dist/sandbox/viewer.d.ts +4 -2
  48. package/dist/temporal-schedule-cleanup.d.ts +26 -0
  49. package/package.json +19 -14
  50. package/src/app.ts +274 -37
  51. package/src/browser-controller-authority.ts +137 -0
  52. package/src/browser-state-authority.ts +236 -0
  53. package/src/codemode.ts +186 -0
  54. package/src/editable-artifact-live-hints.ts +64 -0
  55. package/src/editable-artifact-native-kernel.ts +659 -0
  56. package/src/editable-artifact-office-import.ts +230 -0
  57. package/src/editable-artifact-production.ts +419 -0
  58. package/src/editable-artifact-websocket.ts +311 -0
  59. package/src/editable-artifact-workspace-files.ts +186 -0
  60. package/src/github-browser-flow.ts +35 -6
  61. package/src/http/auth.ts +2 -0
  62. package/src/http/cors.ts +3 -0
  63. package/src/index.ts +119 -20
  64. package/src/integrations/api-integrations.ts +350 -0
  65. package/src/integrations/atlassian.ts +1621 -0
  66. package/src/integrations/github-skill-source.ts +142 -0
  67. package/src/integrations/google-drive.ts +1000 -64
  68. package/src/integrations/oauth-client.ts +123 -33
  69. package/src/integrations/provider-oauth.ts +777 -0
  70. package/src/integrations/slack-bot.ts +31 -2
  71. package/src/integrations/slack-interactions.ts +487 -27
  72. package/src/integrations/social-api.ts +11 -0
  73. package/src/mcp/documents.ts +32 -1
  74. package/src/mcp/editable-artifact-query-schema.ts +236 -0
  75. package/src/mcp/editable-artifacts.ts +448 -0
  76. package/src/mcp/scheduled-task-view.ts +34 -0
  77. package/src/mcp/server.ts +923 -145
  78. package/src/memory-slack-delivery.ts +209 -0
  79. package/src/routes/api-integrations.ts +407 -0
  80. package/src/routes/browser-identities.ts +136 -0
  81. package/src/routes/browser-sessions.ts +2543 -0
  82. package/src/routes/company-profile.ts +255 -0
  83. package/src/routes/computer-sessions.ts +1247 -0
  84. package/src/routes/connections.ts +284 -99
  85. package/src/routes/documents.ts +22 -3
  86. package/src/routes/editable-artifacts.ts +1159 -0
  87. package/src/routes/files.ts +106 -4
  88. package/src/routes/github.ts +18 -2
  89. package/src/routes/install.ts +7 -1
  90. package/src/routes/integration-features.ts +258 -0
  91. package/src/routes/memory-slack-publications.ts +216 -0
  92. package/src/routes/packs.ts +437 -7
  93. package/src/routes/plugins.ts +751 -0
  94. package/src/routes/rigs.ts +77 -20
  95. package/src/routes/scheduled-tasks.ts +67 -40
  96. package/src/routes/sessions.ts +421 -245
  97. package/src/routes/skills.ts +174 -0
  98. package/src/routes/video-generation.ts +132 -0
  99. package/src/routes/workspaces.ts +46 -24
  100. package/src/sandbox/channel-a.ts +723 -116
  101. package/src/sandbox/metrics-ingestion.ts +121 -3
  102. package/src/sandbox/rematerialize.ts +35 -47
  103. package/src/sandbox/viewer.ts +29 -9
  104. package/src/temporal-schedule-cleanup.ts +135 -0
  105. package/dist/chunk-T4T2PGU4.js.map +0 -1
  106. package/dist/mcp/toolspace.d.ts +0 -71
  107. package/src/mcp/toolspace.ts +0 -1190
@@ -0,0 +1,255 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import {
3
+ ActivateCompanyProfileRevisionRequest,
4
+ CompanyProfileConflictResponse,
5
+ CompanyProfileDiffRequest,
6
+ CompanyProfileDiffResponse,
7
+ CompanyProfileListQuery,
8
+ CompanyProfileListResponse,
9
+ CompanyProfileMutationResponse,
10
+ CompanyProfileOperationReuseResponse,
11
+ CompanyProfileRevision,
12
+ RollbackCompanyProfileRequest,
13
+ UpdateCompanyProfileRequest,
14
+ } from "@opengeni/contracts";
15
+ import {
16
+ requireAccessGrant,
17
+ requireAccessGrantAuthorization,
18
+ type AccessGrantAuthorization,
19
+ type ApiRouteDeps,
20
+ } from "@opengeni/core";
21
+ import {
22
+ activateCompanyProfileRevision,
23
+ CompanyProfileConflictError,
24
+ CompanyProfileInvalidOperationError,
25
+ CompanyProfileNotFoundError,
26
+ CompanyProfileOperationReuseError,
27
+ diffCompanyProfileRevisions,
28
+ getCompanyProfileRevision,
29
+ listCompanyProfile,
30
+ rollbackCompanyProfileRevision,
31
+ updateCompanyProfile,
32
+ } from "@opengeni/db";
33
+ import type { Context, Hono } from "hono";
34
+ import { HTTPException } from "hono/http-exception";
35
+ import { z } from "zod";
36
+
37
+ const RevisionId = z.string().uuid();
38
+
39
+ async function parseBody<S extends z.ZodType>(context: Context, schema: S): Promise<z.infer<S>> {
40
+ const parsed = schema.safeParse(await context.req.json().catch(() => null));
41
+ if (!parsed.success) throw new HTTPException(422, { message: "Invalid company-profile request" });
42
+ return parsed.data;
43
+ }
44
+
45
+ function requireDirectAccountAdmin(access: AccessGrantAuthorization): void {
46
+ const { grant } = access;
47
+ if (
48
+ !access.contextIntegrity ||
49
+ access.authenticatedSubjectId !== grant.subjectId ||
50
+ grant.principalKind !== "human_session" ||
51
+ grant.serviceInitiator ||
52
+ grant.serviceInitiatorContext ||
53
+ grant.subjectId.startsWith("api_key:")
54
+ ) {
55
+ throw new HTTPException(403, {
56
+ message: "Company-profile administration requires a direct human-authorized request",
57
+ });
58
+ }
59
+ if (!access.accountGrant?.permissions.includes("account:admin")) {
60
+ throw new HTTPException(403, { message: "missing permission: account:admin" });
61
+ }
62
+ }
63
+
64
+ function profileError(context: Context, error: unknown): Response {
65
+ if (error instanceof CompanyProfileConflictError) {
66
+ return context.json(
67
+ CompanyProfileConflictResponse.parse({
68
+ code: error.code,
69
+ message: error.message,
70
+ currentHead: error.currentHead,
71
+ }),
72
+ 409,
73
+ );
74
+ }
75
+ if (error instanceof CompanyProfileOperationReuseError) {
76
+ return context.json(
77
+ CompanyProfileOperationReuseResponse.parse({ code: error.code, message: error.message }),
78
+ 409,
79
+ );
80
+ }
81
+ if (error instanceof CompanyProfileNotFoundError) {
82
+ return context.json({ code: "COMPANY_PROFILE_NOT_FOUND", message: error.message }, 404);
83
+ }
84
+ if (error instanceof CompanyProfileInvalidOperationError) {
85
+ return context.json({ code: "INVALID_COMPANY_PROFILE_OPERATION", message: error.message }, 422);
86
+ }
87
+ throw error;
88
+ }
89
+
90
+ function revisionId(context: Context): string {
91
+ const parsed = RevisionId.safeParse(context.req.param("revisionId"));
92
+ if (!parsed.success)
93
+ throw new HTTPException(422, { message: "Invalid company-profile revision id" });
94
+ return parsed.data;
95
+ }
96
+
97
+ export function registerCompanyProfileRoutes(app: Hono, deps: ApiRouteDeps): void {
98
+ const base = "/v1/workspaces/:workspaceId/company-profile";
99
+
100
+ app.get(base, async (context) => {
101
+ const workspaceId = context.req.param("workspaceId");
102
+ const grant = await requireAccessGrant(context, deps, workspaceId, "workspace:read");
103
+ const query = CompanyProfileListQuery.safeParse({
104
+ afterRevision: context.req.query("afterRevision"),
105
+ limit: context.req.query("limit"),
106
+ });
107
+ if (!query.success) throw new HTTPException(422, { message: "Invalid company-profile query" });
108
+ return context.json(
109
+ CompanyProfileListResponse.parse(
110
+ await listCompanyProfile(deps.db, {
111
+ accountId: grant.accountId,
112
+ workspaceId,
113
+ limit: query.data.limit,
114
+ ...(query.data.afterRevision === undefined
115
+ ? {}
116
+ : { afterRevision: query.data.afterRevision }),
117
+ }),
118
+ ),
119
+ );
120
+ });
121
+
122
+ app.put(base, async (context) => {
123
+ const workspaceId = context.req.param("workspaceId");
124
+ const access = await requireAccessGrantAuthorization(
125
+ context,
126
+ deps,
127
+ workspaceId,
128
+ "workspace:read",
129
+ );
130
+ requireDirectAccountAdmin(access);
131
+ const request = await parseBody(context, UpdateCompanyProfileRequest);
132
+ try {
133
+ return context.json(
134
+ CompanyProfileMutationResponse.parse(
135
+ await updateCompanyProfile(deps.db, {
136
+ operationId: request.operationId ?? randomUUID(),
137
+ accountId: access.grant.accountId,
138
+ workspaceId,
139
+ profile: request.profile,
140
+ expectedCurrentRevisionId: request.expectedCurrentRevisionId,
141
+ expectedActivationVersion: request.expectedActivationVersion,
142
+ actorSubjectId: access.grant.subjectId,
143
+ principalKind: "human_session",
144
+ reason: request.reason,
145
+ }),
146
+ ),
147
+ );
148
+ } catch (error) {
149
+ return profileError(context, error);
150
+ }
151
+ });
152
+
153
+ app.get(`${base}/diff`, async (context) => {
154
+ const workspaceId = context.req.param("workspaceId");
155
+ const grant = await requireAccessGrant(context, deps, workspaceId, "workspace:read");
156
+ const request = CompanyProfileDiffRequest.safeParse({
157
+ fromRevisionId: context.req.query("fromRevisionId"),
158
+ toRevisionId: context.req.query("toRevisionId"),
159
+ });
160
+ if (!request.success) throw new HTTPException(422, { message: "Invalid company-profile diff" });
161
+ try {
162
+ return context.json(
163
+ CompanyProfileDiffResponse.parse(
164
+ await diffCompanyProfileRevisions(deps.db, {
165
+ accountId: grant.accountId,
166
+ workspaceId,
167
+ ...request.data,
168
+ }),
169
+ ),
170
+ );
171
+ } catch (error) {
172
+ return profileError(context, error);
173
+ }
174
+ });
175
+
176
+ app.post(`${base}/rollback`, async (context) => {
177
+ const workspaceId = context.req.param("workspaceId");
178
+ const access = await requireAccessGrantAuthorization(
179
+ context,
180
+ deps,
181
+ workspaceId,
182
+ "workspace:read",
183
+ );
184
+ requireDirectAccountAdmin(access);
185
+ const request = await parseBody(context, RollbackCompanyProfileRequest);
186
+ try {
187
+ return context.json(
188
+ CompanyProfileMutationResponse.parse(
189
+ await rollbackCompanyProfileRevision(deps.db, {
190
+ operationId: request.operationId ?? randomUUID(),
191
+ accountId: access.grant.accountId,
192
+ workspaceId,
193
+ targetRevisionId: request.targetRevisionId,
194
+ expectedCurrentRevisionId: request.expectedCurrentRevisionId,
195
+ expectedActivationVersion: request.expectedActivationVersion,
196
+ actorSubjectId: access.grant.subjectId,
197
+ principalKind: "human_session",
198
+ reason: request.reason,
199
+ }),
200
+ ),
201
+ );
202
+ } catch (error) {
203
+ return profileError(context, error);
204
+ }
205
+ });
206
+
207
+ app.get(`${base}/revisions/:revisionId`, async (context) => {
208
+ const workspaceId = context.req.param("workspaceId");
209
+ const grant = await requireAccessGrant(context, deps, workspaceId, "workspace:read");
210
+ try {
211
+ return context.json(
212
+ CompanyProfileRevision.parse(
213
+ await getCompanyProfileRevision(deps.db, {
214
+ accountId: grant.accountId,
215
+ workspaceId,
216
+ revisionId: revisionId(context),
217
+ }),
218
+ ),
219
+ );
220
+ } catch (error) {
221
+ return profileError(context, error);
222
+ }
223
+ });
224
+
225
+ app.post(`${base}/revisions/:revisionId/activate`, async (context) => {
226
+ const workspaceId = context.req.param("workspaceId");
227
+ const access = await requireAccessGrantAuthorization(
228
+ context,
229
+ deps,
230
+ workspaceId,
231
+ "workspace:read",
232
+ );
233
+ requireDirectAccountAdmin(access);
234
+ const request = await parseBody(context, ActivateCompanyProfileRevisionRequest);
235
+ try {
236
+ return context.json(
237
+ CompanyProfileMutationResponse.parse(
238
+ await activateCompanyProfileRevision(deps.db, {
239
+ operationId: request.operationId ?? randomUUID(),
240
+ accountId: access.grant.accountId,
241
+ workspaceId,
242
+ revisionId: revisionId(context),
243
+ expectedCurrentRevisionId: request.expectedCurrentRevisionId,
244
+ expectedActivationVersion: request.expectedActivationVersion,
245
+ actorSubjectId: access.grant.subjectId,
246
+ principalKind: "human_session",
247
+ reason: request.reason,
248
+ }),
249
+ ),
250
+ );
251
+ } catch (error) {
252
+ return profileError(context, error);
253
+ }
254
+ });
255
+ }