@salesforce/plugin-agent 1.19.5 → 1.20.1
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 +64 -23
- package/lib/commands/agent/preview.d.ts +30 -1
- package/lib/commands/agent/preview.js +98 -7
- package/lib/commands/agent/preview.js.map +1 -1
- package/lib/components/agent-preview-react.d.ts +7 -1
- package/lib/components/agent-preview-react.js +124 -30
- package/lib/components/agent-preview-react.js.map +1 -1
- package/messages/agent.preview.md +37 -8
- package/npm-shrinkwrap.json +3696 -2907
- package/oclif.lock +2788 -2404
- package/oclif.manifest.json +27 -10
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -132,7 +132,7 @@ EXAMPLES
|
|
|
132
132
|
$ sf agent create --agent-name "Resort Manager" --spec specs/resortManagerAgent.yaml --preview
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
_See code: [src/commands/agent/create.ts](https://github.com/salesforcecli/plugin-agent/blob/1.
|
|
135
|
+
_See code: [src/commands/agent/create.ts](https://github.com/salesforcecli/plugin-agent/blob/1.20.1/src/commands/agent/create.ts)_
|
|
136
136
|
|
|
137
137
|
## `sf agent generate agent-spec`
|
|
138
138
|
|
|
@@ -237,7 +237,7 @@ EXAMPLES
|
|
|
237
237
|
$ sf agent generate agent-spec --tone formal --agent-user resortmanager@myorg.com
|
|
238
238
|
```
|
|
239
239
|
|
|
240
|
-
_See code: [src/commands/agent/generate/agent-spec.ts](https://github.com/salesforcecli/plugin-agent/blob/1.
|
|
240
|
+
_See code: [src/commands/agent/generate/agent-spec.ts](https://github.com/salesforcecli/plugin-agent/blob/1.20.1/src/commands/agent/generate/agent-spec.ts)_
|
|
241
241
|
|
|
242
242
|
## `sf agent generate template`
|
|
243
243
|
|
|
@@ -285,7 +285,7 @@ EXAMPLES
|
|
|
285
285
|
force-app/main/default/bots/My_Awesome_Agent/My_Awesome_Agent.bot-meta.xml --agent-version 1
|
|
286
286
|
```
|
|
287
287
|
|
|
288
|
-
_See code: [src/commands/agent/generate/template.ts](https://github.com/salesforcecli/plugin-agent/blob/1.
|
|
288
|
+
_See code: [src/commands/agent/generate/template.ts](https://github.com/salesforcecli/plugin-agent/blob/1.20.1/src/commands/agent/generate/template.ts)_
|
|
289
289
|
|
|
290
290
|
## `sf agent generate test-spec`
|
|
291
291
|
|
|
@@ -343,42 +343,83 @@ EXAMPLES
|
|
|
343
343
|
force-app//main/default/aiEvaluationDefinitions/Resort_Manager_Tests.aiEvaluationDefinition-meta.xml
|
|
344
344
|
```
|
|
345
345
|
|
|
346
|
-
_See code: [src/commands/agent/generate/test-spec.ts](https://github.com/salesforcecli/plugin-agent/blob/1.
|
|
346
|
+
_See code: [src/commands/agent/generate/test-spec.ts](https://github.com/salesforcecli/plugin-agent/blob/1.20.1/src/commands/agent/generate/test-spec.ts)_
|
|
347
347
|
|
|
348
348
|
## `sf agent preview`
|
|
349
349
|
|
|
350
|
-
Interact with an active agent
|
|
350
|
+
Interact with an active agent to preview how the agent responds to your statements, questions, and commands (utterances).
|
|
351
351
|
|
|
352
352
|
```
|
|
353
353
|
USAGE
|
|
354
|
-
$ sf agent preview -o <value> -
|
|
354
|
+
$ sf agent preview -o <value> -a <value> [--flags-dir <value>] [--api-version <value>] [-n <value>] [-d <value>]
|
|
355
355
|
|
|
356
356
|
FLAGS
|
|
357
|
-
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
357
|
+
-a, --connected-app-user=<value> (required) Username or alias of the connected app user that's configured with
|
|
358
|
+
JWT-based access tokens to the agent.
|
|
359
|
+
-d, --output-dir=<value> Directory where conversation transcripts are saved.
|
|
360
|
+
-n, --api-name=<value> API name of the agent you want to interact with.
|
|
361
|
+
-o, --target-org=<value> (required) Username or alias of the target org. Not required if the `target-org`
|
|
362
|
+
configuration variable is already set.
|
|
363
|
+
--api-version=<value> Override the api version used for api requests made by this command
|
|
361
364
|
|
|
362
365
|
GLOBAL FLAGS
|
|
363
366
|
--flags-dir=<value> Import flag values from a directory.
|
|
364
367
|
|
|
365
368
|
DESCRIPTION
|
|
366
|
-
Interact with an active agent
|
|
369
|
+
Interact with an active agent to preview how the agent responds to your statements, questions, and commands
|
|
370
|
+
(utterances).
|
|
371
|
+
|
|
372
|
+
Use this command to have a natural language conversation with an active agent in your org, as if you were an actual
|
|
373
|
+
user. The interface is simple: in the "Start typing..." prompt, enter a statement, question, or command; when you're
|
|
374
|
+
done, enter Return. Your utterance is posted on the right along with a timestamp. The agent then responds on the left.
|
|
375
|
+
To exit the conversation, hit ESC or Control+C.
|
|
376
|
+
|
|
377
|
+
This command is useful to test if the agent responds to your utterances as you expect. For example, you can test that
|
|
378
|
+
the agent uses a particular topic when asked a question, and then whether it invokes the correct action associated
|
|
379
|
+
with that topic. This command is the CLI-equivalent of the Conversation Preview panel in your org's Agent Builder UI.
|
|
380
|
+
|
|
381
|
+
When the session concludes, the command asks if you want to save the API responses and chat transcripts. By default,
|
|
382
|
+
the files are saved to the "./temp/agent-preview" directory. Specify a new default directory by setting the
|
|
383
|
+
environment variable "SF_AGENT_PREVIEW_OUTPUT_DIR" to the directory. Or you can pass the directory to the --output-dir
|
|
384
|
+
flag.
|
|
385
|
+
|
|
386
|
+
Find the agent's API name in its main details page in your org's Agent page in Setup.
|
|
367
387
|
|
|
368
|
-
|
|
388
|
+
Before you use this command, you must complete these steps:
|
|
389
|
+
|
|
390
|
+
1. Create a connected app in your org as described in the "Create a Connected App" section here:
|
|
391
|
+
https://developer.salesforce.com/docs/einstein/genai/guide/agent-api-get-started.html#create-a-connected-app. Do these
|
|
392
|
+
two additional steps:
|
|
393
|
+
|
|
394
|
+
a. When specifying the connected app's Callback URL, add this second callback URL on a new line:
|
|
395
|
+
http://localhost:1717/OauthRedirect
|
|
396
|
+
|
|
397
|
+
b. Make note of the user that you specified as the "Run As" user when updating the Client Credentials Flow section.
|
|
398
|
+
|
|
399
|
+
2. Add the connected app to your agent as described in the "Add Connected App to Agent" section here:
|
|
400
|
+
https://developer.salesforce.com/docs/einstein/genai/guide/agent-api-get-started.html#add-connected-app-to-agent.
|
|
401
|
+
|
|
402
|
+
3. Using the username of the user you specified as the "Run As" user above, authorize your org using the JWT flow, as
|
|
403
|
+
described in this document:
|
|
404
|
+
https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_auth_jwt_flow.htm.
|
|
405
|
+
|
|
406
|
+
4. When you run this command to interact with an agent, specify the username you authorized in the preceding step with
|
|
407
|
+
the --connected-app-user (-a) flag.
|
|
369
408
|
|
|
370
409
|
EXAMPLES
|
|
371
|
-
|
|
410
|
+
Interact with an agent with API name "Resort_Manager" in the org with alias "my-org". Connect to your agent using
|
|
411
|
+
the alias "my-jwt-user"; this alias must point to the username who is authorized using JWT:
|
|
372
412
|
|
|
373
|
-
|
|
413
|
+
$ sf agent preview --api-name "Resort_Manager" --target-org my-org --connected-app-user my-jwt-user
|
|
374
414
|
|
|
375
|
-
|
|
376
|
-
|
|
415
|
+
Same as the preceding example, but this time save the conversation transcripts to the "./transcripts/my-preview"
|
|
416
|
+
directory rather than the default "./temp/agent-preview":
|
|
377
417
|
|
|
378
|
-
|
|
418
|
+
$ sf agent preview --api-name "Resort_Manager" --target-org my-org --connected-app-user my-jwt-user --output-dir \
|
|
419
|
+
"transcripts/my-preview"
|
|
379
420
|
```
|
|
380
421
|
|
|
381
|
-
_See code: [src/commands/agent/preview.ts](https://github.com/salesforcecli/plugin-agent/blob/1.
|
|
422
|
+
_See code: [src/commands/agent/preview.ts](https://github.com/salesforcecli/plugin-agent/blob/1.20.1/src/commands/agent/preview.ts)_
|
|
382
423
|
|
|
383
424
|
## `sf agent test create`
|
|
384
425
|
|
|
@@ -433,7 +474,7 @@ EXAMPLES
|
|
|
433
474
|
$ sf agent test create --spec specs/Resort_Manager-testSpec.yaml --test-api-name Resort_Manager_Test --preview
|
|
434
475
|
```
|
|
435
476
|
|
|
436
|
-
_See code: [src/commands/agent/test/create.ts](https://github.com/salesforcecli/plugin-agent/blob/1.
|
|
477
|
+
_See code: [src/commands/agent/test/create.ts](https://github.com/salesforcecli/plugin-agent/blob/1.20.1/src/commands/agent/test/create.ts)_
|
|
437
478
|
|
|
438
479
|
## `sf agent test list`
|
|
439
480
|
|
|
@@ -468,7 +509,7 @@ EXAMPLES
|
|
|
468
509
|
$ sf agent test list --target-org my-org
|
|
469
510
|
```
|
|
470
511
|
|
|
471
|
-
_See code: [src/commands/agent/test/list.ts](https://github.com/salesforcecli/plugin-agent/blob/1.
|
|
512
|
+
_See code: [src/commands/agent/test/list.ts](https://github.com/salesforcecli/plugin-agent/blob/1.20.1/src/commands/agent/test/list.ts)_
|
|
472
513
|
|
|
473
514
|
## `sf agent test results`
|
|
474
515
|
|
|
@@ -524,7 +565,7 @@ FLAG DESCRIPTIONS
|
|
|
524
565
|
test results aren't written.
|
|
525
566
|
```
|
|
526
567
|
|
|
527
|
-
_See code: [src/commands/agent/test/results.ts](https://github.com/salesforcecli/plugin-agent/blob/1.
|
|
568
|
+
_See code: [src/commands/agent/test/results.ts](https://github.com/salesforcecli/plugin-agent/blob/1.20.1/src/commands/agent/test/results.ts)_
|
|
528
569
|
|
|
529
570
|
## `sf agent test resume`
|
|
530
571
|
|
|
@@ -587,7 +628,7 @@ FLAG DESCRIPTIONS
|
|
|
587
628
|
test results aren't written.
|
|
588
629
|
```
|
|
589
630
|
|
|
590
|
-
_See code: [src/commands/agent/test/resume.ts](https://github.com/salesforcecli/plugin-agent/blob/1.
|
|
631
|
+
_See code: [src/commands/agent/test/resume.ts](https://github.com/salesforcecli/plugin-agent/blob/1.20.1/src/commands/agent/test/resume.ts)_
|
|
591
632
|
|
|
592
633
|
## `sf agent test run`
|
|
593
634
|
|
|
@@ -651,6 +692,6 @@ FLAG DESCRIPTIONS
|
|
|
651
692
|
test results aren't written.
|
|
652
693
|
```
|
|
653
694
|
|
|
654
|
-
_See code: [src/commands/agent/test/run.ts](https://github.com/salesforcecli/plugin-agent/blob/1.
|
|
695
|
+
_See code: [src/commands/agent/test/run.ts](https://github.com/salesforcecli/plugin-agent/blob/1.20.1/src/commands/agent/test/run.ts)_
|
|
655
696
|
|
|
656
697
|
<!-- commandsstop -->
|
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
type BotVersionStatus = {
|
|
3
|
+
Status: 'Active' | 'Inactive';
|
|
4
|
+
};
|
|
5
|
+
export type AgentData = {
|
|
6
|
+
Id: string;
|
|
7
|
+
DeveloperName: string;
|
|
8
|
+
BotVersions: {
|
|
9
|
+
records: BotVersionStatus[];
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
type Choice<Value> = {
|
|
13
|
+
value: Value;
|
|
14
|
+
name?: string;
|
|
15
|
+
disabled?: boolean | string;
|
|
16
|
+
};
|
|
17
|
+
type AgentValue = {
|
|
18
|
+
Id: string;
|
|
19
|
+
DeveloperName: string;
|
|
20
|
+
};
|
|
21
|
+
export declare const UNSUPPORTED_AGENTS: string[];
|
|
2
22
|
export type AgentPreviewResult = void;
|
|
3
23
|
export default class AgentPreview extends SfCommand<AgentPreviewResult> {
|
|
4
24
|
static readonly summary: string;
|
|
@@ -6,10 +26,19 @@ export default class AgentPreview extends SfCommand<AgentPreviewResult> {
|
|
|
6
26
|
static readonly examples: string[];
|
|
7
27
|
static readonly enableJsonFlag = false;
|
|
8
28
|
static readonly requiresProject = true;
|
|
29
|
+
static state: string;
|
|
9
30
|
static readonly flags: {
|
|
10
31
|
'target-org': import("@oclif/core/interfaces").OptionFlag<import("@salesforce/core").Org, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
32
|
'api-version': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
-
|
|
33
|
+
'connected-app-user': import("@oclif/core/interfaces").OptionFlag<import("@salesforce/core").Org, import("@oclif/core/interfaces").CustomOptions>;
|
|
34
|
+
'api-name': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
35
|
+
'output-dir': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
36
|
};
|
|
14
37
|
run(): Promise<AgentPreviewResult>;
|
|
15
38
|
}
|
|
39
|
+
export declare const agentIsUnsupported: (devName: string) => boolean;
|
|
40
|
+
export declare const agentIsInactive: (agent: AgentData) => boolean;
|
|
41
|
+
export declare const validateAgent: (agent: AgentData) => boolean;
|
|
42
|
+
export declare const getAgentChoices: (agents: AgentData[]) => Array<Choice<AgentValue>>;
|
|
43
|
+
export declare const resolveOutputDir: (outputDir: string | undefined) => Promise<string | undefined>;
|
|
44
|
+
export {};
|
|
@@ -4,34 +4,125 @@
|
|
|
4
4
|
* Licensed under the BSD 3-Clause license.
|
|
5
5
|
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
6
|
*/
|
|
7
|
+
import { resolve } from 'node:path';
|
|
7
8
|
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
8
|
-
import { Messages } from '@salesforce/core';
|
|
9
|
+
import { Messages, SfError } from '@salesforce/core';
|
|
9
10
|
import React from 'react';
|
|
10
11
|
import { render } from 'ink';
|
|
12
|
+
import { env } from '@salesforce/kit';
|
|
13
|
+
import { AgentPreview as Preview } from '@salesforce/agents';
|
|
14
|
+
import { select, confirm, input } from '@inquirer/prompts';
|
|
11
15
|
import { AgentPreviewReact } from '../../components/agent-preview-react.js';
|
|
12
16
|
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
13
17
|
const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.preview');
|
|
18
|
+
// https://developer.salesforce.com/docs/einstein/genai/guide/agent-api-get-started.html#prerequisites
|
|
19
|
+
export const UNSUPPORTED_AGENTS = ['Copilot_for_Salesforce'];
|
|
14
20
|
export default class AgentPreview extends SfCommand {
|
|
15
21
|
static summary = messages.getMessage('summary');
|
|
16
22
|
static description = messages.getMessage('description');
|
|
17
23
|
static examples = messages.getMessages('examples');
|
|
18
24
|
static enableJsonFlag = false;
|
|
19
25
|
static requiresProject = true;
|
|
26
|
+
static state = 'preview';
|
|
20
27
|
static flags = {
|
|
21
28
|
'target-org': Flags.requiredOrg(),
|
|
22
29
|
'api-version': Flags.orgApiVersion(),
|
|
23
|
-
|
|
24
|
-
summary: messages.getMessage('flags.
|
|
25
|
-
|
|
26
|
-
char: 'n',
|
|
30
|
+
'connected-app-user': Flags.requiredOrg({
|
|
31
|
+
summary: messages.getMessage('flags.connected-app-user.summary'),
|
|
32
|
+
char: 'a',
|
|
27
33
|
required: true,
|
|
28
34
|
}),
|
|
35
|
+
'api-name': Flags.string({
|
|
36
|
+
summary: messages.getMessage('flags.api-name.summary'),
|
|
37
|
+
char: 'n',
|
|
38
|
+
}),
|
|
39
|
+
'output-dir': Flags.directory({
|
|
40
|
+
summary: messages.getMessage('flags.output-dir.summary'),
|
|
41
|
+
char: 'd',
|
|
42
|
+
}),
|
|
29
43
|
};
|
|
30
44
|
async run() {
|
|
31
45
|
const { flags } = await this.parse(AgentPreview);
|
|
32
|
-
|
|
33
|
-
const
|
|
46
|
+
const { 'api-name': apiNameFlag } = flags;
|
|
47
|
+
const conn = flags['target-org'].getConnection(flags['api-version']);
|
|
48
|
+
const apiConn = flags['connected-app-user'].getConnection(flags['api-version']);
|
|
49
|
+
const agentsQuery = await conn.query('SELECT Id, DeveloperName, (SELECT Status FROM BotVersions) FROM BotDefinition WHERE IsDeleted = false');
|
|
50
|
+
if (agentsQuery.totalSize === 0)
|
|
51
|
+
throw new SfError('No Agents found in the org');
|
|
52
|
+
const agentsInOrg = agentsQuery.records;
|
|
53
|
+
let selectedAgent;
|
|
54
|
+
if (apiNameFlag) {
|
|
55
|
+
selectedAgent = agentsInOrg.find((agent) => agent.DeveloperName === apiNameFlag);
|
|
56
|
+
if (!selectedAgent)
|
|
57
|
+
throw new Error(`No valid Agents were found with the Api Name ${apiNameFlag}.`);
|
|
58
|
+
validateAgent(selectedAgent);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
selectedAgent = await select({
|
|
62
|
+
message: 'Select an agent',
|
|
63
|
+
choices: getAgentChoices(agentsInOrg),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const outputDir = await resolveOutputDir(flags['output-dir']);
|
|
67
|
+
const agentPreview = new Preview(apiConn);
|
|
68
|
+
const instance = render(React.createElement(AgentPreviewReact, {
|
|
69
|
+
agent: agentPreview,
|
|
70
|
+
id: selectedAgent.Id,
|
|
71
|
+
name: selectedAgent.DeveloperName,
|
|
72
|
+
outputDir,
|
|
73
|
+
}), { exitOnCtrlC: false });
|
|
34
74
|
await instance.waitUntilExit();
|
|
35
75
|
}
|
|
36
76
|
}
|
|
77
|
+
export const agentIsUnsupported = (devName) => UNSUPPORTED_AGENTS.includes(devName);
|
|
78
|
+
export const agentIsInactive = (agent) =>
|
|
79
|
+
// Agent versioning is not fully supported yet, but this should ensure at least one version is active
|
|
80
|
+
agent.BotVersions.records.every((botVersion) => botVersion.Status === 'Inactive');
|
|
81
|
+
export const validateAgent = (agent) => {
|
|
82
|
+
// Agents must be active in Agent Builder
|
|
83
|
+
if (agentIsInactive(agent)) {
|
|
84
|
+
throw new SfError(`Agent ${agent.DeveloperName} is inactive.`);
|
|
85
|
+
}
|
|
86
|
+
// The default agent is not supported
|
|
87
|
+
if (agentIsUnsupported(agent.DeveloperName)) {
|
|
88
|
+
throw new SfError(`Agent ${agent.DeveloperName} is not supported.`, 'DefaultAgentNotSupported', [
|
|
89
|
+
'See https://developer.salesforce.com/docs/einstein/genai/guide/agent-api-get-started.html#prerequisites',
|
|
90
|
+
]);
|
|
91
|
+
}
|
|
92
|
+
return true;
|
|
93
|
+
};
|
|
94
|
+
export const getAgentChoices = (agents) => agents.map((agent) => {
|
|
95
|
+
let disabled = false;
|
|
96
|
+
if (agentIsInactive(agent))
|
|
97
|
+
disabled = '(Inactive)';
|
|
98
|
+
if (agentIsUnsupported(agent.DeveloperName))
|
|
99
|
+
disabled = '(Not Supported)';
|
|
100
|
+
return {
|
|
101
|
+
name: agent.DeveloperName,
|
|
102
|
+
value: {
|
|
103
|
+
Id: agent.Id,
|
|
104
|
+
DeveloperName: agent.DeveloperName,
|
|
105
|
+
},
|
|
106
|
+
disabled,
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
export const resolveOutputDir = async (outputDir) => {
|
|
110
|
+
if (!outputDir) {
|
|
111
|
+
const response = await confirm({
|
|
112
|
+
message: 'Save transcripts to an output directory?',
|
|
113
|
+
default: true,
|
|
114
|
+
});
|
|
115
|
+
if (response) {
|
|
116
|
+
const getDir = await input({
|
|
117
|
+
message: 'Enter the output directory',
|
|
118
|
+
default: env.getString('SF_AGENT_PREVIEW_OUTPUT_DIR', 'temp/agent-preview'),
|
|
119
|
+
required: true,
|
|
120
|
+
});
|
|
121
|
+
return resolve(getDir);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
return resolve(outputDir);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
37
128
|
//# sourceMappingURL=preview.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preview.js","sourceRoot":"","sources":["../../../src/commands/agent/preview.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"preview.js","sourceRoot":"","sources":["../../../src/commands/agent/preview.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { AgentPreview } from '@salesforce/agents';
|
|
2
3
|
/**
|
|
3
4
|
* Ideas:
|
|
4
5
|
* - Limit height based on terminal height
|
|
@@ -6,4 +7,9 @@ import React from 'react';
|
|
|
6
7
|
* - Add keystroke to scroll up
|
|
7
8
|
* - Add keystroke to scroll down
|
|
8
9
|
*/
|
|
9
|
-
export declare function AgentPreviewReact(
|
|
10
|
+
export declare function AgentPreviewReact(props: {
|
|
11
|
+
readonly agent: AgentPreview;
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly outputDir: string | undefined;
|
|
15
|
+
}): React.ReactNode;
|
|
@@ -4,11 +4,39 @@
|
|
|
4
4
|
* Licensed under the BSD 3-Clause license.
|
|
5
5
|
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
6
|
*/
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import fs from 'node:fs';
|
|
7
9
|
import React from 'react';
|
|
8
|
-
import { Box, Text } from 'ink';
|
|
9
|
-
import figures from '@inquirer/figures';
|
|
10
|
+
import { Box, Text, useInput } from 'ink';
|
|
10
11
|
import TextInput from 'ink-text-input';
|
|
11
12
|
import { sleep } from '@salesforce/kit';
|
|
13
|
+
// Component to show a simple typing animation
|
|
14
|
+
function Typing() {
|
|
15
|
+
const [frame, setFrame] = React.useState(0);
|
|
16
|
+
React.useEffect(() => {
|
|
17
|
+
const timer = setInterval(() => {
|
|
18
|
+
setFrame((prev) => (prev + 1) % 4);
|
|
19
|
+
}, 350);
|
|
20
|
+
return () => clearInterval(timer);
|
|
21
|
+
}, []);
|
|
22
|
+
const colors = ['grey', 'grey', 'grey'];
|
|
23
|
+
colors[frame] = 'white';
|
|
24
|
+
return (React.createElement(Text, null,
|
|
25
|
+
React.createElement(Text, { color: colors[0] }, "."),
|
|
26
|
+
React.createElement(Text, { color: colors[1] }, "."),
|
|
27
|
+
React.createElement(Text, { color: colors[2] }, ".")));
|
|
28
|
+
}
|
|
29
|
+
// Split the content on newlines, then find the longest array element
|
|
30
|
+
const calculateWidth = (content) => content.split('\n').reduce((acc, line) => Math.max(acc, line.length), 0) + 4;
|
|
31
|
+
const saveTranscriptsToFile = (outputDir, messages, responses) => {
|
|
32
|
+
if (!outputDir)
|
|
33
|
+
return;
|
|
34
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
35
|
+
const transcriptPath = path.join(outputDir, 'transcript.json');
|
|
36
|
+
fs.writeFileSync(transcriptPath, JSON.stringify(messages, null, 2));
|
|
37
|
+
const responsesPath = path.join(outputDir, 'responses.json');
|
|
38
|
+
fs.writeFileSync(responsesPath, JSON.stringify(responses, null, 2));
|
|
39
|
+
};
|
|
12
40
|
/**
|
|
13
41
|
* Ideas:
|
|
14
42
|
* - Limit height based on terminal height
|
|
@@ -16,41 +44,107 @@ import { sleep } from '@salesforce/kit';
|
|
|
16
44
|
* - Add keystroke to scroll up
|
|
17
45
|
* - Add keystroke to scroll down
|
|
18
46
|
*/
|
|
19
|
-
export function AgentPreviewReact() {
|
|
20
|
-
const [
|
|
47
|
+
export function AgentPreviewReact(props) {
|
|
48
|
+
const [messages, setMessages] = React.useState([]);
|
|
49
|
+
const [header, setHeader] = React.useState('Starting session...');
|
|
50
|
+
const [sessionId, setSessionId] = React.useState('');
|
|
21
51
|
const [query, setQuery] = React.useState('');
|
|
52
|
+
const [isTyping, setIsTyping] = React.useState(true);
|
|
53
|
+
const [sessionEnded, setSessionEnded] = React.useState(false);
|
|
54
|
+
// @ts-expect-error: Complains if this is not defined but it's not used
|
|
55
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
56
|
+
const [timestamp, setTimestamp] = React.useState(new Date().getTime());
|
|
57
|
+
const [tempDir, setTempDir] = React.useState('');
|
|
58
|
+
const [responses, setResponses] = React.useState([]);
|
|
59
|
+
const { agent, id, name, outputDir } = props;
|
|
60
|
+
useInput((input, key) => {
|
|
61
|
+
if (key.escape) {
|
|
62
|
+
setSessionEnded(true);
|
|
63
|
+
}
|
|
64
|
+
if (key.ctrl && input === 'c') {
|
|
65
|
+
setSessionEnded(true);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
React.useEffect(() => {
|
|
69
|
+
const endSession = async () => {
|
|
70
|
+
if (sessionEnded) {
|
|
71
|
+
// TODO: Support other end types (such as Escalate)
|
|
72
|
+
await agent.end(sessionId, 'UserRequest');
|
|
73
|
+
process.exit(0);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
void endSession();
|
|
77
|
+
}, [sessionEnded]);
|
|
78
|
+
React.useEffect(() => {
|
|
79
|
+
const startSession = async () => {
|
|
80
|
+
const session = await agent.start(id);
|
|
81
|
+
setSessionId(session.sessionId);
|
|
82
|
+
setHeader(`New session started with "${props.name}" (${session.sessionId})`);
|
|
83
|
+
await sleep(500); // Add a short delay to make it feel more natural
|
|
84
|
+
setIsTyping(false);
|
|
85
|
+
if (outputDir) {
|
|
86
|
+
const dateForDir = new Date().toISOString().replace(/:/g, '-').split('.')[0];
|
|
87
|
+
setTempDir(path.join(outputDir, `${dateForDir}--${session.sessionId}`));
|
|
88
|
+
}
|
|
89
|
+
setMessages([{ role: name, content: session.messages[0].message, timestamp: new Date() }]);
|
|
90
|
+
};
|
|
91
|
+
void startSession();
|
|
92
|
+
}, []);
|
|
93
|
+
React.useEffect(() => {
|
|
94
|
+
saveTranscriptsToFile(tempDir, messages, responses);
|
|
95
|
+
}, [tempDir, messages, responses]);
|
|
22
96
|
return (React.createElement(Box, { flexDirection: "column" },
|
|
23
|
-
|
|
24
|
-
|
|
97
|
+
React.createElement(Box, { flexDirection: "column", width: process.stdout.columns, borderStyle: "round", alignItems: "center", marginTop: 1, marginBottom: 1, paddingLeft: 1, paddingRight: 1 },
|
|
98
|
+
React.createElement(Text, { bold: true }, header)),
|
|
99
|
+
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" },
|
|
100
|
+
React.createElement(Box, { flexDirection: "row", columnGap: 1 },
|
|
101
|
+
React.createElement(Text, null, role === 'user' ? 'You' : role),
|
|
102
|
+
React.createElement(Text, { color: "grey" }, ts.toLocaleString())),
|
|
103
|
+
React.createElement(Box
|
|
104
|
+
// Use 70% of the terminal width, or the width of a single line of content, whichever is smaller
|
|
105
|
+
, {
|
|
106
|
+
// Use 70% of the terminal width, or the width of a single line of content, whichever is smaller
|
|
107
|
+
width: Math.min(process.stdout.columns * 0.7, calculateWidth(content)), borderStyle: "round", paddingLeft: 1, paddingRight: 1 },
|
|
108
|
+
React.createElement(Text, null, content))))))),
|
|
109
|
+
isTyping ? (React.createElement(Box, { flexDirection: "column" },
|
|
110
|
+
React.createElement(Box, { alignItems: "flex-start", flexDirection: "column" },
|
|
25
111
|
React.createElement(Box, { flexDirection: "row", columnGap: 1 },
|
|
26
|
-
React.createElement(Text, null,
|
|
27
|
-
React.createElement(Text, { color: "
|
|
28
|
-
React.createElement(Box, { width:
|
|
29
|
-
React.createElement(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
React.createElement(Box,
|
|
33
|
-
React.createElement(Text, null,
|
|
34
|
-
|
|
35
|
-
" "),
|
|
36
|
-
React.createElement(TextInput, { showCursor: true, value: query, placeholder: "Start typing\u2026", onChange: setQuery,
|
|
112
|
+
React.createElement(Text, null, name),
|
|
113
|
+
React.createElement(Text, { color: "grey" }, new Date().toLocaleString())),
|
|
114
|
+
React.createElement(Box, { width: 7, borderStyle: "round", paddingLeft: 1, paddingRight: 1 },
|
|
115
|
+
React.createElement(Typing, null))))) : null,
|
|
116
|
+
React.createElement(Box, { paddingLeft: 1, paddingRight: 1 },
|
|
117
|
+
React.createElement(Text, { dimColor: true }, '─'.repeat(process.stdout.columns - 2))),
|
|
118
|
+
React.createElement(Box, { marginBottom: 1 },
|
|
119
|
+
React.createElement(Text, null, "> "),
|
|
120
|
+
React.createElement(TextInput, { showCursor: true, value: query, placeholder: "Start typing (press ESC to exit)", onChange: setQuery,
|
|
37
121
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
38
122
|
onSubmit: async (content) => {
|
|
39
123
|
if (!content)
|
|
40
124
|
return;
|
|
41
125
|
setQuery('');
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
});
|
|
54
|
-
} }))
|
|
126
|
+
// Add the most recent user message to the chat window
|
|
127
|
+
setMessages((prev) => [...prev, { role: 'user', content, timestamp: new Date() }]);
|
|
128
|
+
setIsTyping(true);
|
|
129
|
+
const response = await agent.send(sessionId, content);
|
|
130
|
+
setResponses((prev) => [...prev, response]);
|
|
131
|
+
const message = response.messages[0].message;
|
|
132
|
+
if (!message) {
|
|
133
|
+
throw new Error('Failed to send message');
|
|
134
|
+
}
|
|
135
|
+
setIsTyping(false);
|
|
136
|
+
// Add the agent's response to the chat
|
|
137
|
+
setMessages((prev) => [...prev, { role: name, content: message, timestamp: new Date() }]);
|
|
138
|
+
} })),
|
|
139
|
+
sessionEnded ? (React.createElement(Box, { flexDirection: "column", width: process.stdout.columns, borderStyle: "round", marginTop: 1, marginBottom: 1, paddingLeft: 1, paddingRight: 1 },
|
|
140
|
+
React.createElement(Text, { bold: true }, "Session Ended"),
|
|
141
|
+
outputDir ? React.createElement(Text, null,
|
|
142
|
+
"Conversation log: ",
|
|
143
|
+
tempDir,
|
|
144
|
+
"/transcript.json") : null,
|
|
145
|
+
outputDir ? React.createElement(Text, null,
|
|
146
|
+
"API transactions: ",
|
|
147
|
+
tempDir,
|
|
148
|
+
"/responses.json") : null)) : null));
|
|
55
149
|
}
|
|
56
150
|
//# sourceMappingURL=agent-preview-react.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-preview-react.js","sourceRoot":"","sources":["../../src/components/agent-preview-react.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-preview-react.js","sourceRoot":"","sources":["../../src/components/agent-preview-react.tsx"],"names":[],"mappings":"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"}
|