@buildautomaton/cli 0.1.47 → 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/cli.js +640 -79
- package/dist/cli.js.map +4 -4
- package/dist/index.js +640 -79
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -25174,7 +25174,7 @@ var {
|
|
|
25174
25174
|
} = import_index.default;
|
|
25175
25175
|
|
|
25176
25176
|
// src/cli-version.ts
|
|
25177
|
-
var CLI_VERSION = "0.1.
|
|
25177
|
+
var CLI_VERSION = "0.1.49".length > 0 ? "0.1.49" : "0.0.0-dev";
|
|
25178
25178
|
|
|
25179
25179
|
// src/cli/defaults.ts
|
|
25180
25180
|
var DEFAULT_API_URL = process.env.BUILDAUTOMATON_API_URL ?? "https://api.buildautomaton.com";
|
|
@@ -25477,6 +25477,72 @@ function createCliE2eeRuntime(key) {
|
|
|
25477
25477
|
};
|
|
25478
25478
|
}
|
|
25479
25479
|
|
|
25480
|
+
// src/lib/e2ee/decrypt-stored-e2ee-content.ts
|
|
25481
|
+
function parseJsonObject(raw) {
|
|
25482
|
+
try {
|
|
25483
|
+
const parsed = JSON.parse(raw);
|
|
25484
|
+
if (parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
25485
|
+
return parsed;
|
|
25486
|
+
}
|
|
25487
|
+
} catch {
|
|
25488
|
+
return null;
|
|
25489
|
+
}
|
|
25490
|
+
return null;
|
|
25491
|
+
}
|
|
25492
|
+
function storedStringHasE2eeEnvelope(raw) {
|
|
25493
|
+
const record2 = parseJsonObject(raw);
|
|
25494
|
+
return record2 != null && isE2eeEnvelope(record2.ee);
|
|
25495
|
+
}
|
|
25496
|
+
function e2eeKeyIdFromStoredString(raw) {
|
|
25497
|
+
const record2 = parseJsonObject(raw);
|
|
25498
|
+
if (record2 != null && isE2eeEnvelope(record2.ee)) return record2.ee.k;
|
|
25499
|
+
return null;
|
|
25500
|
+
}
|
|
25501
|
+
function decryptStoredE2eeRecord(record2, e2ee) {
|
|
25502
|
+
if (!isE2eeEnvelope(record2.ee)) return record2;
|
|
25503
|
+
if (!e2ee) {
|
|
25504
|
+
throw new Error(`E2EE_REQUIRED:${record2.ee.k}`);
|
|
25505
|
+
}
|
|
25506
|
+
if (record2.ee.k !== e2ee.keyId) {
|
|
25507
|
+
throw new Error(`E2EE_KEY_MISMATCH:encrypted=${record2.ee.k}:cli=${e2ee.keyId}`);
|
|
25508
|
+
}
|
|
25509
|
+
return e2ee.decryptMessage(record2);
|
|
25510
|
+
}
|
|
25511
|
+
function formatCliE2eeDecryptError(error40, e2ee) {
|
|
25512
|
+
const message = error40 instanceof Error ? error40.message : String(error40);
|
|
25513
|
+
const required2 = /^E2EE_REQUIRED:(.+)$/.exec(message.trim());
|
|
25514
|
+
if (required2) {
|
|
25515
|
+
const keyId = required2[1]?.trim() || "unknown";
|
|
25516
|
+
return `Parent session content is encrypted (key ${keyId}) but this bridge was not started with E2EE certificates. Restart the CLI with your E2EE certificate to read fork parent history.`;
|
|
25517
|
+
}
|
|
25518
|
+
const mismatch = /^E2EE_KEY_MISMATCH:encrypted=(.+):cli=(.*)$/.exec(message.trim());
|
|
25519
|
+
if (mismatch) {
|
|
25520
|
+
const encryptedKeyId = mismatch[1]?.trim() || "unknown";
|
|
25521
|
+
const cliKeyId = mismatch[2]?.trim() || e2ee?.keyId || "none";
|
|
25522
|
+
return `Parent session content is encrypted with key ${encryptedKeyId}, but this bridge certificate key is ${cliKeyId}. Use the same E2EE certificate that was used for the parent session.`;
|
|
25523
|
+
}
|
|
25524
|
+
if (message.includes("E2EE key mismatch")) {
|
|
25525
|
+
return `Parent session content could not be decrypted: ${message}`;
|
|
25526
|
+
}
|
|
25527
|
+
return `Parent session content could not be decrypted: ${message}`;
|
|
25528
|
+
}
|
|
25529
|
+
function decryptCliE2eeTranscriptPayload(payload, e2ee) {
|
|
25530
|
+
const record2 = parseJsonObject(payload);
|
|
25531
|
+
if (!record2 || !isE2eeEnvelope(record2.ee)) return payload;
|
|
25532
|
+
const decrypted = decryptStoredE2eeRecord(record2, e2ee);
|
|
25533
|
+
if (typeof decrypted.payload === "string") return decrypted.payload;
|
|
25534
|
+
return JSON.stringify(decrypted.payload ?? decrypted);
|
|
25535
|
+
}
|
|
25536
|
+
function decryptCliE2eeMessageField(payload, field, e2ee) {
|
|
25537
|
+
if (payload == null) return null;
|
|
25538
|
+
const record2 = parseJsonObject(payload);
|
|
25539
|
+
if (!record2 || !isE2eeEnvelope(record2.ee)) return payload;
|
|
25540
|
+
const decrypted = decryptStoredE2eeRecord(record2, e2ee);
|
|
25541
|
+
const value = decrypted[field];
|
|
25542
|
+
if (value == null) return null;
|
|
25543
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
25544
|
+
}
|
|
25545
|
+
|
|
25480
25546
|
// src/e2e-certificates/certificates.ts
|
|
25481
25547
|
var E2E_CERTIFICATE_ALGORITHM = "A1";
|
|
25482
25548
|
var CERTIFICATE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".pem", ".key", ".crt"]);
|
|
@@ -27612,6 +27678,238 @@ var WebSocketMessageSchema = external_exports.object({
|
|
|
27612
27678
|
error: external_exports.string().optional()
|
|
27613
27679
|
});
|
|
27614
27680
|
|
|
27681
|
+
// ../types/src/integrations/link-detection/linear.ts
|
|
27682
|
+
function detectLinearLink(url2) {
|
|
27683
|
+
const linearMatch = url2.match(
|
|
27684
|
+
/https?:\/\/(?:app\.)?linear\.app\/([^/]+)\/issue\/([A-Z]+-\d+)/i
|
|
27685
|
+
);
|
|
27686
|
+
if (linearMatch) {
|
|
27687
|
+
return {
|
|
27688
|
+
url: url2,
|
|
27689
|
+
integrationType: "linear",
|
|
27690
|
+
resourceType: "work-item",
|
|
27691
|
+
resourceId: linearMatch[2],
|
|
27692
|
+
workspaceId: linearMatch[1]
|
|
27693
|
+
};
|
|
27694
|
+
}
|
|
27695
|
+
return null;
|
|
27696
|
+
}
|
|
27697
|
+
|
|
27698
|
+
// ../types/src/integrations/link-detection/github.ts
|
|
27699
|
+
function detectGitHubLink(url2) {
|
|
27700
|
+
const githubIssueMatch = url2.match(
|
|
27701
|
+
/https?:\/\/github\.com\/([^/]+)\/([^/]+)\/issues\/(\d+)/i
|
|
27702
|
+
);
|
|
27703
|
+
if (githubIssueMatch) {
|
|
27704
|
+
return {
|
|
27705
|
+
url: url2,
|
|
27706
|
+
integrationType: "github",
|
|
27707
|
+
resourceType: "issue",
|
|
27708
|
+
resourceId: githubIssueMatch[3],
|
|
27709
|
+
owner: githubIssueMatch[1],
|
|
27710
|
+
repo: githubIssueMatch[2]
|
|
27711
|
+
};
|
|
27712
|
+
}
|
|
27713
|
+
const githubPRMatch = url2.match(
|
|
27714
|
+
/https?:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/i
|
|
27715
|
+
);
|
|
27716
|
+
if (githubPRMatch) {
|
|
27717
|
+
return {
|
|
27718
|
+
url: url2,
|
|
27719
|
+
integrationType: "github",
|
|
27720
|
+
resourceType: "pull-request",
|
|
27721
|
+
resourceId: githubPRMatch[3],
|
|
27722
|
+
owner: githubPRMatch[1],
|
|
27723
|
+
repo: githubPRMatch[2]
|
|
27724
|
+
};
|
|
27725
|
+
}
|
|
27726
|
+
return null;
|
|
27727
|
+
}
|
|
27728
|
+
|
|
27729
|
+
// ../types/src/integrations/link-detection/jira.ts
|
|
27730
|
+
function detectJIRALink(url2) {
|
|
27731
|
+
const jiraMatch = url2.match(
|
|
27732
|
+
/https?:\/\/([^/]+)\.atlassian\.net\/(?:browse|jira\/software\/projects\/[^/]+\/issues)\/([A-Z]+-\d+)/i
|
|
27733
|
+
);
|
|
27734
|
+
if (jiraMatch) {
|
|
27735
|
+
return {
|
|
27736
|
+
url: url2,
|
|
27737
|
+
integrationType: "jira",
|
|
27738
|
+
resourceType: "issue",
|
|
27739
|
+
resourceId: jiraMatch[2],
|
|
27740
|
+
projectKey: jiraMatch[2].split("-")[0]
|
|
27741
|
+
};
|
|
27742
|
+
}
|
|
27743
|
+
return null;
|
|
27744
|
+
}
|
|
27745
|
+
|
|
27746
|
+
// ../types/src/integrations/link-detection/notion.ts
|
|
27747
|
+
function formatNotionPageId(hex) {
|
|
27748
|
+
if (hex.length !== 32) return hex;
|
|
27749
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
27750
|
+
}
|
|
27751
|
+
function detectNotionLink(url2) {
|
|
27752
|
+
const standardMatch = url2.match(
|
|
27753
|
+
/https?:\/\/(?:www\.)?notion\.(?:so|site)\/(?:[^/#?]+\/)?(?:[^/#?-]+-)?([a-f0-9]{32})/i
|
|
27754
|
+
);
|
|
27755
|
+
if (standardMatch) {
|
|
27756
|
+
return {
|
|
27757
|
+
url: url2,
|
|
27758
|
+
integrationType: "notion",
|
|
27759
|
+
resourceType: "page",
|
|
27760
|
+
resourceId: formatNotionPageId(standardMatch[1])
|
|
27761
|
+
};
|
|
27762
|
+
}
|
|
27763
|
+
const siteMatch = url2.match(
|
|
27764
|
+
/https?:\/\/([^.]+)\.notion\.(?:so|site)\/(?:[^/#?-]+-)?([a-f0-9]{32})/i
|
|
27765
|
+
);
|
|
27766
|
+
if (siteMatch) {
|
|
27767
|
+
return {
|
|
27768
|
+
url: url2,
|
|
27769
|
+
integrationType: "notion",
|
|
27770
|
+
resourceType: "page",
|
|
27771
|
+
resourceId: formatNotionPageId(siteMatch[2]),
|
|
27772
|
+
notionWorkspaceId: siteMatch[1]
|
|
27773
|
+
};
|
|
27774
|
+
}
|
|
27775
|
+
return null;
|
|
27776
|
+
}
|
|
27777
|
+
|
|
27778
|
+
// ../types/src/integrations/link-detection/slack.ts
|
|
27779
|
+
function detectSlackLink(url2) {
|
|
27780
|
+
const archiveThreadMatch = url2.match(
|
|
27781
|
+
/https?:\/\/(?:([^./]+)\.)?slack\.com\/archives\/([A-Z0-9]+)\/p(\d+)(?:\?.*)?$/i
|
|
27782
|
+
);
|
|
27783
|
+
if (archiveThreadMatch) {
|
|
27784
|
+
return {
|
|
27785
|
+
url: url2,
|
|
27786
|
+
integrationType: "slack",
|
|
27787
|
+
resourceType: "thread",
|
|
27788
|
+
resourceId: `${archiveThreadMatch[2]}-${archiveThreadMatch[3]}`,
|
|
27789
|
+
isChannel: false
|
|
27790
|
+
};
|
|
27791
|
+
}
|
|
27792
|
+
const appThreadMatch = url2.match(
|
|
27793
|
+
/https?:\/\/app\.slack\.com\/client\/([^/]+)\/([A-Z0-9]+)\/thread\/[A-Z0-9]+-(\d+)/i
|
|
27794
|
+
);
|
|
27795
|
+
if (appThreadMatch) {
|
|
27796
|
+
return {
|
|
27797
|
+
url: url2,
|
|
27798
|
+
integrationType: "slack",
|
|
27799
|
+
resourceType: "thread",
|
|
27800
|
+
resourceId: `${appThreadMatch[2]}-${appThreadMatch[3]}`,
|
|
27801
|
+
isChannel: false
|
|
27802
|
+
};
|
|
27803
|
+
}
|
|
27804
|
+
const channelOnlyMatch = url2.match(
|
|
27805
|
+
/https?:\/\/(?:app\.)?(?:([^./]+)\.)?slack\.com\/archives\/([A-Z0-9]+)\/?(\?.*)?$/i
|
|
27806
|
+
);
|
|
27807
|
+
if (channelOnlyMatch && !url2.includes("/p")) {
|
|
27808
|
+
return {
|
|
27809
|
+
url: url2,
|
|
27810
|
+
integrationType: "slack",
|
|
27811
|
+
resourceType: "channel",
|
|
27812
|
+
resourceId: channelOnlyMatch[2],
|
|
27813
|
+
isChannel: true
|
|
27814
|
+
};
|
|
27815
|
+
}
|
|
27816
|
+
return null;
|
|
27817
|
+
}
|
|
27818
|
+
|
|
27819
|
+
// ../types/src/integrations/link-detection/zoom.ts
|
|
27820
|
+
function detectZoomLink(url2) {
|
|
27821
|
+
try {
|
|
27822
|
+
const u = new URL(url2);
|
|
27823
|
+
const host = u.hostname.toLowerCase();
|
|
27824
|
+
if (!host.endsWith("zoom.us") && !host.endsWith("zoom.com")) return null;
|
|
27825
|
+
const pathParts = u.pathname.split("/").filter(Boolean);
|
|
27826
|
+
if (pathParts.length >= 2 && (pathParts[0] === "j" || pathParts[0] === "s" || pathParts[0] === "my")) {
|
|
27827
|
+
const meetingId = pathParts[1].replace(/\s/g, "");
|
|
27828
|
+
if (meetingId.length >= 9) {
|
|
27829
|
+
return {
|
|
27830
|
+
url: url2,
|
|
27831
|
+
integrationType: "zoom",
|
|
27832
|
+
resourceType: "meeting",
|
|
27833
|
+
resourceId: meetingId,
|
|
27834
|
+
zoomMeetingId: meetingId
|
|
27835
|
+
};
|
|
27836
|
+
}
|
|
27837
|
+
}
|
|
27838
|
+
} catch {
|
|
27839
|
+
}
|
|
27840
|
+
return null;
|
|
27841
|
+
}
|
|
27842
|
+
|
|
27843
|
+
// ../types/src/integrations/link-detection/asana.ts
|
|
27844
|
+
var ASANA_TASK_GID = /\d{10,}/;
|
|
27845
|
+
function parseAsanaTaskGid(segment) {
|
|
27846
|
+
const trimmed2 = segment.trim();
|
|
27847
|
+
if (!ASANA_TASK_GID.test(trimmed2)) return null;
|
|
27848
|
+
return trimmed2;
|
|
27849
|
+
}
|
|
27850
|
+
function detectAsanaLink(url2) {
|
|
27851
|
+
const v1ProjectMatch = url2.match(
|
|
27852
|
+
/https?:\/\/app\.asana\.com\/1\/[^/]+\/project\/([^/?#]+)\/task\/([^/?#]+)/i
|
|
27853
|
+
);
|
|
27854
|
+
if (v1ProjectMatch) {
|
|
27855
|
+
const taskGid = parseAsanaTaskGid(v1ProjectMatch[2]);
|
|
27856
|
+
if (!taskGid) return null;
|
|
27857
|
+
return {
|
|
27858
|
+
url: url2,
|
|
27859
|
+
integrationType: "asana",
|
|
27860
|
+
resourceType: "task",
|
|
27861
|
+
resourceId: taskGid,
|
|
27862
|
+
asanaProjectGid: v1ProjectMatch[1]
|
|
27863
|
+
};
|
|
27864
|
+
}
|
|
27865
|
+
const v1TaskMatch = url2.match(/https?:\/\/app\.asana\.com\/1\/[^/]+(?:\/[^/]+)*\/task\/([^/?#]+)/i);
|
|
27866
|
+
if (v1TaskMatch) {
|
|
27867
|
+
const taskGid = parseAsanaTaskGid(v1TaskMatch[1]);
|
|
27868
|
+
if (!taskGid) return null;
|
|
27869
|
+
return {
|
|
27870
|
+
url: url2,
|
|
27871
|
+
integrationType: "asana",
|
|
27872
|
+
resourceType: "task",
|
|
27873
|
+
resourceId: taskGid
|
|
27874
|
+
};
|
|
27875
|
+
}
|
|
27876
|
+
const legacyMatch = url2.match(/https?:\/\/app\.asana\.com\/0\/([^/?#]+)\/([^/?#]+)/i);
|
|
27877
|
+
if (legacyMatch) {
|
|
27878
|
+
const projectGid = legacyMatch[1];
|
|
27879
|
+
const taskGid = parseAsanaTaskGid(legacyMatch[2]);
|
|
27880
|
+
if (!taskGid) return null;
|
|
27881
|
+
if (projectGid === "inbox" || projectGid === "my_tasks") {
|
|
27882
|
+
return null;
|
|
27883
|
+
}
|
|
27884
|
+
return {
|
|
27885
|
+
url: url2,
|
|
27886
|
+
integrationType: "asana",
|
|
27887
|
+
resourceType: "task",
|
|
27888
|
+
resourceId: taskGid,
|
|
27889
|
+
asanaProjectGid: projectGid === "0" ? void 0 : projectGid
|
|
27890
|
+
};
|
|
27891
|
+
}
|
|
27892
|
+
return null;
|
|
27893
|
+
}
|
|
27894
|
+
|
|
27895
|
+
// ../types/src/integrations/link-detection/index.ts
|
|
27896
|
+
function detectIntegrationLink(url2) {
|
|
27897
|
+
return detectLinearLink(url2) || detectGitHubLink(url2) || detectJIRALink(url2) || detectNotionLink(url2) || detectSlackLink(url2) || detectZoomLink(url2) || detectAsanaLink(url2);
|
|
27898
|
+
}
|
|
27899
|
+
function extractIntegrationLinks(text) {
|
|
27900
|
+
const urlRegex = /https?:\/\/[^\s<>"{}|\\^`[\]]+/gi;
|
|
27901
|
+
const urls = text.match(urlRegex) || [];
|
|
27902
|
+
const links = [];
|
|
27903
|
+
for (const url2 of urls) {
|
|
27904
|
+
const detected = detectIntegrationLink(url2);
|
|
27905
|
+
if (detected) links.push(detected);
|
|
27906
|
+
}
|
|
27907
|
+
return links;
|
|
27908
|
+
}
|
|
27909
|
+
function extractFetchableIntegrationLinks(text) {
|
|
27910
|
+
return extractIntegrationLinks(text).filter((link) => !(link.integrationType === "slack" && link.isChannel));
|
|
27911
|
+
}
|
|
27912
|
+
|
|
27615
27913
|
// ../types/src/checkpoints.ts
|
|
27616
27914
|
init_zod();
|
|
27617
27915
|
var CheckpointKindSchema = external_exports.enum(["daily", "weekly", "overall"]);
|
|
@@ -28039,6 +28337,16 @@ var GitRepoMetaSchema = external_exports.object({
|
|
|
28039
28337
|
updatedAt: external_exports.string()
|
|
28040
28338
|
});
|
|
28041
28339
|
|
|
28340
|
+
// ../types/src/bridge-mcp-tool-display.ts
|
|
28341
|
+
var GET_INTEGRATION_CONTENT_TOOL = "get_integration_content";
|
|
28342
|
+
var LIST_PARENT_SESSION_PROMPTS_TOOL = "list_parent_session_prompts";
|
|
28343
|
+
var GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL = "get_parent_session_turn_transcript";
|
|
28344
|
+
var BRIDGE_MCP_TOOL_LABELS = {
|
|
28345
|
+
[GET_INTEGRATION_CONTENT_TOOL]: "Fetch external ticket content",
|
|
28346
|
+
[LIST_PARENT_SESSION_PROMPTS_TOOL]: "List parent session prompts",
|
|
28347
|
+
[GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL]: "Read parent session transcript"
|
|
28348
|
+
};
|
|
28349
|
+
|
|
28042
28350
|
// ../types/src/claude-code-permission-mode.ts
|
|
28043
28351
|
var CLAUDE_CODE_PERMISSION_MODES = [
|
|
28044
28352
|
"default",
|
|
@@ -36081,54 +36389,109 @@ function buildForkedSessionAgentPrompt(userPrompt, childSessionId, parentSession
|
|
|
36081
36389
|
].join("\n");
|
|
36082
36390
|
}
|
|
36083
36391
|
|
|
36084
|
-
// src/mcp/tools/session-history/
|
|
36392
|
+
// src/mcp/tools/session-history/cloud/internal-api.ts
|
|
36085
36393
|
function internalApiBase(cloudApiBaseUrl) {
|
|
36086
36394
|
return cloudApiBaseUrl.replace(/\/+$/, "");
|
|
36087
36395
|
}
|
|
36088
|
-
async function
|
|
36396
|
+
async function fetchInternalApiJson(params) {
|
|
36089
36397
|
const token = params.getCloudAccessToken();
|
|
36090
36398
|
if (!token) return { ok: false, error: "Missing cloud access token." };
|
|
36091
|
-
const url2 = `${internalApiBase(params.cloudApiBaseUrl)}
|
|
36092
|
-
const
|
|
36399
|
+
const url2 = `${internalApiBase(params.cloudApiBaseUrl)}${params.path}`;
|
|
36400
|
+
const method = params.method ?? "GET";
|
|
36401
|
+
const res = await fetch(url2, {
|
|
36402
|
+
method,
|
|
36403
|
+
headers: {
|
|
36404
|
+
Authorization: `Bearer ${token}`,
|
|
36405
|
+
...params.body != null ? { "Content-Type": "application/json" } : {}
|
|
36406
|
+
},
|
|
36407
|
+
...params.body != null ? { body: JSON.stringify(params.body) } : {}
|
|
36408
|
+
});
|
|
36093
36409
|
if (!res.ok) {
|
|
36094
36410
|
const t = await res.text().catch(() => "");
|
|
36095
|
-
return { ok: false, error:
|
|
36411
|
+
return { ok: false, error: `${params.errorLabel} (${res.status}): ${t.slice(0, 200)}` };
|
|
36096
36412
|
}
|
|
36097
36413
|
const data = await res.json().catch(() => null);
|
|
36098
|
-
if (!data) return { ok: false, error:
|
|
36414
|
+
if (!data) return { ok: false, error: `Invalid ${params.errorLabel.toLowerCase()} response.` };
|
|
36099
36415
|
return { ok: true, data };
|
|
36100
36416
|
}
|
|
36101
|
-
|
|
36102
|
-
|
|
36103
|
-
|
|
36104
|
-
|
|
36105
|
-
|
|
36106
|
-
|
|
36107
|
-
|
|
36108
|
-
|
|
36417
|
+
|
|
36418
|
+
// src/mcp/tools/session-history/cloud/fetch-session-meta.ts
|
|
36419
|
+
async function fetchCloudSessionMeta(params) {
|
|
36420
|
+
return fetchInternalApiJson({
|
|
36421
|
+
...params,
|
|
36422
|
+
path: `/internal/sessions/${encodeURIComponent(params.sessionId)}/meta`,
|
|
36423
|
+
errorLabel: "Session meta fetch failed"
|
|
36424
|
+
});
|
|
36425
|
+
}
|
|
36426
|
+
|
|
36427
|
+
// src/mcp/tools/session-history/cloud/decrypt-parent-prompt-turns.ts
|
|
36428
|
+
function assertE2eeRuntimeForEnvelope(raw, e2ee) {
|
|
36429
|
+
if (storedStringHasE2eeEnvelope(raw) && !e2ee) {
|
|
36430
|
+
throw new Error(`E2EE_REQUIRED:${e2eeKeyIdFromStoredString(raw) ?? "unknown"}`);
|
|
36109
36431
|
}
|
|
36110
|
-
const data = await res.json().catch(() => null);
|
|
36111
|
-
if (!data) return { ok: false, error: "Invalid parent prompts response." };
|
|
36112
|
-
return { ok: true, data };
|
|
36113
36432
|
}
|
|
36114
|
-
|
|
36115
|
-
|
|
36116
|
-
|
|
36117
|
-
|
|
36118
|
-
|
|
36119
|
-
|
|
36120
|
-
|
|
36121
|
-
|
|
36433
|
+
function decryptParentPromptTurns(turns, e2ee) {
|
|
36434
|
+
return turns.map((turn) => {
|
|
36435
|
+
const promptRaw = typeof turn.promptText === "string" ? turn.promptText : null;
|
|
36436
|
+
const titleRaw = typeof turn.title === "string" ? turn.title : null;
|
|
36437
|
+
if (promptRaw) assertE2eeRuntimeForEnvelope(promptRaw, e2ee);
|
|
36438
|
+
if (titleRaw) assertE2eeRuntimeForEnvelope(titleRaw, e2ee);
|
|
36439
|
+
return {
|
|
36440
|
+
...turn,
|
|
36441
|
+
promptText: decryptCliE2eeMessageField(promptRaw, "prompt", e2ee),
|
|
36442
|
+
title: decryptCliE2eeMessageField(titleRaw, "title", e2ee)
|
|
36443
|
+
};
|
|
36444
|
+
});
|
|
36445
|
+
}
|
|
36446
|
+
|
|
36447
|
+
// src/mcp/tools/session-history/cloud/fetch-parent-prompts.ts
|
|
36448
|
+
async function fetchCloudParentSessionPrompts(params) {
|
|
36449
|
+
const fetched = await fetchInternalApiJson({
|
|
36450
|
+
...params,
|
|
36451
|
+
path: `/internal/sessions/${encodeURIComponent(params.childSessionId)}/parent/prompts`,
|
|
36452
|
+
errorLabel: "Parent prompts fetch failed"
|
|
36453
|
+
});
|
|
36454
|
+
if (!fetched.ok) return fetched;
|
|
36455
|
+
const turns = Array.isArray(fetched.data.turns) ? fetched.data.turns : [];
|
|
36456
|
+
try {
|
|
36457
|
+
const decryptedTurns = decryptParentPromptTurns(turns, params.e2ee);
|
|
36458
|
+
return { ok: true, data: { ...fetched.data, turns: decryptedTurns } };
|
|
36459
|
+
} catch (error40) {
|
|
36460
|
+
return { ok: false, error: formatCliE2eeDecryptError(error40, params.e2ee) };
|
|
36122
36461
|
}
|
|
36123
|
-
|
|
36124
|
-
|
|
36462
|
+
}
|
|
36463
|
+
|
|
36464
|
+
// src/mcp/tools/session-history/cloud/format-parent-transcript-text.ts
|
|
36465
|
+
function formatParentTranscriptText(rows, e2ee) {
|
|
36125
36466
|
const lines = rows.map((row) => {
|
|
36126
36467
|
const kind = typeof row.kind === "string" ? row.kind : "event";
|
|
36127
|
-
const
|
|
36468
|
+
const rawPayload = typeof row.payload === "string" ? row.payload : JSON.stringify(row.payload ?? "");
|
|
36469
|
+
if (storedStringHasE2eeEnvelope(rawPayload) && !e2ee) {
|
|
36470
|
+
throw new Error(`E2EE_REQUIRED:${e2eeKeyIdFromStoredString(rawPayload) ?? "unknown"}`);
|
|
36471
|
+
}
|
|
36472
|
+
const payload = decryptCliE2eeTranscriptPayload(rawPayload, e2ee);
|
|
36128
36473
|
return `[${kind}] ${payload}`;
|
|
36129
36474
|
});
|
|
36130
|
-
return
|
|
36475
|
+
return lines.join("\n");
|
|
36131
36476
|
}
|
|
36477
|
+
|
|
36478
|
+
// src/mcp/tools/session-history/cloud/fetch-parent-transcript.ts
|
|
36479
|
+
async function fetchCloudParentTurnTranscript(params) {
|
|
36480
|
+
const fetched = await fetchInternalApiJson({
|
|
36481
|
+
...params,
|
|
36482
|
+
path: `/internal/sessions/${encodeURIComponent(params.childSessionId)}/parent/turns/${encodeURIComponent(params.turnId)}/transcript`,
|
|
36483
|
+
errorLabel: "Transcript fetch failed"
|
|
36484
|
+
});
|
|
36485
|
+
if (!fetched.ok) return fetched;
|
|
36486
|
+
const rows = Array.isArray(fetched.data.transcript) ? fetched.data.transcript : [];
|
|
36487
|
+
try {
|
|
36488
|
+
return { ok: true, text: formatParentTranscriptText(rows, params.e2ee) };
|
|
36489
|
+
} catch (error40) {
|
|
36490
|
+
return { ok: false, error: formatCliE2eeDecryptError(error40, params.e2ee) };
|
|
36491
|
+
}
|
|
36492
|
+
}
|
|
36493
|
+
|
|
36494
|
+
// src/mcp/tools/session-history/cloud/resolve-parent-session-id.ts
|
|
36132
36495
|
async function resolveParentSessionIdForChild(params) {
|
|
36133
36496
|
const meta = await fetchCloudSessionMeta({
|
|
36134
36497
|
sessionId: params.childSessionId,
|
|
@@ -36159,6 +36522,39 @@ async function enrichForkedSessionPromptForAgent(params) {
|
|
|
36159
36522
|
return buildForkedSessionAgentPrompt(params.promptText, params.sessionId, parentSessionId);
|
|
36160
36523
|
}
|
|
36161
36524
|
|
|
36525
|
+
// src/agents/acp/build-integration-content-agent-prompt-note.ts
|
|
36526
|
+
function buildIntegrationContentAgentPromptNote(sessionId) {
|
|
36527
|
+
const sessionRef = sessionId.trim();
|
|
36528
|
+
return [
|
|
36529
|
+
"The user message includes link(s) to external integration resources (Linear, GitHub, Jira, Notion, Slack thread, Zoom, or Asana).",
|
|
36530
|
+
"Use the get_integration_content MCP tool on the buildautomaton-bridge server to fetch the full content of each link.",
|
|
36531
|
+
`When calling the tool, pass sessionId "${sessionRef}" and the URL as url.`,
|
|
36532
|
+
"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).",
|
|
36533
|
+
"If the tool reports unsupported_url, do not retry with the same URL. If it reports temporarily_unavailable, you may retry later."
|
|
36534
|
+
].join("\n");
|
|
36535
|
+
}
|
|
36536
|
+
function injectIntegrationContentAgentPromptNote(agentPrompt, sessionId) {
|
|
36537
|
+
const note = buildIntegrationContentAgentPromptNote(sessionId);
|
|
36538
|
+
const marker = "\nUser request:\n";
|
|
36539
|
+
const idx = agentPrompt.indexOf(marker);
|
|
36540
|
+
if (idx >= 0) {
|
|
36541
|
+
return `${agentPrompt.slice(0, idx)}
|
|
36542
|
+
${note}${agentPrompt.slice(idx)}`;
|
|
36543
|
+
}
|
|
36544
|
+
return `${note}
|
|
36545
|
+
|
|
36546
|
+
${agentPrompt.trim()}`;
|
|
36547
|
+
}
|
|
36548
|
+
|
|
36549
|
+
// src/agents/acp/enrich-integration-content-prompt-for-agent.ts
|
|
36550
|
+
function enrichIntegrationContentPromptForAgent(params) {
|
|
36551
|
+
if (!params.sessionId.trim()) return params.agentPromptText;
|
|
36552
|
+
if (extractFetchableIntegrationLinks(params.originalPromptText).length === 0) {
|
|
36553
|
+
return params.agentPromptText;
|
|
36554
|
+
}
|
|
36555
|
+
return injectIntegrationContentAgentPromptNote(params.agentPromptText, params.sessionId);
|
|
36556
|
+
}
|
|
36557
|
+
|
|
36162
36558
|
// src/agents/acp/send-prompt-to-agent.ts
|
|
36163
36559
|
async function sendPromptToAgent(options) {
|
|
36164
36560
|
const {
|
|
@@ -36189,6 +36585,13 @@ async function sendPromptToAgent(options) {
|
|
|
36189
36585
|
getCloudAccessToken
|
|
36190
36586
|
});
|
|
36191
36587
|
}
|
|
36588
|
+
if (sessionId) {
|
|
36589
|
+
agentPromptText = enrichIntegrationContentPromptForAgent({
|
|
36590
|
+
sessionId,
|
|
36591
|
+
originalPromptText: promptText,
|
|
36592
|
+
agentPromptText
|
|
36593
|
+
});
|
|
36594
|
+
}
|
|
36192
36595
|
let sendOpts = {};
|
|
36193
36596
|
if (attachments && attachments.length > 0) {
|
|
36194
36597
|
if (!sessionId || !cloudApiBaseUrl || !getCloudAccessToken) {
|
|
@@ -42423,16 +42826,81 @@ async function warmupAgentCapabilitiesOnConnect(params) {
|
|
|
42423
42826
|
})();
|
|
42424
42827
|
}
|
|
42425
42828
|
|
|
42426
|
-
// src/mcp/tools/session-history/fork-
|
|
42427
|
-
|
|
42428
|
-
|
|
42829
|
+
// src/mcp/tools/session-history/fork/mcp-text-result.ts
|
|
42830
|
+
function mcpTextResult(text, isError = false) {
|
|
42831
|
+
return { content: [{ type: "text", text }], ...isError ? { isError: true } : {} };
|
|
42832
|
+
}
|
|
42833
|
+
|
|
42834
|
+
// src/mcp/tools/session-history/fork/call-get-parent-session-turn-transcript.ts
|
|
42835
|
+
async function callGetParentSessionTurnTranscriptTool(ctx, cloud, childSessionId, args) {
|
|
42836
|
+
const turnId = typeof args.turnId === "string" ? args.turnId.trim() : "";
|
|
42837
|
+
if (!turnId) return mcpTextResult("turnId is required.", true);
|
|
42838
|
+
const transcript = await fetchCloudParentTurnTranscript({
|
|
42839
|
+
childSessionId,
|
|
42840
|
+
turnId,
|
|
42841
|
+
cloudApiBaseUrl: cloud.cloudApiBaseUrl,
|
|
42842
|
+
getCloudAccessToken: cloud.getCloudAccessToken,
|
|
42843
|
+
e2ee: ctx.e2ee
|
|
42844
|
+
});
|
|
42845
|
+
if (!transcript.ok) return mcpTextResult(transcript.error, true);
|
|
42846
|
+
return mcpTextResult(transcript.text);
|
|
42847
|
+
}
|
|
42848
|
+
|
|
42849
|
+
// src/mcp/tools/session-history/fork/call-list-parent-session-prompts.ts
|
|
42850
|
+
async function callListParentSessionPromptsTool(ctx, cloud, childSessionId, parentSessionId) {
|
|
42851
|
+
const detail = await fetchCloudParentSessionPrompts({
|
|
42852
|
+
childSessionId,
|
|
42853
|
+
cloudApiBaseUrl: cloud.cloudApiBaseUrl,
|
|
42854
|
+
getCloudAccessToken: cloud.getCloudAccessToken,
|
|
42855
|
+
e2ee: ctx.e2ee
|
|
42856
|
+
});
|
|
42857
|
+
if (!detail.ok) return mcpTextResult(detail.error, true);
|
|
42858
|
+
const turns = Array.isArray(detail.data.turns) ? detail.data.turns : [];
|
|
42859
|
+
const payload = turns.map((t) => ({
|
|
42860
|
+
turnId: typeof t.turnId === "string" ? t.turnId : "",
|
|
42861
|
+
title: typeof t.title === "string" ? t.title : null,
|
|
42862
|
+
status: typeof t.status === "string" ? t.status : null,
|
|
42863
|
+
promptText: typeof t.promptText === "string" ? t.promptText : null
|
|
42864
|
+
}));
|
|
42865
|
+
return mcpTextResult(JSON.stringify({ parentSessionId, turns: payload }, null, 2));
|
|
42866
|
+
}
|
|
42867
|
+
|
|
42868
|
+
// src/mcp/tools/session-history/fork/tool-names.ts
|
|
42869
|
+
var LIST_PARENT_SESSION_PROMPTS_TOOL2 = "list_parent_session_prompts";
|
|
42870
|
+
var GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL2 = "get_parent_session_turn_transcript";
|
|
42871
|
+
|
|
42872
|
+
// src/mcp/tools/session-history/fork/call-fork-session-mcp-tool.ts
|
|
42873
|
+
async function callForkSessionMcpTool(ctx, cloud, name, args) {
|
|
42874
|
+
const childSessionId = ctx.sessionId.trim();
|
|
42875
|
+
if (!childSessionId) {
|
|
42876
|
+
return mcpTextResult("sessionId is required.", true);
|
|
42877
|
+
}
|
|
42878
|
+
const parentResolved = await resolveParentSessionIdForChild({
|
|
42879
|
+
childSessionId,
|
|
42880
|
+
cloudApiBaseUrl: cloud.cloudApiBaseUrl,
|
|
42881
|
+
getCloudAccessToken: cloud.getCloudAccessToken
|
|
42882
|
+
});
|
|
42883
|
+
if (!parentResolved.ok) {
|
|
42884
|
+
return mcpTextResult(parentResolved.error, true);
|
|
42885
|
+
}
|
|
42886
|
+
const parentSessionId = parentResolved.parentSessionId;
|
|
42887
|
+
if (name === LIST_PARENT_SESSION_PROMPTS_TOOL2) {
|
|
42888
|
+
return callListParentSessionPromptsTool(ctx, cloud, childSessionId, parentSessionId);
|
|
42889
|
+
}
|
|
42890
|
+
if (name === GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL2) {
|
|
42891
|
+
return callGetParentSessionTurnTranscriptTool(ctx, cloud, childSessionId, args);
|
|
42892
|
+
}
|
|
42893
|
+
return mcpTextResult(`Unknown fork session tool: ${name}`, true);
|
|
42894
|
+
}
|
|
42895
|
+
|
|
42896
|
+
// src/mcp/tools/session-history/fork/tool-definitions.ts
|
|
42429
42897
|
var SESSION_ID_SCHEMA = {
|
|
42430
42898
|
type: "string",
|
|
42431
42899
|
description: "Id of this forked (child) session \u2014 not the parent session id. Required on every tool call."
|
|
42432
42900
|
};
|
|
42433
42901
|
var FORK_SESSION_MCP_TOOL_DEFINITIONS = [
|
|
42434
42902
|
{
|
|
42435
|
-
name:
|
|
42903
|
+
name: LIST_PARENT_SESSION_PROMPTS_TOOL2,
|
|
42436
42904
|
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).",
|
|
42437
42905
|
inputSchema: {
|
|
42438
42906
|
type: "object",
|
|
@@ -42442,7 +42910,7 @@ var FORK_SESSION_MCP_TOOL_DEFINITIONS = [
|
|
|
42442
42910
|
}
|
|
42443
42911
|
},
|
|
42444
42912
|
{
|
|
42445
|
-
name:
|
|
42913
|
+
name: GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL2,
|
|
42446
42914
|
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).",
|
|
42447
42915
|
inputSchema: {
|
|
42448
42916
|
type: "object",
|
|
@@ -42455,56 +42923,133 @@ var FORK_SESSION_MCP_TOOL_DEFINITIONS = [
|
|
|
42455
42923
|
}
|
|
42456
42924
|
}
|
|
42457
42925
|
];
|
|
42458
|
-
|
|
42459
|
-
|
|
42460
|
-
}
|
|
42926
|
+
|
|
42927
|
+
// src/mcp/tools/session-history/fork/is-fork-session-mcp-tool-name.ts
|
|
42461
42928
|
function isForkSessionMcpToolName(name) {
|
|
42462
|
-
return name ===
|
|
42929
|
+
return name === LIST_PARENT_SESSION_PROMPTS_TOOL2 || name === GET_PARENT_SESSION_TURN_TRANSCRIPT_TOOL2;
|
|
42463
42930
|
}
|
|
42464
|
-
|
|
42465
|
-
|
|
42466
|
-
|
|
42467
|
-
|
|
42931
|
+
|
|
42932
|
+
// src/mcp/tools/integration-content/tool-names.ts
|
|
42933
|
+
var GET_INTEGRATION_CONTENT_TOOL2 = "get_integration_content";
|
|
42934
|
+
|
|
42935
|
+
// src/mcp/tools/integration-content/cloud/fetch-integration-content.ts
|
|
42936
|
+
async function fetchCloudIntegrationContent(params) {
|
|
42937
|
+
return fetchInternalApiJson({
|
|
42938
|
+
...params,
|
|
42939
|
+
path: `/internal/sessions/${encodeURIComponent(params.sessionId)}/integrations/content`,
|
|
42940
|
+
errorLabel: "Integration content fetch failed",
|
|
42941
|
+
method: "POST",
|
|
42942
|
+
body: {
|
|
42943
|
+
url: params.url,
|
|
42944
|
+
associateAsSessionTicket: params.associateAsSessionTicket !== false
|
|
42945
|
+
}
|
|
42946
|
+
});
|
|
42947
|
+
}
|
|
42948
|
+
|
|
42949
|
+
// src/mcp/tools/integration-content/format-integration-content-for-mcp.ts
|
|
42950
|
+
function formatIntegrationContentForMcp(result) {
|
|
42951
|
+
if (!result.ok) {
|
|
42952
|
+
const lines2 = [`status: ${result.code}`, `message: ${result.message}`];
|
|
42953
|
+
if (result.integrationType) lines2.push(`integrationType: ${result.integrationType}`);
|
|
42954
|
+
if (result.retryable) lines2.push("retryable: true");
|
|
42955
|
+
lines2.push(...formatSessionTicketAssociationLines(result.sessionTicketAssociation));
|
|
42956
|
+
return lines2.join("\n");
|
|
42468
42957
|
}
|
|
42469
|
-
const
|
|
42470
|
-
|
|
42958
|
+
const lines = [
|
|
42959
|
+
formatIntegrationContentBody(result.integrationType, result.content),
|
|
42960
|
+
...formatSessionTicketAssociationLines(result.sessionTicketAssociation)
|
|
42961
|
+
];
|
|
42962
|
+
return lines.join("\n");
|
|
42963
|
+
}
|
|
42964
|
+
function formatSessionTicketAssociationLines(association) {
|
|
42965
|
+
if (association.status === "associated") {
|
|
42966
|
+
const title = association.externalTicket.displayTitle?.trim() || association.externalTicket.normalizedUrl;
|
|
42967
|
+
return ["", "--- session ticket ---", "status: associated", `displayTitle: ${title}`];
|
|
42968
|
+
}
|
|
42969
|
+
if (association.status === "failed") {
|
|
42970
|
+
return ["", "--- session ticket ---", "status: failed", `reason: ${association.reason}`];
|
|
42971
|
+
}
|
|
42972
|
+
return ["", "--- session ticket ---", `status: ${association.status}`, `reason: ${association.reason}`];
|
|
42973
|
+
}
|
|
42974
|
+
function formatIntegrationContentBody(integrationType, content) {
|
|
42975
|
+
const lines = [
|
|
42976
|
+
`integrationType: ${integrationType}`,
|
|
42977
|
+
`title: ${content.title}`,
|
|
42978
|
+
`url: ${content.url}`,
|
|
42979
|
+
"",
|
|
42980
|
+
"--- body ---",
|
|
42981
|
+
content.body
|
|
42982
|
+
];
|
|
42983
|
+
if (content.comments?.length) {
|
|
42984
|
+
lines.push("", "--- comments ---");
|
|
42985
|
+
for (const comment of content.comments) {
|
|
42986
|
+
lines.push(`[${comment.createdAt}] ${comment.author}:`, comment.body, "");
|
|
42987
|
+
}
|
|
42988
|
+
}
|
|
42989
|
+
const threadMessages = content.threadMessages;
|
|
42990
|
+
if (threadMessages?.length) {
|
|
42991
|
+
lines.push("", "--- thread messages ---");
|
|
42992
|
+
for (const msg of threadMessages) {
|
|
42993
|
+
lines.push(`[${msg.ts}] ${msg.displayName}: ${msg.text}`);
|
|
42994
|
+
}
|
|
42995
|
+
}
|
|
42996
|
+
if (content.metadata && Object.keys(content.metadata).length > 0) {
|
|
42997
|
+
lines.push("", "--- metadata ---", JSON.stringify(content.metadata, null, 2));
|
|
42998
|
+
}
|
|
42999
|
+
return lines.join("\n");
|
|
43000
|
+
}
|
|
43001
|
+
|
|
43002
|
+
// src/mcp/tools/integration-content/call-integration-content-mcp-tool.ts
|
|
43003
|
+
async function callIntegrationContentMcpTool(ctx, cloud, name, args) {
|
|
43004
|
+
if (name !== GET_INTEGRATION_CONTENT_TOOL2) {
|
|
43005
|
+
return mcpTextResult(`Unknown integration content tool: ${name}`, true);
|
|
43006
|
+
}
|
|
43007
|
+
const sessionId = ctx.sessionId.trim();
|
|
43008
|
+
if (!sessionId) return mcpTextResult("sessionId is required.", true);
|
|
43009
|
+
const url2 = typeof args.url === "string" ? args.url.trim() : "";
|
|
43010
|
+
if (!url2) return mcpTextResult("url is required.", true);
|
|
43011
|
+
const associateAsSessionTicket = args.associateAsSessionTicket !== false;
|
|
43012
|
+
const fetched = await fetchCloudIntegrationContent({
|
|
43013
|
+
sessionId,
|
|
43014
|
+
url: url2,
|
|
43015
|
+
associateAsSessionTicket,
|
|
42471
43016
|
cloudApiBaseUrl: cloud.cloudApiBaseUrl,
|
|
42472
43017
|
getCloudAccessToken: cloud.getCloudAccessToken
|
|
42473
43018
|
});
|
|
42474
|
-
if (!
|
|
42475
|
-
|
|
42476
|
-
|
|
42477
|
-
|
|
42478
|
-
|
|
42479
|
-
|
|
42480
|
-
|
|
42481
|
-
|
|
42482
|
-
|
|
42483
|
-
|
|
42484
|
-
|
|
42485
|
-
|
|
42486
|
-
|
|
42487
|
-
|
|
42488
|
-
|
|
42489
|
-
|
|
42490
|
-
|
|
42491
|
-
|
|
42492
|
-
|
|
42493
|
-
|
|
42494
|
-
|
|
42495
|
-
|
|
42496
|
-
|
|
42497
|
-
|
|
42498
|
-
|
|
42499
|
-
|
|
42500
|
-
|
|
42501
|
-
|
|
42502
|
-
e2ee: ctx.e2ee
|
|
42503
|
-
});
|
|
42504
|
-
if (!transcript.ok) return textResult(transcript.error, true);
|
|
42505
|
-
return textResult(transcript.text);
|
|
43019
|
+
if (!fetched.ok) return mcpTextResult(fetched.error, true);
|
|
43020
|
+
const text = formatIntegrationContentForMcp(fetched.data);
|
|
43021
|
+
const isError = !fetched.data.ok;
|
|
43022
|
+
return mcpTextResult(text, isError);
|
|
43023
|
+
}
|
|
43024
|
+
|
|
43025
|
+
// src/mcp/tools/integration-content/tool-definitions.ts
|
|
43026
|
+
var SESSION_ID_SCHEMA2 = {
|
|
43027
|
+
type: "string",
|
|
43028
|
+
description: "Id of the current session. Required on every tool call so the workspace integration credentials can be resolved."
|
|
43029
|
+
};
|
|
43030
|
+
var INTEGRATION_CONTENT_MCP_TOOL_DEFINITIONS = [
|
|
43031
|
+
{
|
|
43032
|
+
name: GET_INTEGRATION_CONTENT_TOOL2,
|
|
43033
|
+
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).",
|
|
43034
|
+
inputSchema: {
|
|
43035
|
+
type: "object",
|
|
43036
|
+
properties: {
|
|
43037
|
+
sessionId: SESSION_ID_SCHEMA2,
|
|
43038
|
+
url: { type: "string", description: "External integration URL to fetch" },
|
|
43039
|
+
associateAsSessionTicket: {
|
|
43040
|
+
type: "boolean",
|
|
43041
|
+
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."
|
|
43042
|
+
}
|
|
43043
|
+
},
|
|
43044
|
+
required: ["sessionId", "url"],
|
|
43045
|
+
additionalProperties: false
|
|
43046
|
+
}
|
|
42506
43047
|
}
|
|
42507
|
-
|
|
43048
|
+
];
|
|
43049
|
+
|
|
43050
|
+
// src/mcp/tools/integration-content/index.ts
|
|
43051
|
+
function isIntegrationContentMcpToolName(name) {
|
|
43052
|
+
return name === GET_INTEGRATION_CONTENT_TOOL2;
|
|
42508
43053
|
}
|
|
42509
43054
|
|
|
42510
43055
|
// src/mcp/bridge-mcp-tools.ts
|
|
@@ -42517,7 +43062,7 @@ function requireCloud(shared) {
|
|
|
42517
43062
|
function createBridgeMcpToolRegistry(shared) {
|
|
42518
43063
|
const cloud = requireCloud(shared);
|
|
42519
43064
|
return {
|
|
42520
|
-
listTools: async () => [...FORK_SESSION_MCP_TOOL_DEFINITIONS],
|
|
43065
|
+
listTools: async () => [...FORK_SESSION_MCP_TOOL_DEFINITIONS, ...INTEGRATION_CONTENT_MCP_TOOL_DEFINITIONS],
|
|
42521
43066
|
callTool: async (name, args) => {
|
|
42522
43067
|
if (isForkSessionMcpToolName(name)) {
|
|
42523
43068
|
if (!cloud) {
|
|
@@ -42535,6 +43080,22 @@ function createBridgeMcpToolRegistry(shared) {
|
|
|
42535
43080
|
}
|
|
42536
43081
|
return callForkSessionMcpTool({ ...shared, sessionId }, cloud, name, args);
|
|
42537
43082
|
}
|
|
43083
|
+
if (isIntegrationContentMcpToolName(name)) {
|
|
43084
|
+
if (!cloud) {
|
|
43085
|
+
return {
|
|
43086
|
+
content: [{ type: "text", text: "Bridge MCP tools require cloud API credentials." }],
|
|
43087
|
+
isError: true
|
|
43088
|
+
};
|
|
43089
|
+
}
|
|
43090
|
+
const sessionId = typeof args.sessionId === "string" ? args.sessionId.trim() : "";
|
|
43091
|
+
if (!sessionId) {
|
|
43092
|
+
return {
|
|
43093
|
+
content: [{ type: "text", text: "sessionId is required." }],
|
|
43094
|
+
isError: true
|
|
43095
|
+
};
|
|
43096
|
+
}
|
|
43097
|
+
return callIntegrationContentMcpTool({ ...shared, sessionId }, cloud, name, args);
|
|
43098
|
+
}
|
|
42538
43099
|
throw new Error(`Unknown bridge MCP tool: ${name}`);
|
|
42539
43100
|
}
|
|
42540
43101
|
};
|