@opengeni/api-router 0.12.5 → 0.12.7

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 CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  validateToolRefs,
20
20
  withDefaultEnabledCapabilityMcpTools,
21
21
  workflowIdForSession
22
- } from "./chunk-3BHOMOSD.js";
22
+ } from "./chunk-SD5GJTZ4.js";
23
23
  export {
24
24
  API_MAX_REQUEST_BODY_BYTES,
25
25
  allowedCorsOrigin,
@@ -21,13 +21,13 @@ import {
21
21
  import { dbSql, getWorkspace as getWorkspace2 } from "@opengeni/db";
22
22
  import { createObservability } from "@opengeni/observability";
23
23
  import { createObjectStorage } from "@opengeni/storage";
24
- import { WebStandardStreamableHTTPServerTransport as WebStandardStreamableHTTPServerTransport2 } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
24
+ import { WebStandardStreamableHTTPServerTransport as WebStandardStreamableHTTPServerTransport3 } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
25
25
  import { Hono } from "hono";
26
26
  import { bodyLimit } from "hono/body-limit";
27
27
  import { cors } from "hono/cors";
28
28
  import { HTTPException as HTTPException26 } from "hono/http-exception";
29
29
  import {
30
- hasPermission as hasPermission9,
30
+ hasPermission as hasPermission10,
31
31
  requireAccessGrant as requireAccessGrant18,
32
32
  requirePermission,
33
33
  requireSessionAuthorization as requireSessionAuthorization3,
@@ -291,6 +291,8 @@ import { requireLimit as requireLimit8 } from "@opengeni/core";
291
291
  // src/mcp/server.ts
292
292
  import {
293
293
  CreateScheduledTaskRequest,
294
+ DEFAULT_FIRST_PARTY_MCP_TOOLS,
295
+ FIRST_PARTY_MCP_TOOL_NAMES,
294
296
  defaultRepositoryMountPath,
295
297
  SESSION_EVENT_RAW_DELTA_TYPES,
296
298
  SessionEventLatestClass,
@@ -335,7 +337,6 @@ import {
335
337
  MEMORY_CORRECT_TOOL_DESCRIPTION,
336
338
  MEMORY_SAVE_TOOL_DESCRIPTION,
337
339
  MEMORY_SEARCH_TOOL_DESCRIPTION,
338
- requireFile,
339
340
  requireScheduledTask,
340
341
  requireSession,
341
342
  saveWorkspaceMemory,
@@ -356,7 +357,9 @@ import {
356
357
  GitHubAppConfigurationError,
357
358
  githubAppMissingSettings
358
359
  } from "@opengeni/github";
359
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
360
+ import {
361
+ McpServer
362
+ } from "@modelcontextprotocol/sdk/server/mcp.js";
360
363
  import * as z4 from "zod/v4";
361
364
  import {
362
365
  hasPermission as hasPermission2,
@@ -2607,17 +2610,124 @@ function slackPostOutcomeMayBeAmbiguous(error) {
2607
2610
  }
2608
2611
 
2609
2612
  // src/mcp/server.ts
2613
+ var FIRST_PARTY_TOOL_AUTHORIZATION = {
2614
+ set_session_title: { sessionRequired: true, allOf: ["sessions:control"] },
2615
+ goal_set: { sessionRequired: true, allOf: ["goals:manage"] },
2616
+ goal_update: { sessionRequired: true, allOf: ["goals:manage"] },
2617
+ goal_complete: { sessionRequired: true, allOf: ["goals:manage"] },
2618
+ goal_pause: { sessionRequired: true, allOf: ["goals:manage"] },
2619
+ memory_search: { sessionRequired: true, allOf: ["documents:search"] },
2620
+ memory_save: { sessionRequired: true, allOf: ["documents:search"] },
2621
+ memory_correct: { sessionRequired: true, allOf: ["documents:search"] },
2622
+ sandboxes_list: { sessionRequired: true, allOf: ["sessions:read"] },
2623
+ sandbox_attach: { sessionRequired: true, allOf: ["sessions:control"] },
2624
+ sandbox_swap: { sessionRequired: true, allOf: ["sessions:control"] },
2625
+ run_on: { sessionRequired: true, allOf: ["sessions:control"] },
2626
+ sandbox_provision: { sessionRequired: true, allOf: ["sessions:control"] },
2627
+ rig_list: { allOf: ["rigs:use"] },
2628
+ rig_get: { allOf: ["rigs:use"] },
2629
+ rig_propose_change: { allOf: ["rigs:use"] },
2630
+ rig_verify: { allOf: ["rigs:use"] },
2631
+ rig_promote: { allOf: ["rigs:manage"] },
2632
+ sessions_list: { allOf: ["sessions:read"] },
2633
+ session_get: { allOf: ["sessions:read"] },
2634
+ session_events: { allOf: ["sessions:read"] },
2635
+ session_create: { allOf: ["sessions:create"] },
2636
+ session_send_message: { allOf: ["sessions:control"] },
2637
+ session_pause: { allOf: ["sessions:control"] },
2638
+ session_resume: { allOf: ["sessions:control"] },
2639
+ session_steer: { sessionRequired: true, allOf: ["sessions:control"] },
2640
+ set_other_session_title: { allOf: ["sessions:control"] },
2641
+ variable_set_list: { allOf: ["variable-sets:use"] },
2642
+ environment_list: { allOf: ["variable-sets:use"] },
2643
+ variable_set_set_variable: { allOf: ["variable-sets:manage"] },
2644
+ environment_set_variable: { allOf: ["variable-sets:manage"] },
2645
+ github_connect_link: { allOf: ["github:use"] },
2646
+ github_token: { sessionRequired: true, allOf: ["github:use"] },
2647
+ github_repositories_list: { allOf: ["github:use"] },
2648
+ social_connections_list: { allOf: ["connections:read"] },
2649
+ social_posts_recent: { allOf: ["connections:read"] },
2650
+ social_daily_analysis_context: { allOf: ["connections:read"] },
2651
+ scheduled_tasks_list: { anyOf: ["scheduled_tasks:manage", "scheduled_tasks:run"] },
2652
+ scheduled_tasks_get: { anyOf: ["scheduled_tasks:manage", "scheduled_tasks:run"] },
2653
+ scheduled_tasks_create: { allOf: ["scheduled_tasks:manage"] },
2654
+ scheduled_tasks_update: { allOf: ["scheduled_tasks:manage"] },
2655
+ scheduled_tasks_pause: { allOf: ["scheduled_tasks:manage"] },
2656
+ scheduled_tasks_resume: { allOf: ["scheduled_tasks:manage"] },
2657
+ scheduled_tasks_trigger: { allOf: ["scheduled_tasks:run"] },
2658
+ scheduled_tasks_delete: { allOf: ["scheduled_tasks:manage"] },
2659
+ scheduled_task_runs_list: { anyOf: ["scheduled_tasks:manage", "scheduled_tasks:run"] },
2660
+ slack_bot_list_channels: { allOf: ["connections:read"] },
2661
+ slack_bot_channel_history: { allOf: ["connections:read"] },
2662
+ slack_bot_list_users: { allOf: ["connections:read"] },
2663
+ slack_bot_post_message: { allOf: ["connections:read"] }
2664
+ };
2665
+ var FIRST_PARTY_MCP_TOOL_NAME_SET = new Set(FIRST_PARTY_MCP_TOOL_NAMES);
2666
+ var PolicyMcpServer = class extends McpServer {
2667
+ constructor(grant, sessionId, selectedTools, allowUncatalogued) {
2668
+ super({ name: "opengeni", version: "1.0.0" });
2669
+ this.grant = grant;
2670
+ this.sessionId = sessionId;
2671
+ this.selectedTools = selectedTools;
2672
+ this.allowUncatalogued = allowUncatalogued;
2673
+ }
2674
+ registeredToolCount = 0;
2675
+ registerTool(name, config, cb) {
2676
+ const catalogued = FIRST_PARTY_MCP_TOOL_NAME_SET.has(name);
2677
+ let admitted = this.allowUncatalogued && !catalogued;
2678
+ if (catalogued) {
2679
+ const toolName = name;
2680
+ const policy = FIRST_PARTY_TOOL_AUTHORIZATION[toolName];
2681
+ const authorized = (!policy.sessionRequired || this.sessionId !== null) && (policy.allOf?.every((permission) => hasPermission2(this.grant.permissions, permission)) ?? true) && (policy.anyOf?.some((permission) => hasPermission2(this.grant.permissions, permission)) ?? true);
2682
+ const selected = this.selectedTools === null || this.selectedTools.has(toolName);
2683
+ admitted = authorized && selected;
2684
+ }
2685
+ if (!admitted) {
2686
+ return {
2687
+ ...config.title ? { title: config.title } : {},
2688
+ ...config.description ? { description: config.description } : {},
2689
+ ...config.annotations ? { annotations: config.annotations } : {},
2690
+ ...config._meta ? { _meta: config._meta } : {},
2691
+ handler: cb,
2692
+ enabled: false,
2693
+ enable() {
2694
+ },
2695
+ disable() {
2696
+ },
2697
+ update() {
2698
+ },
2699
+ remove() {
2700
+ }
2701
+ };
2702
+ }
2703
+ this.registeredToolCount += 1;
2704
+ return super.registerTool(name, config, cb);
2705
+ }
2706
+ ensureToolsListHandler() {
2707
+ if (this.registeredToolCount > 0) return;
2708
+ super.registerTool(
2709
+ "__opengeni_empty_first_party_surface__",
2710
+ {
2711
+ description: "Internal disabled placeholder for an empty first-party surface.",
2712
+ inputSchema: z4.object({})
2713
+ },
2714
+ async () => ({
2715
+ content: [{ type: "text", text: '{"unavailable":true}' }]
2716
+ })
2717
+ ).disable();
2718
+ }
2719
+ };
2610
2720
  function buildOpenGeniMcpServer(deps, grant, options = {}) {
2611
- const server = new McpServer({
2612
- name: "opengeni",
2613
- version: "1.0.0"
2614
- });
2615
2721
  const json = (value) => ({
2616
2722
  content: [{ type: "text", text: JSON.stringify(value, null, 2) }]
2617
2723
  });
2618
2724
  const can = (permission) => hasPermission2(grant.permissions, permission);
2619
2725
  const toolspaceMode = options.toolspace != null;
2620
2726
  const sessionId = typeof grant.metadata?.["sessionId"] === "string" ? grant.metadata["sessionId"] : null;
2727
+ const selectedTools = sessionId !== null && !toolspaceMode ? new Set(
2728
+ grant.metadata?.["firstPartyMcpTools"] ?? DEFAULT_FIRST_PARTY_MCP_TOOLS
2729
+ ) : null;
2730
+ const server = new PolicyMcpServer(grant, sessionId, selectedTools, toolspaceMode);
2621
2731
  if (sessionId !== null && (!toolspaceMode || can("sessions:control"))) {
2622
2732
  server.registerTool(
2623
2733
  "set_session_title",
@@ -2657,44 +2767,6 @@ function buildOpenGeniMcpServer(deps, grant, options = {}) {
2657
2767
  registerGitHubTokenTool(server, deps, grant, sessionId, json);
2658
2768
  }
2659
2769
  }
2660
- if (!toolspaceMode || can("files:read")) {
2661
- server.registerTool(
2662
- "files_get_download_url",
2663
- {
2664
- description: "Create a short-lived download URL for a ready file asset.",
2665
- inputSchema: { fileId: z4.string().uuid() }
2666
- },
2667
- async ({ fileId }) => {
2668
- if (!deps.objectStorage) {
2669
- throw new Error("object storage is not configured");
2670
- }
2671
- const file = await requireFile(deps.db, grant.workspaceId, fileId);
2672
- if (file.status !== "ready") {
2673
- throw new Error(`file is ${file.status}`);
2674
- }
2675
- const signed = await deps.objectStorage.createGetUrl({
2676
- key: file.objectKey
2677
- });
2678
- return json({
2679
- file: {
2680
- id: file.id,
2681
- filename: file.filename,
2682
- safeFilename: file.safeFilename,
2683
- contentType: file.contentType,
2684
- sizeBytes: file.sizeBytes,
2685
- sha256: file.sha256,
2686
- status: file.status,
2687
- createdAt: file.createdAt,
2688
- updatedAt: file.updatedAt
2689
- },
2690
- downloadUrl: {
2691
- url: signed.url,
2692
- expiresAt: signed.expiresAt.toISOString()
2693
- }
2694
- });
2695
- }
2696
- );
2697
- }
2698
2770
  if (!toolspaceMode || can("github:use")) {
2699
2771
  server.registerTool(
2700
2772
  "github_repositories_list",
@@ -2985,7 +3057,8 @@ function buildOpenGeniMcpServer(deps, grant, options = {}) {
2985
3057
  await deps.workflowClient.triggerScheduledTask({
2986
3058
  task,
2987
3059
  agentRunUsageIdempotencyKey,
2988
- triggerWorkflowId
3060
+ triggerWorkflowId,
3061
+ initiator: { kind: "subject", subjectId: grant.subjectId }
2989
3062
  });
2990
3063
  await recordWorkspaceUsage(deps, {
2991
3064
  accountId: grant.accountId,
@@ -3031,6 +3104,7 @@ function buildOpenGeniMcpServer(deps, grant, options = {}) {
3031
3104
  );
3032
3105
  }
3033
3106
  registerToolspaceProxyTools(server, options.toolspace ?? null);
3107
+ server.ensureToolsListHandler();
3034
3108
  return server;
3035
3109
  }
3036
3110
  function registerSlackBotTools(server, deps, grant, sessionId, json) {
@@ -3896,6 +3970,9 @@ function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSes
3896
3970
  firstPartyMcpPermissions: z4.array(z4.string()).optional().describe(
3897
3971
  "Optional first-party capability set for the child. Omit to inherit this session's effective permissions. An explicit set may only narrow capabilities held by this session. A goal-bearing child requires goals:manage in the resulting set; creation fails rather than adding it implicitly."
3898
3972
  ),
3973
+ firstPartyMcpTools: z4.array(z4.enum(FIRST_PARTY_MCP_TOOL_NAMES)).optional().describe(
3974
+ "Exact model-visible first-party tool selection for the child. Omit to inherit this session's effective selection. This does not grant permissions."
3975
+ ),
3899
3976
  // Shared-sandbox placement (addendum 05 §D). OMIT (default) to SHARE the
3900
3977
  // creator's box — one filesystem/repo/desktop, N independent conversations;
3901
3978
  // this is the SAFE DEFAULT. Pass "new" for a fresh isolated box (a different
@@ -3949,7 +4026,7 @@ function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSes
3949
4026
  server.registerTool(
3950
4027
  "session_send_message",
3951
4028
  {
3952
- description: "Send information to another session. From an OpenGeni worker this becomes a coalescible internal update, never a visible prompt-queue row; pending updates are delivered together on the target's next inference. A sessionless operator call appends one visible prompt.",
4029
+ description: "Send information to another session. From an OpenGeni worker this becomes a canonical coalescible machine input: it appears in the target's compact incoming queue group, is durably added to model history when claimed, and remains visible in the timeline. A sessionless operator call appends one human/API prompt.",
3953
4030
  inputSchema: {
3954
4031
  sessionId: z4.string().uuid(),
3955
4032
  text: z4.string().min(1),
@@ -4129,7 +4206,7 @@ function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSes
4129
4206
  server.registerTool(
4130
4207
  "session_steer",
4131
4208
  {
4132
- description: "Atomically replace another session's current direction and resume it. The instruction is an internal update, never a human queue row.",
4209
+ description: "Atomically replace another session's current direction and resume it. The Agent Steer is a typed machine input shown in the target queue/timeline and durably retained in model history; it never impersonates a human prompt.",
4133
4210
  inputSchema: {
4134
4211
  sessionId: z4.string().uuid(),
4135
4212
  instruction: z4.string().min(1),
@@ -5881,8 +5958,8 @@ function registerCatalogAssetRoutes(app, deps) {
5881
5958
  if (!contentType) {
5882
5959
  throw new HTTPException5(404, { message: "asset not found" });
5883
5960
  }
5884
- const object4 = await objectStorage.getObjectBytes(key);
5885
- if (!object4) {
5961
+ const object5 = await objectStorage.getObjectBytes(key);
5962
+ if (!object5) {
5886
5963
  throw new HTTPException5(404, { message: "asset not found" });
5887
5964
  }
5888
5965
  const etag = etagForKey(key);
@@ -5895,7 +5972,7 @@ function registerCatalogAssetRoutes(app, deps) {
5895
5972
  if (ifNoneMatchSatisfied(c.req.header("if-none-match"), etag)) {
5896
5973
  return c.body(null, 304, headers);
5897
5974
  }
5898
- return c.body(new Uint8Array(object4.bytes), 200, { ...headers, "Content-Type": contentType });
5975
+ return c.body(new Uint8Array(object5.bytes), 200, { ...headers, "Content-Type": contentType });
5899
5976
  });
5900
5977
  }
5901
5978
  function catalogAssetKeyFromPath(pathname) {
@@ -8931,7 +9008,7 @@ import {
8931
9008
  queueDocumentForReindex,
8932
9009
  searchDocuments as searchDocuments2
8933
9010
  } from "@opengeni/documents";
8934
- import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
9011
+ import { WebStandardStreamableHTTPServerTransport as WebStandardStreamableHTTPServerTransport2 } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
8935
9012
  import { HTTPException as HTTPException11 } from "hono/http-exception";
8936
9013
  import { requireAccessGrant as requireAccessGrant5 } from "@opengeni/core";
8937
9014
  import { recordWorkspaceUsage as recordWorkspaceUsage3, requireLimit as requireLimit3 } from "@opengeni/core";
@@ -9162,8 +9239,90 @@ import {
9162
9239
  import { HTTPException as HTTPException10 } from "hono/http-exception";
9163
9240
  import { requireAccessGrant as requireAccessGrant4 } from "@opengeni/core";
9164
9241
  import { recordWorkspaceUsage as recordWorkspaceUsage2, requireLimit as requireLimit2 } from "@opengeni/core";
9242
+ import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
9243
+
9244
+ // src/mcp/files.ts
9245
+ import { requireFile } from "@opengeni/db";
9246
+ import { hasPermission as hasPermission7 } from "@opengeni/core";
9247
+ import { McpServer as McpServer3 } from "@modelcontextprotocol/sdk/server/mcp.js";
9248
+ import * as z3 from "zod/v4";
9249
+ function buildFilesMcpServer(deps, grant) {
9250
+ const server = new McpServer3({
9251
+ name: "opengeni-files",
9252
+ version: "1.0.0"
9253
+ });
9254
+ if (!hasPermission7(grant.permissions, "files:read")) {
9255
+ server.registerTool(
9256
+ "__opengeni_empty_files_surface__",
9257
+ {
9258
+ description: "Internal disabled placeholder for an unauthorized files surface.",
9259
+ inputSchema: z3.object({})
9260
+ },
9261
+ async () => ({
9262
+ content: [{ type: "text", text: '{"unavailable":true}' }]
9263
+ })
9264
+ ).disable();
9265
+ return server;
9266
+ }
9267
+ server.registerTool(
9268
+ "files_get_download_url",
9269
+ {
9270
+ description: "Create a short-lived download URL for a ready file asset.",
9271
+ inputSchema: { fileId: z3.string().uuid() }
9272
+ },
9273
+ async ({ fileId }) => {
9274
+ if (!deps.objectStorage) {
9275
+ throw new Error("object storage is not configured");
9276
+ }
9277
+ const file = await requireFile(deps.db, grant.workspaceId, fileId);
9278
+ if (file.status !== "ready") {
9279
+ throw new Error(`file is ${file.status}`);
9280
+ }
9281
+ const signed = await deps.objectStorage.createGetUrl({ key: file.objectKey });
9282
+ return {
9283
+ content: [
9284
+ {
9285
+ type: "text",
9286
+ text: JSON.stringify(
9287
+ {
9288
+ file: {
9289
+ id: file.id,
9290
+ filename: file.filename,
9291
+ safeFilename: file.safeFilename,
9292
+ contentType: file.contentType,
9293
+ sizeBytes: file.sizeBytes,
9294
+ sha256: file.sha256,
9295
+ status: file.status,
9296
+ createdAt: file.createdAt,
9297
+ updatedAt: file.updatedAt
9298
+ },
9299
+ downloadUrl: {
9300
+ url: signed.url,
9301
+ expiresAt: signed.expiresAt.toISOString()
9302
+ }
9303
+ },
9304
+ null,
9305
+ 2
9306
+ )
9307
+ }
9308
+ ]
9309
+ };
9310
+ }
9311
+ );
9312
+ return server;
9313
+ }
9314
+
9315
+ // src/routes/files.ts
9165
9316
  function registerFileRoutes(app, deps) {
9166
9317
  const { db, objectStorage } = deps;
9318
+ app.all("/v1/workspaces/:workspaceId/mcp/files", async (c) => {
9319
+ const workspaceId = c.req.param("workspaceId");
9320
+ const grant = await requireAccessGrant4(c, deps, workspaceId, "files:read");
9321
+ const transport = new WebStandardStreamableHTTPServerTransport({ enableJsonResponse: true });
9322
+ const server = buildFilesMcpServer(deps, grant);
9323
+ await server.connect(transport);
9324
+ return await transport.handleRequest(c.req.raw);
9325
+ });
9167
9326
  app.post("/v1/workspaces/:workspaceId/files/uploads", async (c) => {
9168
9327
  const workspaceId = c.req.param("workspaceId");
9169
9328
  const grant = await requireAccessGrant4(c, deps, workspaceId, "files:upload");
@@ -9972,7 +10131,7 @@ function registerDocumentRoutes(app, deps) {
9972
10131
  const workspaceId = c.req.param("workspaceId");
9973
10132
  const grant = await requireAccessGrant5(c, deps, workspaceId, "documents:search");
9974
10133
  const sessionId = typeof grant.metadata?.sessionId === "string" ? grant.metadata.sessionId : void 0;
9975
- const transport = new WebStandardStreamableHTTPServerTransport({ enableJsonResponse: true });
10134
+ const transport = new WebStandardStreamableHTTPServerTransport2({ enableJsonResponse: true });
9976
10135
  const server = buildDocumentsMcpServer(
9977
10136
  db,
9978
10137
  grant.accountId,
@@ -11667,7 +11826,7 @@ import {
11667
11826
  } from "@opengeni/github";
11668
11827
  import { deleteCookie, setCookie } from "hono/cookie";
11669
11828
  import { HTTPException as HTTPException17 } from "hono/http-exception";
11670
- import { hasPermission as hasPermission7, requireAccessGrant as requireAccessGrant10 } from "@opengeni/core";
11829
+ import { hasPermission as hasPermission8, requireAccessGrant as requireAccessGrant10 } from "@opengeni/core";
11671
11830
  var githubStateCookie = "opengeni_github_state";
11672
11831
  var githubBindingStateMaxAgeSeconds = 10 * 60;
11673
11832
  var legacyInstallationChooserDisabledMessage = "The legacy repository-admin GitHub installation chooser is disabled; use the GitHub owner-consent connect flow";
@@ -11680,7 +11839,7 @@ function registerGitHubRoutes(app, deps) {
11680
11839
  const slug = settings.githubAppSlug?.trim() || null;
11681
11840
  const installations = missing.length === 0 ? await listWorkspaceGitHubInstallationBindings(deps, grant.workspaceId) : [];
11682
11841
  const status = githubBindingStatus(missing.length === 0, installations);
11683
- const canManage = hasPermission7(grant.permissions, "github:manage");
11842
+ const canManage = hasPermission8(grant.permissions, "github:manage");
11684
11843
  const connectState = missing.length === 0 && slug && canManage ? createSignedState5(githubStateSecret, {
11685
11844
  accountId: grant.accountId,
11686
11845
  workspaceId: grant.workspaceId,
@@ -12618,7 +12777,8 @@ function registerScheduledTaskRoutes(app, deps) {
12618
12777
  await workflowClient.triggerScheduledTask({
12619
12778
  task,
12620
12779
  agentRunUsageIdempotencyKey,
12621
- triggerWorkflowId
12780
+ triggerWorkflowId,
12781
+ initiator: { kind: "subject", subjectId: grant.subjectId }
12622
12782
  });
12623
12783
  await recordWorkspaceUsage4(deps, {
12624
12784
  accountId: grant.accountId,
@@ -12758,7 +12918,7 @@ import {
12758
12918
  coalesceSessionEventDeltas,
12759
12919
  publishDurableSessionEvents as publishDurableSessionEvents2
12760
12920
  } from "@opengeni/events";
12761
- import { z as z3, ZodError } from "zod";
12921
+ import { z as z5, ZodError } from "zod";
12762
12922
 
12763
12923
  // src/sandbox/channel-a.ts
12764
12924
  import {
@@ -13962,7 +14122,7 @@ function registerSessionRoutes(app, deps) {
13962
14122
  const workspaceId = c.req.param("workspaceId");
13963
14123
  const grant = await requireAccessGrant14(c, deps, workspaceId, "sessions:read");
13964
14124
  const sessionId = c.req.param("sessionId");
13965
- if (!z3.string().uuid().safeParse(sessionId).success) {
14125
+ if (!z5.string().uuid().safeParse(sessionId).success) {
13966
14126
  throw new HTTPException22(404, { message: "session not found" });
13967
14127
  }
13968
14128
  const session = await getSessionForSubject(
@@ -13981,7 +14141,7 @@ function registerSessionRoutes(app, deps) {
13981
14141
  const workspaceId = c.req.param("workspaceId");
13982
14142
  const grant = await requireAccessGrant14(c, deps, workspaceId, "sessions:read");
13983
14143
  const sessionId = c.req.param("sessionId");
13984
- if (!z3.string().uuid().safeParse(sessionId).success) {
14144
+ if (!z5.string().uuid().safeParse(sessionId).success) {
13985
14145
  throw new HTTPException22(404, { message: "session not found" });
13986
14146
  }
13987
14147
  const parsed = UpdateSessionPinRequest.safeParse(await c.req.json().catch(() => null));
@@ -15681,7 +15841,7 @@ function eventEnumList(raw, schema, name) {
15681
15841
  }
15682
15842
  function sessionListQuery(query, allowCursor = true) {
15683
15843
  const parentSessionId = query.parentSessionId;
15684
- if (parentSessionId !== void 0 && parentSessionId !== "null" && !z3.string().uuid().safeParse(parentSessionId).success) {
15844
+ if (parentSessionId !== void 0 && parentSessionId !== "null" && !z5.string().uuid().safeParse(parentSessionId).success) {
15685
15845
  throw new HTTPException22(400, {
15686
15846
  message: 'parentSessionId must be a session id or the literal "null"'
15687
15847
  });
@@ -15837,7 +15997,7 @@ import {
15837
15997
  listSocialPosts as listSocialPosts2
15838
15998
  } from "@opengeni/db";
15839
15999
  import { HTTPException as HTTPException23 } from "hono/http-exception";
15840
- import { z as z5 } from "zod";
16000
+ import { z as z6 } from "zod";
15841
16001
  import { requireAccessGrant as requireAccessGrant15 } from "@opengeni/core";
15842
16002
  function registerSocialRoutes(app, deps) {
15843
16003
  const { db } = deps;
@@ -15927,7 +16087,7 @@ function parseConnectionIds(raw) {
15927
16087
  return void 0;
15928
16088
  }
15929
16089
  const values = raw.split(",").map((value) => value.trim()).filter(Boolean);
15930
- const parsed = z5.array(z5.string().uuid()).safeParse(values);
16090
+ const parsed = z6.array(z6.string().uuid()).safeParse(values);
15931
16091
  if (!parsed.success) {
15932
16092
  throw new HTTPException23(422, {
15933
16093
  message: "connectionIds must be a comma-separated list of UUIDs"
@@ -15988,7 +16148,7 @@ import {
15988
16148
  } from "@opengeni/db";
15989
16149
  import { boundWorkspaceControlHttpPage } from "@opengeni/events";
15990
16150
  import { HTTPException as HTTPException24 } from "hono/http-exception";
15991
- import { hasPermission as hasPermission8, requireAccessContext as requireAccessContext2, requireAccessGrant as requireAccessGrant16 } from "@opengeni/core";
16151
+ import { hasPermission as hasPermission9, requireAccessContext as requireAccessContext2, requireAccessGrant as requireAccessGrant16 } from "@opengeni/core";
15992
16152
  import { requireLimit as requireLimit7 } from "@opengeni/core";
15993
16153
  import {
15994
16154
  assertWorkspaceDeletable,
@@ -16235,7 +16395,7 @@ function registerWorkspaceRoutes(app, deps) {
16235
16395
  const context = await requireAccessContext2(c, deps);
16236
16396
  const readableWorkspaceIds = [
16237
16397
  ...new Set(
16238
- context.workspaceGrants.filter((grant) => hasPermission8(grant.permissions, "workspace:read")).map((grant) => grant.workspaceId)
16398
+ context.workspaceGrants.filter((grant) => hasPermission9(grant.permissions, "workspace:read")).map((grant) => grant.workspaceId)
16239
16399
  )
16240
16400
  ];
16241
16401
  if (readableWorkspaceIds.length > 0) {
@@ -16524,8 +16684,8 @@ import {
16524
16684
  WorkspaceInstructionPolicyNotFoundError
16525
16685
  } from "@opengeni/db";
16526
16686
  import { HTTPException as HTTPException25 } from "hono/http-exception";
16527
- import { z as z6 } from "zod";
16528
- var WorkspaceInstructionPolicyRevisionId = z6.string().uuid();
16687
+ import { z as z7 } from "zod";
16688
+ var WorkspaceInstructionPolicyRevisionId = z7.string().uuid();
16529
16689
  async function parseBody(context, schema) {
16530
16690
  const parsed = schema.safeParse(await context.req.json().catch(() => null));
16531
16691
  if (!parsed.success) {
@@ -17025,7 +17185,7 @@ function createApp(deps) {
17025
17185
  }
17026
17186
  const workspace = await getWorkspace2(routeDeps.db, workspaceId);
17027
17187
  const workspaceMemoryEnabled = resolveWorkspaceMemoryEnabled(workspace?.settings);
17028
- const transport = new WebStandardStreamableHTTPServerTransport2({
17188
+ const transport = new WebStandardStreamableHTTPServerTransport3({
17029
17189
  enableJsonResponse: true
17030
17190
  });
17031
17191
  const mcp = buildOpenGeniMcpServer(routeDeps, grant, {
@@ -17099,7 +17259,7 @@ function createApp(deps) {
17099
17259
  }
17100
17260
  async function requireMcpAccessGrant(c, deps, workspaceId) {
17101
17261
  const grant = await requireAccessGrant18(c, deps, workspaceId);
17102
- if (hasPermission9(grant.permissions, "workspace:read")) {
17262
+ if (hasPermission10(grant.permissions, "workspace:read")) {
17103
17263
  return grant;
17104
17264
  }
17105
17265
  if (isToolspaceGrant(deps.settings, grant)) {
@@ -17280,6 +17440,10 @@ var routeLabelPatterns = [
17280
17440
  pattern: /^\/v1\/workspaces\/[^/]+\/mcp\/docs$/,
17281
17441
  label: "/v1/workspaces/:workspaceId/mcp/docs"
17282
17442
  },
17443
+ {
17444
+ pattern: /^\/v1\/workspaces\/[^/]+\/mcp\/files$/,
17445
+ label: "/v1/workspaces/:workspaceId/mcp/files"
17446
+ },
17283
17447
  {
17284
17448
  pattern: /^\/v1\/workspaces\/[^/]+\/default-rig$/,
17285
17449
  label: "/v1/workspaces/:workspaceId/default-rig"
@@ -17641,4 +17805,4 @@ export {
17641
17805
  withDefaultEnabledCapabilityMcpTools,
17642
17806
  workflowIdForSession2 as workflowIdForSession
17643
17807
  };
17644
- //# sourceMappingURL=chunk-3BHOMOSD.js.map
17808
+ //# sourceMappingURL=chunk-SD5GJTZ4.js.map