@salesforce/plugin-agent 1.36.1 → 1.38.0
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/README.md +294 -19
- package/lib/agentSessionScanner.d.ts +12 -0
- package/lib/agentSessionScanner.js +56 -0
- package/lib/agentSessionScanner.js.map +1 -0
- package/lib/commands/agent/test/run-eval.d.ts +1 -5
- package/lib/commands/agent/test/run-eval.js +54 -149
- package/lib/commands/agent/test/run-eval.js.map +1 -1
- package/lib/commands/agent/trace/delete.d.ts +21 -0
- package/lib/commands/agent/trace/delete.js +118 -0
- package/lib/commands/agent/trace/delete.js.map +1 -0
- package/lib/commands/agent/trace/list.d.ts +22 -0
- package/lib/commands/agent/trace/list.js +101 -0
- package/lib/commands/agent/trace/list.js.map +1 -0
- package/lib/commands/agent/trace/read.d.ts +75 -0
- package/lib/commands/agent/trace/read.js +308 -0
- package/lib/commands/agent/trace/read.js.map +1 -0
- package/messages/agent.test.run-eval.md +0 -4
- package/messages/agent.trace.delete.md +87 -0
- package/messages/agent.trace.list.md +87 -0
- package/messages/agent.trace.read.md +171 -0
- package/oclif.manifest.json +801 -525
- package/package.json +4 -4
- package/schemas/agent-trace-delete.json +28 -0
- package/schemas/agent-trace-list.json +34 -0
- package/schemas/agent-trace-read.json +466 -0
- package/lib/evalFormatter.d.ts +0 -30
- package/lib/evalFormatter.js +0 -263
- package/lib/evalFormatter.js.map +0 -1
- package/lib/evalNormalizer.d.ts +0 -57
- package/lib/evalNormalizer.js +0 -431
- package/lib/evalNormalizer.js.map +0 -1
- package/lib/yamlSpecTranslator.d.ts +0 -20
- package/lib/yamlSpecTranslator.js +0 -227
- package/lib/yamlSpecTranslator.js.map +0 -1
|
@@ -16,100 +16,35 @@
|
|
|
16
16
|
import { readFile } from 'node:fs/promises';
|
|
17
17
|
import { Flags, SfCommand, toHelpSection } from '@salesforce/sf-plugins-core';
|
|
18
18
|
import { EnvironmentVariable, Messages, SfError } from '@salesforce/core';
|
|
19
|
-
import { normalizePayload, splitIntoBatches } from '
|
|
20
|
-
import { formatResults } from '../../../evalFormatter.js';
|
|
19
|
+
import { normalizePayload, splitIntoBatches, formatResults, isYamlTestSpec, parseTestSpec, translateTestSpec, resolveAgent, executeBatches, buildResultSummary, } from '@salesforce/agents';
|
|
21
20
|
import { resultFormatFlag } from '../../../flags.js';
|
|
22
|
-
import { isYamlTestSpec, parseTestSpec, translateTestSpec } from '../../../yamlSpecTranslator.js';
|
|
23
21
|
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
24
22
|
const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.test.run-eval');
|
|
25
|
-
async function
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
userId: userInfo.user_id,
|
|
31
|
-
instanceUrl: conn.instanceUrl,
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
async function callEvalApi(org, payload, headers) {
|
|
35
|
-
const conn = org.getConnection();
|
|
36
|
-
return conn.request({
|
|
37
|
-
url: 'https://api.salesforce.com/einstein/evaluation/v1/tests',
|
|
38
|
-
method: 'POST',
|
|
39
|
-
headers: {
|
|
40
|
-
'Content-Type': 'application/json',
|
|
41
|
-
'x-sfdc-core-tenant-id': `core/prod/${headers.orgId}`,
|
|
42
|
-
'x-org-id': headers.orgId,
|
|
43
|
-
'x-sfdc-core-instance-url': headers.instanceUrl,
|
|
44
|
-
'x-sfdc-user-id': headers.userId,
|
|
45
|
-
'x-client-feature-id': 'AIPlatformEvaluation',
|
|
46
|
-
'x-sfdc-app-context': 'EinsteinGPT',
|
|
47
|
-
},
|
|
48
|
-
body: JSON.stringify(payload),
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
async function resolveAgent(org, apiName) {
|
|
52
|
-
const conn = org.getConnection();
|
|
53
|
-
// Escape single quotes to prevent SOQL injection
|
|
54
|
-
const escapedApiName = apiName.replace(/'/g, "\\'");
|
|
55
|
-
const botResult = await conn.query(`SELECT Id FROM BotDefinition WHERE DeveloperName = '${escapedApiName}'`);
|
|
56
|
-
if (!botResult.records.length) {
|
|
57
|
-
throw messages.createError('error.agentNotFound', [apiName]);
|
|
23
|
+
async function resolveAndInjectAgent(org, agentApiName, payload) {
|
|
24
|
+
let agentId;
|
|
25
|
+
let versionId;
|
|
26
|
+
try {
|
|
27
|
+
({ agentId, versionId } = await resolveAgent(org, agentApiName));
|
|
58
28
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (!versionResult.records.length) {
|
|
63
|
-
throw messages.createError('error.agentVersionNotFound', [apiName]);
|
|
29
|
+
catch (e) {
|
|
30
|
+
const wrapped = SfError.wrap(e);
|
|
31
|
+
throw new SfError(`Agent '${agentApiName}' not found.`, 'AgentNotFound', [], 2, wrapped);
|
|
64
32
|
}
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
const batchPromises = batches.map(async (batch) => {
|
|
76
|
-
const batchPayload = { tests: batch };
|
|
77
|
-
const resultObj = await callEvalApi(org, batchPayload, headers);
|
|
78
|
-
return resultObj.results ?? [];
|
|
79
|
-
});
|
|
80
|
-
const batchResults = await Promise.all(batchPromises);
|
|
81
|
-
return batchResults.flat();
|
|
82
|
-
}
|
|
83
|
-
function buildResultSummary(mergedResponse) {
|
|
84
|
-
const summary = { passed: 0, failed: 0, scored: 0, errors: 0 };
|
|
85
|
-
const testSummaries = [];
|
|
86
|
-
for (const testResult of mergedResponse.results ?? []) {
|
|
87
|
-
const tr = testResult;
|
|
88
|
-
const testId = tr.id ?? 'unknown';
|
|
89
|
-
const evalResults = tr.evaluation_results ?? [];
|
|
90
|
-
const testErrors = tr.errors ?? [];
|
|
91
|
-
const passed = evalResults.filter((e) => e.is_pass === true).length;
|
|
92
|
-
const failed = evalResults.filter((e) => e.is_pass === false).length;
|
|
93
|
-
const scored = evalResults.filter((e) => e.score != null && e.is_pass == null).length;
|
|
94
|
-
summary.passed += passed;
|
|
95
|
-
summary.failed += failed;
|
|
96
|
-
summary.scored += scored;
|
|
97
|
-
summary.errors += testErrors.length;
|
|
98
|
-
testSummaries.push({
|
|
99
|
-
id: testId,
|
|
100
|
-
status: failed > 0 || testErrors.length > 0 ? 'failed' : 'passed',
|
|
101
|
-
evaluations: evalResults,
|
|
102
|
-
outputs: tr.outputs ?? [],
|
|
103
|
-
});
|
|
33
|
+
for (const test of payload.tests) {
|
|
34
|
+
for (const step of test.steps) {
|
|
35
|
+
if (step.type === 'agent.create_session') {
|
|
36
|
+
// eslint-disable-next-line camelcase
|
|
37
|
+
step.agent_id = agentId;
|
|
38
|
+
// eslint-disable-next-line camelcase
|
|
39
|
+
step.agent_version_id = versionId;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
104
42
|
}
|
|
105
|
-
return { summary, testSummaries };
|
|
106
43
|
}
|
|
107
44
|
export default class AgentTestRunEval extends SfCommand {
|
|
108
45
|
static summary = messages.getMessage('summary');
|
|
109
46
|
static description = messages.getMessage('description');
|
|
110
47
|
static examples = messages.getMessages('examples');
|
|
111
|
-
static state = 'beta';
|
|
112
|
-
static hidden = true;
|
|
113
48
|
static envVariablesSection = toHelpSection('ENVIRONMENT VARIABLES', EnvironmentVariable.SF_TARGET_ORG);
|
|
114
49
|
static errorCodes = toHelpSection('ERROR CODES', {
|
|
115
50
|
'Succeeded (0)': 'Tests completed successfully. Test results (passed/failed) are in the JSON output.',
|
|
@@ -130,11 +65,6 @@ export default class AgentTestRunEval extends SfCommand {
|
|
|
130
65
|
char: 'n',
|
|
131
66
|
summary: messages.getMessage('flags.api-name.summary'),
|
|
132
67
|
}),
|
|
133
|
-
wait: Flags.integer({
|
|
134
|
-
char: 'w',
|
|
135
|
-
default: 10,
|
|
136
|
-
summary: messages.getMessage('flags.wait.summary'),
|
|
137
|
-
}),
|
|
138
68
|
'result-format': resultFormatFlag(),
|
|
139
69
|
'batch-size': Flags.integer({
|
|
140
70
|
default: 5,
|
|
@@ -150,40 +80,39 @@ export default class AgentTestRunEval extends SfCommand {
|
|
|
150
80
|
const org = flags['target-org'];
|
|
151
81
|
// 1. Get spec content (from file or stdin via allowStdin)
|
|
152
82
|
let rawContent = flags.spec;
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
// Try to detect if it's actual content vs a file path
|
|
156
|
-
// If it's a valid YAML/JSON, it's content; otherwise treat as file path
|
|
157
|
-
if (!isYamlTestSpec(rawContent)) {
|
|
158
|
-
JSON.parse(rawContent);
|
|
159
|
-
}
|
|
160
|
-
// If we got here, it's valid content
|
|
161
|
-
}
|
|
162
|
-
catch {
|
|
163
|
-
// Not valid content, must be a file path - read it
|
|
83
|
+
let isYaml = isYamlTestSpec(rawContent);
|
|
84
|
+
if (!isYaml) {
|
|
164
85
|
try {
|
|
165
|
-
rawContent
|
|
86
|
+
JSON.parse(rawContent);
|
|
166
87
|
}
|
|
167
|
-
catch
|
|
168
|
-
|
|
169
|
-
|
|
88
|
+
catch {
|
|
89
|
+
try {
|
|
90
|
+
rawContent = await readFile(flags.spec, 'utf-8');
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
const wrapped = SfError.wrap(e);
|
|
94
|
+
throw new SfError(`Spec file not found: ${flags.spec}`, 'SpecFileNotFound', [], 2, wrapped);
|
|
95
|
+
}
|
|
96
|
+
isYaml = isYamlTestSpec(rawContent);
|
|
170
97
|
}
|
|
171
98
|
}
|
|
172
99
|
// 2. Detect format and parse
|
|
173
100
|
let payload;
|
|
174
101
|
let agentApiName = flags['api-name'];
|
|
175
|
-
if (
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
102
|
+
if (isYaml) {
|
|
103
|
+
try {
|
|
104
|
+
const spec = parseTestSpec(rawContent);
|
|
105
|
+
payload = translateTestSpec(spec);
|
|
106
|
+
if (!agentApiName) {
|
|
107
|
+
agentApiName = spec.subjectName;
|
|
108
|
+
this.log(messages.getMessage('info.yamlDetected', [spec.subjectName, spec.testCases.length.toString()]));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (e) {
|
|
112
|
+
throw messages.createError('error.invalidPayload', [e.message]);
|
|
183
113
|
}
|
|
184
114
|
}
|
|
185
115
|
else {
|
|
186
|
-
// JSON EvalPayload (original behavior)
|
|
187
116
|
try {
|
|
188
117
|
payload = JSON.parse(rawContent);
|
|
189
118
|
}
|
|
@@ -194,56 +123,32 @@ export default class AgentTestRunEval extends SfCommand {
|
|
|
194
123
|
if (!payload.tests || !Array.isArray(payload.tests) || payload.tests.length === 0) {
|
|
195
124
|
throw messages.createError('error.invalidPayload', ['missing or empty "tests" array']);
|
|
196
125
|
}
|
|
126
|
+
for (const test of payload.tests) {
|
|
127
|
+
if (!Array.isArray(test.steps)) {
|
|
128
|
+
throw messages.createError('error.invalidPayload', [`test '${test.id}' has missing or invalid 'steps' array`]);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
197
131
|
// 3. If --api-name (or auto-inferred from YAML), resolve IDs and inject
|
|
198
132
|
if (agentApiName) {
|
|
199
|
-
|
|
200
|
-
let versionId;
|
|
201
|
-
try {
|
|
202
|
-
const resolved = await resolveAgent(org, agentApiName);
|
|
203
|
-
agentId = resolved.agentId;
|
|
204
|
-
versionId = resolved.versionId;
|
|
205
|
-
}
|
|
206
|
-
catch (e) {
|
|
207
|
-
const wrapped = SfError.wrap(e);
|
|
208
|
-
throw new SfError(`Agent '${agentApiName}' not found.`, 'AgentNotFound', [], 2, wrapped);
|
|
209
|
-
}
|
|
210
|
-
for (const test of payload.tests) {
|
|
211
|
-
for (const step of test.steps) {
|
|
212
|
-
if (step.type === 'agent.create_session') {
|
|
213
|
-
// eslint-disable-next-line camelcase
|
|
214
|
-
step.agent_id = agentId;
|
|
215
|
-
// eslint-disable-next-line camelcase
|
|
216
|
-
step.agent_version_id = versionId;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
133
|
+
await resolveAndInjectAgent(org, agentApiName, payload);
|
|
220
134
|
}
|
|
221
135
|
// 4. Normalize payload unless --no-normalize
|
|
222
136
|
if (!flags['no-normalize']) {
|
|
223
137
|
payload = normalizePayload(payload);
|
|
224
138
|
}
|
|
225
|
-
// 5. Clamp batch size
|
|
139
|
+
// 5. Clamp batch size and split into batches
|
|
226
140
|
const batchSize = Math.min(Math.max(flags['batch-size'], 1), 5);
|
|
227
|
-
// 6. Split into batches
|
|
228
141
|
const batches = splitIntoBatches(payload.tests, batchSize);
|
|
229
|
-
//
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
allResults = await executeBatches(org, batches, (msg) => this.log(msg));
|
|
233
|
-
}
|
|
234
|
-
catch (e) {
|
|
142
|
+
// 6. Execute batches
|
|
143
|
+
const allResults = await executeBatches(org, batches, (msg) => this.log(msg)).catch((e) => {
|
|
235
144
|
const wrapped = SfError.wrap(e);
|
|
236
145
|
throw new SfError(`Failed to execute tests: ${wrapped.message}`, 'TestExecutionFailed', [wrapped.message], 4, wrapped);
|
|
237
|
-
}
|
|
146
|
+
});
|
|
238
147
|
const mergedResponse = { results: allResults };
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
this.log(formatted);
|
|
243
|
-
// 10. Build structured result for --json
|
|
148
|
+
// 7. Format output
|
|
149
|
+
this.log(formatResults(mergedResponse, (flags['result-format'] ?? 'human')));
|
|
150
|
+
// 8. Build structured result for --json
|
|
244
151
|
const { summary, testSummaries } = buildResultSummary(mergedResponse);
|
|
245
|
-
// Set exit code to 1 only for execution errors (tests couldn't run)
|
|
246
|
-
// Test failures (assertions failed) are business logic and should not affect exit code
|
|
247
152
|
if (summary.errors > 0) {
|
|
248
153
|
process.exitCode = 1;
|
|
249
154
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-eval.js","sourceRoot":"","sources":["../../../../src/commands/agent/test/run-eval.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"run-eval.js","sourceRoot":"","sources":["../../../../src/commands/agent/test/run-eval.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
export type AgentTraceDeleteResult = Array<{
|
|
3
|
+
agent: string;
|
|
4
|
+
sessionId: string;
|
|
5
|
+
planId: string;
|
|
6
|
+
path: string;
|
|
7
|
+
}>;
|
|
8
|
+
export default class AgentTraceDelete extends SfCommand<AgentTraceDeleteResult> {
|
|
9
|
+
static readonly summary: string;
|
|
10
|
+
static readonly description: string;
|
|
11
|
+
static readonly examples: string[];
|
|
12
|
+
static readonly requiresProject = true;
|
|
13
|
+
static readonly errorCodes: import("@oclif/core").HelpSection;
|
|
14
|
+
static readonly flags: {
|
|
15
|
+
agent: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
'session-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
'older-than': import("@oclif/core/interfaces").OptionFlag<Date | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
'no-prompt': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
19
|
+
};
|
|
20
|
+
run(): Promise<AgentTraceDeleteResult>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026, Salesforce, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { unlink } from 'node:fs/promises';
|
|
17
|
+
import { Flags, SfCommand, toHelpSection } from '@salesforce/sf-plugins-core';
|
|
18
|
+
import { Messages, SfError } from '@salesforce/core';
|
|
19
|
+
import { listSessionTraces } from '@salesforce/agents';
|
|
20
|
+
import yesNoOrCancel from '../../../yes-no-cancel.js';
|
|
21
|
+
import { listAllAgentSessions } from '../../../agentSessionScanner.js';
|
|
22
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
23
|
+
const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.trace.delete');
|
|
24
|
+
const DURATION_RE = /^(\d+)(d|h|m|w|days?|hours?|minutes?|weeks?)$/i;
|
|
25
|
+
const UNIT_MS = {
|
|
26
|
+
m: 60_000,
|
|
27
|
+
minute: 60_000,
|
|
28
|
+
minutes: 60_000,
|
|
29
|
+
h: 3_600_000,
|
|
30
|
+
hour: 3_600_000,
|
|
31
|
+
hours: 3_600_000,
|
|
32
|
+
d: 86_400_000,
|
|
33
|
+
day: 86_400_000,
|
|
34
|
+
days: 86_400_000,
|
|
35
|
+
w: 604_800_000,
|
|
36
|
+
week: 604_800_000,
|
|
37
|
+
weeks: 604_800_000,
|
|
38
|
+
};
|
|
39
|
+
export default class AgentTraceDelete extends SfCommand {
|
|
40
|
+
static summary = messages.getMessage('summary');
|
|
41
|
+
static description = messages.getMessage('description');
|
|
42
|
+
static examples = messages.getMessages('examples');
|
|
43
|
+
static requiresProject = true;
|
|
44
|
+
static errorCodes = toHelpSection('ERROR CODES', {
|
|
45
|
+
'Succeeded (0)': 'Traces deleted successfully (or no traces matched).',
|
|
46
|
+
});
|
|
47
|
+
static flags = {
|
|
48
|
+
agent: Flags.string({
|
|
49
|
+
summary: messages.getMessage('flags.agent.summary'),
|
|
50
|
+
char: 'a',
|
|
51
|
+
}),
|
|
52
|
+
'session-id': Flags.string({
|
|
53
|
+
summary: messages.getMessage('flags.session-id.summary'),
|
|
54
|
+
}),
|
|
55
|
+
'older-than': Flags.custom({
|
|
56
|
+
summary: messages.getMessage('flags.older-than.summary'),
|
|
57
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
58
|
+
parse: async (raw) => {
|
|
59
|
+
const match = DURATION_RE.exec(raw);
|
|
60
|
+
if (!match) {
|
|
61
|
+
throw new SfError(messages.getMessage('error.invalidOlderThan', [raw]), 'InvalidDuration');
|
|
62
|
+
}
|
|
63
|
+
const ms = parseInt(match[1], 10) * UNIT_MS[match[2].toLowerCase()];
|
|
64
|
+
return new Date(Date.now() - ms);
|
|
65
|
+
},
|
|
66
|
+
})(),
|
|
67
|
+
'no-prompt': Flags.boolean({
|
|
68
|
+
summary: messages.getMessage('flags.no-prompt.summary'),
|
|
69
|
+
}),
|
|
70
|
+
};
|
|
71
|
+
async run() {
|
|
72
|
+
const { flags } = await this.parse(AgentTraceDelete);
|
|
73
|
+
const agentFilter = flags.agent?.toLowerCase();
|
|
74
|
+
const allSessions = await listAllAgentSessions(this.project);
|
|
75
|
+
const candidates = [];
|
|
76
|
+
for (const { agentId, displayName, sessionId } of allSessions) {
|
|
77
|
+
if (agentFilter && !displayName.toLowerCase().includes(agentFilter))
|
|
78
|
+
continue;
|
|
79
|
+
if (flags['session-id'] && sessionId !== flags['session-id'])
|
|
80
|
+
continue;
|
|
81
|
+
// eslint-disable-next-line no-await-in-loop
|
|
82
|
+
let traces = await listSessionTraces(agentId, sessionId);
|
|
83
|
+
if (flags['older-than']) {
|
|
84
|
+
traces = traces.filter((t) => t.mtime < flags['older-than']);
|
|
85
|
+
}
|
|
86
|
+
for (const t of traces) {
|
|
87
|
+
candidates.push({ agent: displayName, sessionId, planId: t.planId, path: t.path });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (candidates.length === 0) {
|
|
91
|
+
this.log(messages.getMessage('output.noneFound'));
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
if (!flags['no-prompt']) {
|
|
95
|
+
this.log(messages.getMessage('output.preview', [candidates.length]));
|
|
96
|
+
this.table({
|
|
97
|
+
data: candidates.map((c) => ({ agent: c.agent, sessionId: c.sessionId, planId: c.planId })),
|
|
98
|
+
columns: [
|
|
99
|
+
{ key: 'agent', name: messages.getMessage('output.tableHeader.agent') },
|
|
100
|
+
{ key: 'sessionId', name: messages.getMessage('output.tableHeader.sessionId') },
|
|
101
|
+
{ key: 'planId', name: messages.getMessage('output.tableHeader.planId') },
|
|
102
|
+
],
|
|
103
|
+
});
|
|
104
|
+
const confirmed = await yesNoOrCancel({
|
|
105
|
+
message: messages.getMessage('prompt.confirm', [candidates.length]),
|
|
106
|
+
default: false,
|
|
107
|
+
});
|
|
108
|
+
if (confirmed === 'cancel' || confirmed === false) {
|
|
109
|
+
this.log(messages.getMessage('output.cancelled'));
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
await Promise.all(candidates.map((c) => unlink(c.path)));
|
|
114
|
+
this.log(messages.getMessage('output.deleted', [candidates.length]));
|
|
115
|
+
return candidates;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=delete.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete.js","sourceRoot":"","sources":["../../../../src/commands/agent/trace/delete.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
export type AgentTraceListResult = Array<{
|
|
3
|
+
agent: string;
|
|
4
|
+
sessionId: string;
|
|
5
|
+
planId: string;
|
|
6
|
+
path: string;
|
|
7
|
+
size: number;
|
|
8
|
+
mtime: string;
|
|
9
|
+
}>;
|
|
10
|
+
export default class AgentTraceList extends SfCommand<AgentTraceListResult> {
|
|
11
|
+
static readonly summary: string;
|
|
12
|
+
static readonly description: string;
|
|
13
|
+
static readonly examples: string[];
|
|
14
|
+
static readonly requiresProject = true;
|
|
15
|
+
static readonly errorCodes: import("@oclif/core").HelpSection;
|
|
16
|
+
static readonly flags: {
|
|
17
|
+
'session-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
agent: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
|
+
since: import("@oclif/core/interfaces").OptionFlag<Date | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
+
};
|
|
21
|
+
run(): Promise<AgentTraceListResult>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2026, Salesforce, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { Flags, SfCommand, toHelpSection } from '@salesforce/sf-plugins-core';
|
|
17
|
+
import { Messages, SfError } from '@salesforce/core';
|
|
18
|
+
import { listSessionTraces } from '@salesforce/agents';
|
|
19
|
+
import { listAllAgentSessions } from '../../../agentSessionScanner.js';
|
|
20
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
21
|
+
const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.trace.list');
|
|
22
|
+
const ISO_8601 = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d+)?Z)?$/;
|
|
23
|
+
export default class AgentTraceList extends SfCommand {
|
|
24
|
+
static summary = messages.getMessage('summary');
|
|
25
|
+
static description = messages.getMessage('description');
|
|
26
|
+
static examples = messages.getMessages('examples');
|
|
27
|
+
static requiresProject = true;
|
|
28
|
+
static errorCodes = toHelpSection('ERROR CODES', {
|
|
29
|
+
'Succeeded (0)': 'Trace files listed successfully (or empty list if none found).',
|
|
30
|
+
});
|
|
31
|
+
static flags = {
|
|
32
|
+
'session-id': Flags.string({
|
|
33
|
+
summary: messages.getMessage('flags.session-id.summary'),
|
|
34
|
+
}),
|
|
35
|
+
agent: Flags.string({
|
|
36
|
+
summary: messages.getMessage('flags.agent.summary'),
|
|
37
|
+
char: 'a',
|
|
38
|
+
}),
|
|
39
|
+
since: Flags.custom({
|
|
40
|
+
summary: messages.getMessage('flags.since.summary'),
|
|
41
|
+
description: messages.getMessage('flags.since.description'),
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
43
|
+
parse: async (raw) => {
|
|
44
|
+
if (!ISO_8601.test(raw)) {
|
|
45
|
+
throw new SfError(messages.getMessage('error.invalidSince', [raw]), 'InvalidDate');
|
|
46
|
+
}
|
|
47
|
+
const d = new Date(raw);
|
|
48
|
+
if (isNaN(d.getTime())) {
|
|
49
|
+
throw new SfError(messages.getMessage('error.invalidSince', [raw]), 'InvalidDate');
|
|
50
|
+
}
|
|
51
|
+
return d;
|
|
52
|
+
},
|
|
53
|
+
})(),
|
|
54
|
+
};
|
|
55
|
+
async run() {
|
|
56
|
+
const { flags } = await this.parse(AgentTraceList);
|
|
57
|
+
const agentNameFilter = flags.agent?.toLowerCase();
|
|
58
|
+
const allSessions = await listAllAgentSessions(this.project);
|
|
59
|
+
const result = [];
|
|
60
|
+
for (const { agentId, displayName, sessionId } of allSessions) {
|
|
61
|
+
if (agentNameFilter && !displayName.toLowerCase().includes(agentNameFilter))
|
|
62
|
+
continue;
|
|
63
|
+
if (flags['session-id'] && sessionId !== flags['session-id'])
|
|
64
|
+
continue;
|
|
65
|
+
// eslint-disable-next-line no-await-in-loop
|
|
66
|
+
let traces = await listSessionTraces(agentId, sessionId);
|
|
67
|
+
if (flags.since) {
|
|
68
|
+
traces = traces.filter((t) => t.mtime >= flags.since);
|
|
69
|
+
}
|
|
70
|
+
for (const t of traces) {
|
|
71
|
+
result.push({
|
|
72
|
+
agent: displayName,
|
|
73
|
+
sessionId,
|
|
74
|
+
planId: t.planId,
|
|
75
|
+
path: t.path,
|
|
76
|
+
size: t.size,
|
|
77
|
+
mtime: t.mtime.toISOString(),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (result.length === 0) {
|
|
82
|
+
this.log(messages.getMessage('output.empty'));
|
|
83
|
+
return [];
|
|
84
|
+
}
|
|
85
|
+
if (!this.jsonEnabled()) {
|
|
86
|
+
this.table({
|
|
87
|
+
data: result.map((r) => ({ ...r, size: `${r.size}B` })),
|
|
88
|
+
columns: [
|
|
89
|
+
{ key: 'agent', name: messages.getMessage('output.tableHeader.agent') },
|
|
90
|
+
{ key: 'sessionId', name: messages.getMessage('output.tableHeader.sessionId') },
|
|
91
|
+
{ key: 'planId', name: messages.getMessage('output.tableHeader.planId') },
|
|
92
|
+
{ key: 'mtime', name: messages.getMessage('output.tableHeader.mtime') },
|
|
93
|
+
{ key: 'size', name: messages.getMessage('output.tableHeader.size') },
|
|
94
|
+
{ key: 'path', name: messages.getMessage('output.tableHeader.path') },
|
|
95
|
+
],
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../../../src/commands/agent/trace/list.ts"],"names":[],"mappings":"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"}
|