@salesforce/plugin-agent 1.24.35 → 1.25.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/LICENSE.txt +200 -6
- package/README.md +240 -55
- package/lib/agentActivation.js +13 -4
- package/lib/agentActivation.js.map +1 -1
- package/lib/agentTestCache.js +13 -4
- package/lib/agentTestCache.js.map +1 -1
- package/lib/commands/agent/activate.js +13 -4
- package/lib/commands/agent/activate.js.map +1 -1
- package/lib/commands/agent/create.js +13 -4
- package/lib/commands/agent/create.js.map +1 -1
- package/lib/commands/agent/deactivate.js +13 -4
- package/lib/commands/agent/deactivate.js.map +1 -1
- package/lib/commands/agent/generate/agent-spec.js +13 -4
- package/lib/commands/agent/generate/agent-spec.js.map +1 -1
- package/lib/commands/agent/generate/authoring-bundle.d.ts +23 -0
- package/lib/commands/agent/generate/authoring-bundle.js +140 -0
- package/lib/commands/agent/generate/authoring-bundle.js.map +1 -0
- package/lib/commands/agent/generate/template.js +13 -4
- package/lib/commands/agent/generate/template.js.map +1 -1
- package/lib/commands/agent/generate/test-spec.js +13 -4
- package/lib/commands/agent/generate/test-spec.js.map +1 -1
- package/lib/commands/agent/preview.d.ts +6 -12
- package/lib/commands/agent/preview.js +130 -67
- package/lib/commands/agent/preview.js.map +1 -1
- package/lib/commands/agent/publish/authoring-bundle.d.ts +20 -0
- package/lib/commands/agent/publish/authoring-bundle.js +154 -0
- package/lib/commands/agent/publish/authoring-bundle.js.map +1 -0
- package/lib/commands/agent/test/create.js +13 -4
- package/lib/commands/agent/test/create.js.map +1 -1
- package/lib/commands/agent/test/list.js +13 -4
- package/lib/commands/agent/test/list.js.map +1 -1
- package/lib/commands/agent/test/results.js +13 -4
- package/lib/commands/agent/test/results.js.map +1 -1
- package/lib/commands/agent/test/resume.js +13 -4
- package/lib/commands/agent/test/resume.js.map +1 -1
- package/lib/commands/agent/test/run.js +14 -4
- package/lib/commands/agent/test/run.js.map +1 -1
- package/lib/commands/agent/validate/authoring-bundle.d.ts +19 -0
- package/lib/commands/agent/validate/authoring-bundle.js +128 -0
- package/lib/commands/agent/validate/authoring-bundle.js.map +1 -0
- package/lib/common.d.ts +8 -0
- package/lib/common.js +39 -0
- package/lib/common.js.map +1 -0
- package/lib/components/agent-preview-react.d.ts +9 -2
- package/lib/components/agent-preview-react.js +188 -62
- package/lib/components/agent-preview-react.js.map +1 -1
- package/lib/flags.d.ts +6 -2
- package/lib/flags.js +55 -20
- package/lib/flags.js.map +1 -1
- package/lib/handleTestResults.js +13 -4
- package/lib/handleTestResults.js.map +1 -1
- package/lib/index.js +13 -4
- package/lib/index.js.map +1 -1
- package/lib/inquirer-theme.js +13 -4
- package/lib/inquirer-theme.js.map +1 -1
- package/lib/testStages.js +13 -4
- package/lib/testStages.js.map +1 -1
- package/lib/yes-no-cancel.js +13 -4
- package/lib/yes-no-cancel.js.map +1 -1
- package/messages/agent.create.md +2 -0
- package/messages/agent.generate.agent-spec.md +2 -2
- package/messages/agent.generate.authoring-bundle.md +69 -0
- package/messages/agent.preview.md +25 -12
- package/messages/agent.publish.authoring-bundle.md +50 -0
- package/messages/agent.test.run.md +4 -0
- package/messages/agent.validate.authoring-bundle.md +50 -0
- package/oclif.manifest.json +311 -10
- package/package.json +17 -10
- package/schemas/agent-generate-agent__spec.json +1 -1
- package/schemas/agent-generate-authoring__bundle.json +22 -0
- package/schemas/agent-publish-authoring__bundle.json +25 -0
- package/schemas/agent-validate-authoring__bundle.json +22 -0
- package/npm-shrinkwrap.json +0 -17457
- package/oclif.lock +0 -9156
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resume.js","sourceRoot":"","sources":["../../../../src/commands/agent/test/resume.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"resume.js","sourceRoot":"","sources":["../../../../src/commands/agent/test/resume.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the
|
|
5
|
-
*
|
|
2
|
+
* Copyright 2025, 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.
|
|
6
15
|
*/
|
|
7
16
|
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
8
17
|
import { Messages, SfError } from '@salesforce/core';
|
|
@@ -19,6 +28,7 @@ const FLAGGABLE_PROMPTS = {
|
|
|
19
28
|
char: 'n',
|
|
20
29
|
required: true,
|
|
21
30
|
message: messages.getMessage('flags.api-name.summary'),
|
|
31
|
+
promptMessage: messages.getMessage('flags.api-name.prompt'),
|
|
22
32
|
validate: (d) => {
|
|
23
33
|
if (d.length === 0) {
|
|
24
34
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../src/commands/agent/test/run.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../src/commands/agent/test/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
export type AgentValidateAuthoringBundleResult = {
|
|
3
|
+
success: boolean;
|
|
4
|
+
errors?: string[];
|
|
5
|
+
};
|
|
6
|
+
export default class AgentValidateAuthoringBundle extends SfCommand<AgentValidateAuthoringBundleResult> {
|
|
7
|
+
static readonly summary: string;
|
|
8
|
+
static readonly description: string;
|
|
9
|
+
static readonly examples: string[];
|
|
10
|
+
static readonly requiresProject = true;
|
|
11
|
+
static state: string;
|
|
12
|
+
static readonly flags: {
|
|
13
|
+
'target-org': import("@oclif/core/interfaces").OptionFlag<import("@salesforce/core").Org, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
'api-version': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
'api-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
};
|
|
17
|
+
private static readonly FLAGGABLE_PROMPTS;
|
|
18
|
+
run(): Promise<AgentValidateAuthoringBundleResult>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025, 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 { readFileSync } from 'node:fs';
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
19
|
+
import { Messages, SfError } from '@salesforce/core';
|
|
20
|
+
import { MultiStageOutput } from '@oclif/multi-stage-output';
|
|
21
|
+
import { Agent, findAuthoringBundle } from '@salesforce/agents';
|
|
22
|
+
import { colorize } from '@oclif/core/ux';
|
|
23
|
+
import { throwAgentCompilationError } from '../../../common.js';
|
|
24
|
+
import { promptForAgentFiles } from '../../../flags.js';
|
|
25
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
26
|
+
const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.validate.authoring-bundle');
|
|
27
|
+
export default class AgentValidateAuthoringBundle extends SfCommand {
|
|
28
|
+
static summary = messages.getMessage('summary');
|
|
29
|
+
static description = messages.getMessage('description');
|
|
30
|
+
static examples = messages.getMessages('examples');
|
|
31
|
+
static requiresProject = true;
|
|
32
|
+
static state = 'beta';
|
|
33
|
+
static flags = {
|
|
34
|
+
'target-org': Flags.requiredOrg(),
|
|
35
|
+
'api-version': Flags.orgApiVersion(),
|
|
36
|
+
'api-name': Flags.string({
|
|
37
|
+
char: 'n',
|
|
38
|
+
summary: messages.getMessage('flags.api-name.summary'),
|
|
39
|
+
}),
|
|
40
|
+
};
|
|
41
|
+
static FLAGGABLE_PROMPTS = {
|
|
42
|
+
'api-name': {
|
|
43
|
+
message: messages.getMessage('flags.api-name.summary'),
|
|
44
|
+
promptMessage: messages.getMessage('flags.api-name.prompt'),
|
|
45
|
+
validate: (d) => {
|
|
46
|
+
if (d.length > 80) {
|
|
47
|
+
return 'API name cannot be over 80 characters.';
|
|
48
|
+
}
|
|
49
|
+
const regex = /^[A-Za-z][A-Za-z0-9_]*[A-Za-z0-9]+$/;
|
|
50
|
+
if (d.length === 0 || !regex.test(d)) {
|
|
51
|
+
return 'Invalid API name.';
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
async run() {
|
|
58
|
+
const { flags } = await this.parse(AgentValidateAuthoringBundle);
|
|
59
|
+
// If api-name is not provided, prompt user to select an .agent file from the project and extract the API name from it
|
|
60
|
+
const apiName = flags['api-name'] ??
|
|
61
|
+
(await promptForAgentFiles(this.project, AgentValidateAuthoringBundle.FLAGGABLE_PROMPTS['api-name']));
|
|
62
|
+
const authoringBundleDir = findAuthoringBundle(this.project.getPackageDirectories().map((dir) => dir.fullPath), apiName);
|
|
63
|
+
if (!authoringBundleDir) {
|
|
64
|
+
throw new SfError(messages.getMessage('error.agentNotFound', [apiName]), 'AgentNotFoundError', [
|
|
65
|
+
messages.getMessage('error.agentNotFoundAction'),
|
|
66
|
+
]);
|
|
67
|
+
}
|
|
68
|
+
const mso = new MultiStageOutput({
|
|
69
|
+
jsonEnabled: this.jsonEnabled(),
|
|
70
|
+
title: `Validating ${apiName} Authoring Bundle`,
|
|
71
|
+
showTitle: true,
|
|
72
|
+
stages: ['Validating Authoring Bundle'],
|
|
73
|
+
stageSpecificBlock: [
|
|
74
|
+
{
|
|
75
|
+
stage: 'Validating Authoring Bundle',
|
|
76
|
+
label: 'Status',
|
|
77
|
+
type: 'dynamic-key-value',
|
|
78
|
+
get: (data) => data?.status ?? 'IN PROGRESS',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
stage: 'Validating Authoring Bundle',
|
|
82
|
+
label: 'Errors',
|
|
83
|
+
type: 'dynamic-key-value',
|
|
84
|
+
get: (data) => data?.errors ?? '0',
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
});
|
|
88
|
+
try {
|
|
89
|
+
mso.skipTo('Validating Authoring Bundle');
|
|
90
|
+
const targetOrg = flags['target-org'];
|
|
91
|
+
const conn = targetOrg.getConnection(flags['api-version']);
|
|
92
|
+
const result = await Agent.compileAgentScript(conn, readFileSync(join(authoringBundleDir, `${apiName}.agent`), 'utf8'));
|
|
93
|
+
if (result.status === 'success') {
|
|
94
|
+
mso.updateData({ status: 'COMPLETED' });
|
|
95
|
+
mso.stop('completed');
|
|
96
|
+
return {
|
|
97
|
+
success: true,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
throwAgentCompilationError(result.errors);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
// Handle validation errors
|
|
106
|
+
const err = SfError.wrap(error);
|
|
107
|
+
let count = 0;
|
|
108
|
+
const rawError = err.message ? err.message : err.name;
|
|
109
|
+
const formattedError = rawError
|
|
110
|
+
.split('\n')
|
|
111
|
+
.map((line) => {
|
|
112
|
+
count += 1;
|
|
113
|
+
const type = line.split(':')[0];
|
|
114
|
+
const rest = line.includes(':') ? line.substring(line.indexOf(':')).trim() : '';
|
|
115
|
+
return `- ${colorize('red', type)}${rest}`;
|
|
116
|
+
})
|
|
117
|
+
.join('\n');
|
|
118
|
+
mso.updateData({ errors: count.toString(), status: 'ERROR' });
|
|
119
|
+
mso.error();
|
|
120
|
+
this.error(messages.getMessage('error.compilationFailed', [formattedError]));
|
|
121
|
+
return {
|
|
122
|
+
success: false,
|
|
123
|
+
errors: err.message.split('\n'),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=authoring-bundle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authoring-bundle.js","sourceRoot":"","sources":["../../../../src/commands/agent/validate/authoring-bundle.ts"],"names":[],"mappings":"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"}
|
package/lib/common.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { CompilationError } from '@salesforce/agents';
|
|
2
|
+
/**
|
|
3
|
+
* Utility function to generate SfError when there are agent compilation errors.
|
|
4
|
+
*
|
|
5
|
+
* @param compilationErrors - The compilation errors as strings, CompilationError objects, or array of either
|
|
6
|
+
* @throws SfError - Always throws a Salesforce CLI error
|
|
7
|
+
*/
|
|
8
|
+
export declare function throwAgentCompilationError(compilationErrors: CompilationError[]): never;
|
package/lib/common.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025, 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 { EOL } from 'node:os';
|
|
17
|
+
import { SfError } from '@salesforce/core';
|
|
18
|
+
/**
|
|
19
|
+
* Utility function to generate SfError when there are agent compilation errors.
|
|
20
|
+
*
|
|
21
|
+
* @param compilationErrors - The compilation errors as strings, CompilationError objects, or array of either
|
|
22
|
+
* @throws SfError - Always throws a Salesforce CLI error
|
|
23
|
+
*/
|
|
24
|
+
export function throwAgentCompilationError(compilationErrors) {
|
|
25
|
+
if (compilationErrors.length === 0) {
|
|
26
|
+
throw SfError.create({
|
|
27
|
+
name: 'CompileAgentScriptError',
|
|
28
|
+
message: 'Unknown compilation error occurred',
|
|
29
|
+
data: compilationErrors,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
const errors = compilationErrors;
|
|
33
|
+
throw SfError.create({
|
|
34
|
+
name: 'CompileAgentScriptError',
|
|
35
|
+
message: errors.map((e) => `${e.errorType}: ${e.description} [Ln ${e.lineStart}, Col ${e.colStart}]`).join(EOL),
|
|
36
|
+
data: errors,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAG3C;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CAAC,iBAAqC;IAC9E,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,OAAO,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,oCAAoC;YAC7C,IAAI,EAAE,iBAAiB;SACxB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,MAAM,GAAG,iBAAiB,CAAC;IAEjC,MAAM,OAAO,CAAC,MAAM,CAAC;QACnB,IAAI,EAAE,yBAAyB;QAC/B,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,WAAW,QAAQ,CAAC,CAAC,SAAS,SAAS,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAC/G,IAAI,EAAE,MAAM;KACb,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { Connection } from '@salesforce/core';
|
|
3
|
-
import {
|
|
3
|
+
import { AgentPreviewBase, AgentPreviewSendResponse } from '@salesforce/agents';
|
|
4
|
+
export declare const saveTranscriptsToFile: (outputDir: string, messages: Array<{
|
|
5
|
+
timestamp: Date;
|
|
6
|
+
role: string;
|
|
7
|
+
content: string;
|
|
8
|
+
}>, responses: AgentPreviewSendResponse[]) => void;
|
|
4
9
|
/**
|
|
5
10
|
* Ideas:
|
|
6
11
|
* - Limit height based on terminal height
|
|
@@ -10,7 +15,9 @@ import { AgentPreview } from '@salesforce/agents';
|
|
|
10
15
|
*/
|
|
11
16
|
export declare function AgentPreviewReact(props: {
|
|
12
17
|
readonly connection: Connection;
|
|
13
|
-
readonly agent:
|
|
18
|
+
readonly agent: AgentPreviewBase;
|
|
14
19
|
readonly name: string;
|
|
15
20
|
readonly outputDir: string | undefined;
|
|
21
|
+
readonly isLocalAgent: boolean;
|
|
22
|
+
readonly apexDebug: boolean | undefined;
|
|
16
23
|
}): React.ReactNode;
|
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright
|
|
3
|
-
*
|
|
4
|
-
* Licensed under the
|
|
5
|
-
*
|
|
2
|
+
* Copyright 2025, 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.
|
|
6
15
|
*/
|
|
7
16
|
import path from 'node:path';
|
|
8
17
|
import fs from 'node:fs';
|
|
18
|
+
import * as process from 'node:process';
|
|
19
|
+
import { resolve } from 'node:path';
|
|
9
20
|
import React from 'react';
|
|
10
21
|
import { Box, Text, useInput } from 'ink';
|
|
11
22
|
import TextInput from 'ink-text-input';
|
|
23
|
+
import { SfError, Lifecycle } from '@salesforce/core';
|
|
12
24
|
import { writeDebugLog } from '@salesforce/agents';
|
|
13
|
-
import { sleep } from '@salesforce/kit';
|
|
25
|
+
import { sleep, env } from '@salesforce/kit';
|
|
14
26
|
// Component to show a simple typing animation
|
|
15
27
|
function Typing() {
|
|
16
28
|
const [frame, setFrame] = React.useState(0);
|
|
@@ -27,9 +39,7 @@ function Typing() {
|
|
|
27
39
|
React.createElement(Text, { color: colors[1] }, "."),
|
|
28
40
|
React.createElement(Text, { color: colors[2] }, ".")));
|
|
29
41
|
}
|
|
30
|
-
|
|
31
|
-
const calculateWidth = (content) => content.split('\n').reduce((acc, line) => Math.max(acc, line.length), 0) + 4;
|
|
32
|
-
const saveTranscriptsToFile = (outputDir, messages, responses) => {
|
|
42
|
+
export const saveTranscriptsToFile = (outputDir, messages, responses) => {
|
|
33
43
|
if (!outputDir)
|
|
34
44
|
return;
|
|
35
45
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
@@ -52,62 +62,158 @@ export function AgentPreviewReact(props) {
|
|
|
52
62
|
const [query, setQuery] = React.useState('');
|
|
53
63
|
const [isTyping, setIsTyping] = React.useState(true);
|
|
54
64
|
const [sessionEnded, setSessionEnded] = React.useState(false);
|
|
65
|
+
const [exitRequested, setExitRequested] = React.useState(false);
|
|
66
|
+
const [showSavePrompt, setShowSavePrompt] = React.useState(false);
|
|
67
|
+
const [showDirInput, setShowDirInput] = React.useState(false);
|
|
68
|
+
const [saveDir, setSaveDir] = React.useState('');
|
|
69
|
+
const [saveConfirmed, setSaveConfirmed] = React.useState(false);
|
|
55
70
|
// @ts-expect-error: Complains if this is not defined but it's not used
|
|
56
71
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
57
72
|
const [timestamp, setTimestamp] = React.useState(new Date().getTime());
|
|
58
73
|
const [tempDir, setTempDir] = React.useState('');
|
|
59
74
|
const [responses, setResponses] = React.useState([]);
|
|
60
75
|
const [apexDebugLogs, setApexDebugLogs] = React.useState([]);
|
|
61
|
-
const { connection, agent, name, outputDir } = props;
|
|
76
|
+
const { connection, agent, name, outputDir, isLocalAgent, apexDebug } = props;
|
|
62
77
|
useInput((input, key) => {
|
|
63
|
-
|
|
78
|
+
// If user is in directory input and presses ESC, cancel and exit without saving
|
|
79
|
+
if (showDirInput && (key.escape || (key.ctrl && input === 'c'))) {
|
|
64
80
|
setSessionEnded(true);
|
|
81
|
+
return;
|
|
65
82
|
}
|
|
66
|
-
|
|
67
|
-
|
|
83
|
+
// Only handle exit if we're not already in save prompt flow
|
|
84
|
+
if (!exitRequested && !showSavePrompt && !showDirInput) {
|
|
85
|
+
if (key.escape || (key.ctrl && input === 'c')) {
|
|
86
|
+
setExitRequested(true);
|
|
87
|
+
setShowSavePrompt(true);
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
// Handle save prompt navigation
|
|
92
|
+
if (showSavePrompt && !showDirInput) {
|
|
93
|
+
if (input.toLowerCase() === 'y' || input.toLowerCase() === 'n') {
|
|
94
|
+
if (input.toLowerCase() === 'y') {
|
|
95
|
+
// If outputDir was provided via flag, use it directly
|
|
96
|
+
if (outputDir) {
|
|
97
|
+
setSaveDir(outputDir);
|
|
98
|
+
setSaveConfirmed(true);
|
|
99
|
+
setShowSavePrompt(false);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
// Otherwise, prompt for directory
|
|
103
|
+
setShowSavePrompt(false);
|
|
104
|
+
setShowDirInput(true);
|
|
105
|
+
const defaultDir = env.getString('SF_AGENT_PREVIEW_OUTPUT_DIR', path.join('temp', 'agent-preview'));
|
|
106
|
+
setSaveDir(defaultDir);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// User said no, exit without saving
|
|
111
|
+
setSessionEnded(true);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
68
114
|
}
|
|
69
115
|
});
|
|
70
116
|
React.useEffect(() => {
|
|
71
117
|
const endSession = async () => {
|
|
72
118
|
if (sessionEnded) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
119
|
+
try {
|
|
120
|
+
// TODO: Support other end types (such as Escalate)
|
|
121
|
+
await agent.end(sessionId, 'UserRequest');
|
|
122
|
+
process.exit(0);
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
// in case the agent session never started, calling agent.end will throw an error, but we've already shown the error to the user
|
|
126
|
+
process.exit(0);
|
|
127
|
+
}
|
|
76
128
|
}
|
|
77
129
|
};
|
|
78
130
|
void endSession();
|
|
79
|
-
}, [sessionEnded]);
|
|
131
|
+
}, [sessionEnded, sessionId, agent]);
|
|
80
132
|
React.useEffect(() => {
|
|
133
|
+
// Set up event listeners for agent compilation and simulation events
|
|
134
|
+
const lifecycle = Lifecycle.getInstance();
|
|
135
|
+
const handleCompilingEvent = () => {
|
|
136
|
+
setHeader('Compiling agent...');
|
|
137
|
+
return Promise.resolve();
|
|
138
|
+
};
|
|
139
|
+
const handleSimulationStartingEvent = () => {
|
|
140
|
+
setHeader('Starting session...');
|
|
141
|
+
return Promise.resolve();
|
|
142
|
+
};
|
|
143
|
+
const handleSessionStartedEvent = () => {
|
|
144
|
+
setHeader(`New session started with "${props.name}"`);
|
|
145
|
+
return Promise.resolve();
|
|
146
|
+
};
|
|
147
|
+
// Listen for the events
|
|
148
|
+
lifecycle.on('agents:compiling', handleCompilingEvent);
|
|
149
|
+
lifecycle.on('agents:simulation-starting', handleSimulationStartingEvent);
|
|
150
|
+
lifecycle.on('agents:session-started', handleSessionStartedEvent);
|
|
81
151
|
const startSession = async () => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
152
|
+
try {
|
|
153
|
+
const session = await agent.start();
|
|
154
|
+
setSessionId(session.sessionId);
|
|
155
|
+
setHeader(`New session started with "${props.name}" (${session.sessionId})`);
|
|
156
|
+
await sleep(500); // Add a short delay to make it feel more natural
|
|
157
|
+
setIsTyping(false);
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
const sfError = SfError.wrap(e);
|
|
161
|
+
setIsTyping(false);
|
|
162
|
+
setHeader('Error starting session');
|
|
163
|
+
setMessages([{ role: name, content: `${sfError.name} - ${sfError.message}`, timestamp: new Date() }]);
|
|
164
|
+
setSessionEnded(true);
|
|
90
165
|
}
|
|
91
|
-
setMessages([{ role: name, content: session.messages[0].message, timestamp: new Date() }]);
|
|
92
166
|
};
|
|
93
167
|
void startSession();
|
|
94
|
-
}, []);
|
|
168
|
+
}, [agent, name, outputDir, props.name, isLocalAgent]);
|
|
95
169
|
React.useEffect(() => {
|
|
96
|
-
|
|
170
|
+
// Save to tempDir if it was set (during session)
|
|
171
|
+
if (tempDir) {
|
|
172
|
+
saveTranscriptsToFile(tempDir, messages, responses);
|
|
173
|
+
}
|
|
97
174
|
}, [tempDir, messages, responses]);
|
|
175
|
+
// Handle saving when user confirms save on exit
|
|
176
|
+
React.useEffect(() => {
|
|
177
|
+
const saveAndExit = async () => {
|
|
178
|
+
if (saveConfirmed && saveDir) {
|
|
179
|
+
const finalDir = resolve(saveDir);
|
|
180
|
+
fs.mkdirSync(finalDir, { recursive: true });
|
|
181
|
+
// Create a timestamped subdirectory for this session
|
|
182
|
+
const dateForDir = new Date().toISOString().replace(/:/g, '-').split('.')[0];
|
|
183
|
+
const sessionDir = path.join(finalDir, `${dateForDir}--${sessionId || 'session'}`);
|
|
184
|
+
fs.mkdirSync(sessionDir, { recursive: true });
|
|
185
|
+
saveTranscriptsToFile(sessionDir, messages, responses);
|
|
186
|
+
// Write apex debug logs if any
|
|
187
|
+
if (apexDebug) {
|
|
188
|
+
for (const response of responses) {
|
|
189
|
+
if (response.apexDebugLog) {
|
|
190
|
+
// eslint-disable-next-line no-await-in-loop
|
|
191
|
+
await writeDebugLog(connection, response.apexDebugLog, sessionDir);
|
|
192
|
+
const logId = response.apexDebugLog.Id;
|
|
193
|
+
if (logId) {
|
|
194
|
+
setApexDebugLogs((prev) => [...prev, path.join(sessionDir, `${logId}.log`)]);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Update tempDir so the save message shows the correct path
|
|
200
|
+
setTempDir(sessionDir);
|
|
201
|
+
// Mark session as ended to trigger exit
|
|
202
|
+
setSessionEnded(true);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
void saveAndExit();
|
|
206
|
+
}, [saveConfirmed, saveDir, messages, responses, sessionId, apexDebug, connection]);
|
|
98
207
|
return (React.createElement(Box, { flexDirection: "column" },
|
|
99
208
|
React.createElement(Box, { flexDirection: "column", width: process.stdout.columns, borderStyle: "round", alignItems: "center", marginTop: 1, marginBottom: 1, paddingLeft: 1, paddingRight: 1 },
|
|
100
209
|
React.createElement(Text, { bold: true }, header)),
|
|
101
|
-
messages.length > 0 && (React.createElement(Box, { flexDirection: "column" }, messages.map(({ timestamp: ts, role, content }, idx) => (React.createElement(Box, { key: role + '__' + ts.toISOString() + '__' + idx.toString(), alignItems: role === 'user' ? 'flex-end' : 'flex-start', flexDirection: "column" },
|
|
210
|
+
messages.length > 0 && (React.createElement(Box, { flexDirection: "column" }, messages.map(({ timestamp: ts, role, content }, idx) => (React.createElement(Box, { key: role + '__' + ts.toISOString() + '__' + idx.toString(), alignItems: role === 'user' ? 'flex-end' : 'flex-start', flexDirection: "column" }, role === 'system' ? (React.createElement(Box, { width: process.stdout.columns, borderStyle: "round", borderColor: "yellow", paddingLeft: 1, paddingRight: 1, marginBottom: 1 },
|
|
211
|
+
React.createElement(Text, null, content))) : (React.createElement(React.Fragment, null,
|
|
102
212
|
React.createElement(Box, { flexDirection: "row", columnGap: 1 },
|
|
103
213
|
React.createElement(Text, null, role === 'user' ? 'You' : role),
|
|
104
214
|
React.createElement(Text, { color: "grey" }, ts.toLocaleString())),
|
|
105
|
-
React.createElement(Box
|
|
106
|
-
|
|
107
|
-
, {
|
|
108
|
-
// Use 70% of the terminal width, or the width of a single line of content, whichever is smaller
|
|
109
|
-
width: Math.min(process.stdout.columns * 0.7, calculateWidth(content)), borderStyle: "round", paddingLeft: 1, paddingRight: 1 },
|
|
110
|
-
React.createElement(Text, null, content))))))),
|
|
215
|
+
React.createElement(Box, { borderStyle: "round", paddingLeft: 1, paddingRight: 1 },
|
|
216
|
+
React.createElement(Text, null, content))))))))),
|
|
111
217
|
isTyping ? (React.createElement(Box, { flexDirection: "column" },
|
|
112
218
|
React.createElement(Box, { alignItems: "flex-start", flexDirection: "column" },
|
|
113
219
|
React.createElement(Box, { flexDirection: "row", columnGap: 1 },
|
|
@@ -117,48 +223,68 @@ export function AgentPreviewReact(props) {
|
|
|
117
223
|
React.createElement(Typing, null))))) : null,
|
|
118
224
|
React.createElement(Box, { paddingLeft: 1, paddingRight: 1 },
|
|
119
225
|
React.createElement(Text, { dimColor: true }, '─'.repeat(process.stdout.columns - 2))),
|
|
120
|
-
React.createElement(Box, { marginBottom: 1 },
|
|
226
|
+
showSavePrompt && !showDirInput ? (React.createElement(Box, { flexDirection: "column", width: process.stdout.columns, borderStyle: "round", borderColor: "yellow", marginTop: 1, marginBottom: 1, paddingLeft: 1, paddingRight: 1 },
|
|
227
|
+
React.createElement(Text, { bold: true }, "Save chat history before exiting? (y/n)"),
|
|
228
|
+
outputDir ? (React.createElement(Text, { dimColor: true },
|
|
229
|
+
"Will save to: ",
|
|
230
|
+
outputDir)) : (React.createElement(Text, { dimColor: true }, "Press 'y' to save, 'n' to exit without saving")))) : null,
|
|
231
|
+
showDirInput ? (React.createElement(Box, { flexDirection: "column", width: process.stdout.columns, borderStyle: "round", borderColor: "yellow", marginTop: 1, marginBottom: 1, paddingLeft: 1, paddingRight: 1 },
|
|
232
|
+
React.createElement(Text, { bold: true },
|
|
233
|
+
"Enter output directory for ",
|
|
234
|
+
apexDebug ? 'debug logs and transcripts' : 'transcripts',
|
|
235
|
+
":"),
|
|
236
|
+
React.createElement(Box, { marginTop: 1 },
|
|
237
|
+
React.createElement(Text, null, "> "),
|
|
238
|
+
React.createElement(TextInput, { showCursor: true, value: saveDir, placeholder: "Press Enter to confirm", onChange: setSaveDir, onSubmit: (dir) => {
|
|
239
|
+
if (dir) {
|
|
240
|
+
setSaveDir(dir);
|
|
241
|
+
setSaveConfirmed(true);
|
|
242
|
+
setShowDirInput(false);
|
|
243
|
+
}
|
|
244
|
+
} })))) : null,
|
|
245
|
+
!sessionEnded && !exitRequested && !showSavePrompt && !showDirInput ? (React.createElement(Box, { marginBottom: 1 },
|
|
121
246
|
React.createElement(Text, null, "> "),
|
|
122
|
-
React.createElement(TextInput, { showCursor: true, value: query, placeholder: "Start typing (press ESC to exit)", onChange: setQuery,
|
|
247
|
+
React.createElement(TextInput, { showCursor: true, value: query, placeholder: "Start typing (press ESC or Ctrl+C to exit)", onChange: setQuery,
|
|
123
248
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
124
249
|
onSubmit: async (content) => {
|
|
125
250
|
if (!content)
|
|
126
251
|
return;
|
|
127
252
|
setQuery('');
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
setIsTyping(false);
|
|
138
|
-
// Add the agent's response to the chat
|
|
139
|
-
setMessages((prev) => [...prev, { role: name, content: message, timestamp: new Date() }]);
|
|
140
|
-
// If there is an apex debug log entry, get the log and write it to the output dir
|
|
141
|
-
if (response.apexDebugLog && tempDir) {
|
|
142
|
-
// Write the apex debug to the output dir
|
|
143
|
-
await writeDebugLog(connection, response.apexDebugLog, tempDir);
|
|
144
|
-
const logId = response.apexDebugLog.Id;
|
|
145
|
-
if (logId) {
|
|
146
|
-
setApexDebugLogs((prev) => [...prev, path.join(tempDir, `${logId}.log`)]);
|
|
253
|
+
try {
|
|
254
|
+
// Add the most recent user message to the chat window
|
|
255
|
+
setMessages((prev) => [...prev, { role: 'user', content, timestamp: new Date() }]);
|
|
256
|
+
setIsTyping(true);
|
|
257
|
+
const response = await agent.send(sessionId, content);
|
|
258
|
+
setResponses((prev) => [...prev, response]);
|
|
259
|
+
const message = response.messages[0].message;
|
|
260
|
+
if (!message) {
|
|
261
|
+
throw new Error('Failed to send message');
|
|
147
262
|
}
|
|
263
|
+
setIsTyping(false);
|
|
264
|
+
// Add the agent's response to the chat
|
|
265
|
+
setMessages((prev) => [...prev, { role: name, content: message, timestamp: new Date() }]);
|
|
266
|
+
// Apex debug logs will be saved when user exits and chooses to save
|
|
267
|
+
}
|
|
268
|
+
catch (e) {
|
|
269
|
+
const sfError = SfError.wrap(e);
|
|
270
|
+
setIsTyping(false);
|
|
271
|
+
setHeader(`Error: ${sfError.name}`);
|
|
272
|
+
setMessages([{ role: name, content: `${sfError.name} - ${sfError.message}`, timestamp: new Date() }]);
|
|
273
|
+
setSessionEnded(true);
|
|
148
274
|
}
|
|
149
|
-
} })),
|
|
150
|
-
sessionEnded ? (React.createElement(Box, { flexDirection: "column", width: process.stdout.columns, borderStyle: "round", marginTop: 1, marginBottom: 1, paddingLeft: 1, paddingRight: 1 },
|
|
275
|
+
} }))) : null,
|
|
276
|
+
sessionEnded && !showSavePrompt && !showDirInput ? (React.createElement(Box, { flexDirection: "column", width: process.stdout.columns, borderStyle: "round", marginTop: 1, marginBottom: 1, paddingLeft: 1, paddingRight: 1 },
|
|
151
277
|
React.createElement(Text, { bold: true }, "Session Ended"),
|
|
152
|
-
|
|
278
|
+
tempDir ? React.createElement(Text, null,
|
|
153
279
|
"Conversation log: ",
|
|
154
280
|
tempDir,
|
|
155
281
|
"/transcript.json") : null,
|
|
156
|
-
|
|
282
|
+
tempDir ? React.createElement(Text, null,
|
|
157
283
|
"API transactions: ",
|
|
158
284
|
tempDir,
|
|
159
285
|
"/responses.json") : null,
|
|
160
|
-
apexDebugLogs.length > 0 && React.createElement(Text, null,
|
|
161
|
-
"Apex Debug Logs: ",
|
|
162
|
-
|
|
286
|
+
apexDebugLogs.length > 0 && tempDir && React.createElement(Text, null,
|
|
287
|
+
"Apex Debug Logs saved to: ",
|
|
288
|
+
tempDir))) : null));
|
|
163
289
|
}
|
|
164
290
|
//# sourceMappingURL=agent-preview-react.js.map
|