@opengeni/api-router 0.16.5 → 0.20.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.js +1 -1
- package/dist/{chunk-FGNCK7HE.js → chunk-AEVD7E2F.js} +2579 -141
- package/dist/chunk-AEVD7E2F.js.map +1 -0
- package/dist/codex-realtime.d.ts +43 -0
- package/dist/gateway-realtime.d.ts +24 -0
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/integrations/google-drive.d.ts +16 -1
- package/dist/integrations/slack-bot.d.ts +122 -0
- package/dist/integrations/slack-interactions.d.ts +5 -0
- package/dist/mcp/documents.d.ts +3 -3
- package/dist/mcp/server.d.ts +1 -1
- package/dist/session-realtime-context.d.ts +19 -0
- package/dist/workspace-state-projection.d.ts +29 -1
- package/package.json +12 -12
- package/src/app.ts +33 -2
- package/src/codex-realtime.ts +371 -0
- package/src/gateway-realtime.ts +143 -0
- package/src/index.ts +3 -2
- package/src/integrations/google-drive.ts +399 -24
- package/src/integrations/slack-bot.ts +536 -0
- package/src/integrations/slack-interactions.ts +467 -2
- package/src/mcp/documents.ts +49 -27
- package/src/routes/connections.ts +63 -11
- package/src/routes/documents.ts +134 -43
- package/src/routes/sessions.ts +622 -11
- package/src/routes/workspace-instruction-policies.ts +22 -0
- package/src/routes/workspace-state.ts +46 -1
- package/src/routes/workspaces.ts +56 -1
- package/src/session-realtime-context.ts +134 -0
- package/src/workspace-state-projection.ts +203 -4
- package/dist/chunk-FGNCK7HE.js.map +0 -1
|
@@ -3,6 +3,7 @@ import { OPENGENI_SLACK_BOT_CREDENTIAL_LABEL, OPENGENI_SLACK_BOT_CREDENTIAL_ROLE
|
|
|
3
3
|
import { type Database } from "@opengeni/db";
|
|
4
4
|
import { type FetchLike } from "@opengeni/network";
|
|
5
5
|
import { HTTPException } from "hono/http-exception";
|
|
6
|
+
declare const SLACK_REACTION_CONTEXT_CHECKPOINT_VERSION = 1;
|
|
6
7
|
type SlackPayload = Record<string, unknown> & {
|
|
7
8
|
ok?: unknown;
|
|
8
9
|
error?: unknown;
|
|
@@ -42,6 +43,44 @@ type SlackBotContext = {
|
|
|
42
43
|
sessionId?: string | null;
|
|
43
44
|
scheduledTaskId?: string | null;
|
|
44
45
|
};
|
|
46
|
+
export type SlackReactionContextCheckpointBinding = {
|
|
47
|
+
inboxId: string;
|
|
48
|
+
accountId: string;
|
|
49
|
+
workspaceId: string;
|
|
50
|
+
connectionId: string;
|
|
51
|
+
providerEventId: string;
|
|
52
|
+
providerMessageId: string;
|
|
53
|
+
slackTeamId: string;
|
|
54
|
+
slackChannelId: string;
|
|
55
|
+
slackMessageTs: string;
|
|
56
|
+
};
|
|
57
|
+
type SlackReactionCheckpointMessage = {
|
|
58
|
+
timestamp: string;
|
|
59
|
+
userId: string;
|
|
60
|
+
botId: string;
|
|
61
|
+
threadTimestamp: string;
|
|
62
|
+
text: string;
|
|
63
|
+
files: Array<{
|
|
64
|
+
id: string;
|
|
65
|
+
label: string;
|
|
66
|
+
}>;
|
|
67
|
+
};
|
|
68
|
+
type SlackReactionContextCheckpointUnsigned = {
|
|
69
|
+
version: typeof SLACK_REACTION_CONTEXT_CHECKPOINT_VERSION;
|
|
70
|
+
binding: SlackReactionContextCheckpointBinding;
|
|
71
|
+
state: {
|
|
72
|
+
createdAtMs: number;
|
|
73
|
+
pageCount: number;
|
|
74
|
+
nextCursor: string;
|
|
75
|
+
seenCursors: string[];
|
|
76
|
+
seenMessageTimestamps: string[];
|
|
77
|
+
threadTimestamp: string | null;
|
|
78
|
+
messages: SlackReactionCheckpointMessage[];
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
export type SlackReactionContextCheckpoint = SlackReactionContextCheckpointUnsigned & {
|
|
82
|
+
signature: string;
|
|
83
|
+
};
|
|
45
84
|
export declare class SlackBotProviderError extends Error {
|
|
46
85
|
readonly code: string;
|
|
47
86
|
readonly retryAfterMs: number | null;
|
|
@@ -89,6 +128,9 @@ export declare class OpenGeniSlackBotClient {
|
|
|
89
128
|
isMember: boolean;
|
|
90
129
|
isDirectMessage: boolean;
|
|
91
130
|
isArchived: boolean;
|
|
131
|
+
isShared: boolean;
|
|
132
|
+
isExternallyShared: boolean;
|
|
133
|
+
isOrgShared: boolean;
|
|
92
134
|
topic: string;
|
|
93
135
|
purpose: string;
|
|
94
136
|
numMembers: number | null;
|
|
@@ -104,6 +146,9 @@ export declare class OpenGeniSlackBotClient {
|
|
|
104
146
|
isMember: boolean;
|
|
105
147
|
isDirectMessage: boolean;
|
|
106
148
|
isArchived: boolean;
|
|
149
|
+
isShared: boolean;
|
|
150
|
+
isExternallyShared: boolean;
|
|
151
|
+
isOrgShared: boolean;
|
|
107
152
|
topic: string;
|
|
108
153
|
purpose: string;
|
|
109
154
|
numMembers: number | null;
|
|
@@ -120,6 +165,9 @@ export declare class OpenGeniSlackBotClient {
|
|
|
120
165
|
isMember: boolean;
|
|
121
166
|
isDirectMessage: boolean;
|
|
122
167
|
isArchived: boolean;
|
|
168
|
+
isShared: boolean;
|
|
169
|
+
isExternallyShared: boolean;
|
|
170
|
+
isOrgShared: boolean;
|
|
123
171
|
topic: string;
|
|
124
172
|
purpose: string;
|
|
125
173
|
numMembers: number | null;
|
|
@@ -159,6 +207,9 @@ export declare class OpenGeniSlackBotClient {
|
|
|
159
207
|
isMember: boolean;
|
|
160
208
|
isDirectMessage: boolean;
|
|
161
209
|
isArchived: boolean;
|
|
210
|
+
isShared: boolean;
|
|
211
|
+
isExternallyShared: boolean;
|
|
212
|
+
isOrgShared: boolean;
|
|
162
213
|
topic: string;
|
|
163
214
|
purpose: string;
|
|
164
215
|
numMembers: number | null;
|
|
@@ -186,6 +237,68 @@ export declare class OpenGeniSlackBotClient {
|
|
|
186
237
|
} & {
|
|
187
238
|
receipt: SlackBotReceipt;
|
|
188
239
|
}>;
|
|
240
|
+
reactionMessageContext(input: {
|
|
241
|
+
channelId: string;
|
|
242
|
+
messageTimestamp: string;
|
|
243
|
+
checkpoint: unknown | null;
|
|
244
|
+
checkpointBinding: SlackReactionContextCheckpointBinding;
|
|
245
|
+
saveCheckpoint: (checkpoint: SlackReactionContextCheckpoint) => Promise<void>;
|
|
246
|
+
}): Promise<{
|
|
247
|
+
channel: {
|
|
248
|
+
id: string;
|
|
249
|
+
name: string;
|
|
250
|
+
isPrivate: boolean;
|
|
251
|
+
isMember: boolean;
|
|
252
|
+
isDirectMessage: boolean;
|
|
253
|
+
isArchived: boolean;
|
|
254
|
+
isShared: boolean;
|
|
255
|
+
isExternallyShared: boolean;
|
|
256
|
+
isOrgShared: boolean;
|
|
257
|
+
topic: string;
|
|
258
|
+
purpose: string;
|
|
259
|
+
numMembers: number | null;
|
|
260
|
+
};
|
|
261
|
+
threadTimestamp: string;
|
|
262
|
+
reactedMessage: {
|
|
263
|
+
timestamp: string;
|
|
264
|
+
userId: string;
|
|
265
|
+
botId: string;
|
|
266
|
+
threadTimestamp: string;
|
|
267
|
+
text: string;
|
|
268
|
+
files: {
|
|
269
|
+
id: string;
|
|
270
|
+
name: string;
|
|
271
|
+
title: string;
|
|
272
|
+
mimetype: string;
|
|
273
|
+
filetype: string;
|
|
274
|
+
mode: string;
|
|
275
|
+
size: number | null;
|
|
276
|
+
originatingHuddleId: string;
|
|
277
|
+
huddleTranscriptFileId: string;
|
|
278
|
+
}[];
|
|
279
|
+
};
|
|
280
|
+
messages: {
|
|
281
|
+
timestamp: string;
|
|
282
|
+
userId: string;
|
|
283
|
+
botId: string;
|
|
284
|
+
threadTimestamp: string;
|
|
285
|
+
text: string;
|
|
286
|
+
files: {
|
|
287
|
+
id: string;
|
|
288
|
+
name: string;
|
|
289
|
+
title: string;
|
|
290
|
+
mimetype: string;
|
|
291
|
+
filetype: string;
|
|
292
|
+
mode: string;
|
|
293
|
+
size: number | null;
|
|
294
|
+
originatingHuddleId: string;
|
|
295
|
+
huddleTranscriptFileId: string;
|
|
296
|
+
}[];
|
|
297
|
+
}[];
|
|
298
|
+
truncated: boolean;
|
|
299
|
+
} & {
|
|
300
|
+
receipt: SlackBotReceipt;
|
|
301
|
+
}>;
|
|
189
302
|
listUsers(input?: {
|
|
190
303
|
limit?: number;
|
|
191
304
|
cursor?: string;
|
|
@@ -214,6 +327,9 @@ export declare class OpenGeniSlackBotClient {
|
|
|
214
327
|
isMember: boolean;
|
|
215
328
|
isDirectMessage: boolean;
|
|
216
329
|
isArchived: boolean;
|
|
330
|
+
isShared: boolean;
|
|
331
|
+
isExternallyShared: boolean;
|
|
332
|
+
isOrgShared: boolean;
|
|
217
333
|
topic: string;
|
|
218
334
|
purpose: string;
|
|
219
335
|
numMembers: number | null;
|
|
@@ -245,6 +361,9 @@ export declare class OpenGeniSlackBotClient {
|
|
|
245
361
|
isMember: boolean;
|
|
246
362
|
isDirectMessage: boolean;
|
|
247
363
|
isArchived: boolean;
|
|
364
|
+
isShared: boolean;
|
|
365
|
+
isExternallyShared: boolean;
|
|
366
|
+
isOrgShared: boolean;
|
|
248
367
|
topic: string;
|
|
249
368
|
purpose: string;
|
|
250
369
|
numMembers: number | null;
|
|
@@ -276,6 +395,9 @@ export declare class OpenGeniSlackBotClient {
|
|
|
276
395
|
isMember: boolean;
|
|
277
396
|
isDirectMessage: boolean;
|
|
278
397
|
isArchived: boolean;
|
|
398
|
+
isShared: boolean;
|
|
399
|
+
isExternallyShared: boolean;
|
|
400
|
+
isOrgShared: boolean;
|
|
279
401
|
topic: string;
|
|
280
402
|
purpose: string;
|
|
281
403
|
numMembers: number | null;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { type WorkspaceSlackReactionSummonSettings } from "@opengeni/contracts";
|
|
1
2
|
import { type SlackInstallationRoute, type SlackInteractionInboxEntry, type SlackInteractionTriggerKind } from "@opengeni/db";
|
|
2
3
|
import { type ApiRouteDeps } from "@opengeni/core";
|
|
3
4
|
import type { Hono } from "hono";
|
|
5
|
+
import { type OpenGeniSlackBotClient } from "./slack-bot";
|
|
4
6
|
export declare const SLACK_INTERACTION_MAX_BODY_BYTES: number;
|
|
5
7
|
export declare const SLACK_SIGNATURE_REPLAY_WINDOW_SECONDS = 300;
|
|
6
8
|
export declare const SLACK_DELIVERY_EVENT_TYPES: readonly ["agent.message.completed", "session.humanInput.requested", "turn.completed", "turn.failed", "turn.cancelled", "session.status.changed"];
|
|
@@ -29,12 +31,15 @@ export declare function verifySlackRequestSignature(input: {
|
|
|
29
31
|
rawBody: string;
|
|
30
32
|
}, signingSecret: string, nowMs?: number): boolean;
|
|
31
33
|
export declare function slackEventInboxEntry(payload: unknown, bot: Pick<SlackInstallationRoute, "botId" | "botUserId">): NormalizedSlackInteraction | null;
|
|
34
|
+
export declare function slackReactionInboxEntry(payload: unknown, bot: Pick<SlackInstallationRoute, "botUserId">, settings: WorkspaceSlackReactionSummonSettings): NormalizedSlackInteraction | null;
|
|
32
35
|
export declare function registerSlackInteractionRoutes(app: Hono, deps: ApiRouteDeps): void;
|
|
33
36
|
export declare function drainSlackInteractionsOnce(deps: ApiRouteDeps): Promise<boolean>;
|
|
34
37
|
export declare function startSlackInteractionPump(deps: ApiRouteDeps, options?: {
|
|
35
38
|
intervalMs?: number;
|
|
36
39
|
maxPerTick?: number;
|
|
37
40
|
}): () => void;
|
|
41
|
+
type SlackReactionMessageContext = Awaited<ReturnType<OpenGeniSlackBotClient["reactionMessageContext"]>>;
|
|
42
|
+
export declare function slackReactionTaskText(context: SlackReactionMessageContext): string;
|
|
38
43
|
type SlackUserLinkToken = {
|
|
39
44
|
workspaceId: string;
|
|
40
45
|
connectionId: string;
|
package/dist/mcp/documents.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { type DocumentServices } from "@opengeni/documents";
|
|
2
2
|
import { type Database } from "@opengeni/db";
|
|
3
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
-
export declare function buildDocumentsMcpServer(db: Database, accountId: string, workspaceId: string, documentServices: DocumentServices, options
|
|
4
|
+
export declare function buildDocumentsMcpServer(db: Database, accountId: string, workspaceId: string, documentServices: DocumentServices, options: {
|
|
5
5
|
createdBySessionId?: string | undefined;
|
|
6
|
-
/**
|
|
7
|
-
|
|
6
|
+
/** Immutable human subject whose agent is making this retrieval request. */
|
|
7
|
+
initiatingSubjectId: string;
|
|
8
8
|
}): McpServer;
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -70,7 +70,7 @@ export declare function capSessionDiscoveryPage(page: Awaited<ReturnType<typeof
|
|
|
70
70
|
truncated: boolean;
|
|
71
71
|
};
|
|
72
72
|
latestMessage?: {
|
|
73
|
-
type: "agent.message.completed" | "agent.message.delta" | "agent.model.request" | "agent.model.usage" | "agent.reasoning.delta" | "agent.toolCall.created" | "agent.toolCall.output" | "agent.updated" | "artifact.created" | "codex.account.switched" | "codex.capacity.resumed" | "codex.capacity.superseded" | "codex.capacity.waiting" | "codex.credential.selected" | "codex.fleet.decision" | "credential.auth_needed" | "fs.changed" | "git.changed" | "goal.cleared" | "goal.completed" | "goal.continuation" | "goal.paused" | "goal.resumed" | "goal.set" | "goal.updated" | "machine.link.lost" | "machine.link.restored" | "machine.op.failed" | "machine.op.recovered" | "machine.runner.restarted" | "memory.corrected" | "memory.saved" | "recording.available" | "recording.failed" | "recording.started" | "rig.setup.completed" | "rig.setup.failed" | "rig.setup.skipped" | "rig.setup.started" | "sandbox.box.created" | "sandbox.box.lost" | "sandbox.box.snapshot" | "sandbox.box.terminated" | "sandbox.command.output.delta" | "sandbox.env.drift" | "sandbox.operation.completed" | "sandbox.operation.failed" | "sandbox.operation.started" | "session.context.cleared" | "session.context.compacted" | "session.context.compaction.requested" | "session.context.compaction.skipped" | "session.context.compaction.started" | "session.control.paused" | "session.control.resumed" | "session.control.steer_requested" | "session.created" | "session.event.envelope_omitted" | "session.humanInput.requested" | "session.mcp.approval_policy.updated" | "session.queue.changed" | "session.queue.history" | "session.queue.prompt.cancelled" | "session.requiresAction" | "session.route.reconciled" | "session.status.changed" | "session.title_set" | "session.tool_policy.updated" | "stream.closed" | "stream.opened" | "stream.revoked" | "stream.url.rotated" | "system.update.cancelled" | "system.update.delivered" | "system.update.pending" | "system.update.settled" | "system.update.superseded" | "terminal.pty.exited" | "terminal.pty.output.delta" | "terminal.pty.started" | "tool.auth_needed" | "turn.cancelled" | "turn.capacity_waiting" | "turn.completed" | "turn.event.rejected_late" | "turn.failed" | "turn.queued" | "turn.recovery.requested" | "turn.started" | "turn.superseded" | "user.approvalDecision" | "user.humanInputResponse" | "user.message" | "user.pause" | "workspace.inference.paused" | "workspace.inference.resumed" | "workspace.revision.captured" | "workspace.revision.degraded";
|
|
73
|
+
type: "agent.message.completed" | "agent.message.delta" | "agent.model.request" | "agent.model.usage" | "agent.reasoning.delta" | "agent.toolCall.created" | "agent.toolCall.output" | "agent.updated" | "artifact.created" | "codex.account.switched" | "codex.capacity.resumed" | "codex.capacity.superseded" | "codex.capacity.waiting" | "codex.credential.selected" | "codex.fleet.decision" | "credential.auth_needed" | "fs.changed" | "git.changed" | "goal.cleared" | "goal.completed" | "goal.continuation" | "goal.paused" | "goal.resumed" | "goal.set" | "goal.updated" | "machine.link.lost" | "machine.link.restored" | "machine.op.failed" | "machine.op.recovered" | "machine.runner.restarted" | "memory.corrected" | "memory.saved" | "recording.available" | "recording.failed" | "recording.started" | "rig.setup.completed" | "rig.setup.failed" | "rig.setup.skipped" | "rig.setup.started" | "sandbox.box.created" | "sandbox.box.lost" | "sandbox.box.snapshot" | "sandbox.box.terminated" | "sandbox.command.output.delta" | "sandbox.env.drift" | "sandbox.operation.completed" | "sandbox.operation.failed" | "sandbox.operation.started" | "session.context.cleared" | "session.context.compacted" | "session.context.compaction.requested" | "session.context.compaction.skipped" | "session.context.compaction.started" | "session.control.paused" | "session.control.resumed" | "session.control.steer_requested" | "session.created" | "session.event.envelope_omitted" | "session.humanInput.requested" | "session.mcp.approval_policy.updated" | "session.queue.changed" | "session.queue.history" | "session.queue.prompt.cancelled" | "session.realtime.ended" | "session.realtime.started" | "session.requiresAction" | "session.route.reconciled" | "session.status.changed" | "session.title_set" | "session.tool_policy.updated" | "stream.closed" | "stream.opened" | "stream.revoked" | "stream.url.rotated" | "system.update.cancelled" | "system.update.delivered" | "system.update.pending" | "system.update.settled" | "system.update.superseded" | "terminal.pty.exited" | "terminal.pty.output.delta" | "terminal.pty.started" | "tool.auth_needed" | "turn.cancelled" | "turn.capacity_waiting" | "turn.completed" | "turn.event.rejected_late" | "turn.failed" | "turn.queued" | "turn.recovery.requested" | "turn.started" | "turn.superseded" | "user.approvalDecision" | "user.humanInputResponse" | "user.message" | "user.pause" | "workspace.inference.paused" | "workspace.inference.resumed" | "workspace.revision.captured" | "workspace.revision.degraded";
|
|
74
74
|
preview: string | null;
|
|
75
75
|
previewTruncated: boolean;
|
|
76
76
|
} | null;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type CodexRealtimeInitialItem } from "@opengeni/codex";
|
|
2
|
+
export type SessionRealtimeHistoryRow = {
|
|
3
|
+
position: number;
|
|
4
|
+
item: Record<string, unknown>;
|
|
5
|
+
};
|
|
6
|
+
export type SessionRealtimeContinuityEntry = {
|
|
7
|
+
role: "user" | "assistant";
|
|
8
|
+
text: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Project ordinary model-facing conversation truth into Frameless V3 startup
|
|
12
|
+
* items. Only complete role-bearing messages are legal V3 initial items;
|
|
13
|
+
* reasoning, tool protocol records, images, and raw provider metadata are never
|
|
14
|
+
* copied into the browser-owned call bootstrap.
|
|
15
|
+
*
|
|
16
|
+
* The newest complete tail wins deterministically. This mirrors Codex's exact
|
|
17
|
+
* byte/4 token estimate and hard 128-item/8,192-token limits.
|
|
18
|
+
*/
|
|
19
|
+
export declare function projectSessionRealtimeInitialItems(rows: readonly SessionRealtimeHistoryRow[], continuityEntries?: readonly SessionRealtimeContinuityEntry[]): CodexRealtimeInitialItem[];
|
|
@@ -1,16 +1,44 @@
|
|
|
1
|
-
import { type WorkspaceInstructionPolicyListResponse, type WorkspaceStateResponse as WorkspaceStateResponseType } from "@opengeni/contracts";
|
|
1
|
+
import { type WorkspaceInstructionPolicyListResponse, type WorkspaceInstructionPolicySnapshot, type WorkspaceStateResponse as WorkspaceStateResponseType } from "@opengeni/contracts";
|
|
2
2
|
import type { WorkspaceStateMemoryRecord } from "@opengeni/db";
|
|
3
3
|
import type { DocumentInventory } from "@opengeni/documents";
|
|
4
4
|
type KnowledgeProjectionInput = {
|
|
5
5
|
documents: DocumentInventory;
|
|
6
6
|
memories: WorkspaceStateMemoryRecord[];
|
|
7
7
|
};
|
|
8
|
+
type PreferenceGovernanceIdentity = {
|
|
9
|
+
id: string;
|
|
10
|
+
revisionId: string;
|
|
11
|
+
contentHash: string;
|
|
12
|
+
activeVersion: number;
|
|
13
|
+
scope: "organization" | "workspace" | "user";
|
|
14
|
+
};
|
|
15
|
+
type AttemptGovernanceProjectionInput = {
|
|
16
|
+
status: "unavailable";
|
|
17
|
+
} | {
|
|
18
|
+
status: "available";
|
|
19
|
+
attemptId: string;
|
|
20
|
+
executionGeneration: number;
|
|
21
|
+
acceptedAt: string;
|
|
22
|
+
policySnapshot: WorkspaceInstructionPolicySnapshot | null;
|
|
23
|
+
preferenceSnapshot: {
|
|
24
|
+
id: string;
|
|
25
|
+
descriptorHash: string;
|
|
26
|
+
descriptors: PreferenceGovernanceIdentity[];
|
|
27
|
+
truncated: boolean;
|
|
28
|
+
createdAt: string;
|
|
29
|
+
} | null;
|
|
30
|
+
currentPreferences: {
|
|
31
|
+
descriptors: PreferenceGovernanceIdentity[];
|
|
32
|
+
truncated: boolean;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
8
35
|
export type WorkspaceStateProjectionInput = {
|
|
9
36
|
workspaceId: string;
|
|
10
37
|
generatedAt: string;
|
|
11
38
|
workspaceAgentInstructions: string | null;
|
|
12
39
|
policies: WorkspaceInstructionPolicyListResponse;
|
|
13
40
|
knowledge: KnowledgeProjectionInput | null;
|
|
41
|
+
attemptGovernance?: AttemptGovernanceProjectionInput | null;
|
|
14
42
|
};
|
|
15
43
|
export declare function projectWorkspaceState(input: WorkspaceStateProjectionInput): WorkspaceStateResponseType;
|
|
16
44
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/api-router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "OpenGeni HTTP surface: the Hono adapter/router (createApp), routes, MCP HTTP transport, and HTTP access adapters over @opengeni/core. An engine-distribution surface — its runtime closure includes engine-internal packages.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -43,18 +43,18 @@
|
|
|
43
43
|
"@hono/zod-validator": "^0.7.6",
|
|
44
44
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
45
45
|
"@opengeni/agent-proto": "^0.3.0",
|
|
46
|
-
"@opengeni/codex": "^0.2.
|
|
47
|
-
"@opengeni/config": "^0.10.
|
|
48
|
-
"@opengeni/contracts": "^0.
|
|
49
|
-
"@opengeni/core": "^0.
|
|
50
|
-
"@opengeni/db": "^0.
|
|
51
|
-
"@opengeni/documents": "^0.2
|
|
52
|
-
"@opengeni/events": "^0.3.
|
|
53
|
-
"@opengeni/github": "^0.4.
|
|
46
|
+
"@opengeni/codex": "^0.2.10",
|
|
47
|
+
"@opengeni/config": "^0.10.6",
|
|
48
|
+
"@opengeni/contracts": "^0.35.0",
|
|
49
|
+
"@opengeni/core": "^0.20.2",
|
|
50
|
+
"@opengeni/db": "^0.26.0",
|
|
51
|
+
"@opengeni/documents": "^0.3.2",
|
|
52
|
+
"@opengeni/events": "^0.3.65",
|
|
53
|
+
"@opengeni/github": "^0.4.22",
|
|
54
54
|
"@opengeni/network": "^0.1.1",
|
|
55
|
-
"@opengeni/observability": "^0.4.
|
|
56
|
-
"@opengeni/runtime": "^0.
|
|
57
|
-
"@opengeni/storage": "^0.2.
|
|
55
|
+
"@opengeni/observability": "^0.4.9",
|
|
56
|
+
"@opengeni/runtime": "^0.18.3",
|
|
57
|
+
"@opengeni/storage": "^0.2.59",
|
|
58
58
|
"@temporalio/client": "^1.17.0",
|
|
59
59
|
"better-auth": "^1.6.14",
|
|
60
60
|
"hono": "^4.12.18",
|
package/src/app.ts
CHANGED
|
@@ -18,10 +18,11 @@ import {
|
|
|
18
18
|
} from "@opengeni/contracts";
|
|
19
19
|
import {
|
|
20
20
|
createDocumentServices,
|
|
21
|
+
getDocument,
|
|
21
22
|
indexDocumentNow,
|
|
22
23
|
type DocumentServices,
|
|
23
24
|
} from "@opengeni/documents";
|
|
24
|
-
import { dbSql, getWorkspace } from "@opengeni/db";
|
|
25
|
+
import { dbSql, getWorkspace, rlsContextForWorkspace } from "@opengeni/db";
|
|
25
26
|
import { createObservability } from "@opengeni/observability";
|
|
26
27
|
import { createObjectStorage } from "@opengeni/storage";
|
|
27
28
|
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
@@ -127,17 +128,38 @@ export function createAppComposition(deps: AppDependencies): {
|
|
|
127
128
|
accountId,
|
|
128
129
|
workspaceId,
|
|
129
130
|
documentId,
|
|
131
|
+
authorityKind,
|
|
132
|
+
authorityWorkspaceId,
|
|
133
|
+
authoritySubjectId,
|
|
130
134
|
}: {
|
|
131
135
|
accountId: string;
|
|
132
136
|
workspaceId: string;
|
|
133
137
|
documentId: string;
|
|
138
|
+
authorityKind: import("@opengeni/contracts").DocumentAuthorityKind;
|
|
139
|
+
authorityWorkspaceId: string | null;
|
|
140
|
+
authoritySubjectId: string | null;
|
|
134
141
|
}) => {
|
|
135
142
|
if (!objectStorage) {
|
|
136
143
|
throw new HTTPException(503, {
|
|
137
144
|
message: "object storage is not configured",
|
|
138
145
|
});
|
|
139
146
|
}
|
|
140
|
-
|
|
147
|
+
const context = await rlsContextForWorkspace(deps.db, workspaceId);
|
|
148
|
+
if (context.accountId !== accountId) {
|
|
149
|
+
throw new Error("document account/workspace authority mismatch");
|
|
150
|
+
}
|
|
151
|
+
const claimedDocument = await getDocument(deps.db, workspaceId, documentId, {
|
|
152
|
+
viewerSubjectId: authoritySubjectId,
|
|
153
|
+
});
|
|
154
|
+
if (
|
|
155
|
+
!claimedDocument ||
|
|
156
|
+
claimedDocument.authorityKind !== authorityKind ||
|
|
157
|
+
claimedDocument.authorityWorkspaceId !== authorityWorkspaceId ||
|
|
158
|
+
claimedDocument.authoritySubjectId !== authoritySubjectId
|
|
159
|
+
) {
|
|
160
|
+
throw new Error("document authority changed before indexing");
|
|
161
|
+
}
|
|
162
|
+
const document = await indexDocumentNow(
|
|
141
163
|
deps.db,
|
|
142
164
|
objectStorage,
|
|
143
165
|
workspaceId,
|
|
@@ -153,7 +175,16 @@ export function createAppComposition(deps: AppDependencies): {
|
|
|
153
175
|
});
|
|
154
176
|
},
|
|
155
177
|
},
|
|
178
|
+
{ viewerSubjectId: authoritySubjectId },
|
|
156
179
|
);
|
|
180
|
+
if (
|
|
181
|
+
document.authorityKind !== authorityKind ||
|
|
182
|
+
document.authorityWorkspaceId !== authorityWorkspaceId ||
|
|
183
|
+
document.authoritySubjectId !== authoritySubjectId
|
|
184
|
+
) {
|
|
185
|
+
throw new Error("document authority changed before indexing");
|
|
186
|
+
}
|
|
187
|
+
return document;
|
|
157
188
|
},
|
|
158
189
|
};
|
|
159
190
|
// The API process's own agent-loop-free sandbox client — the API-direct
|