salesforce-metadata-mcp 2.1.2 → 2.1.4

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.
@@ -1,5 +1,5 @@
1
1
  import { execSync } from "child_process";
2
- export const API_VERSION = "62.0";
2
+ export const API_VERSION = "66.0";
3
3
  // ─── Token cache ──────────────────────────────────────────────────────────────
4
4
  let cachedToken = null;
5
5
  const TOKEN_TTL_MS = 55 * 60 * 1000;
@@ -1212,26 +1212,58 @@ function buildBotXml(params) {
1212
1212
  <met:fullName>${x(params.agentName)}</met:fullName>
1213
1213
  <met:label>${x(params.label)}</met:label>
1214
1214
  ${params.description ? `<met:description>${x(params.description)}</met:description>` : ""}
1215
- <met:type>${x(params.type)}</met:type>
1216
- <met:status>Active</met:status>
1217
- ${params.company ? `<met:company>${x(params.company)}</met:company>` : ""}
1218
- ${params.persona ? `<met:persona>${x(params.persona)}</met:persona>` : ""}
1219
- <met:tone>${x(params.tone)}</met:tone>
1220
- ${params.instructions ? `<met:systemPrompt>${x(params.instructions)}</met:systemPrompt>` : ""}
1215
+ <met:agentTemplate>AiCopilot__AgentforceAgent</met:agentTemplate>
1216
+ <met:agentType>EinsteinServiceAgent</met:agentType>
1217
+ <met:botSource>None</met:botSource>
1218
+ <met:logPrivateConversationData>false</met:logPrivateConversationData>
1219
+ <met:richContentEnabled>true</met:richContentEnabled>
1220
+ <met:sessionTimeout>0</met:sessionTimeout>
1221
+ <met:type>${x(params.type ?? "EinsteinCopilot")}</met:type>
1222
+ ${params.systemPrompt ? `<met:systemPrompt>${x(params.systemPrompt)}</met:systemPrompt>` : ""}
1223
+ ${params.openingMessage ? `<met:welcomeMessage>${x(params.openingMessage)}</met:welcomeMessage>` : ""}
1221
1224
  </met:metadata>`;
1222
1225
  }
1223
- function buildBotVersionXml(params) {
1224
- const actionsXml = (params.actions ?? []).map(a => `
1225
- <met:botActions>
1226
- <met:botActionName>${x(a)}</met:botActionName>
1227
- </met:botActions>`).join("\n");
1228
- return `<met:metadata xsi:type="met:BotVersion" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
1229
- <met:fullName>${x(params.agentName)}.${x(params.topicName)}</met:fullName>
1230
- <met:label>${x(params.label)}</met:label>
1226
+ function buildGenAiPluginXml(params) {
1227
+ const instructionsXml = (params.instructions ?? []).map((instr, i) => `
1228
+ <met:genAiPluginInstructions>
1229
+ <met:description>${x(instr)}</met:description>
1230
+ <met:developerName>instruction_${i}</met:developerName>
1231
+ <met:masterLabel>instruction_${i}</met:masterLabel>
1232
+ <met:sortOrder>${i}</met:sortOrder>
1233
+ </met:genAiPluginInstructions>`).join("\n");
1234
+ const functionsXml = (params.actions ?? []).map(a => `
1235
+ <met:genAiFunctions>
1236
+ <met:functionName>${x(a)}</met:functionName>
1237
+ </met:genAiFunctions>`).join("\n");
1238
+ return `<met:metadata xsi:type="met:GenAiPlugin" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
1239
+ <met:fullName>${x(params.topicName)}</met:fullName>
1240
+ <met:masterLabel>${x(params.label)}</met:masterLabel>
1231
1241
  <met:description>${x(params.description)}</met:description>
1232
1242
  <met:scope>${x(params.scope)}</met:scope>
1233
- ${params.instructions ? `<met:instructions>${x(params.instructions)}</met:instructions>` : ""}
1234
- ${actionsXml}
1243
+ <met:pluginType>Topic</met:pluginType>
1244
+ <met:canEscalate>${params.escalationEnabled === true ? "true" : "false"}</met:canEscalate>
1245
+ <met:language>en_US</met:language>
1246
+ ${params.fallbackTopic ? `<met:fallbackPlugin>${x(params.fallbackTopic)}</met:fallbackPlugin>` : ""}
1247
+ ${instructionsXml}
1248
+ ${functionsXml}
1249
+ </met:metadata>`;
1250
+ }
1251
+ function buildGenAiPlannerBundleXml(params) {
1252
+ const pluginsXml = params.topicNames.map(t => `
1253
+ <met:genAiPlugins>
1254
+ <met:genAiPluginName>${x(t)}</met:genAiPluginName>
1255
+ </met:genAiPlugins>`).join("\n");
1256
+ const dataLibXml = params.dataLibraryName ? `
1257
+ <met:dataLibraries>
1258
+ <met:dataLibraryName>${x(params.dataLibraryName)}</met:dataLibraryName>
1259
+ </met:dataLibraries>` : "";
1260
+ return `<met:metadata xsi:type="met:GenAiPlannerBundle" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
1261
+ <met:fullName>${x(params.plannerName)}</met:fullName>
1262
+ <met:masterLabel>${x(params.label)}</met:masterLabel>
1263
+ ${params.description ? `<met:description>${x(params.description)}</met:description>` : ""}
1264
+ <met:plannerType>AiCopilot__ReAct</met:plannerType>
1265
+ ${dataLibXml}
1266
+ ${pluginsXml}
1235
1267
  </met:metadata>`;
1236
1268
  }
1237
1269
  function buildMatchingRuleXml(params) {
@@ -1474,6 +1506,357 @@ export async function createAgent(auth, params) {
1474
1506
  return upsertMetadata(auth, buildBotXml(params));
1475
1507
  }
1476
1508
  export async function createAgentTopic(auth, params) {
1477
- return upsertMetadata(auth, buildBotVersionXml(params));
1509
+ return upsertMetadata(auth, buildGenAiPluginXml(params));
1510
+ }
1511
+ export async function createAgentPlanner(auth, params) {
1512
+ return upsertMetadata(auth, buildGenAiPlannerBundleXml(params));
1513
+ }
1514
+ export async function activateAgent(auth, agentApiName) {
1515
+ try {
1516
+ const resp = await fetchWithTimeout(`${auth.instanceUrl}/services/data/v${API_VERSION}/connect/einstein/copilot/${agentApiName}/activate`, { method: "POST", headers: { "Authorization": `Bearer ${auth.accessToken}`, "Content-Type": "application/json" } }, 30_000);
1517
+ if (resp.ok)
1518
+ return { success: true, message: `Agent '${agentApiName}' activated successfully.` };
1519
+ const body = await resp.text().catch(() => "");
1520
+ return { success: false, message: `Activation failed (HTTP ${resp.status}): ${body}` };
1521
+ }
1522
+ catch (err) {
1523
+ return { success: false, message: sanitizeError(err instanceof Error ? err.message : String(err)) };
1524
+ }
1525
+ }
1526
+ export async function deactivateAgent(auth, agentApiName) {
1527
+ try {
1528
+ const resp = await fetchWithTimeout(`${auth.instanceUrl}/services/data/v${API_VERSION}/connect/einstein/copilot/${agentApiName}/deactivate`, { method: "POST", headers: { "Authorization": `Bearer ${auth.accessToken}`, "Content-Type": "application/json" } }, 30_000);
1529
+ if (resp.ok)
1530
+ return { success: true, message: `Agent '${agentApiName}' deactivated successfully.` };
1531
+ const body = await resp.text().catch(() => "");
1532
+ return { success: false, message: `Deactivation failed (HTTP ${resp.status}): ${body}` };
1533
+ }
1534
+ catch (err) {
1535
+ return { success: false, message: sanitizeError(err instanceof Error ? err.message : String(err)) };
1536
+ }
1537
+ }
1538
+ // ─── Metadata read/list/delete helpers ───────────────────────────────────────
1539
+ export async function readMetadataItem(auth, type, fullName) {
1540
+ const body = `<met:readMetadata>
1541
+ <met:type>${type}</met:type>
1542
+ <met:fullNames>${x(fullName)}</met:fullNames>
1543
+ </met:readMetadata>`;
1544
+ try {
1545
+ const xml = await callMetadataSoap(auth, "readMetadata", body);
1546
+ const error = extractSoapError(xml);
1547
+ if (error)
1548
+ return { success: false, message: error };
1549
+ return { success: true, rawXml: xml };
1550
+ }
1551
+ catch (err) {
1552
+ return { success: false, message: sanitizeError(err instanceof Error ? err.message : String(err)) };
1553
+ }
1554
+ }
1555
+ export async function listMetadataType(auth, type) {
1556
+ const body = `<met:listMetadata>
1557
+ <met:queries><met:type>${x(type)}</met:type></met:queries>
1558
+ <met:asOfVersion>${API_VERSION}</met:asOfVersion>
1559
+ </met:listMetadata>`;
1560
+ try {
1561
+ const xml = await callMetadataSoap(auth, "listMetadata", body);
1562
+ const error = extractSoapError(xml);
1563
+ if (error)
1564
+ return { success: false, message: error, items: [] };
1565
+ const items = [];
1566
+ for (const block of [...xml.matchAll(/<result>([\s\S]*?)<\/result>/gi)]) {
1567
+ const inner = block[1];
1568
+ const fullNameMatch = inner.match(/<fullName[^>]*>([\s\S]*?)<\/fullName>/i);
1569
+ if (fullNameMatch) {
1570
+ const labelMatch = inner.match(/<label[^>]*>([\s\S]*?)<\/label>/i);
1571
+ const lastModifiedMatch = inner.match(/<lastModifiedDate[^>]*>([\s\S]*?)<\/lastModifiedDate>/i);
1572
+ items.push({
1573
+ fullName: fullNameMatch[1].trim(),
1574
+ label: labelMatch?.[1].trim() ?? "",
1575
+ lastModifiedDate: lastModifiedMatch?.[1].trim() ?? "",
1576
+ type,
1577
+ });
1578
+ }
1579
+ }
1580
+ return { success: true, items };
1581
+ }
1582
+ catch (err) {
1583
+ return { success: false, message: sanitizeError(err instanceof Error ? err.message : String(err)), items: [] };
1584
+ }
1585
+ }
1586
+ export async function deleteMetadataItems(auth, type, fullNames) {
1587
+ if (fullNames.length === 0)
1588
+ return { success: true, deleted: [], message: "Nothing to delete" };
1589
+ const fullNamesXml = fullNames.map(n => `<met:fullNames>${x(n)}</met:fullNames>`).join("\n");
1590
+ const body = `<met:deleteMetadata>
1591
+ <met:type>${x(type)}</met:type>
1592
+ ${fullNamesXml}
1593
+ </met:deleteMetadata>`;
1594
+ try {
1595
+ const xml = await callMetadataSoap(auth, "deleteMetadata", body);
1596
+ const error = extractSoapError(xml);
1597
+ if (error)
1598
+ return { success: false, message: error, deleted: [] };
1599
+ const deleted = [];
1600
+ const errors = [];
1601
+ for (const block of [...xml.matchAll(/<result>([\s\S]*?)<\/result>/gi)]) {
1602
+ const inner = block[1];
1603
+ const fullNameMatch = inner.match(/<fullName[^>]*>([\s\S]*?)<\/fullName>/i);
1604
+ const successMatch = inner.match(/<success>(true|false)<\/success>/i);
1605
+ const fnName = fullNameMatch?.[1].trim() ?? "";
1606
+ if (successMatch?.[1] === "true") {
1607
+ deleted.push(fnName);
1608
+ }
1609
+ else {
1610
+ const msgMatch = inner.match(/<message[^>]*>([\s\S]*?)<\/message>/i);
1611
+ errors.push(`${fnName}: ${msgMatch?.[1].trim() ?? "Unknown error"}`);
1612
+ }
1613
+ }
1614
+ return {
1615
+ success: errors.length === 0,
1616
+ deleted,
1617
+ message: deleted.length > 0 ? `Deleted: ${deleted.join(", ")}` : "Nothing deleted",
1618
+ ...(errors.length > 0 ? { errors } : {}),
1619
+ };
1620
+ }
1621
+ catch (err) {
1622
+ return { success: false, message: sanitizeError(err instanceof Error ? err.message : String(err)), deleted: [] };
1623
+ }
1624
+ }
1625
+ // ─── Agentforce query/management functions ────────────────────────────────────
1626
+ export async function getAgent(auth, agentApiName) {
1627
+ try {
1628
+ let status = "Unknown";
1629
+ const statusResp = await fetchWithTimeout(`${auth.instanceUrl}/services/data/v${API_VERSION}/connect/einstein/copilot/${agentApiName}`, { method: "GET", headers: { "Authorization": `Bearer ${auth.accessToken}`, "Content-Type": "application/json" } }, 15_000).catch(() => null);
1630
+ if (statusResp?.ok) {
1631
+ const data = await statusResp.json().catch(() => ({}));
1632
+ status = data.status ?? data.botStatus ?? "Unknown";
1633
+ }
1634
+ const [botResult, pluginList, funcList, plannerList] = await Promise.all([
1635
+ readMetadataItem(auth, "Bot", agentApiName),
1636
+ listMetadataType(auth, "GenAiPlugin"),
1637
+ listMetadataType(auth, "GenAiFunction"),
1638
+ listMetadataType(auth, "GenAiPlannerBundle"),
1639
+ ]);
1640
+ return {
1641
+ success: true,
1642
+ agent: { apiName: agentApiName, status, metadataFound: botResult.success },
1643
+ topics: pluginList.items,
1644
+ actions: funcList.items,
1645
+ planners: plannerList.items,
1646
+ message: `Agent '${agentApiName}' — status: ${status}, ${pluginList.items.length} topic(s), ${funcList.items.length} action(s), ${plannerList.items.length} planner(s).`,
1647
+ };
1648
+ }
1649
+ catch (err) {
1650
+ return { success: false, message: sanitizeError(err instanceof Error ? err.message : String(err)) };
1651
+ }
1652
+ }
1653
+ export async function listAgents(auth) {
1654
+ try {
1655
+ const botList = await listMetadataType(auth, "Bot");
1656
+ if (!botList.success)
1657
+ return { success: false, message: botList.message ?? "Failed to list agents", agents: [] };
1658
+ const agents = [];
1659
+ for (const bot of botList.items) {
1660
+ let status = "Unknown";
1661
+ const resp = await fetchWithTimeout(`${auth.instanceUrl}/services/data/v${API_VERSION}/connect/einstein/copilot/${bot.fullName}`, { method: "GET", headers: { "Authorization": `Bearer ${auth.accessToken}` } }, 10_000).catch(() => null);
1662
+ if (resp?.ok) {
1663
+ const data = await resp.json().catch(() => ({}));
1664
+ status = data.status ?? data.botStatus ?? "Unknown";
1665
+ }
1666
+ agents.push({ apiName: bot.fullName, label: bot.label, status, lastModifiedDate: bot.lastModifiedDate });
1667
+ }
1668
+ return { success: true, agents, message: `Found ${agents.length} agent(s).` };
1669
+ }
1670
+ catch (err) {
1671
+ return { success: false, message: sanitizeError(err instanceof Error ? err.message : String(err)), agents: [] };
1672
+ }
1673
+ }
1674
+ export async function updateAgentTopic(auth, params, agentApiName) {
1675
+ try {
1676
+ if (agentApiName) {
1677
+ const deactResult = await deactivateAgent(auth, agentApiName);
1678
+ if (!deactResult.success)
1679
+ console.error(`Warning: deactivation returned: ${deactResult.message}`);
1680
+ }
1681
+ const result = await upsertMetadata(auth, buildGenAiPluginXml(params));
1682
+ if (agentApiName) {
1683
+ const actResult = await activateAgent(auth, agentApiName);
1684
+ if (!actResult.success)
1685
+ return { ...result, warning: `Topic updated but agent reactivation failed: ${actResult.message}` };
1686
+ }
1687
+ return result;
1688
+ }
1689
+ catch (err) {
1690
+ if (agentApiName)
1691
+ await activateAgent(auth, agentApiName).catch(() => { });
1692
+ return { success: false, message: sanitizeError(err instanceof Error ? err.message : String(err)) };
1693
+ }
1694
+ }
1695
+ export async function deleteAgent(auth, params) {
1696
+ const deleted = [];
1697
+ const errors = [];
1698
+ try {
1699
+ await deactivateAgent(auth, params.agentApiName).catch(() => { });
1700
+ const botRead = await readMetadataItem(auth, "Bot", params.agentApiName);
1701
+ let topicsToDelete = [];
1702
+ let actionsToDelete = [];
1703
+ let plannerToDelete = null;
1704
+ if (botRead.success && botRead.rawXml) {
1705
+ const plannerMatch = botRead.rawXml.match(/<plannerBundle[^>]*>([\s\S]*?)<\/plannerBundle>/i)
1706
+ || botRead.rawXml.match(/<plannerBundleName[^>]*>([\s\S]*?)<\/plannerBundleName>/i);
1707
+ if (plannerMatch)
1708
+ plannerToDelete = plannerMatch[1].trim();
1709
+ }
1710
+ if ((params.deleteTopics || params.deleteActions) && plannerToDelete) {
1711
+ const plannerRead = await readMetadataItem(auth, "GenAiPlannerBundle", plannerToDelete);
1712
+ if (plannerRead.success && plannerRead.rawXml) {
1713
+ topicsToDelete = [...plannerRead.rawXml.matchAll(/<genAiPluginName[^>]*>([\s\S]*?)<\/genAiPluginName>/gi)].map(m => m[1].trim());
1714
+ if (params.deleteActions) {
1715
+ for (const topicName of topicsToDelete) {
1716
+ const topicRead = await readMetadataItem(auth, "GenAiPlugin", topicName);
1717
+ if (topicRead.success && topicRead.rawXml) {
1718
+ const actionNames = [...topicRead.rawXml.matchAll(/<functionName[^>]*>([\s\S]*?)<\/functionName>/gi)].map(m => m[1].trim());
1719
+ actionsToDelete.push(...actionNames);
1720
+ }
1721
+ }
1722
+ actionsToDelete = [...new Set(actionsToDelete)];
1723
+ }
1724
+ }
1725
+ }
1726
+ if (actionsToDelete.length > 0) {
1727
+ const res = await deleteMetadataItems(auth, "GenAiFunction", actionsToDelete);
1728
+ deleted.push(...(res.deleted ?? []));
1729
+ if (res.errors)
1730
+ errors.push(...res.errors);
1731
+ }
1732
+ if (topicsToDelete.length > 0) {
1733
+ const res = await deleteMetadataItems(auth, "GenAiPlugin", topicsToDelete);
1734
+ deleted.push(...(res.deleted ?? []));
1735
+ if (res.errors)
1736
+ errors.push(...res.errors);
1737
+ }
1738
+ if (plannerToDelete) {
1739
+ const res = await deleteMetadataItems(auth, "GenAiPlannerBundle", [plannerToDelete]);
1740
+ deleted.push(...(res.deleted ?? []));
1741
+ if (res.errors)
1742
+ errors.push(...res.errors);
1743
+ }
1744
+ const botRes = await deleteMetadataItems(auth, "Bot", [params.agentApiName]);
1745
+ deleted.push(...(botRes.deleted ?? []));
1746
+ if (botRes.errors)
1747
+ errors.push(...botRes.errors);
1748
+ return {
1749
+ success: errors.length === 0,
1750
+ deleted,
1751
+ message: `Deleted ${deleted.length} component(s)${deleted.length > 0 ? ": " + deleted.join(", ") : ""}.`,
1752
+ ...(errors.length > 0 ? { errors } : {}),
1753
+ };
1754
+ }
1755
+ catch (err) {
1756
+ return { success: false, message: sanitizeError(err instanceof Error ? err.message : String(err)), deleted };
1757
+ }
1758
+ }
1759
+ export async function testAgent(auth, params) {
1760
+ try {
1761
+ const orgUrl = (params.orgUrl ?? auth.instanceUrl).replace(/\/$/, "");
1762
+ const externalSessionKey = `mcp_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
1763
+ const bootstrapResp = await fetchWithTimeout(`${orgUrl}/agentforce/bootstrap/nameduser`, {
1764
+ method: "POST",
1765
+ headers: { "Authorization": `Bearer ${auth.accessToken}`, "Content-Type": "application/json" },
1766
+ body: JSON.stringify({ botApiName: params.agentApiName, externalSessionKey, forceConfig: { endpoint: orgUrl } }),
1767
+ }, 30_000);
1768
+ if (!bootstrapResp.ok) {
1769
+ const body = await bootstrapResp.text().catch(() => "");
1770
+ return { success: false, message: `Bootstrap failed (HTTP ${bootstrapResp.status}): ${body.slice(0, 400)}` };
1771
+ }
1772
+ const bootstrap = await bootstrapResp.json();
1773
+ const agentToken = bootstrap.token;
1774
+ const agentUrl = (bootstrap.agentUrl ?? "").replace(/\/$/, "");
1775
+ if (!agentToken || !agentUrl)
1776
+ return { success: false, message: `Bootstrap missing token or agentUrl. Response: ${JSON.stringify(bootstrap).slice(0, 300)}` };
1777
+ const sessionResp = await fetchWithTimeout(`${agentUrl}/sessions`, {
1778
+ method: "POST",
1779
+ headers: { "Authorization": `Bearer ${agentToken}`, "Content-Type": "application/json", "x-sfdc-app-context": "EinsteinGPT", "x-client-feature-id": "ai-platform-einstein-gpt" },
1780
+ body: JSON.stringify({ externalSessionKey, instanceConfig: { endpoint: orgUrl } }),
1781
+ }, 30_000);
1782
+ if (!sessionResp.ok) {
1783
+ const body = await sessionResp.text().catch(() => "");
1784
+ return { success: false, message: `Session creation failed (HTTP ${sessionResp.status}): ${body.slice(0, 400)}` };
1785
+ }
1786
+ const sessionData = await sessionResp.json();
1787
+ const sessionId = sessionData.sessionId ?? sessionData.id;
1788
+ if (!sessionId)
1789
+ return { success: false, message: `No sessionId in response: ${JSON.stringify(sessionData).slice(0, 300)}` };
1790
+ const msgResp = await fetchWithTimeout(`${agentUrl}/sessions/${sessionId}/messages`, {
1791
+ method: "POST",
1792
+ headers: { "Authorization": `Bearer ${agentToken}`, "Content-Type": "application/json", "x-sfdc-app-context": "EinsteinGPT", "x-client-feature-id": "ai-platform-einstein-gpt" },
1793
+ body: JSON.stringify({ message: { role: "user", content: [{ type: "text", text: params.message }] }, variables: [] }),
1794
+ }, 90_000);
1795
+ if (!msgResp.ok) {
1796
+ const body = await msgResp.text().catch(() => "");
1797
+ return { success: false, sessionId, message: `Message failed (HTTP ${msgResp.status}): ${body.slice(0, 400)}` };
1798
+ }
1799
+ const msgData = await msgResp.json();
1800
+ const messages = msgData.messages ?? msgData.result?.messages ?? [];
1801
+ const responseText = messages
1802
+ .filter(m => m.type === "Reply" || m.role === "agent")
1803
+ .map(m => {
1804
+ if (typeof m.message === "string")
1805
+ return m.message;
1806
+ if (Array.isArray(m.content))
1807
+ return m.content.map(c => c.text ?? "").join("");
1808
+ return m.text ?? "";
1809
+ })
1810
+ .filter(Boolean)
1811
+ .join("\n")
1812
+ .trim();
1813
+ return {
1814
+ success: true,
1815
+ sessionId,
1816
+ response: responseText || JSON.stringify(msgData).slice(0, 1000),
1817
+ message: responseText ? "Agent responded successfully." : "Message sent successfully.",
1818
+ };
1819
+ }
1820
+ catch (err) {
1821
+ return { success: false, message: sanitizeError(err instanceof Error ? err.message : String(err)) };
1822
+ }
1823
+ }
1824
+ export async function getAgentLogs(auth, params) {
1825
+ try {
1826
+ const client = createClient(auth);
1827
+ const limit = params.limit ?? 20;
1828
+ let whereClause = "LogDate = TODAY";
1829
+ if (params.agentApiName) {
1830
+ const safe = params.agentApiName.replace(/'/g, "\\'");
1831
+ whereClause += ` AND (EventTarget LIKE '%${safe}%' OR EventDetails LIKE '%${safe}%')`;
1832
+ }
1833
+ const query = `SELECT EventLabel, EventTarget, EventDetails, EventDate FROM ConversationDefinitionEventLog WHERE ${whereClause} ORDER BY EventDate DESC LIMIT ${limit}`;
1834
+ const resp = await client.get(`/query?q=${encodeURIComponent(query)}`);
1835
+ const records = resp.data.records ?? [];
1836
+ const topicEvents = records.filter(r => (r.EventLabel ?? "").includes("TopicClassification")).length;
1837
+ const actionEvents = records.filter(r => (r.EventLabel ?? "").includes("ActionExecuted")).length;
1838
+ const errorEvents = records.filter(r => (r.EventLabel ?? "").toLowerCase().includes("error") || (r.EventLabel ?? "").toLowerCase().includes("fail")).length;
1839
+ const logs = records.map(r => {
1840
+ let details = r.EventDetails;
1841
+ try {
1842
+ details = JSON.parse(r.EventDetails ?? "{}");
1843
+ }
1844
+ catch { /* keep raw */ }
1845
+ return { time: r.EventDate, event: r.EventLabel, target: r.EventTarget, details };
1846
+ });
1847
+ return {
1848
+ success: true,
1849
+ totalRecords: records.length,
1850
+ summary: { topicClassifications: topicEvents, actionsExecuted: actionEvents, errors: errorEvents },
1851
+ logs,
1852
+ message: `${records.length} entries: ${topicEvents} topic classification(s), ${actionEvents} action execution(s), ${errorEvents} error(s).`,
1853
+ };
1854
+ }
1855
+ catch (err) {
1856
+ const msg = sanitizeError(err instanceof Error ? err.message : String(err));
1857
+ if (msg.includes("INVALID_TYPE") || msg.includes("ConversationDefinition"))
1858
+ return { success: false, message: "ConversationDefinitionEventLog is not available in this org. Requires Event Monitoring or Agentforce debugging enabled.", logs: [] };
1859
+ return { success: false, message: msg, logs: [] };
1860
+ }
1478
1861
  }
1479
1862
  //# sourceMappingURL=salesforce.js.map