@opengeni/api-router 0.30.3 → 2.2.0-canary.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/api-websocket.d.ts +18 -0
- package/dist/app.js +1 -1
- package/dist/auth/managed-auth.d.ts +6 -0
- package/dist/{chunk-WCXHI3FF.js → chunk-3TP54PPX.js} +26692 -15389
- package/dist/chunk-3TP54PPX.js.map +1 -0
- package/dist/codemode.d.ts +8 -1
- package/dist/company-brain-okf.d.ts +24 -0
- package/dist/connected-machine-computer-access.d.ts +11 -0
- package/dist/connection-authority-owner.d.ts +59 -0
- package/dist/connection-ownership.d.ts +47 -0
- package/dist/controller-data-plane.d.ts +16 -0
- package/dist/editable-artifact-websocket.d.ts +5 -15
- package/dist/editable-artifact-workspace-files.d.ts +1 -1
- package/dist/http/api-error.d.ts +10 -0
- package/dist/http/cors.d.ts +5 -0
- package/dist/http/interaction-control-error.d.ts +13 -0
- package/dist/http/sse.d.ts +2 -3
- package/dist/index.d.ts +5 -2
- package/dist/index.js +326 -82
- package/dist/index.js.map +1 -1
- package/dist/integrations/atlassian.d.ts +17 -0
- package/dist/integrations/fiken.d.ts +7 -2
- package/dist/integrations/google-drive.d.ts +18 -0
- package/dist/integrations/oauth-client.d.ts +22 -3
- package/dist/integrations/oauth-profiles.d.ts +195 -0
- package/dist/integrations/personal-github-repositories.d.ts +45 -0
- package/dist/integrations/personal-github.d.ts +40 -0
- package/dist/integrations/pr-review-provider.d.ts +22 -0
- package/dist/integrations/provider-oauth.d.ts +8 -0
- package/dist/integrations/slack-app-home.d.ts +24 -0
- package/dist/integrations/slack-bot.d.ts +157 -9
- package/dist/integrations/slack-interactions.d.ts +39 -5
- package/dist/integrations/slack-routing.d.ts +120 -0
- package/dist/integrations/social-oauth.d.ts +5 -0
- package/dist/interaction-frame-proxy.d.ts +68 -0
- package/dist/mcp/company-brain-governed-writes.d.ts +26 -0
- package/dist/mcp/company-profile-agent-admin.d.ts +44 -0
- package/dist/mcp/documents.d.ts +1 -0
- package/dist/mcp/remember.d.ts +28 -0
- package/dist/mcp/request-abort.d.ts +19 -0
- package/dist/mcp/scheduled-task-view.d.ts +4 -4
- package/dist/mcp/server.d.ts +15 -2
- package/dist/mcp/session-view.d.ts +4 -0
- package/dist/mcp/session-wait.d.ts +137 -0
- package/dist/routes/automations.d.ts +4 -0
- package/dist/routes/billing.d.ts +5 -0
- package/dist/routes/browser-sessions.d.ts +4 -1
- package/dist/routes/company-brain.d.ts +3 -0
- package/dist/routes/company-profile.d.ts +2 -1
- package/dist/routes/connection-authorities.d.ts +3 -0
- package/dist/routes/personal-github-git-broker.d.ts +29 -0
- package/dist/routes/personal-github.d.ts +3 -0
- package/dist/routes/pr-review.d.ts +3 -0
- package/dist/routes/sessions.d.ts +1 -0
- package/dist/routes/user-resource-authorities.d.ts +3 -0
- package/dist/routes/workspace-capture.d.ts +10 -2
- package/dist/routes/workspace-learning.d.ts +3 -0
- package/dist/routes/workspaces.d.ts +19 -0
- package/dist/sandbox/channel-a.d.ts +11 -1
- package/dist/sandbox/connection-authority.d.ts +3 -0
- package/dist/sandbox/enrollment.d.ts +2 -0
- package/dist/sandbox/machines.d.ts +2 -2
- package/dist/sandbox/metrics-ingestion.d.ts +10 -20
- package/dist/sandbox/viewer.d.ts +24 -1
- package/dist/sandbox-file-artifacts.d.ts +11 -0
- package/dist/scheduled-task-deletion.d.ts +14 -0
- package/dist/slack-reaction-files.d.ts +1 -1
- package/dist/temporal-schedule-cleanup.d.ts +1 -0
- package/package.json +20 -18
- package/src/api-websocket.ts +23 -0
- package/src/app.ts +161 -23
- package/src/auth/managed-auth.ts +25 -3
- package/src/codemode.ts +53 -23
- package/src/codex-realtime.ts +8 -2
- package/src/company-brain-okf.ts +340 -0
- package/src/connected-machine-computer-access.ts +33 -0
- package/src/connection-authority-owner.ts +61 -0
- package/src/connection-ownership.ts +180 -0
- package/src/controller-data-plane.ts +47 -0
- package/src/editable-artifact-native-kernel.ts +26 -15
- package/src/editable-artifact-office-import.ts +28 -3
- package/src/editable-artifact-production.ts +13 -7
- package/src/editable-artifact-websocket.ts +11 -18
- package/src/editable-artifact-workspace-files.ts +31 -6
- package/src/http/api-error.ts +28 -0
- package/src/http/auth.ts +4 -0
- package/src/http/cors.ts +35 -0
- package/src/http/interaction-control-error.ts +164 -0
- package/src/http/sse.ts +112 -66
- package/src/index.ts +46 -6
- package/src/integrations/atlassian.ts +146 -35
- package/src/integrations/fiken.ts +102 -22
- package/src/integrations/google-drive.ts +301 -92
- package/src/integrations/oauth-client.ts +272 -143
- package/src/integrations/oauth-profiles.ts +477 -0
- package/src/integrations/personal-github-repositories.ts +445 -0
- package/src/integrations/personal-github.ts +705 -0
- package/src/integrations/pr-review-provider.ts +246 -0
- package/src/integrations/provider-oauth.ts +121 -5
- package/src/integrations/slack-app-home.ts +300 -0
- package/src/integrations/slack-bot.ts +342 -57
- package/src/integrations/slack-interactions.ts +1898 -259
- package/src/integrations/slack-routing.ts +337 -0
- package/src/integrations/social-oauth.ts +25 -0
- package/src/interaction-frame-proxy.ts +409 -0
- package/src/mcp/company-brain-governed-writes.ts +262 -0
- package/src/mcp/company-profile-agent-admin.ts +205 -0
- package/src/mcp/documents.ts +37 -6
- package/src/mcp/files.ts +16 -1
- package/src/mcp/remember.ts +181 -0
- package/src/mcp/request-abort.ts +44 -0
- package/src/mcp/scheduled-task-view.ts +1 -0
- package/src/mcp/server.ts +719 -369
- package/src/mcp/session-view.ts +54 -0
- package/src/mcp/session-wait.ts +554 -0
- package/src/model-catalog.ts +20 -12
- package/src/routes/api-integrations.ts +4 -0
- package/src/routes/api-keys.ts +1 -0
- package/src/routes/automations.ts +534 -0
- package/src/routes/billing.ts +57 -1
- package/src/routes/browser-sessions.ts +329 -79
- package/src/routes/channels.ts +17 -1
- package/src/routes/codex.ts +50 -0
- package/src/routes/company-brain.ts +367 -0
- package/src/routes/company-profile.ts +1 -1
- package/src/routes/computer-sessions.ts +320 -93
- package/src/routes/connection-authorities.ts +139 -0
- package/src/routes/connections.ts +144 -34
- package/src/routes/documents.ts +353 -4
- package/src/routes/editable-artifacts.ts +11 -3
- package/src/routes/enrollments.ts +116 -26
- package/src/routes/environments.ts +127 -55
- package/src/routes/files.ts +72 -11
- package/src/routes/install.ts +82 -28
- package/src/routes/integration-facets.ts +29 -0
- package/src/routes/interaction-resources.ts +20 -2
- package/src/routes/machines.ts +275 -13
- package/src/routes/organization-memberships.ts +717 -28
- package/src/routes/packs.ts +4 -3
- package/src/routes/personal-github-git-broker.ts +785 -0
- package/src/routes/personal-github.ts +319 -0
- package/src/routes/pr-review.ts +531 -0
- package/src/routes/rigs.ts +104 -39
- package/src/routes/scheduled-tasks.ts +19 -21
- package/src/routes/sessions.ts +775 -38
- package/src/routes/social.ts +14 -2
- package/src/routes/supergrok.ts +23 -4
- package/src/routes/transcription-recordings.ts +8 -2
- package/src/routes/user-resource-authorities.ts +138 -0
- package/src/routes/workspace-artifacts.ts +4 -1
- package/src/routes/workspace-capture.ts +21 -0
- package/src/routes/workspace-learning.ts +228 -0
- package/src/routes/workspaces.ts +59 -6
- package/src/sandbox/auth-callout.ts +38 -12
- package/src/sandbox/channel-a.ts +242 -19
- package/src/sandbox/connection-authority.ts +3 -0
- package/src/sandbox/enrollment.ts +15 -3
- package/src/sandbox/machines.ts +186 -64
- package/src/sandbox/metrics-ingestion.ts +220 -58
- package/src/sandbox/viewer.ts +243 -19
- package/src/sandbox-file-artifacts.ts +329 -0
- package/src/scheduled-task-deletion.ts +127 -0
- package/src/slack-reaction-files.ts +16 -5
- package/src/temporal-schedule-cleanup.ts +13 -0
- package/dist/chunk-WCXHI3FF.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Settings } from "@opengeni/config";
|
|
2
|
-
import { OPENGENI_SLACK_BOT_CREDENTIAL_LABEL, OPENGENI_SLACK_BOT_CREDENTIAL_ROLE, type AccessGrant, type ConnectionMetadata, type OpenGeniSlackBotConnectionMetadata } from "@opengeni/contracts";
|
|
2
|
+
import { OPENGENI_SLACK_BOT_CREDENTIAL_LABEL, OPENGENI_SLACK_BOT_CREDENTIAL_ROLE, type AccessGrant, type ConnectionMetadata, type OpenGeniSlackBotDisplayName, type OpenGeniSlackBotConnectionMetadata } from "@opengeni/contracts";
|
|
3
3
|
import { type Database } from "@opengeni/db";
|
|
4
4
|
import { type FetchLike } from "@opengeni/network";
|
|
5
5
|
import { HTTPException } from "hono/http-exception";
|
|
@@ -34,12 +34,16 @@ export type DownloadedSlackReactionImage = Readonly<{
|
|
|
34
34
|
contentType: "image/png" | "image/jpeg" | "image/webp";
|
|
35
35
|
bytes: Uint8Array;
|
|
36
36
|
}>;
|
|
37
|
+
export type ExchangedOpenGeniSlackAuthorization = Readonly<{
|
|
38
|
+
accessToken: string;
|
|
39
|
+
appId: string;
|
|
40
|
+
}>;
|
|
37
41
|
export declare function exchangeOpenGeniSlackAuthorizationCode(input: {
|
|
38
42
|
code: string;
|
|
39
43
|
clientId: string;
|
|
40
44
|
clientSecret: string;
|
|
41
45
|
redirectUri: string;
|
|
42
|
-
}, fetchImpl?: FetchLike): Promise<
|
|
46
|
+
}, fetchImpl?: FetchLike): Promise<ExchangedOpenGeniSlackAuthorization>;
|
|
43
47
|
export type SlackBotReceipt = {
|
|
44
48
|
credentialRole: typeof OPENGENI_SLACK_BOT_CREDENTIAL_ROLE;
|
|
45
49
|
credentialLabel: typeof OPENGENI_SLACK_BOT_CREDENTIAL_LABEL;
|
|
@@ -71,10 +75,69 @@ export type SlackMessageBlock = {
|
|
|
71
75
|
};
|
|
72
76
|
style?: "primary" | "danger";
|
|
73
77
|
}>;
|
|
78
|
+
} | {
|
|
79
|
+
type: "context";
|
|
80
|
+
block_id?: string;
|
|
81
|
+
elements: Array<{
|
|
82
|
+
type: "mrkdwn" | "plain_text";
|
|
83
|
+
text: string;
|
|
84
|
+
emoji?: boolean;
|
|
85
|
+
}>;
|
|
74
86
|
} | {
|
|
75
87
|
type: "divider";
|
|
76
88
|
};
|
|
77
|
-
type
|
|
89
|
+
export type SlackHomeBlock = {
|
|
90
|
+
type: "header";
|
|
91
|
+
block_id?: string;
|
|
92
|
+
text: {
|
|
93
|
+
type: "plain_text";
|
|
94
|
+
text: string;
|
|
95
|
+
emoji?: boolean;
|
|
96
|
+
};
|
|
97
|
+
} | {
|
|
98
|
+
type: "section";
|
|
99
|
+
block_id?: string;
|
|
100
|
+
text: {
|
|
101
|
+
type: "mrkdwn" | "plain_text";
|
|
102
|
+
text: string;
|
|
103
|
+
emoji?: boolean;
|
|
104
|
+
};
|
|
105
|
+
accessory?: {
|
|
106
|
+
type: "button";
|
|
107
|
+
action_id: string;
|
|
108
|
+
text: {
|
|
109
|
+
type: "plain_text";
|
|
110
|
+
text: string;
|
|
111
|
+
emoji?: boolean;
|
|
112
|
+
};
|
|
113
|
+
url: string;
|
|
114
|
+
};
|
|
115
|
+
} | {
|
|
116
|
+
type: "context";
|
|
117
|
+
block_id?: string;
|
|
118
|
+
elements: Array<{
|
|
119
|
+
type: "mrkdwn" | "plain_text";
|
|
120
|
+
text: string;
|
|
121
|
+
emoji?: boolean;
|
|
122
|
+
}>;
|
|
123
|
+
} | {
|
|
124
|
+
type: "actions";
|
|
125
|
+
block_id: string;
|
|
126
|
+
elements: Array<{
|
|
127
|
+
type: "button";
|
|
128
|
+
action_id: string;
|
|
129
|
+
text: {
|
|
130
|
+
type: "plain_text";
|
|
131
|
+
text: string;
|
|
132
|
+
emoji?: boolean;
|
|
133
|
+
};
|
|
134
|
+
url: string;
|
|
135
|
+
style?: "primary" | "danger";
|
|
136
|
+
}>;
|
|
137
|
+
} | {
|
|
138
|
+
type: "divider";
|
|
139
|
+
};
|
|
140
|
+
type SlackBotOperation = "channels.list" | "search.context" | "channel_history.read" | "thread_replies.read" | "users.list" | "files.list" | "file.info" | "file.content.read" | "home.publish" | "message.post" | "message.update" | "message.delete";
|
|
78
141
|
type SlackBotContext = {
|
|
79
142
|
accountId: string;
|
|
80
143
|
workspaceId: string;
|
|
@@ -82,6 +145,7 @@ type SlackBotContext = {
|
|
|
82
145
|
sessionId?: string | null;
|
|
83
146
|
scheduledTaskId?: string | null;
|
|
84
147
|
};
|
|
148
|
+
type SlackProviderAuthorization = () => Promise<boolean | void>;
|
|
85
149
|
export type SlackReactionContextCheckpointBinding = {
|
|
86
150
|
inboxId: string;
|
|
87
151
|
accountId: string;
|
|
@@ -125,6 +189,14 @@ export declare class SlackBotProviderError extends Error {
|
|
|
125
189
|
readonly retryAfterMs: number | null;
|
|
126
190
|
constructor(code: string, retryAfterMs?: number | null);
|
|
127
191
|
}
|
|
192
|
+
export declare function authorizeSlackSharedImageRead(channel: {
|
|
193
|
+
isArchived: boolean;
|
|
194
|
+
isShared: boolean;
|
|
195
|
+
isExternallyShared: boolean;
|
|
196
|
+
isOrgShared: boolean;
|
|
197
|
+
isPendingExternallyShared: boolean;
|
|
198
|
+
isMpim: boolean;
|
|
199
|
+
}, authorizeSharedRead: (() => Promise<void>) | undefined): Promise<void>;
|
|
128
200
|
export type SlackBotCredentialVerificationFailureReason = "scope_mismatch" | "identity_mismatch";
|
|
129
201
|
export declare class SlackBotCredentialVerificationError extends HTTPException {
|
|
130
202
|
readonly failureReason: SlackBotCredentialVerificationFailureReason;
|
|
@@ -132,11 +204,14 @@ export declare class SlackBotCredentialVerificationError extends HTTPException {
|
|
|
132
204
|
}
|
|
133
205
|
/**
|
|
134
206
|
* Validates a write-only xoxb credential before it can enter encrypted storage.
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
207
|
+
* The OAuth exchange's app_id is the immutable app authority. Slack bot profile
|
|
208
|
+
* names are mutable presentation data and may lag manifest/App Home changes, so
|
|
209
|
+
* they must not decide whether a credential belongs to this installation.
|
|
138
210
|
*/
|
|
139
|
-
export declare function verifyOpenGeniSlackBotCredential(token: string,
|
|
211
|
+
export declare function verifyOpenGeniSlackBotCredential(token: string, expected: Readonly<{
|
|
212
|
+
appId: string;
|
|
213
|
+
displayName: OpenGeniSlackBotDisplayName;
|
|
214
|
+
}>, fetchImpl?: FetchLike, now?: Date): Promise<VerifiedOpenGeniSlackBot>;
|
|
140
215
|
export declare function resolveSlackBotConnectionForTool(input: {
|
|
141
216
|
db: Database;
|
|
142
217
|
grant: AccessGrant;
|
|
@@ -154,8 +229,9 @@ export declare class OpenGeniSlackBotClient {
|
|
|
154
229
|
private readonly metadata;
|
|
155
230
|
private readonly context;
|
|
156
231
|
private readonly fetchImpl;
|
|
232
|
+
private readonly authorizeProviderRequest?;
|
|
157
233
|
private readonly resolveCredential;
|
|
158
|
-
constructor(db: Database, settings: Settings, connection: ConnectionMetadata, metadata: OpenGeniSlackBotConnectionMetadata, context: SlackBotContext, fetchImpl?: FetchLike);
|
|
234
|
+
constructor(db: Database, settings: Settings, connection: ConnectionMetadata, metadata: OpenGeniSlackBotConnectionMetadata, context: SlackBotContext, fetchImpl?: FetchLike, authorizeProviderRequest?: SlackProviderAuthorization | undefined);
|
|
159
235
|
listChannels(input?: {
|
|
160
236
|
limit?: number;
|
|
161
237
|
cursor?: string;
|
|
@@ -202,6 +278,20 @@ export declare class OpenGeniSlackBotClient {
|
|
|
202
278
|
purpose: string;
|
|
203
279
|
numMembers: number | null;
|
|
204
280
|
}>;
|
|
281
|
+
/**
|
|
282
|
+
* Replace one Slack user's private App Home view. `views.publish` is a
|
|
283
|
+
* naturally convergent replace operation: Slack event retries may safely
|
|
284
|
+
* repeat the exact bounded view without creating duplicate provider state.
|
|
285
|
+
*/
|
|
286
|
+
publishHomeView(input: {
|
|
287
|
+
userId: string;
|
|
288
|
+
blocks: SlackHomeBlock[];
|
|
289
|
+
hash?: string | null;
|
|
290
|
+
}): Promise<{
|
|
291
|
+
viewId: string;
|
|
292
|
+
} & {
|
|
293
|
+
receipt: SlackBotReceipt;
|
|
294
|
+
}>;
|
|
205
295
|
slackTaskPolicyFacts(channelId: string, userId: string): Promise<({
|
|
206
296
|
conversation: {
|
|
207
297
|
id: string;
|
|
@@ -433,9 +523,10 @@ export declare class OpenGeniSlackBotClient {
|
|
|
433
523
|
name: string;
|
|
434
524
|
title: string;
|
|
435
525
|
}[];
|
|
526
|
+
authorizeSharedRead?: () => Promise<void>;
|
|
436
527
|
}): Promise<PreparedSlackReactionImage[]>;
|
|
437
528
|
/** Download and fully validate one previously authorized Slack image. */
|
|
438
|
-
downloadReactionImage(input: PreparedSlackReactionImage): Promise<DownloadedSlackReactionImage>;
|
|
529
|
+
downloadReactionImage(input: PreparedSlackReactionImage, authorizeSharedRead?: () => Promise<void>): Promise<DownloadedSlackReactionImage>;
|
|
439
530
|
listUsers(input?: {
|
|
440
531
|
limit?: number;
|
|
441
532
|
cursor?: string;
|
|
@@ -452,6 +543,61 @@ export declare class OpenGeniSlackBotClient {
|
|
|
452
543
|
} & {
|
|
453
544
|
receipt: SlackBotReceipt;
|
|
454
545
|
}>;
|
|
546
|
+
/**
|
|
547
|
+
* Workspace-wide public search through Slack's Real-time Search API
|
|
548
|
+
* (`assistant.search.context`) under the bot identity.
|
|
549
|
+
*
|
|
550
|
+
* The bot never carries private-search authority: `channel_types` is pinned
|
|
551
|
+
* to `public_channel` server-side regardless of caller input, so private
|
|
552
|
+
* channels, DMs, and MPIMs remain reachable only through a member's personal
|
|
553
|
+
* hosted-MCP grant. An install predating the search scopes fails closed with
|
|
554
|
+
* a reinstall hint instead of leaking Slack's `missing_scope` error.
|
|
555
|
+
*/
|
|
556
|
+
searchContext(input: {
|
|
557
|
+
query: string;
|
|
558
|
+
contentTypes?: readonly ("messages" | "files" | "channels")[];
|
|
559
|
+
includeBots?: boolean;
|
|
560
|
+
/** UNIX seconds bounds on message timestamps. */
|
|
561
|
+
before?: number;
|
|
562
|
+
after?: number;
|
|
563
|
+
sort?: "score" | "timestamp";
|
|
564
|
+
sortDir?: "asc" | "desc";
|
|
565
|
+
cursor?: string;
|
|
566
|
+
limit?: number;
|
|
567
|
+
}): Promise<{
|
|
568
|
+
messages: {
|
|
569
|
+
channelId: string;
|
|
570
|
+
channelName: string;
|
|
571
|
+
ts: string;
|
|
572
|
+
authorUserId: string;
|
|
573
|
+
authorName: string;
|
|
574
|
+
isAuthorBot: boolean;
|
|
575
|
+
content: string;
|
|
576
|
+
permalink: string | null;
|
|
577
|
+
}[];
|
|
578
|
+
files: {
|
|
579
|
+
id: string;
|
|
580
|
+
title: string;
|
|
581
|
+
filetype: string;
|
|
582
|
+
authorUserId: string;
|
|
583
|
+
authorName: string;
|
|
584
|
+
dateCreated: number | null;
|
|
585
|
+
dateUpdated: number | null;
|
|
586
|
+
content: string;
|
|
587
|
+
permalink: string | null;
|
|
588
|
+
}[];
|
|
589
|
+
channels: {
|
|
590
|
+
name: string;
|
|
591
|
+
topic: string;
|
|
592
|
+
purpose: string;
|
|
593
|
+
creatorUserId: string;
|
|
594
|
+
dateCreated: number | null;
|
|
595
|
+
permalink: string | null;
|
|
596
|
+
}[];
|
|
597
|
+
nextCursor: string | null;
|
|
598
|
+
} & {
|
|
599
|
+
receipt: SlackBotReceipt;
|
|
600
|
+
}>;
|
|
455
601
|
listFiles(input: {
|
|
456
602
|
channelId: string;
|
|
457
603
|
limit?: number;
|
|
@@ -641,11 +787,13 @@ export declare function createOpenGeniSlackBotClient(deps: {
|
|
|
641
787
|
db: Database;
|
|
642
788
|
settings: Settings;
|
|
643
789
|
slackFetch?: typeof fetch;
|
|
790
|
+
authorizeProviderRequest?: SlackProviderAuthorization;
|
|
644
791
|
}, resolved: Awaited<ReturnType<typeof resolveSlackBotConnectionForTool>>): OpenGeniSlackBotClient;
|
|
645
792
|
export declare function createOpenGeniSlackBotInteractionClient(deps: {
|
|
646
793
|
db: Database;
|
|
647
794
|
settings: Settings;
|
|
648
795
|
slackFetch?: typeof fetch;
|
|
796
|
+
authorizeProviderRequest?: SlackProviderAuthorization;
|
|
649
797
|
}, input: {
|
|
650
798
|
accountId: string;
|
|
651
799
|
workspaceId: string;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { type FileResourceRef, type WorkspaceSlackReactionSummonSettings } from "@opengeni/contracts";
|
|
2
|
-
import { type SlackInstallationRoute, type SlackInteractionInboxEntry, type SlackInteractionTriggerKind } from "@opengeni/db";
|
|
2
|
+
import { type SlackInstallationRoute, type SlackInteraction, type SlackInteractionInboxEntry, type SlackInteractionTriggerKind } from "@opengeni/db";
|
|
3
3
|
import { type ApiRouteDeps } from "@opengeni/core";
|
|
4
4
|
import type { Hono } from "hono";
|
|
5
|
-
import { type OpenGeniSlackBotClient } from "./slack-bot.js";
|
|
5
|
+
import { type OpenGeniSlackBotClient, type SlackMessageBlock } from "./slack-bot.js";
|
|
6
6
|
import { type ImportedSlackReactionImage } from "../slack-reaction-files.js";
|
|
7
7
|
export declare const SLACK_INTERACTION_MAX_BODY_BYTES: number;
|
|
8
8
|
export declare const SLACK_SIGNATURE_REPLAY_WINDOW_SECONDS = 300;
|
|
9
|
-
export declare const SLACK_DELIVERY_EVENT_TYPES: readonly ["agent.message.completed", "session.humanInput.requested", "session.requiresAction", "turn.completed", "turn.failed", "turn.cancelled", "session.status.changed"];
|
|
9
|
+
export declare const SLACK_DELIVERY_EVENT_TYPES: readonly ["agent.message.completed", "session.humanInput.requested", "session.requiresAction", "turn.completed", "turn.failed", "turn.cancelled", "session.status.changed", "system.update.pending", "goal.paused"];
|
|
10
10
|
/**
|
|
11
11
|
* Slack delivery restrictions are durable session-level authority, not
|
|
12
12
|
* attacker-adjacent user-message context. Migration 0240 backfills this exact
|
|
@@ -19,7 +19,7 @@ export declare const SLACK_SESSION_INSTRUCTIONS: string;
|
|
|
19
19
|
* selection at session creation while keeping Slack mutations out of the model
|
|
20
20
|
* surface; interaction delivery remains owned by the durable delivery pump.
|
|
21
21
|
*/
|
|
22
|
-
export declare const SLACK_TASK_FIRST_PARTY_MCP_TOOLS: ("artifacts_create" | "artifacts_get_source" | "artifacts_list" | "artifacts_publish" | "artifacts_rollback" | "atlassian_get" | "atlassian_search" | "atlassian_sources_list" | "browser_act" | "browser_auth" | "browser_clipboard" | "browser_debug" | "browser_identity" | "browser_lifecycle" | "browser_observe" | "browser_open" | "browser_publish" | "browser_tabs" | "capability_authorization_request" | "capability_catalog_search" | "computer_act" | "computer_clipboard" | "computer_lifecycle" | "computer_observe" | "computer_open" | "computer_targets" | "connected_machine_remove" | "editable_artifact_apply" | "editable_artifact_create" | "editable_artifact_export" | "editable_artifact_export_status" | "editable_artifact_get" | "editable_artifact_import" | "editable_artifact_inspect" | "editable_artifact_list" | "environment_list" | "environment_set_variable" | "fiken_bank_accounts_list" | "fiken_companies_list" | "fiken_contact_create" | "fiken_contacts_list" | "fiken_invoice_draft_create" | "fiken_invoice_get" | "fiken_invoices_list" | "fiken_products_list" | "fiken_purchases_list" | "fiken_sales_list" | "github_connect_link" | "github_repositories_list" | "goal_complete" | "goal_pause" | "goal_progress" | "goal_set" | "goal_update" | "interaction_discover" | "interaction_request_human" | "memory_correct" | "memory_save" | "memory_search" | "preference_registry_get" | "preference_registry_summary" | "reddit_accounts_list" | "reddit_mentions_live" | "reddit_post_reply" | "reddit_posts_sync" | "reddit_search_live" | "reddit_thread_fetch" | "rig_get" | "rig_list" | "rig_promote" | "rig_propose_change" | "rig_verify" | "run_on" | "sandbox_attach" | "sandbox_provision" | "sandbox_swap" | "sandboxes_list" | "scheduled_task_runs_list" | "scheduled_tasks_create" | "scheduled_tasks_delete" | "scheduled_tasks_get" | "scheduled_tasks_list" | "scheduled_tasks_pause" | "scheduled_tasks_resume" | "scheduled_tasks_trigger" | "scheduled_tasks_update" | "session_create" | "session_events" | "session_get" | "session_pause" | "session_resume" | "session_send_message" | "session_steer" | "sessions_list" | "set_other_session_title" | "set_session_title" | "slack_bot_channel_history" | "slack_bot_delete_message" | "slack_bot_file_content" | "slack_bot_file_info" | "slack_bot_list_channels" | "slack_bot_list_files" | "slack_bot_list_users" | "slack_bot_post_message" | "slack_bot_thread_replies" | "social_connections_list" | "social_daily_analysis_context" | "social_mentions_live" | "social_post_reply" | "social_posts_recent" | "social_posts_sync" | "social_search_live" | "social_thread_fetch" | "task_note_archive" | "task_note_save" | "task_notes_list" | "variable_set_get_variable" | "variable_set_list" | "variable_set_set_variable" | "x_accounts_list" | "x_mentions_live" | "x_post_reply" | "x_posts_sync" | "x_search_live" | "x_thread_fetch")[];
|
|
22
|
+
export declare const SLACK_TASK_FIRST_PARTY_MCP_TOOLS: ("artifacts_create" | "artifacts_get_source" | "artifacts_list" | "artifacts_publish" | "artifacts_rollback" | "atlassian_get" | "atlassian_search" | "atlassian_sources_list" | "browser_act" | "browser_auth" | "browser_clipboard" | "browser_debug" | "browser_identity" | "browser_lifecycle" | "browser_observe" | "browser_open" | "browser_publish" | "browser_tabs" | "capability_authorization_request" | "capability_catalog_search" | "company_profile_confirm" | "company_profile_propose" | "computer_act" | "computer_clipboard" | "computer_lifecycle" | "computer_observe" | "computer_open" | "computer_targets" | "connected_machine_remove" | "editable_artifact_apply" | "editable_artifact_create" | "editable_artifact_export" | "editable_artifact_export_status" | "editable_artifact_get" | "editable_artifact_import" | "editable_artifact_inspect" | "editable_artifact_list" | "environment_list" | "environment_set_variable" | "fiken_bank_accounts_list" | "fiken_companies_list" | "fiken_contact_create" | "fiken_contacts_list" | "fiken_invoice_draft_create" | "fiken_invoice_get" | "fiken_invoices_list" | "fiken_products_list" | "fiken_purchases_list" | "fiken_sales_list" | "github_connect_link" | "github_repositories_list" | "goal_complete" | "goal_pause" | "goal_progress" | "goal_set" | "goal_update" | "goal_wait" | "instruction_policy_propose" | "interaction_discover" | "interaction_request_human" | "knowledge_correct" | "knowledge_propose" | "memory_correct" | "memory_save" | "memory_search" | "preference_propose" | "preference_registry_get" | "preference_registry_summary" | "reddit_accounts_list" | "reddit_mentions_live" | "reddit_post_reply" | "reddit_posts_sync" | "reddit_search_live" | "reddit_thread_fetch" | "remember" | "remember_confirm" | "rig_get" | "rig_list" | "rig_promote" | "rig_propose_change" | "rig_verify" | "run_on" | "sandbox_attach" | "sandbox_file_publish" | "sandbox_provision" | "sandbox_swap" | "sandboxes_list" | "scheduled_task_runs_list" | "scheduled_tasks_create" | "scheduled_tasks_delete" | "scheduled_tasks_get" | "scheduled_tasks_list" | "scheduled_tasks_pause" | "scheduled_tasks_resume" | "scheduled_tasks_trigger" | "scheduled_tasks_update" | "session_create" | "session_events" | "session_get" | "session_human_input_respond" | "session_pause" | "session_resume" | "session_send_message" | "session_steer" | "session_wait" | "sessions_list" | "set_other_session_title" | "set_session_title" | "slack_bot_channel_history" | "slack_bot_delete_message" | "slack_bot_file_content" | "slack_bot_file_info" | "slack_bot_list_channels" | "slack_bot_list_files" | "slack_bot_list_users" | "slack_bot_post_message" | "slack_bot_search" | "slack_bot_thread_replies" | "social_connections_list" | "social_daily_analysis_context" | "social_mentions_live" | "social_post_reply" | "social_posts_recent" | "social_posts_sync" | "social_search_live" | "social_thread_fetch" | "task_note_archive" | "task_note_promote_instruction_policy" | "task_note_promote_knowledge" | "task_note_promote_preference" | "task_note_replace" | "task_note_save" | "task_notes_list" | "variable_set_get_variable" | "variable_set_list" | "variable_set_set_variable" | "x_accounts_list" | "x_mentions_live" | "x_post_reply" | "x_posts_sync" | "x_search_live" | "x_thread_fetch")[];
|
|
23
23
|
export type NormalizedSlackInteraction = {
|
|
24
24
|
providerEventId: string;
|
|
25
25
|
providerMessageId: string;
|
|
@@ -53,12 +53,45 @@ export declare function startSlackInteractionPump(deps: ApiRouteDeps, options?:
|
|
|
53
53
|
intervalMs?: number;
|
|
54
54
|
maxPerTick?: number;
|
|
55
55
|
}): () => void;
|
|
56
|
+
/**
|
|
57
|
+
* Say where the work went, quietly.
|
|
58
|
+
*
|
|
59
|
+
* The line exists to stop work landing somewhere surprising, so it appears only
|
|
60
|
+
* when the routing decision was a genuine choice: a null label means routing is
|
|
61
|
+
* off, or the person had exactly one workspace anyway, and a constant footer on
|
|
62
|
+
* every message would be noise rather than information.
|
|
63
|
+
*
|
|
64
|
+
* The label is frozen on the interaction rather than looked up here, because a
|
|
65
|
+
* workspace rename between the original post and a reconciliation would make the
|
|
66
|
+
* post ledger's byte comparison raise.
|
|
67
|
+
*/
|
|
68
|
+
export declare function withWorkspaceLine(label: string | null, text: string, blocks?: SlackMessageBlock[]): {
|
|
69
|
+
text: string;
|
|
70
|
+
blocks?: SlackMessageBlock[];
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The post-ledger seed for one interaction's messages.
|
|
74
|
+
*
|
|
75
|
+
* The ledger binds one operation id to a digest over the rendered bytes, so
|
|
76
|
+
* adding the workspace line under an unchanged id would wedge every interaction
|
|
77
|
+
* with a claimed-but-unposted row. But bumping the id for interactions whose
|
|
78
|
+
* bytes did NOT change is not free either: their ledger rows become unreachable,
|
|
79
|
+
* so a repair or a cross-deploy retry posts a duplicate instead of finding the
|
|
80
|
+
* completed original, and an action handle still points at the old operation.
|
|
81
|
+
*
|
|
82
|
+
* Only a labelled interaction renders different bytes, and the label is written
|
|
83
|
+
* once at insert and never updated, so it is a stable discriminator. Version the
|
|
84
|
+
* id on the label rather than on the release: a labelled interaction can only
|
|
85
|
+
* have been created by an image that already renders the line, and every
|
|
86
|
+
* pre-existing and unlabelled interaction keeps its exact ledger identity.
|
|
87
|
+
*/
|
|
88
|
+
export declare function slackPostSeed(interaction: Pick<SlackInteraction, "routedWorkspaceLabel">, seed: string): string;
|
|
56
89
|
export type SlackInvocationMessageContext = {
|
|
57
90
|
messages: Awaited<ReturnType<OpenGeniSlackBotClient["threadReplies"]>>["messages"];
|
|
58
91
|
nextCursor: string | null;
|
|
59
92
|
kind: "thread" | "channel";
|
|
60
93
|
};
|
|
61
|
-
export declare function
|
|
94
|
+
export declare function slackInvocationModelContext(invocationTimestamp: string, context: SlackInvocationMessageContext): string;
|
|
62
95
|
type SlackReactionMessageContext = Awaited<ReturnType<OpenGeniSlackBotClient["reactionMessageContext"]>>;
|
|
63
96
|
type PreparedSlackReactionTask = Readonly<{
|
|
64
97
|
resources: FileResourceRef[];
|
|
@@ -69,6 +102,7 @@ type PreparedSlackReactionTask = Readonly<{
|
|
|
69
102
|
export declare function slackReactionTaskText(context: SlackReactionMessageContext, prepared?: PreparedSlackReactionTask): string;
|
|
70
103
|
export declare function slackDeliveryTextsCoalesce(left: string, right: string): boolean;
|
|
71
104
|
export declare function normalizedBlockActionInteraction(payload: Record<string, unknown>): NormalizedSlackInteraction;
|
|
105
|
+
export declare function isSlackInfoCommand(text: string): boolean;
|
|
72
106
|
type SlackUserLinkToken = {
|
|
73
107
|
workspaceId: string;
|
|
74
108
|
connectionId: string;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-channel and per-DM Slack workspace routing.
|
|
3
|
+
*
|
|
4
|
+
* Routing is decided BEFORE any agent runs, from durable facts only, so it can
|
|
5
|
+
* never be a model judgement. The resolver is pure with respect to the database
|
|
6
|
+
* reads it is handed: it returns a decision, and the caller persists and acts on
|
|
7
|
+
* it.
|
|
8
|
+
*
|
|
9
|
+
* Two rules are load-bearing and easy to break by accident:
|
|
10
|
+
*
|
|
11
|
+
* A mapped thread keeps the workspace it was created in, unconditionally,
|
|
12
|
+
* including after the channel has been re-pointed. Otherwise a live
|
|
13
|
+
* conversation would silently change tenants mid-thread.
|
|
14
|
+
*
|
|
15
|
+
* A subject who lacks access to the routed workspace is NEVER quietly served
|
|
16
|
+
* from another workspace they happen to belong to. Every failure is explicit
|
|
17
|
+
* and creates no session.
|
|
18
|
+
*/
|
|
19
|
+
import type { AccessGrant } from "@opengeni/contracts";
|
|
20
|
+
import type { SlackChannelRoute, SlackInteractionInboxEntry, SlackRoutableWorkspace, SlackUserDmRoute } from "@opengeni/db";
|
|
21
|
+
export type SlackRouteTenancy = {
|
|
22
|
+
accountId: string;
|
|
23
|
+
workspaceId: string;
|
|
24
|
+
};
|
|
25
|
+
export type SlackRouteResolution = (SlackRouteTenancy & {
|
|
26
|
+
kind: "resolved";
|
|
27
|
+
label: string | null;
|
|
28
|
+
source: "thread" | "prefix" | "channel" | "dm_route" | "dm_personal" | "sole_candidate" | "installation";
|
|
29
|
+
}) | {
|
|
30
|
+
kind: "ask";
|
|
31
|
+
candidates: readonly SlackRoutableWorkspace[];
|
|
32
|
+
} | {
|
|
33
|
+
kind: "denied";
|
|
34
|
+
reason: "no_access_to_named" | "no_access_to_route" | "no_candidates";
|
|
35
|
+
requested: string | null;
|
|
36
|
+
candidates: readonly SlackRoutableWorkspace[];
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* A Slack direct message to the bot, by any trigger that can carry one.
|
|
40
|
+
*
|
|
41
|
+
* `isDirectMessageShortcut` is deliberately narrower: it means "a message
|
|
42
|
+
* shortcut invoked inside a DM", which is a private-handoff concern. Routing
|
|
43
|
+
* cares about the broader question of whether this conversation is one human's
|
|
44
|
+
* private channel with the bot, which is also true of an ordinary `dm` event.
|
|
45
|
+
*/
|
|
46
|
+
export declare function isSlackDirectMessageConversation(entry: Pick<SlackInteractionInboxEntry, "triggerKind" | "slackChannelId">): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Split a leading bot mention off the message text.
|
|
49
|
+
*
|
|
50
|
+
* Slack delivers an `app_mention` with the mention still in the text
|
|
51
|
+
* (`<@U123> do the thing`), and OpenGeni stores it verbatim. The workspace
|
|
52
|
+
* prefix is only an override when it is the first thing the person typed, so it
|
|
53
|
+
* is parsed after the mention rather than at byte 0 of the raw text. Everything
|
|
54
|
+
* split off here is put back, so the message the model sees is unchanged apart
|
|
55
|
+
* from the addressing the person used to route it.
|
|
56
|
+
*/
|
|
57
|
+
export declare function splitSlackLeadingMention(text: string, botUserId: string | null): {
|
|
58
|
+
lead: string;
|
|
59
|
+
rest: string;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* The strict `in <workspace>: ...` override.
|
|
63
|
+
*
|
|
64
|
+
* Parsed only at byte 0, so ordinary prose that happens to contain the word
|
|
65
|
+
* cannot trigger it, and matched case-insensitively against the exact label of a
|
|
66
|
+
* workspace the subject can already start work in. A prefix that names nothing
|
|
67
|
+
* recognizable is NOT a suggestion that falls through: it is a refusal, because
|
|
68
|
+
* silently ignoring an explicit override is how a message lands somewhere the
|
|
69
|
+
* person did not intend.
|
|
70
|
+
*/
|
|
71
|
+
export declare function parseSlackWorkspacePrefix(text: string): {
|
|
72
|
+
requested: string;
|
|
73
|
+
remainder: string;
|
|
74
|
+
} | null;
|
|
75
|
+
export type SlackRouteInputs = {
|
|
76
|
+
/** The installation binding's tenancy. Always the fallback, never a silent one. */
|
|
77
|
+
home: SlackRouteTenancy;
|
|
78
|
+
entry: Pick<SlackInteractionInboxEntry, "triggerKind" | "slackChannelId" | "slackUserId" | "text">;
|
|
79
|
+
/**
|
|
80
|
+
* The tenancy of an interaction already mapped to this thread, if any. A
|
|
81
|
+
* mapped thread wins unconditionally.
|
|
82
|
+
*/
|
|
83
|
+
threadTenancy: SlackRouteTenancy | null;
|
|
84
|
+
channelRoute: SlackChannelRoute | null;
|
|
85
|
+
dmRoute: SlackUserDmRoute | null;
|
|
86
|
+
/** The subject's own personal workspace in the home organization, if any. */
|
|
87
|
+
personalWorkspaceId: string | null;
|
|
88
|
+
/** Workspaces this subject may actually start work in, ordered stably. */
|
|
89
|
+
candidates: readonly SlackRoutableWorkspace[];
|
|
90
|
+
/** The installation's bot user, so a mention does not hide the prefix. */
|
|
91
|
+
botUserId: string | null;
|
|
92
|
+
/** `OPENGENI_SLACK_WORKSPACE_ROUTING_ENABLED`. */
|
|
93
|
+
routingEnabled: boolean;
|
|
94
|
+
/** Whether the first-use picker exists yet. Until it does, ambiguity keeps home. */
|
|
95
|
+
askEnabled: boolean;
|
|
96
|
+
};
|
|
97
|
+
/**
|
|
98
|
+
* Decide which workspace this Slack message starts work in.
|
|
99
|
+
*
|
|
100
|
+
* First match wins, and the order is deliberate: continuity beats an explicit
|
|
101
|
+
* override beats configuration beats derivation beats asking.
|
|
102
|
+
*/
|
|
103
|
+
export declare function resolveSlackWorkspaceRoute(input: SlackRouteInputs): SlackRouteResolution;
|
|
104
|
+
/**
|
|
105
|
+
* The message text the model actually sees.
|
|
106
|
+
*
|
|
107
|
+
* A prefix override is addressing information, not part of the request, so it is
|
|
108
|
+
* stripped exactly once and only when it matched.
|
|
109
|
+
*/
|
|
110
|
+
export declare function slackRoutedRequestText(text: string, resolution: SlackRouteResolution, botUserId: string | null): string;
|
|
111
|
+
export type SlackRouteAuthorization = {
|
|
112
|
+
kind: "authorized";
|
|
113
|
+
grant: AccessGrant;
|
|
114
|
+
tenancy: SlackRouteTenancy;
|
|
115
|
+
label: string | null;
|
|
116
|
+
} | {
|
|
117
|
+
kind: "denied";
|
|
118
|
+
reason: "no_access_to_route";
|
|
119
|
+
tenancy: SlackRouteTenancy;
|
|
120
|
+
};
|
|
@@ -45,6 +45,11 @@ export type SocialOAuthStartContext = {
|
|
|
45
45
|
accountId: string;
|
|
46
46
|
workspaceId: string;
|
|
47
47
|
subjectId: string;
|
|
48
|
+
/**
|
|
49
|
+
* False for every principal that cannot own a personal Connection. Resolved
|
|
50
|
+
* by the route from the live authenticated principal, never inferred here.
|
|
51
|
+
*/
|
|
52
|
+
personalOwnershipAllowed: boolean;
|
|
48
53
|
requestUrl: string;
|
|
49
54
|
payload: SocialOAuthStartRequest;
|
|
50
55
|
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { ApiWebSocketConnection, ApiWebSocketLike, ApiWebSocketUpgradeServer } from "./api-websocket.js";
|
|
2
|
+
export declare const INTERACTION_FRAME_PROXY_PATH = "/v1/interaction/frame-proxy";
|
|
3
|
+
export declare const INTERACTION_FRAME_PROXY_PROTOCOL_PREFIX = "opengeni-frame-proxy.";
|
|
4
|
+
type ProxyGrant = Readonly<{
|
|
5
|
+
version: 1;
|
|
6
|
+
upstreamUrl: string;
|
|
7
|
+
upstreamProtocols: readonly string[];
|
|
8
|
+
responseProtocol: string;
|
|
9
|
+
origin: string | null;
|
|
10
|
+
expiresAt: number;
|
|
11
|
+
}>;
|
|
12
|
+
export type InteractionFrameProxyAttachment = Readonly<{
|
|
13
|
+
url: string;
|
|
14
|
+
protocols: readonly string[];
|
|
15
|
+
}>;
|
|
16
|
+
/** Docker boxes cannot carry browserd's WebSocket subprotocol grant to the
|
|
17
|
+
* viewer. Unsigned OpenSandbox Channel B still uses the lifecycle proxy, so
|
|
18
|
+
* it needs the same hatch. Signed URI-mode ingress keeps native subprotocols;
|
|
19
|
+
* `openSandboxInteractionFrameProxy` is an emergency override only. */
|
|
20
|
+
export declare function placementUsesInteractionFrameProxy(backend: string | null | undefined, options?: {
|
|
21
|
+
openSandboxSignedEndpoints?: boolean;
|
|
22
|
+
openSandboxInteractionFrameProxy?: boolean;
|
|
23
|
+
}): boolean;
|
|
24
|
+
/** Public origin the browser can open. TLS-terminating reverse proxies make
|
|
25
|
+
* `requestUrl` `http://127.0.0.1` / the API container; that would mint `ws://`
|
|
26
|
+
* and Chrome blocks it from an `https://` console. */
|
|
27
|
+
export declare function resolveInteractionFrameProxyRequestUrl(input: {
|
|
28
|
+
requestUrl: string;
|
|
29
|
+
publicBaseUrl?: string | undefined;
|
|
30
|
+
webBaseUrl?: string | undefined;
|
|
31
|
+
forwardedProto?: string | null | undefined;
|
|
32
|
+
forwardedHost?: string | null | undefined;
|
|
33
|
+
}): string;
|
|
34
|
+
export declare function createInteractionFrameProxyAttachment(input: {
|
|
35
|
+
requestUrl: string;
|
|
36
|
+
publicBaseUrl?: string | undefined;
|
|
37
|
+
webBaseUrl?: string | undefined;
|
|
38
|
+
forwardedProto?: string | null | undefined;
|
|
39
|
+
forwardedHost?: string | null | undefined;
|
|
40
|
+
rootSecret: string;
|
|
41
|
+
upstreamUrl: string;
|
|
42
|
+
upstreamProtocols: readonly string[];
|
|
43
|
+
origin: string | null;
|
|
44
|
+
expiresAt: string;
|
|
45
|
+
}): InteractionFrameProxyAttachment;
|
|
46
|
+
export declare class InteractionFrameProxyTransport {
|
|
47
|
+
private readonly rootSecret;
|
|
48
|
+
private readonly clock;
|
|
49
|
+
constructor(rootSecret: string | undefined, clock?: () => number);
|
|
50
|
+
handles(request: Request): boolean;
|
|
51
|
+
upgrade(request: Request, server: ApiWebSocketUpgradeServer): Response | undefined;
|
|
52
|
+
}
|
|
53
|
+
export declare class InteractionFrameProxyConnection implements ApiWebSocketConnection {
|
|
54
|
+
private readonly grant;
|
|
55
|
+
private socket;
|
|
56
|
+
private upstream;
|
|
57
|
+
private upstreamOpen;
|
|
58
|
+
private terminal;
|
|
59
|
+
private queued;
|
|
60
|
+
private queuedBytes;
|
|
61
|
+
constructor(grant: ProxyGrant);
|
|
62
|
+
attach(socket: ApiWebSocketLike): void;
|
|
63
|
+
receive(message: string | Uint8Array | ArrayBuffer): void;
|
|
64
|
+
transportClosed(): void;
|
|
65
|
+
private fail;
|
|
66
|
+
private clear;
|
|
67
|
+
}
|
|
68
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type CompanyBrainGovernedWriteAttempt } from "@opengeni/contracts";
|
|
2
|
+
import { createCompanyBrainLearningPolicyRouter } from "@opengeni/core";
|
|
3
|
+
import type { Database } from "@opengeni/db";
|
|
4
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
type JsonResult = (value: unknown) => {
|
|
6
|
+
content: {
|
|
7
|
+
type: "text";
|
|
8
|
+
text: string;
|
|
9
|
+
}[];
|
|
10
|
+
};
|
|
11
|
+
export type RegisterCompanyBrainGovernedWriteToolsInput = {
|
|
12
|
+
server: McpServer;
|
|
13
|
+
db: Database;
|
|
14
|
+
attempt: CompanyBrainGovernedWriteAttempt;
|
|
15
|
+
authorize: () => Promise<void>;
|
|
16
|
+
json: JsonResult;
|
|
17
|
+
router?: Pick<ReturnType<typeof createCompanyBrainLearningPolicyRouter>, "write">;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Register explicit proposal-only Company Brain tools. The signed host attempt
|
|
21
|
+
* owns tenant/session authority and the exact evidence id owns the learning
|
|
22
|
+
* policy source override. Tool input cannot select scope, active authority, or
|
|
23
|
+
* another policy source.
|
|
24
|
+
*/
|
|
25
|
+
export declare function registerCompanyBrainGovernedWriteTools(input: RegisterCompanyBrainGovernedWriteToolsInput): void;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type CompanyProfileAgentAttempt, type CompanyProfileEntry } from "@opengeni/contracts";
|
|
2
|
+
import { createCompanyProfileAgentAdminRouter } from "@opengeni/core";
|
|
3
|
+
import type { Database } from "@opengeni/db";
|
|
4
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import * as z from "zod/v4";
|
|
6
|
+
type JsonResult = (value: unknown) => {
|
|
7
|
+
content: {
|
|
8
|
+
type: "text";
|
|
9
|
+
text: string;
|
|
10
|
+
}[];
|
|
11
|
+
};
|
|
12
|
+
export type RegisterCompanyProfileAgentAdminToolsInput = {
|
|
13
|
+
server: McpServer;
|
|
14
|
+
db: Database;
|
|
15
|
+
attempt: CompanyProfileAgentAttempt;
|
|
16
|
+
authorize: () => Promise<void>;
|
|
17
|
+
json: JsonResult;
|
|
18
|
+
router?: Pick<ReturnType<typeof createCompanyProfileAgentAdminRouter>, "propose" | "confirm">;
|
|
19
|
+
};
|
|
20
|
+
declare const entry: z.ZodObject<{
|
|
21
|
+
key: z.ZodOptional<z.ZodString>;
|
|
22
|
+
content: z.ZodString;
|
|
23
|
+
}, z.core.$strip>;
|
|
24
|
+
type EntryInput = z.infer<typeof entry>;
|
|
25
|
+
/**
|
|
26
|
+
* Derive a stable key from entry content: the first few words, normalized into
|
|
27
|
+
* the company-profile key alphabet and bounded to the stable-key length.
|
|
28
|
+
*/
|
|
29
|
+
export declare function deriveCompanyProfileStableKey(content: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Resolve explicit or derived keys for one list and de-duplicate by suffixing
|
|
32
|
+
* `-2`, `-3`, ... so the profile passes the unique-key contract.
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveCompanyProfileEntries(input: readonly EntryInput[]): CompanyProfileEntry[];
|
|
35
|
+
/**
|
|
36
|
+
* Register the explicit owner-confirmed organization profile path. This is
|
|
37
|
+
* administration, not derived learning: workspace learning mode is never
|
|
38
|
+
* consulted, the initiating human must be the organization's active owner (the
|
|
39
|
+
* same authority as the manual `account:admin` route), and the proposal cannot
|
|
40
|
+
* become active without the exact bound human-input response returned by the
|
|
41
|
+
* first call.
|
|
42
|
+
*/
|
|
43
|
+
export declare function registerCompanyProfileAgentAdminTools(input: RegisterCompanyProfileAgentAdminToolsInput): void;
|
|
44
|
+
export {};
|
package/dist/mcp/documents.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { type Database } from "@opengeni/db";
|
|
|
3
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
4
|
export declare function buildDocumentsMcpServer(db: Database, accountId: string, workspaceId: string, documentServices: DocumentServices, options: {
|
|
5
5
|
createdBySessionId?: string | undefined;
|
|
6
|
+
attemptId?: string | undefined;
|
|
6
7
|
/** Immutable human subject whose agent is making this retrieval request. */
|
|
7
8
|
initiatingSubjectId: string;
|
|
8
9
|
}): McpServer;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type CompanyBrainGovernedWriteAttempt } from "@opengeni/contracts";
|
|
2
|
+
import { createRememberRouter } from "@opengeni/core";
|
|
3
|
+
import type { Database } from "@opengeni/db";
|
|
4
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
type JsonResult = (value: unknown) => {
|
|
6
|
+
content: {
|
|
7
|
+
type: "text";
|
|
8
|
+
text: string;
|
|
9
|
+
}[];
|
|
10
|
+
};
|
|
11
|
+
export type RegisterRememberToolsInput = {
|
|
12
|
+
server: McpServer;
|
|
13
|
+
db: Database;
|
|
14
|
+
attempt: CompanyBrainGovernedWriteAttempt;
|
|
15
|
+
authorize: () => Promise<void>;
|
|
16
|
+
json: JsonResult;
|
|
17
|
+
router?: Pick<ReturnType<typeof createRememberRouter>, "remember" | "confirm">;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Explicit user-directed remember. Content becomes exact task-note evidence,
|
|
21
|
+
* promotion runs through the frozen workspace learning policy, and activation
|
|
22
|
+
* is either automatic (preference under Automatic mode) or requires exactly one
|
|
23
|
+
* bound human confirmation through the built-in `request_human_input` tool.
|
|
24
|
+
* Tool input cannot select scope beyond the workspace, active authority, or
|
|
25
|
+
* another learning-policy source.
|
|
26
|
+
*/
|
|
27
|
+
export declare function registerRememberTools(input: RegisterRememberToolsInput): void;
|
|
28
|
+
export {};
|