Skip to content

Commit bce191f

Browse files
feat: use linked connected apps for auth W-18394868 (#157)
* feat: add linked connected apps for auth * chore: flag rename * Update agent.preview.md (#159) * chore: bump core --------- Co-authored-by: Juliet Shackell <[email protected]>
1 parent f9b3aa0 commit bce191f

File tree

5 files changed

+52
-45
lines changed

5 files changed

+52
-45
lines changed

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", "x"],
59-
"flags": ["apex-debug", "api-name", "api-version", "connected-app-user", "flags-dir", "output-dir", "target-org"],
58+
"flagChars": ["c", "d", "n", "o", "x"],
59+
"flags": ["apex-debug", "api-name", "api-version", "client-app", "flags-dir", "output-dir", "target-org"],
6060
"plugin": "@salesforce/plugin-agent"
6161
},
6262
{

messages/agent.preview.md

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,37 +14,35 @@ Find the agent's API name in its main details page in your org's Agent page in S
1414

1515
Before you use this command, you must complete these steps:
1616

17-
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:
17+
1. Using your org's Setup UI, 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 additional steps:
1818

1919
a. When specifying the connected app's Callback URL, add this second callback URL on a new line: "http://localhost:1717/OauthRedirect".
2020

2121
b. When adding the scopes to the connected app, add "Manage user data via Web browsers (web)".
2222

23-
c. Ensure that the "Require Secret for Web Server Flow" option is not selected.
24-
25-
d. Make note of the user that you specified as the "Run As" user when updating the Client Credentials Flow section.
26-
2723
2. Add the connected app to your agent as described in the "Add Connected App to Agent" section here: https://developer.salesforce.com/docs/einstein/genai/guide/agent-api-get-started.html#add-connected-app-to-agent.
2824

2925
3. Copy the consumer key from your connected app as described in the "Obtain Credentials" section here: https://developer.salesforce.com/docs/einstein/genai/guide/agent-api-get-started.html#obtain-credentials.
3026

31-
4. Set the "SFDX_AUTH_SCOPES" environment variable to "refresh_token sfap_api chatbot_api web api". This step ensures that you get the specific OAuth scopes required by this command.
27+
4. If you haven't already, run the "org login web" CLI command as usual to authorize the development org that contains the agent you want to preview.
28+
29+
5. Re-run the "org web login" command to link the new connected app to your already-authenticated user. Use the --client-app flag to give the link a name; you can specify any string, but make a note of it because you'll need it later. Use --username to specify the username that you used to log into the org in the previous step. Use --client-id to specify the consumer key you previously copied. Finally, use --scopes as indicated to specify the required API scopes. Here's an example:
3230

33-
5. Using the username of the user you specified as the "Run As" user above, authorize your org using the web server flow, as described in this document: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_auth_web_flow.htm.
31+
sf org login web --client-app agent-app --username <username> --client-id <consumer-key> --scopes "sfap_api chatbot_api refresh_token api web"
3432

35-
IMPORTANT: You must use the "--client-id <CONNECTED-APP-CONSUMER-KEY>" flag of "org login web", where CONNECTED-APP-CONSUMER-KEY is the consumer key you previously copied. This step ensures that the "org login web" command uses your custom connected app, and not the default CLI connected app.
33+
IMPORTANT: You must use the "--client-id <CONNECTED-APP-CONSUMER-KEY>" flag of "org login web", where CONNECTED-APP-CONSUMER-KEY is the consumer key you previously copied. This step ensures that the "org login web" command uses your custom connected app, and not the default CLI connected app.
3634

37-
Press Enter to skip sharing the client secret.
35+
6. Press Enter to skip sharing the client secret, then log in with your org username as usual and click Accept.
3836

39-
6. When you run this command to interact with an agent, specify the username you authorized in the preceding step with the --connected-app-user (-a) flag.
37+
7. Run this command ("agent preview") to interact with an agent by using the --target-org flag to specify the org username or alias as usual and --client-app to specify the linked connected app ("agent-app" in the previous example). Use the "org display" command to get the list of client apps associated with an org.
4038

4139
# flags.api-name.summary
4240

4341
API name of the agent you want to interact with.
4442

45-
# flags.connected-app-user.summary
43+
# flags.client-app.summary
4644

47-
Username or alias of the connected app user that's configured with web-based access tokens to the agent.
45+
Name of the linked client app to use for the agent connection. You must have previously created this link with "org login web --client-app". Run "org display" to see the available linked client apps.
4846

4947
# flags.output-dir.summary
5048

@@ -56,10 +54,10 @@ Enable Apex debug logging during the agent preview conversation.
5654

5755
# examples
5856

59-
- 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:
57+
- Interact with an agent with API name "Resort_Manager" in the org with alias "my-org" and the linked "agent-app" connected app:
6058

61-
<%= config.bin %> <%= command.id %> --api-name "Resort_Manager" --target-org my-org --connected-app-user my-agent-user
59+
<%= config.bin %> <%= command.id %> --api-name "Resort_Manager" --target-org my-org --client-app agent-app
6260

6361
- Same as the preceding example, but this time save the conversation transcripts to the "./transcripts/my-preview" directory rather than the default "./temp/agent-preview":
6462

65-
<%= config.bin %> <%= command.id %> --api-name "Resort_Manager" --target-org my-org --connected-app-user my-agent-user --output-dir "transcripts/my-preview"
63+
<%= config.bin %> <%= command.id %> --api-name "Resort_Manager" --target-org my-org --client-app agent-app --output-dir "transcripts/my-preview"

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"@oclif/core": "^4",
1111
"@oclif/multi-stage-output": "^0.7.12",
1212
"@salesforce/agents": "0.15.0",
13-
"@salesforce/core": "^8.10.2",
13+
"@salesforce/core": "^8.13.0",
1414
"@salesforce/kit": "^3.2.3",
1515
"@salesforce/sf-plugins-core": "^12.2.0",
1616
"@salesforce/source-deploy-retrieve": "^12.19.3",

src/commands/agent/preview.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import { resolve, join } from 'node:path';
99
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
10-
import { Messages, SfError } from '@salesforce/core';
10+
import { AuthInfo, Connection, Messages, SfError } from '@salesforce/core';
1111
import React from 'react';
1212
import { render } from 'ink';
1313
import { env } from '@salesforce/kit';
@@ -54,10 +54,11 @@ export default class AgentPreview extends SfCommand<AgentPreviewResult> {
5454
public static readonly flags = {
5555
'target-org': Flags.requiredOrg(),
5656
'api-version': Flags.orgApiVersion(),
57-
'connected-app-user': Flags.requiredOrg({
58-
summary: messages.getMessage('flags.connected-app-user.summary'),
59-
char: 'a',
57+
'client-app': Flags.string({
58+
char: 'c',
59+
summary: messages.getMessage('flags.client-app.summary'),
6060
required: true,
61+
dependsOn: ['target-org'],
6162
}),
6263
'api-name': Flags.string({
6364
summary: messages.getMessage('flags.api-name.summary'),
@@ -78,7 +79,15 @@ export default class AgentPreview extends SfCommand<AgentPreviewResult> {
7879

7980
const { 'api-name': apiNameFlag } = flags;
8081
const conn = flags['target-org'].getConnection(flags['api-version']);
81-
const apiConn = flags['connected-app-user'].getConnection(flags['api-version']);
82+
83+
const authInfo = await AuthInfo.create({
84+
username: flags['target-org'].getUsername(),
85+
});
86+
87+
const jwtConn = await Connection.create({
88+
authInfo,
89+
clientApp: flags['client-app'],
90+
});
8291

8392
const agentsQuery = await conn.query<AgentData>(
8493
'SELECT Id, DeveloperName, (SELECT Status FROM BotVersions) FROM BotDefinition WHERE IsDeleted = false'
@@ -102,7 +111,7 @@ export default class AgentPreview extends SfCommand<AgentPreviewResult> {
102111
}
103112

104113
const outputDir = await resolveOutputDir(flags['output-dir'], flags['apex-debug']);
105-
const agentPreview = new Preview(apiConn, selectedAgent.Id);
114+
const agentPreview = new Preview(jwtConn, selectedAgent.Id);
106115
agentPreview.toggleApexDebugMode(flags['apex-debug']);
107116

108117
const instance = render(

yarn.lock

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1271,10 +1271,10 @@
12711271
"@jridgewell/resolve-uri" "^3.1.0"
12721272
"@jridgewell/sourcemap-codec" "^1.4.14"
12731273

1274-
"@jsforce/jsforce-node@^3.8.1":
1275-
version "3.8.1"
1276-
resolved "https://registry.yarnpkg.com/@jsforce/jsforce-node/-/jsforce-node-3.8.1.tgz#482fcf2820b48a6b10930d33550eb4e4cbd1e480"
1277-
integrity sha512-+IZZC7VfNjhkTyeAspBc4Z35Y5eAP0RIWQnyfKahsbY/aLjiFRIM9ejl1YbWbrbabf5ODFSUgBGmOiEYLW3f7Q==
1274+
"@jsforce/jsforce-node@^3.8.2":
1275+
version "3.8.2"
1276+
resolved "https://registry.yarnpkg.com/@jsforce/jsforce-node/-/jsforce-node-3.8.2.tgz#68b903f6733ae479086ab02ea4a2de87a7f208eb"
1277+
integrity sha512-ewaRr9JnZRW6I28C/TzUnv5p70zMrWsKCq2ovRW6X557/ikdfvA24F9k4cQXZnTG2lZLEfVn+WwdBGEtY7pPnQ==
12781278
dependencies:
12791279
"@sindresorhus/is" "^4"
12801280
base64url "^3.0.1"
@@ -1472,12 +1472,12 @@
14721472
strip-ansi "6.0.1"
14731473
ts-retry-promise "^0.8.1"
14741474

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==
1475+
"@salesforce/core@^8.10.0", "@salesforce/core@^8.10.3", "@salesforce/core@^8.13.0", "@salesforce/core@^8.5.1", "@salesforce/core@^8.8.0", "@salesforce/core@^8.8.5":
1476+
version "8.13.0"
1477+
resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-8.13.0.tgz#ffc00a776c60a401d4385abfeb6cd7fee0d90f3b"
1478+
integrity sha512-FyAn0UGa93D0N++8poeJt7yEaWQH++qxrv/Wf4TjNaUCLoh19g57lrXuos3qDJPr8Ut4x6QjVxEc49XLy+vBkw==
14791479
dependencies:
1480-
"@jsforce/jsforce-node" "^3.8.1"
1480+
"@jsforce/jsforce-node" "^3.8.2"
14811481
"@salesforce/kit" "^3.2.2"
14821482
"@salesforce/schemas" "^1.9.0"
14831483
"@salesforce/ts-types" "^2.0.10"
@@ -1489,9 +1489,9 @@
14891489
js2xmlparser "^4.0.1"
14901490
jsonwebtoken "9.0.2"
14911491
jszip "3.10.1"
1492-
pino "^9.4.0"
1492+
pino "^9.7.0"
14931493
pino-abstract-transport "^1.2.0"
1494-
pino-pretty "^11.2.2"
1494+
pino-pretty "^11.3.0"
14951495
proper-lockfile "^4.1.2"
14961496
semver "^7.6.3"
14971497
ts-retry-promise "^0.8.1"
@@ -6985,7 +6985,7 @@ pino-abstract-transport@^2.0.0:
69856985
dependencies:
69866986
split2 "^4.0.0"
69876987

6988-
pino-pretty@^11.2.2:
6988+
pino-pretty@^11.3.0:
69896989
version "11.3.0"
69906990
resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-11.3.0.tgz#390b3be044cf3d2e9192c7d19d44f6b690468f2e"
69916991
integrity sha512-oXwn7ICywaZPHmu3epHGU2oJX4nPmKvHvB/bwrJHlGcbEWaVcotkpyVHMKLKmiVryWYByNp0jpgAcXpFJDXJzA==
@@ -7010,17 +7010,17 @@ pino-std-serializers@^7.0.0:
70107010
resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz#7c625038b13718dbbd84ab446bd673dc52259e3b"
70117011
integrity sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==
70127012

7013-
pino@^9.4.0:
7014-
version "9.6.0"
7015-
resolved "https://registry.yarnpkg.com/pino/-/pino-9.6.0.tgz#6bc628159ba0cc81806d286718903b7fc6b13169"
7016-
integrity sha512-i85pKRCt4qMjZ1+L7sy2Ag4t1atFcdbEt76+7iRJn1g2BvsnRMGu9p8pivl9fs63M2kF/A0OacFZhTub+m/qMg==
7013+
pino@^9.7.0:
7014+
version "9.7.0"
7015+
resolved "https://registry.yarnpkg.com/pino/-/pino-9.7.0.tgz#ff7cd86eb3103ee620204dbd5ca6ffda8b53f645"
7016+
integrity sha512-vnMCM6xZTb1WDmLvtG2lE/2p+t9hDEIvTWJsu6FejkE62vB7gDhvzrpFR4Cw2to+9JNQxVnkAKVPA1KPB98vWg==
70177017
dependencies:
70187018
atomic-sleep "^1.0.0"
70197019
fast-redact "^3.1.1"
70207020
on-exit-leak-free "^2.1.0"
70217021
pino-abstract-transport "^2.0.0"
70227022
pino-std-serializers "^7.0.0"
7023-
process-warning "^4.0.0"
7023+
process-warning "^5.0.0"
70247024
quick-format-unescaped "^4.0.3"
70257025
real-require "^0.2.0"
70267026
safe-stable-stringify "^2.3.1"
@@ -7079,10 +7079,10 @@ process-on-spawn@^1.0.0:
70797079
dependencies:
70807080
fromentries "^1.2.0"
70817081

7082-
process-warning@^4.0.0:
7083-
version "4.0.1"
7084-
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-4.0.1.tgz#5c1db66007c67c756e4e09eb170cdece15da32fb"
7085-
integrity sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==
7082+
process-warning@^5.0.0:
7083+
version "5.0.0"
7084+
resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-5.0.0.tgz#566e0bf79d1dff30a72d8bbbe9e8ecefe8d378d7"
7085+
integrity sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==
70867086

70877087
process@^0.11.10:
70887088
version "0.11.10"

0 commit comments

Comments
 (0)