Skip to content

Commit 32368ed

Browse files
shetzeljshackell-sfdccristiand391
authored
feat: add agent preview debug mode - W-18417013 (#141)
* feat: add support for getting apex debug logs during agent conversation * fix: update the snapshot and schema * Update agent.preview.md * Update agent.preview.md * Update messages/agent.preview.md Co-authored-by: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> * fix: add debug log files to output and ensure an output dir for apex debug logs * chore: bump agents lib --------- Co-authored-by: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> Co-authored-by: Cristian Dominguez <cdominguez@salesforce.com>
1 parent 113a55a commit 32368ed

6 files changed

Lines changed: 61 additions & 33 deletions

File tree

command-snapshot.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@
5555
"alias": [],
5656
"command": "agent:preview",
5757
"flagAliases": [],
58-
"flagChars": ["a", "d", "n", "o"],
59-
"flags": ["api-name", "api-version", "connected-app-user", "flags-dir", "output-dir", "target-org"],
58+
"flagChars": ["a", "d", "n", "o", "x"],
59+
"flags": ["apex-debug", "api-name", "api-version", "connected-app-user", "flags-dir", "output-dir", "target-org"],
6060
"plugin": "@salesforce/plugin-agent"
6161
},
6262
{

messages/agent.preview.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ When the session concludes, the command asks if you want to save the API respons
1313
Find the agent's API name in its main details page in your org's Agent page in Setup.
1414

1515
Before you use this command, you must complete these steps:
16-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1716

1817
1. Create a connected app in your org as described in the "Create a Connected App" section here: https://developer.salesforce.com/docs/einstein/genai/guide/agent-api-get-started.html#create-a-connected-app. Do these four additional steps:
1918

@@ -51,6 +50,10 @@ Username or alias of the connected app user that's configured with web-based acc
5150

5251
Directory where conversation transcripts are saved.
5352

53+
# flags.apex-debug.summary
54+
55+
Enable Apex debug logging during the agent preview conversation.
56+
5457
# examples
5558

5659
- Interact with an agent with API name "Resort_Manager" in the org with alias "my-org". Connect to your agent using the alias "my-agent-user"; this alias must point to the username who is authorized using the Web server flow:

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"@inquirer/prompts": "^7.2.0",
1010
"@oclif/core": "^4",
1111
"@oclif/multi-stage-output": "^0.7.12",
12-
"@salesforce/agents": "0.14.11",
12+
"@salesforce/agents": "0.15.0",
1313
"@salesforce/core": "^8.10.2",
1414
"@salesforce/kit": "^3.2.3",
1515
"@salesforce/sf-plugins-core": "^12.2.0",

src/commands/agent/preview.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ export default class AgentPreview extends SfCommand<AgentPreviewResult> {
6767
summary: messages.getMessage('flags.output-dir.summary'),
6868
char: 'd',
6969
}),
70+
'apex-debug': Flags.boolean({
71+
summary: messages.getMessage('flags.apex-debug.summary'),
72+
char: 'x',
73+
}),
7074
};
7175

7276
public async run(): Promise<AgentPreviewResult> {
@@ -97,13 +101,14 @@ export default class AgentPreview extends SfCommand<AgentPreviewResult> {
97101
});
98102
}
99103

100-
const outputDir = await resolveOutputDir(flags['output-dir']);
101-
const agentPreview = new Preview(apiConn);
104+
const outputDir = await resolveOutputDir(flags['output-dir'], flags['apex-debug']);
105+
const agentPreview = new Preview(apiConn, selectedAgent.Id);
106+
agentPreview.toggleApexDebugMode(flags['apex-debug']);
102107

103108
const instance = render(
104109
React.createElement(AgentPreviewReact, {
110+
connection: conn,
105111
agent: agentPreview,
106-
id: selectedAgent.Id,
107112
name: selectedAgent.DeveloperName,
108113
outputDir,
109114
}),
@@ -151,16 +156,22 @@ export const getAgentChoices = (agents: AgentData[]): Array<Choice<AgentValue>>
151156
};
152157
});
153158

