@buildautomaton/cli 0.1.48 → 0.1.49

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/index.js CHANGED
@@ -22733,6 +22733,238 @@ var WebSocketMessageSchema = external_exports.object({
22733
22733
  error: external_exports.string().optional()
22734
22734
  });
22735
22735
 
22736
+ // ../types/src/integrations/link-detection/linear.ts
22737
+ function detectLinearLink(url2) {
22738
+ const linearMatch = url2.match(
22739
+ /https?:\/\/(?:app\.)?linear\.app\/([^/]+)\/issue\/([A-Z]+-\d+)/i
22740
+ );
22741
+ if (linearMatch) {
22742
+ return {
22743
+ url: url2,
22744
+ integrationType: "linear",
22745
+ resourceType: "work-item",
22746
+ resourceId: linearMatch[2],
22747
+ workspaceId: linearMatch[1]
22748
+ };
22749
+ }
22750
+ return null;
22751
+ }
22752
+
22753
+ // ../types/src/integrations/link-detection/github.ts
22754
+ function detectGitHubLink(url2) {
22755
+ const githubIssueMatch = url2.match(
22756
+ /https?:\/\/github\.com\/([^/]+)\/([^/]+)\/issues\/(\d+)/i
22757
+ );
22758
+ if (githubIssueMatch) {
22759
+ return {
22760
+ url: url2,
22761
+ integrationType: "github",
22762
+ resourceType: "issue",
22763
+ resourceId: githubIssueMatch[3],
22764
+ owner: githubIssueMatch[1],
22765
+ repo: githubIssueMatch[2]
22766
+ };
22767
+ }
22768
+ const githubPRMatch = url2.match(
22769
+ /https?:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/i
22770
+ );
22771
+ if (githubPRMatch) {
22772
+ return {
22773
+ url: url2,
22774
+ integrationType: "github",
22775
+ resourceType: "pull-request",
22776
+ resourceId: githubPRMatch[3],
22777
+ owner: githubPRMatch[1],
22778
+ repo: githubPRMatch[2]
22779
+ };
22780
+ }
22781
+ return null;
22782
+ }
22783
+
22784
+ // ../types/src/integrations/link-detection/jira.ts
22785
+ function detectJIRALink(url2) {
22786
+ const jiraMatch = url2.match(
22787
+ /https?:\/\/([^/]+)\.atlassian\.net\/(?:browse|jira\/software\/projects\/[^/]+\/issues)\/([A-Z]+-\d+)/i
22788
+ );
22789
+ if (jiraMatch) {
22790
+ return {
22791
+ url: url2,
22792
+ integrationType: "jira",
22793
+ resourceType: "issue",
22794
+ resourceId: jiraMatch[2],
22795
+ projectKey: jiraMatch[2].split("-")[0]
22796
+ };
22797
+ }
22798
+ return null;
22799
+ }
22800
+
22801
+ // ../types/src/integrations/link-detection/notion.ts
22802
+ function formatNotionPageId(hex) {
22803
+ if (hex.length !== 32) return hex;
22804
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
22805
+ }
22806
+ function detectNotionLink(url2) {
22807
+ const standardMatch = url2.match(
22808
+ /https?:\/\/(?:www\.)?notion\.(?:so|site)\/(?:[^/#?]+\/)?(?:[^/#?-]+-)?([a-f0-9]{32})/i
22809
+ );
22810
+ if (standardMatch) {
22811
+ return {
22812
+ url: url2,
22813
+ integrationType: "notion",
22814
+ resourceType: "page",
22815
+ resourceId: formatNotionPageId(standardMatch[1])
22816
+ };
22817
+ }
22818
+ const siteMatch = url2.match(
22819
+ /https?:\/\/([^.]+)\.notion\.(?:so|site)\/(?:[^/#?-]+-)?([a-f0-9]{32})/i
22820
+ );
22821
+ if (siteMatch) {
22822
+ return {
22823
+ url: url2,
22824
+ integrationType: "notion",
22825
+ resourceType: "page",
22826
+ resourceId: formatNotionPageId(siteMatch[2]),
22827
+ notionWorkspaceId: siteMatch[1]
22828
+ };
22829
+ }
22830
+ return null;
22831
+ }
22832
+
22833
+ // ../types/src/integrations/link-detection/slack.ts
22834
+ function detectSlackLink(url2) {
22835
+ const archiveThreadMatch = url2.match(
22836
+ /https?:\/\/(?:([^./]+)\.)?slack\.com\/archives\/([A-Z0-9]+)\/p(\d+)(?:\?.*)?$/i
22837
+ );
22838
+ if (archiveThreadMatch) {
22839
+ return {
22840
+ url: url2,
22841
+ integrationType: "slack",
22842
+ resourceType: "thread",
22843
+ resourceId: `${archiveThreadMatch[2]}-${archiveThreadMatch[3]}`,
22844
+ isChannel: false
22845
+ };
22846
+ }
22847
+ const appThreadMatch = url2.match(
22848
+ /https?:\/\/app\.slack\.com\/client\/([^/]+)\/([A-Z0-9]+)\/thread\/[A-Z0-9]+-(\d+)/i
22849
+ );
22850
+ if (appThreadMatch) {
22851
+ return {
22852
+ url: url2,
22853
+ integrationType: "slack",
22854
+ resourceType: "thread",
22855
+ resourceId: `${appThreadMatch[2]}-${appThreadMatch[3]}`,
22856
+ isChannel: false
22857
+ };
22858
+ }
22859
+ const channelOnlyMatch = url2.match(
22860
+ /https?:\/\/(?:app\.)?(?:([^./]+)\.)?slack\.com\/archives\/([A-Z0-9]+)\/?(\?.*)?$/i
22861
+ );
22862
+ if (channelOnlyMatch && !url2.includes("/p")) {
22863
+ return {
22864
+ url: url2,
22865
+ integrationType: "slack",
22866
+ resourceType: "channel",
22867
+ resourceId: channelOnlyMatch[2],
22868
+ isChannel: true
22869
+ };
22870
+ }
22871
+ return null;
22872
+ }
22873
+
22874
+ // ../types/src/integrations/link-detection/zoom.ts
22875
+ function detectZoomLink(url2) {
22876
+ try {
22877
+ const u = new URL(url2);
22878
+ const host = u.hostname.toLowerCase();
22879
+ if (!host.endsWith("zoom.us") && !host.endsWith("zoom.com")) return null;
22880
+ const pathParts = u.pathname.split("/").filter(Boolean);
22881
+ if (pathParts.length >= 2 && (pathParts[0] === "j" || pathParts[0] === "s" || pathParts[0] === "my")) {
22882
+ const meetingId = pathParts[1].replace(/\s/g, "");
22883
+ if (meetingId.length >= 9) {
22884
+ return {
22885
+ url: url2,
22886
+ integrationType: "zoom",
22887
+ resourceType: "meeting",
22888
+ resourceId: meetingId,
22889
+ zoomMeetingId: meetingId
22890
+ };
22891
+ }
22892
+ }
22893
+ } catch {
22894
+ }
22895
+ return null;
22896
+ }
22897
+
22898
+ // ../types/src/integrations/link-detection/asana.ts
22899
+ var ASANA_TASK_GID = /\d{10,}/;
22900
+ function parseAsanaTaskGid(segment) {
22901
+ const trimmed2 = segment.trim();
22902
+ if (!ASANA_TASK_GID.test(trimmed2)) return null;
22903
+ return trimmed2;
22904
+ }
22905
+ function detectAsanaLink(url2) {
22906
+ const v1ProjectMatch = url2.match(
22907
+ /https?:\/\/app\.asana\.com\/1\/[^/]+\/project\/([^/?#]+)\/task\/([^/?#]+)/i
22908
+ );
22909
+ if (v1ProjectMatch) {
22910
+ const taskGid = parseAsanaTaskGid(v1ProjectMatch[2]);
22911
+ if (!taskGid) return null;
22912
+ return {
22913
+ url: url2,
22914
+ integrationType: "asana",
22915
+ resourceType: "task",
22916
+ resourceId: taskGid,
22917
+ asanaProjectGid: v1ProjectMatch[1]
22918
+ };
22919
+ }
22920
+ const v1TaskMatch = url2.match(/https?:\/\/app\.asana\.com\/1\/[^/]+(?:\/[^/]+)*\/task\/([^/?#]+)/i);
22921
+ if (v1TaskMatch) {
22922
+ const taskGid = parseAsanaTaskGid(v1TaskMatch[1]);
22923
+ if (!taskGid) return null;
22924
+ return {
22925
+ url: url2,
22926
+ integrationType: "asana",
22927
+ resourceType: "task",
22928
+ resourceId: taskGid
22929
+ };
22930
+ }
22931
+ const legacyMatch = url2.match(/https?:\/\/app\.asana\.com\/0\/([^/?#]+)\/([^/?#]+)/i);
22932
+ if (legacyMatch) {
22933
+ const projectGid = legacyMatch[1];
22934
+ const taskGid = parseAsanaTaskGid(legacyMatch[2]);
22935
+ if (!taskGid) return null;
22936
+ if (projectGid === "inbox" || projectGid === "my_tasks") {
22937
+ return null;
22938
+ }
22939
+ return {
22940
+ url: url2,
22941
+ integrationType: "asana",
22942
+ resourceType: "task",
22943
+ resourceId: taskGid,
22944
+ asanaProjectGid: projectGid === "0" ? void 0 : projectGid
22945
+ };
22946
+ }
22947
+ return null;
22948
+ }
22949
+
22950
+ // ../types/src/integrations/link-detection/index.ts
22951
+ function detectIntegrationLink(url2) {
22952
+ return detectLinearLink(url2) || detectGitHubLink(url2) || detectJIRALink(url2) || detectNotionLink(url2) || detectSlackLink(url2) || detectZoomLink(url2) || detectAsanaLink(url2);
22953
+ }
22954
+ function extractIntegrationLinks(text) {
22955
+ const urlRegex = /https?:\/\/[^\s<>"{}|\\^`[\]]+/gi;
22956
+ const urls = text.match(urlRegex) || [];
22957
+ const links = [];
22958
+ for (const url2 of urls) {
22959
+ const detected = detectIntegrationLink(url2);
22960
+ if (detected) links.push(detected);
22961
+ }
22962
+ return links;
22963
+ }
22964
+ function extractFetchableIntegrationLinks(text) {
22965
+ return extractIntegrationLinks(text).filter((link) => !(link.integrationType === "slack" && link.isChannel));
22966
+ }
22967
+
22736
22968
  // ../types/src/checkpoints.ts
22737
22969
  init_zod();
22738
22970
  var CheckpointKindSchema = external_exports.enum(["daily", "weekly", "overall"]);
@@ -23160,6 +23392,16 @@ var GitRepoMetaSchema = external_exports.object({
23160
23392
  updatedAt: external_exports.string()
23161
23393
  });
23162
23394
 
23395
+ // ../types/src/bridge-mcp-tool-display.ts
23396
+ var GET_INTEGRATION_CONTENT_TOOL = "get_integration_content";
23397
+ var LIST_PARENT_SESSION_PROMPTS_TOOL = "list_parent_session_prompts";
23398
+ var GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL = "get_parent_session_turn_transcript";
23399
+ var BRIDGE_MCP_TOOL_LABELS = {
23400
+ [GET_INTEGRATION_CONTENT_TOOL]: "Fetch external ticket content",
23401
+ [LIST_PARENT_SESSION_PROMPTS_TOOL]: "List parent session prompts",
23402
+ [GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL]: "Read parent session transcript"
23403
+ };
23404
+
23163
23405
  // ../types/src/claude-code-permission-mode.ts
23164
23406
  var CLAUDE_CODE_PERMISSION_MODES = [
23165
23407
  "default",
@@ -24469,7 +24711,7 @@ function installBridgeProcessResilience() {
24469
24711
  }
24470
24712
 
24471
24713
  // src/cli-version.ts
24472
- var CLI_VERSION = "0.1.48".length > 0 ? "0.1.48" : "0.0.0-dev";
24714
+ var CLI_VERSION = "0.1.49".length > 0 ? "0.1.49" : "0.0.0-dev";
24473
24715
 
24474
24716
  // src/connection/heartbeat/constants.ts
24475
24717
  var BRIDGE_APP_HEARTBEAT_INTERVAL_MS = 1e4;
@@ -33129,7 +33371,15 @@ async function fetchInternalApiJson(params) {
33129
33371
  const token = params.getCloudAccessToken();
33130
33372
  if (!token) return { ok: false, error: "Missing cloud access token." };
33131
33373
  const url2 = `${internalApiBase(params.cloudApiBaseUrl)}${params.path}`;
33132
- const res = await fetch(url2, { headers: { Authorization: `Bearer ${token}` } });
33374
+ const method = params.method ?? "GET";
33375
+ const res = await fetch(url2, {
33376
+ method,
33377
+ headers: {
33378
+ Authorization: `Bearer ${token}`,
33379
+ ...params.body != null ? { "Content-Type": "application/json" } : {}
33380
+ },
33381
+ ...params.body != null ? { body: JSON.stringify(params.body) } : {}
33382
+ });
33133
33383
  if (!res.ok) {
33134
33384
  const t = await res.text().catch(() => "");
33135
33385
  return { ok: false, error: `${params.errorLabel} (${res.status}): ${t.slice(0, 200)}` };
@@ -33312,6 +33562,39 @@ async function enrichForkedSessionPromptForAgent(params) {
33312
33562
  return buildForkedSessionAgentPrompt(params.promptText, params.sessionId, parentSessionId);
33313
33563
  }
33314
33564
 
33565
+ // src/agents/acp/build-integration-content-agent-prompt-note.ts
33566
+ function buildIntegrationContentAgentPromptNote(sessionId) {
33567
+ const sessionRef = sessionId.trim();
33568
+ return [
33569
+ "The user message includes link(s) to external integration resources (Linear, GitHub, Jira, Notion, Slack thread, Zoom, or Asana).",
33570
+ "Use the get_integration_content MCP tool on the buildautomaton-bridge server to fetch the full content of each link.",
33571
+ `When calling the tool, pass sessionId "${sessionRef}" and the URL as url.`,
33572
+ "By default the tool links the fetched URL as this session external ticket when the session has none yet. Pass associateAsSessionTicket: false when fetching additional links for context only (after the primary ticket is linked, or when you do not want association).",
33573
+ "If the tool reports unsupported_url, do not retry with the same URL. If it reports temporarily_unavailable, you may retry later."
33574
+ ].join("\n");
33575
+ }
33576
+ function injectIntegrationContentAgentPromptNote(agentPrompt, sessionId) {
33577
+ const note = buildIntegrationContentAgentPromptNote(sessionId);
33578
+ const marker = "\nUser request:\n";
33579
+ const idx = agentPrompt.indexOf(marker);
33580
+ if (idx >= 0) {
33581
+ return `${agentPrompt.slice(0, idx)}
33582
+ ${note}${agentPrompt.slice(idx)}`;
33583
+ }
33584
+ return `${note}
33585
+
33586
+ ${agentPrompt.trim()}`;
33587
+ }
33588
+
33589
+ // src/agents/acp/enrich-integration-content-prompt-for-agent.ts
33590
+ function enrichIntegrationContentPromptForAgent(params) {
33591
+ if (!params.sessionId.trim()) return params.agentPromptText;
33592
+ if (extractFetchableIntegrationLinks(params.originalPromptText).length === 0) {
33593
+ return params.agentPromptText;
33594
+ }
33595
+ return injectIntegrationContentAgentPromptNote(params.agentPromptText, params.sessionId);
33596
+ }
33597
+
33315
33598
  // src/agents/acp/send-prompt-to-agent.ts
33316
33599
  async function sendPromptToAgent(options) {
33317
33600
  const {
@@ -33342,6 +33625,13 @@ async function sendPromptToAgent(options) {
33342
33625
  getCloudAccessToken
33343
33626
  });
33344
33627
  }
33628
+ if (sessionId) {
33629
+ agentPromptText = enrichIntegrationContentPromptForAgent({
33630
+ sessionId,
33631
+ originalPromptText: promptText,
33632
+ agentPromptText
33633
+ });
33634
+ }
33345
33635
  let sendOpts = {};
33346
33636
  if (attachments && attachments.length > 0) {
33347
33637
  if (!sessionId || !cloudApiBaseUrl || !getCloudAccessToken) {
@@ -39353,8 +39643,8 @@ async function callListParentSessionPromptsTool(ctx, cloud, childSessionId, pare
39353
39643
  }
39354
39644
 
39355
39645
  // src/mcp/tools/session-history/fork/tool-names.ts
39356
- var LIST_PARENT_SESSION_PROMPTS_TOOL = "list_parent_session_prompts";
39357
- var GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL = "get_parent_session_turn_transcript";
39646
+ var LIST_PARENT_SESSION_PROMPTS_TOOL2 = "list_parent_session_prompts";
39647
+ var GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL2 = "get_parent_session_turn_transcript";
39358
39648
 
39359
39649
  // src/mcp/tools/session-history/fork/call-fork-session-mcp-tool.ts
39360
39650
  async function callForkSessionMcpTool(ctx, cloud, name, args) {
@@ -39371,10 +39661,10 @@ async function callForkSessionMcpTool(ctx, cloud, name, args) {
39371
39661
  return mcpTextResult(parentResolved.error, true);
39372
39662
  }
39373
39663
  const parentSessionId = parentResolved.parentSessionId;
39374
- if (name === LIST_PARENT_SESSION_PROMPTS_TOOL) {
39664
+ if (name === LIST_PARENT_SESSION_PROMPTS_TOOL2) {
39375
39665
  return callListParentSessionPromptsTool(ctx, cloud, childSessionId, parentSessionId);
39376
39666
  }
39377
- if (name === GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL) {
39667
+ if (name === GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL2) {
39378
39668
  return callGetParentSessionTurnTranscriptTool(ctx, cloud, childSessionId, args);
39379
39669
  }
39380
39670
  return mcpTextResult(`Unknown fork session tool: ${name}`, true);
@@ -39387,7 +39677,7 @@ var SESSION_ID_SCHEMA = {
39387
39677
  };
39388
39678
  var FORK_SESSION_MCP_TOOL_DEFINITIONS = [
39389
39679
  {
39390
- name: LIST_PARENT_SESSION_PROMPTS_TOOL,
39680
+ name: LIST_PARENT_SESSION_PROMPTS_TOOL2,
39391
39681
  description: "List user prompts (main turns) from the parent session a fork was created from. Requires sessionId. Returns an error if the session has no parent history (not a fork).",
39392
39682
  inputSchema: {
39393
39683
  type: "object",
@@ -39397,7 +39687,7 @@ var FORK_SESSION_MCP_TOOL_DEFINITIONS = [
39397
39687
  }
39398
39688
  },
39399
39689
  {
39400
- name: GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL,
39690
+ name: GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL2,
39401
39691
  description: "Full transcript for one parent-session turn, including tool calls and agent messages. Requires sessionId and turnId. Returns an error if the session has no parent history (not a fork).",
39402
39692
  inputSchema: {
39403
39693
  type: "object",
@@ -39413,7 +39703,130 @@ var FORK_SESSION_MCP_TOOL_DEFINITIONS = [
39413
39703
 
39414
39704
  // src/mcp/tools/session-history/fork/is-fork-session-mcp-tool-name.ts
39415
39705
  function isForkSessionMcpToolName(name) {
39416
- return name === LIST_PARENT_SESSION_PROMPTS_TOOL || name === GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL;
39706
+ return name === LIST_PARENT_SESSION_PROMPTS_TOOL2 || name === GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL2;
39707
+ }
39708
+
39709
+ // src/mcp/tools/integration-content/tool-names.ts
39710
+ var GET_INTEGRATION_CONTENT_TOOL2 = "get_integration_content";
39711
+
39712
+ // src/mcp/tools/integration-content/cloud/fetch-integration-content.ts
39713
+ async function fetchCloudIntegrationContent(params) {
39714
+ return fetchInternalApiJson({
39715
+ ...params,
39716
+ path: `/internal/sessions/${encodeURIComponent(params.sessionId)}/integrations/content`,
39717
+ errorLabel: "Integration content fetch failed",
39718
+ method: "POST",
39719
+ body: {
39720
+ url: params.url,
39721
+ associateAsSessionTicket: params.associateAsSessionTicket !== false
39722
+ }
39723
+ });
39724
+ }
39725
+
39726
+ // src/mcp/tools/integration-content/format-integration-content-for-mcp.ts
39727
+ function formatIntegrationContentForMcp(result) {
39728
+ if (!result.ok) {
39729
+ const lines2 = [`status: ${result.code}`, `message: ${result.message}`];
39730
+ if (result.integrationType) lines2.push(`integrationType: ${result.integrationType}`);
39731
+ if (result.retryable) lines2.push("retryable: true");
39732
+ lines2.push(...formatSessionTicketAssociationLines(result.sessionTicketAssociation));
39733
+ return lines2.join("\n");
39734
+ }
39735
+ const lines = [
39736
+ formatIntegrationContentBody(result.integrationType, result.content),
39737
+ ...formatSessionTicketAssociationLines(result.sessionTicketAssociation)
39738
+ ];
39739
+ return lines.join("\n");
39740
+ }
39741
+ function formatSessionTicketAssociationLines(association) {
39742
+ if (association.status === "associated") {
39743
+ const title = association.externalTicket.displayTitle?.trim() || association.externalTicket.normalizedUrl;
39744
+ return ["", "--- session ticket ---", "status: associated", `displayTitle: ${title}`];
39745
+ }
39746
+ if (association.status === "failed") {
39747
+ return ["", "--- session ticket ---", "status: failed", `reason: ${association.reason}`];
39748
+ }
39749
+ return ["", "--- session ticket ---", `status: ${association.status}`, `reason: ${association.reason}`];
39750
+ }
39751
+ function formatIntegrationContentBody(integrationType, content) {
39752
+ const lines = [
39753
+ `integrationType: ${integrationType}`,
39754
+ `title: ${content.title}`,
39755
+ `url: ${content.url}`,
39756
+ "",
39757
+ "--- body ---",
39758
+ content.body
39759
+ ];
39760
+ if (content.comments?.length) {
39761
+ lines.push("", "--- comments ---");
39762
+ for (const comment of content.comments) {
39763
+ lines.push(`[${comment.createdAt}] ${comment.author}:`, comment.body, "");
39764
+ }
39765
+ }
39766
+ const threadMessages = content.threadMessages;
39767
+ if (threadMessages?.length) {
39768
+ lines.push("", "--- thread messages ---");
39769
+ for (const msg of threadMessages) {
39770
+ lines.push(`[${msg.ts}] ${msg.displayName}: ${msg.text}`);
39771
+ }
39772
+ }
39773
+ if (content.metadata && Object.keys(content.metadata).length > 0) {
39774
+ lines.push("", "--- metadata ---", JSON.stringify(content.metadata, null, 2));
39775
+ }
39776
+ return lines.join("\n");
39777
+ }
39778
+
39779
+ // src/mcp/tools/integration-content/call-integration-content-mcp-tool.ts
39780
+ async function callIntegrationContentMcpTool(ctx, cloud, name, args) {
39781
+ if (name !== GET_INTEGRATION_CONTENT_TOOL2) {
39782
+ return mcpTextResult(`Unknown integration content tool: ${name}`, true);
39783
+ }
39784
+ const sessionId = ctx.sessionId.trim();
39785
+ if (!sessionId) return mcpTextResult("sessionId is required.", true);
39786
+ const url2 = typeof args.url === "string" ? args.url.trim() : "";
39787
+ if (!url2) return mcpTextResult("url is required.", true);
39788
+ const associateAsSessionTicket = args.associateAsSessionTicket !== false;
39789
+ const fetched = await fetchCloudIntegrationContent({
39790
+ sessionId,
39791
+ url: url2,
39792
+ associateAsSessionTicket,
39793
+ cloudApiBaseUrl: cloud.cloudApiBaseUrl,
39794
+ getCloudAccessToken: cloud.getCloudAccessToken
39795
+ });
39796
+ if (!fetched.ok) return mcpTextResult(fetched.error, true);
39797
+ const text = formatIntegrationContentForMcp(fetched.data);
39798
+ const isError = !fetched.data.ok;
39799
+ return mcpTextResult(text, isError);
39800
+ }
39801
+
39802
+ // src/mcp/tools/integration-content/tool-definitions.ts
39803
+ var SESSION_ID_SCHEMA2 = {
39804
+ type: "string",
39805
+ description: "Id of the current session. Required on every tool call so the workspace integration credentials can be resolved."
39806
+ };
39807
+ var INTEGRATION_CONTENT_MCP_TOOL_DEFINITIONS = [
39808
+ {
39809
+ name: GET_INTEGRATION_CONTENT_TOOL2,
39810
+ description: "Fetch the full content of a supported external integration link (Linear, GitHub, Jira, Notion, Slack thread, Zoom meeting, Asana). Requires sessionId and url. By default, links the URL as this session external ticket when the session has none yet. Pass associateAsSessionTicket: false to fetch content only (e.g. additional context links). Returns an error when the URL is unsupported, the integration is not connected, or content is temporarily unavailable (retry may succeed).",
39811
+ inputSchema: {
39812
+ type: "object",
39813
+ properties: {
39814
+ sessionId: SESSION_ID_SCHEMA2,
39815
+ url: { type: "string", description: "External integration URL to fetch" },
39816
+ associateAsSessionTicket: {
39817
+ type: "boolean",
39818
+ description: "Defaults to true. When true and the session has no linked external ticket yet, links this URL as the session external ticket. Pass false when fetching additional links for context only."
39819
+ }
39820
+ },
39821
+ required: ["sessionId", "url"],
39822
+ additionalProperties: false
39823
+ }
39824
+ }
39825
+ ];
39826
+
39827
+ // src/mcp/tools/integration-content/index.ts
39828
+ function isIntegrationContentMcpToolName(name) {
39829
+ return name === GET_INTEGRATION_CONTENT_TOOL2;
39417
39830
  }
39418
39831
 
39419
39832
  // src/mcp/bridge-mcp-tools.ts
@@ -39426,7 +39839,7 @@ function requireCloud(shared) {
39426
39839
  function createBridgeMcpToolRegistry(shared) {
39427
39840
  const cloud = requireCloud(shared);
39428
39841
  return {
39429
- listTools: async () => [...FORK_SESSION_MCP_TOOL_DEFINITIONS],
39842
+ listTools: async () => [...FORK_SESSION_MCP_TOOL_DEFINITIONS, ...INTEGRATION_CONTENT_MCP_TOOL_DEFINITIONS],
39430
39843
  callTool: async (name, args) => {
39431
39844
  if (isForkSessionMcpToolName(name)) {
39432
39845
  if (!cloud) {
@@ -39444,6 +39857,22 @@ function createBridgeMcpToolRegistry(shared) {
39444
39857
  }
39445
39858
  return callForkSessionMcpTool({ ...shared, sessionId }, cloud, name, args);
39446
39859
  }
39860
+ if (isIntegrationContentMcpToolName(name)) {
39861
+ if (!cloud) {
39862
+ return {
39863
+ content: [{ type: "text", text: "Bridge MCP tools require cloud API credentials." }],
39864
+ isError: true
39865
+ };
39866
+ }
39867
+ const sessionId = typeof args.sessionId === "string" ? args.sessionId.trim() : "";
39868
+ if (!sessionId) {
39869
+ return {
39870
+ content: [{ type: "text", text: "sessionId is required." }],
39871
+ isError: true
39872
+ };
39873
+ }
39874
+ return callIntegrationContentMcpTool({ ...shared, sessionId }, cloud, name, args);
39875
+ }
39447
39876
  throw new Error(`Unknown bridge MCP tool: ${name}`);
39448
39877
  }
39449
39878
  };