154-
export const resolveOutputDir = async (outputDir: string | undefined): Promise<string | undefined> => {
159+
export const resolveOutputDir = async (
160+
outputDir: string | undefined,
161+
apexDebug: boolean | undefined
162+
): Promise<string | undefined> => {
155163
if (!outputDir) {
156-
const response = await confirm({
157-
message: 'Save transcripts to an output directory?',
158-
default: true,
159-
});
160-
164+
const response = apexDebug
165+
? true
166+
: await confirm({
167+
message: 'Save transcripts to an output directory?',
168+
default: true,
169+
});
170+
171+
const outputTypes = apexDebug ? 'debug logs and transcripts' : 'transcripts';
161172
if (response) {
162173
const getDir = await input({
163-
message: 'Enter the output directory',
174+
message: `Enter the output directory for ${outputTypes}`,
164175
default: env.getString('SF_AGENT_PREVIEW_OUTPUT_DIR', join('temp', 'agent-preview')),
165176
required: true,
166177
});

src/components/agent-preview-react.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import fs from 'node:fs';
1010
import React from 'react';
1111
import { Box, Text, useInput } from 'ink';
1212
import TextInput from 'ink-text-input';
13-
import { AgentPreview, AgentPreviewSendResponse } from '@salesforce/agents';
13+
import { Connection } from '@salesforce/core';
14+
import { AgentPreview, AgentPreviewSendResponse, writeDebugLog } from '@salesforce/agents';
1415
import { sleep } from '@salesforce/kit';
1516

1617
// Component to show a simple typing animation
@@ -64,8 +65,8 @@ const saveTranscriptsToFile = (
6465
* - Add keystroke to scroll down
6566
*/
6667
export function AgentPreviewReact(props: {
68+
readonly connection: Connection;
6769
readonly agent: AgentPreview;
68-
readonly id: string;
6970
readonly name: string;
7071
readonly outputDir: string | undefined;
7172
}): React.ReactNode {
@@ -80,8 +81,9 @@ export function AgentPreviewReact(props: {
8081
const [timestamp, setTimestamp] = React.useState(new Date().getTime());
8182
const [tempDir, setTempDir] = React.useState('');
8283
const [responses, setResponses] = React.useState<AgentPreviewSendResponse[]>([]);
84+
const [apexDebugLogs, setApexDebugLogs] = React.useState<string[]>([]);
8385

84-
const { agent, id, name, outputDir } = props;
86+
const { connection, agent, name, outputDir } = props;
8587

8688
useInput((input, key) => {
8789
if (key.escape) {
@@ -105,7 +107,7 @@ export function AgentPreviewReact(props: {
105107

106108
React.useEffect(() => {
107109
const startSession = async (): Promise<void> => {
108-
const session = await agent.start(id);
110+
const session = await agent.start();
109111
setSessionId(session.sessionId);
110112
setHeader(`New session started with "${props.name}" (${session.sessionId})`);
111113
await sleep(500); // Add a short delay to make it feel more natural
@@ -209,6 +211,16 @@ export function AgentPreviewReact(props: {
209211

210212
// Add the agent's response to the chat
211213
setMessages((prev) => [...prev, { role: name, content: message, timestamp: new Date() }]);
214+
215+
// If there is an apex debug log entry, get the log and write it to the output dir
216+
if (response.apexDebugLog && tempDir) {
217+
// Write the apex debug to the output dir
218+
await writeDebugLog(connection, response.apexDebugLog, tempDir);
219+
const logId = response.apexDebugLog.Id;
220+
if (logId) {
221+
setApexDebugLogs((prev) => [...prev, path.join(tempDir, `${logId}.log`)]);
222+
}
223+
}
212224
}}
213225
/>
214226
</Box>
@@ -226,6 +238,7 @@ export function AgentPreviewReact(props: {
226238
<Text bold>Session Ended</Text>
227239
{outputDir ? <Text>Conversation log: {tempDir}/transcript.json</Text> : null}
228240
{outputDir ? <Text>API transactions: {tempDir}/responses.json</Text> : null}
241+
{apexDebugLogs.length > 0 && <Text>Apex Debug Logs: {'\n' + apexDebugLogs.join('\n')}</Text>}
229242
</Box>
230243
) : null}
231244
</Box>

yarn.lock

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,14 +1443,15 @@
14431443
resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
14441444
integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==
14451445

1446-
"@salesforce/agents@0.14.11":
1447-
version "0.14.11"
1448-
resolved "https://registry.yarnpkg.com/@salesforce/agents/-/agents-0.14.11.tgz#3623d5d9708b9be12e72257592c1cc954a0a4d64"
1449-
integrity sha512-pRswx4MY7NfGAvPhKh6HDgGcvorcMJVjOaD2CHYLynVAhnvSioBv81BAc236sJoMpnOC68x/+DN312dlm3w9pw==
1446+
"@salesforce/agents@0.15.0":
1447+
version "0.15.0"
1448+
resolved "https://registry.yarnpkg.com/@salesforce/agents/-/agents-0.15.0.tgz#0cec640cef0f02714bfa8cf842239c9d00e6ca15"
1449+
integrity sha512-chshRBql+Yxm68vl2vI3BlmJdIBvyxVcj9WqlXQ51XwtzIsC64JSXZ1maybf05tdLQQiq+y8Z+b9/Vn6bfzvyw==
14501450
dependencies:
1451-
"@salesforce/core" "^8.10.2"
1451+
"@salesforce/core" "^8.10.3"
14521452
"@salesforce/kit" "^3.2.3"
1453-
"@salesforce/source-deploy-retrieve" "^12.19.3"
1453+
"@salesforce/source-deploy-retrieve" "^12.19.5"
1454+
"@salesforce/types" "^1.3.0"
14541455
fast-xml-parser "^4.5.3"
14551456
nock "^13.5.6"
14561457
yaml "^2.7.1"
@@ -1471,10 +1472,10 @@
14711472
strip-ansi "6.0.1"
14721473
ts-retry-promise "^0.8.1"
14731474

1474-
"@salesforce/core@^8.10.0", "@salesforce/core@^8.10.2", "@salesforce/core@^8.5.1", "@salesforce/core@^8.8.0", "@salesforce/core@^8.8.5", "@salesforce/core@^8.8.7":
1475-
version "8.10.2"
1476-
resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-8.10.2.tgz#22727a7dee2e69a34b0b14dae39c025f2b258af0"
1477-
integrity sha512-o/Qvm0U9+nuHAdFfjXZoAXyLaeG7lDnrLmUkCQ38oquiFrwzWSbXh6crHqFEmeZyK6MYYgh0KCaInrui06XP6Q==
1475+
"@salesforce/core@^8.10.0", "@salesforce/core@^8.10.2", "@salesforce/core@^8.10.3", "@salesforce/core@^8.5.1", "@salesforce/core@^8.8.0", "@salesforce/core@^8.8.5":
1476+
version "8.10.3"
1477+
resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-8.10.3.tgz#3cc2c99d097757cb4b08dab921254cfa3a00c7c1"
1478+
integrity sha512-juqbU304TBrrjb8sZGw+QkeAJISKu4+v2XIMTCxGJoEjs4LLhsyI7/drxCUY+7FNye+veAGeJdn/PCxkKhSgcA==
14781479
dependencies:
14791480
"@jsforce/jsforce-node" "^3.8.1"
14801481
"@salesforce/kit" "^3.2.2"
@@ -1597,12 +1598,12 @@
15971598
cli-progress "^3.12.0"
15981599
terminal-link "^3.0.0"
15991600

1600-
"@salesforce/source-deploy-retrieve@^12.19.3":
1601-
version "12.19.3"
1602-
resolved "https://registry.yarnpkg.com/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-12.19.3.tgz#42b34913b624115aee36cd289cb5ea1d5de9b7b1"
1603-
integrity sha512-rvdEfi2beJmVbN4NQ3Ve4dULq+wMFuLKBKpmNBIb9udXNVZd8Q0P7TO9pM/tzfeAfwfdTE7swXaYe2Qv5UAd+g==
1601+
"@salesforce/source-deploy-retrieve@^12.19.3", "@salesforce/source-deploy-retrieve@^12.19.5":
1602+
version "12.19.6"
1603+
resolved "https://registry.yarnpkg.com/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-12.19.6.tgz#0c208d2dfef6944e24afcea74ed05aa823e966aa"
1604+
integrity sha512-A/886Ht23G1snfyUj26pNDjaRWuMmiWIk5ckp+d9mdQjV8i45kPiOFJj5aHzAQ8071i/JgfnDYEhnk1voDujUA==
16041605
dependencies:
1605-
"@salesforce/core" "^8.8.7"
1606+
"@salesforce/core" "^8.10.3"
16061607
"@salesforce/kit" "^3.2.3"
16071608
"@salesforce/ts-types" "^2.0.12"
16081609
"@salesforce/types" "^1.3.0"

0 commit comments

Comments
 (0)