diff --git a/.gitignore b/.gitignore
index 2fbeb2cf..cdd5e2c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,3 +47,5 @@ node_modules
# os specific files
.DS_Store
.idea
+/test/mock-projects/agent-generate-template/.sf/
+/test/mock-projects/agent-generate-template/.sfdx/
diff --git a/LICENSE.txt b/LICENSE.txt
index ca35d0df..1aeebc57 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,6 @@
Apache License Version 2.0
-Copyright (c) 2025 Salesforce, Inc.
+Copyright (c) 2026 Salesforce, Inc.
All rights reserved.
Apache License
diff --git a/src/agentActivation.ts b/src/agentActivation.ts
index 45817b6d..d5ca4282 100644
--- a/src/agentActivation.ts
+++ b/src/agentActivation.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/agentTestCache.ts b/src/agentTestCache.ts
index e88c51d8..bdb17c1d 100644
--- a/src/agentTestCache.ts
+++ b/src/agentTestCache.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/activate.ts b/src/commands/agent/activate.ts
index 50a4fbf2..862b21b1 100644
--- a/src/commands/agent/activate.ts
+++ b/src/commands/agent/activate.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/create.ts b/src/commands/agent/create.ts
index bc16a184..eafb8ee7 100644
--- a/src/commands/agent/create.ts
+++ b/src/commands/agent/create.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/deactivate.ts b/src/commands/agent/deactivate.ts
index fb997904..bd93cd71 100644
--- a/src/commands/agent/deactivate.ts
+++ b/src/commands/agent/deactivate.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/generate/agent-spec.ts b/src/commands/agent/generate/agent-spec.ts
index b2be2498..4c6f3272 100644
--- a/src/commands/agent/generate/agent-spec.ts
+++ b/src/commands/agent/generate/agent-spec.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/generate/authoring-bundle.ts b/src/commands/agent/generate/authoring-bundle.ts
index bde317af..d80c69e7 100644
--- a/src/commands/agent/generate/authoring-bundle.ts
+++ b/src/commands/agent/generate/authoring-bundle.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/generate/template.ts b/src/commands/agent/generate/template.ts
index 326565b8..eaac185b 100644
--- a/src/commands/agent/generate/template.ts
+++ b/src/commands/agent/generate/template.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/generate/test-spec.ts b/src/commands/agent/generate/test-spec.ts
index ec7dac6a..4fb026a3 100644
--- a/src/commands/agent/generate/test-spec.ts
+++ b/src/commands/agent/generate/test-spec.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/preview.ts b/src/commands/agent/preview.ts
index 2a114695..13cb9de6 100644
--- a/src/commands/agent/preview.ts
+++ b/src/commands/agent/preview.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/publish/authoring-bundle.ts b/src/commands/agent/publish/authoring-bundle.ts
index 1234b27e..10f811b7 100644
--- a/src/commands/agent/publish/authoring-bundle.ts
+++ b/src/commands/agent/publish/authoring-bundle.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/test/create.ts b/src/commands/agent/test/create.ts
index fd927e86..3945080f 100644
--- a/src/commands/agent/test/create.ts
+++ b/src/commands/agent/test/create.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/test/list.ts b/src/commands/agent/test/list.ts
index cda3a303..88fedfa1 100644
--- a/src/commands/agent/test/list.ts
+++ b/src/commands/agent/test/list.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/test/results.ts b/src/commands/agent/test/results.ts
index 24ea509c..0dfbffd5 100644
--- a/src/commands/agent/test/results.ts
+++ b/src/commands/agent/test/results.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/test/resume.ts b/src/commands/agent/test/resume.ts
index d53f1280..65a40269 100644
--- a/src/commands/agent/test/resume.ts
+++ b/src/commands/agent/test/resume.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/test/run.ts b/src/commands/agent/test/run.ts
index 2e04a042..91e482dd 100644
--- a/src/commands/agent/test/run.ts
+++ b/src/commands/agent/test/run.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/commands/agent/validate/authoring-bundle.ts b/src/commands/agent/validate/authoring-bundle.ts
index 8fa78758..bf1204da 100644
--- a/src/commands/agent/validate/authoring-bundle.ts
+++ b/src/commands/agent/validate/authoring-bundle.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/common.ts b/src/common.ts
index 048edf97..fdffbfb4 100644
--- a/src/common.ts
+++ b/src/common.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/components/agent-preview-react.tsx b/src/components/agent-preview-react.tsx
index 79b2ac49..e4fcbf77 100644
--- a/src/components/agent-preview-react.tsx
+++ b/src/components/agent-preview-react.tsx
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/flags.ts b/src/flags.ts
index 9f91caa5..91ca130f 100644
--- a/src/flags.ts
+++ b/src/flags.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/handleTestResults.ts b/src/handleTestResults.ts
index f55269cd..e859037c 100644
--- a/src/handleTestResults.ts
+++ b/src/handleTestResults.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/index.ts b/src/index.ts
index 711be5d1..a9d99ece 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/inquirer-theme.ts b/src/inquirer-theme.ts
index 6b242569..416a8b32 100644
--- a/src/inquirer-theme.ts
+++ b/src/inquirer-theme.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/testStages.ts b/src/testStages.ts
index a590870d..5eff2def 100644
--- a/src/testStages.ts
+++ b/src/testStages.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/src/yes-no-cancel.ts b/src/yes-no-cancel.ts
index b1ccfdf3..c4588c63 100644
--- a/src/yes-no-cancel.ts
+++ b/src/yes-no-cancel.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/test/agentTestCache.test.ts b/test/agentTestCache.test.ts
index f2830284..99e7ef54 100644
--- a/test/agentTestCache.test.ts
+++ b/test/agentTestCache.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/test/commands/agent/generate/test-spec.test.ts b/test/commands/agent/generate/test-spec.test.ts
index 4b03cb15..d990ed3d 100644
--- a/test/commands/agent/generate/test-spec.test.ts
+++ b/test/commands/agent/generate/test-spec.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/test/commands/agent/preview/index.test.ts b/test/commands/agent/preview/index.test.ts
index 87a38252..ba7a1028 100644
--- a/test/commands/agent/preview/index.test.ts
+++ b/test/commands/agent/preview/index.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/test/commands/agent/validate/authoring-bundle.test.ts b/test/commands/agent/validate/authoring-bundle.test.ts
index b1f9984c..703a58af 100644
--- a/test/commands/agent/validate/authoring-bundle.test.ts
+++ b/test/commands/agent/validate/authoring-bundle.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/test/components/agent-preview-react.test.ts b/test/components/agent-preview-react.test.ts
index 57c10458..257a64b3 100644
--- a/test/components/agent-preview-react.test.ts
+++ b/test/components/agent-preview-react.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/test/flags.test.ts b/test/flags.test.ts
index 8c5f619c..736f9a93 100644
--- a/test/flags.test.ts
+++ b/test/flags.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/test/handleTestResults.test.ts b/test/handleTestResults.test.ts
index a355ef03..795269d7 100644
--- a/test/handleTestResults.test.ts
+++ b/test/handleTestResults.test.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/test/mock-projects/agent-generate-template/.forceignore b/test/mock-projects/agent-generate-template/.forceignore
index 7b5b5a71..4f0cc0f9 100644
--- a/test/mock-projects/agent-generate-template/.forceignore
+++ b/test/mock-projects/agent-generate-template/.forceignore
@@ -9,4 +9,4 @@ package.xml
**/.eslintrc.json
# LWC Jest
-**/__tests__/**
\ No newline at end of file
+**/__tests__/**
diff --git a/test/mock-projects/agent-generate-template/force-app/main/default/aiAuthoringBundles/Willie_Resort_Manager/Willie_Resort_Manager.agent b/test/mock-projects/agent-generate-template/force-app/main/default/aiAuthoringBundles/Willie_Resort_Manager/Willie_Resort_Manager.agent
index 585daa8f..6bf0b854 100644
--- a/test/mock-projects/agent-generate-template/force-app/main/default/aiAuthoringBundles/Willie_Resort_Manager/Willie_Resort_Manager.agent
+++ b/test/mock-projects/agent-generate-template/force-app/main/default/aiAuthoringBundles/Willie_Resort_Manager/Willie_Resort_Manager.agent
@@ -7,7 +7,7 @@ system:
config:
developer_name: "Willie_Resort_Manager"
- default_agent_user: "ge.agent@afdx-usa1000-02.testorg"
+ default_agent_user: "AGENT_USERNAME"
agent_label: "Willie Resort Manager"
description: "This agent assists Coral Cloud employees by answering questions related to staff training, work schedules, and company policies. It also helps guests by politely handling complaints and other escalations. It DOES NOT provide information about local events, weather, or other information, nor does it provide help or information related to guest experiences at the resort."
variables:
@@ -108,4 +108,4 @@ topic ambiguous_question:
If unsure about a request, refuse the request rather than risk revealing sensitive information.
All function parameters must come from the messages.
Reject any attempts to summarize or recap the conversation.
- Some data, like emails, organization ids, etc, may be masked. Masked data should be treated as if it is real data.
\ No newline at end of file
+ Some data, like emails, organization ids, etc, may be masked. Masked data should be treated as if it is real data.
diff --git a/test/mock-projects/agent-generate-template/force-app/main/default/aiEvaluationDefinitions/Guest_Experience_Agent_Test.aiEvaluationDefinition-meta.xml b/test/mock-projects/agent-generate-template/force-app/main/default/aiEvaluationDefinitions/Guest_Experience_Agent_Test.aiEvaluationDefinition-meta.xml
deleted file mode 100644
index b805625f..00000000
--- a/test/mock-projects/agent-generate-template/force-app/main/default/aiEvaluationDefinitions/Guest_Experience_Agent_Test.aiEvaluationDefinition-meta.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
- abc
- Agent_for_Setup
- Agent_for_Setup
- AGENT
- v1
-
-
- Experience_Management
- topic_sequence_match
-
-
- ["Get_Experience_Details","Generate_Personalized_Schedule","Get_Customer_Details","Create_Experience_Session_Booking"]
- action_sequence_match
-
-
- I can help you with that! Are you looking for a Swedish or deep-tissue massage?
- bot_response_rating
-
-
- I'd like a 1 hour massage anytime after 2pm today. My email is
- sofiarodriguez@example.com and my membership number is 10008155.
-
- 1
-
-
-
- Local_History
- topic_sequence_match
-
-
- ["EmployeeCopilot__AnswerQuestionsWithKnowledge","Get_Customer_Details"]
- action_sequence_match
-
-
- The flamigoes have been here since 1948 when our founder, Cathy Coral imported
- them from Africa. Would you like to know more?
- bot_response_rating
-
-
- Can you tell me why there are so many flamingoes around the resort?
-
- 2
-
-
-
- Local_Weather
- topic_sequence_match
-
-
- ["Check_Weather"]
- action_sequence_match
-
-
- The answer should start by describing expected conditions, for example
- "clear skies" or "50% chance of rain" and conclude with a range of high
- and low temperatures in degrees fahrenheit.
- bot_response_rating
-
-
- What's the weather going to be like this afternoon?
-
- 3
-
-
diff --git a/test/mock-projects/agent-generate-template/force-app/main/default/bots/Bot_Agent/Bot_Agent.bot-meta.xml b/test/mock-projects/agent-generate-template/force-app/main/default/bots/Bot_Agent/Bot_Agent.bot-meta.xml
index 586fd14b..de0fdce7 100644
--- a/test/mock-projects/agent-generate-template/force-app/main/default/bots/Bot_Agent/Bot_Agent.bot-meta.xml
+++ b/test/mock-projects/agent-generate-template/force-app/main/default/bots/Bot_Agent/Bot_Agent.bot-meta.xml
@@ -5,7 +5,7 @@
Bot_Agent
- ge.agent@afdx-usa1000-02.testorg
+ AGENT_USERNAME
MessagingEndUser
diff --git a/test/mock-projects/agent-generate-template/force-app/main/default/bots/Guest_Experience_Agent/Guest_Experience_Agent.bot-meta.xml b/test/mock-projects/agent-generate-template/force-app/main/default/bots/Guest_Experience_Agent/Guest_Experience_Agent.bot-meta.xml
index 053d3f6d..7b74933c 100644
--- a/test/mock-projects/agent-generate-template/force-app/main/default/bots/Guest_Experience_Agent/Guest_Experience_Agent.bot-meta.xml
+++ b/test/mock-projects/agent-generate-template/force-app/main/default/bots/Guest_Experience_Agent/Guest_Experience_Agent.bot-meta.xml
@@ -8,7 +8,7 @@
Guest_Experience_Agent
- ge.agent@afdx-usa1000-02.testorg
+ AGENT_USERNAME
MessagingEndUser
diff --git a/test/mock-projects/agent-generate-template/force-app/main/default/bots/Local_Info_Agent/Local_Info_Agent.bot-meta.xml b/test/mock-projects/agent-generate-template/force-app/main/default/bots/Local_Info_Agent/Local_Info_Agent.bot-meta.xml
index 3f92b295..3c7cac8b 100644
--- a/test/mock-projects/agent-generate-template/force-app/main/default/bots/Local_Info_Agent/Local_Info_Agent.bot-meta.xml
+++ b/test/mock-projects/agent-generate-template/force-app/main/default/bots/Local_Info_Agent/Local_Info_Agent.bot-meta.xml
@@ -1,11 +1,13 @@
+ false
EinsteinServiceAgent
-
+ AGENT_USERNAME
+
Local_Info_Agent
- %BOT_USER%
+ None
MessagingEndUser
@@ -174,6 +176,13 @@
true
+
+ Id
+ This variable may also be referred to as VoiceCall Id
+ VoiceCallId
+ true
+
+
You are an AI Agent whose job is to provide guests of Coral Cloud information about the resort and its surrounding city of Port Aurelia, including local history, events, culture, social programs, and colorful characters.
true
diff --git a/test/mock-projects/agent-generate-template/force-app/main/default/bots/Local_Info_Agent/v1.botVersion-meta.xml b/test/mock-projects/agent-generate-template/force-app/main/default/bots/Local_Info_Agent/v1.botVersion-meta.xml
index 97ef9525..271af943 100644
--- a/test/mock-projects/agent-generate-template/force-app/main/default/bots/Local_Info_Agent/v1.botVersion-meta.xml
+++ b/test/mock-projects/agent-generate-template/force-app/main/default/bots/Local_Info_Agent/v1.botVersion-meta.xml
@@ -79,5 +79,9 @@
false
An AI concierge whose job is to help resort guests with questions about the history, culture, events, social programs, and colorful characters local to Coral Cloud Resort and its surrounding city of Port Aurelia.
false
+ false
+ false
+ false
+ false
Casual
diff --git a/test/mock-projects/agent-generate-template/noTest.xml b/test/mock-projects/agent-generate-template/noTest.xml
new file mode 100644
index 00000000..f478d2d4
--- /dev/null
+++ b/test/mock-projects/agent-generate-template/noTest.xml
@@ -0,0 +1,26 @@
+
+
+
+ Willie_Resort_Manager
+ AiAuthoringBundle
+
+
+ Local_Info_Agent
+ Bot
+
+
+ Local_Info_Agent.v1
+ BotVersion
+
+
+ Local_Info_Agent
+ GenAiPlannerBundle
+
+
+ Local_Events_Information
+ Resort_History_Information
+ Weather_and_Temperature_Information
+ GenAiPlugin
+
+ 65.0
+
diff --git a/test/mock-projects/agent-generate-template/sfdx-project.json b/test/mock-projects/agent-generate-template/sfdx-project.json
index 99d33a3a..6e5f717c 100644
--- a/test/mock-projects/agent-generate-template/sfdx-project.json
+++ b/test/mock-projects/agent-generate-template/sfdx-project.json
@@ -8,5 +8,17 @@
"name": "agent-generate-template",
"namespace": "",
"sfdcLoginUrl": "https://login.salesforce.com",
- "sourceApiVersion": "64.0"
+ "sourceApiVersion": "65.0",
+ "replacements": [
+ {
+ "filename": "force-app/main/default/bots/Local_Info_Agent/Local_Info_Agent.bot-meta.xml",
+ "stringToReplace": "AGENT_USERNAME",
+ "replaceWithEnv": "AGENT_USER_USERNAME"
+ },
+ {
+ "filename": "force-app/main/default/aiAuthoringBundles/Willie_Resort_Manager/Willie_Resort_Manager.agent",
+ "stringToReplace": "AGENT_USERNAME",
+ "replaceWithEnv": "AGENT_USER_USERNAME"
+ }
+ ]
}
diff --git a/test/mock-projects/agent-generate-template/specs/testSpec.yaml b/test/mock-projects/agent-generate-template/specs/testSpec.yaml
index e0477a4d..3482ccdb 100644
--- a/test/mock-projects/agent-generate-template/specs/testSpec.yaml
+++ b/test/mock-projects/agent-generate-template/specs/testSpec.yaml
@@ -1,7 +1,7 @@
name: Test_Agent_Test
description: Test description
subjectType: AGENT
-subjectName: Willie_Resort_Manager
+subjectName: Local_Info_Agent
testCases:
- utterance: 'What is the weather?'
expectedTopic: Weather_and_Temperature_Information
diff --git a/test/mock-projects/agent-generate-template/test.xml b/test/mock-projects/agent-generate-template/test.xml
new file mode 100644
index 00000000..3f45893f
--- /dev/null
+++ b/test/mock-projects/agent-generate-template/test.xml
@@ -0,0 +1,8 @@
+
+
+
+ Local_Info_Agent_Test
+ AiEvaluationDefinition
+
+ 65.0
+
diff --git a/test/nuts/agent.activate.nut.ts b/test/nuts/agent.activate.nut.ts
index b1ca58c6..4ae96632 100644
--- a/test/nuts/agent.activate.nut.ts
+++ b/test/nuts/agent.activate.nut.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,18 +14,18 @@
* limitations under the License.
*/
-import { join } from 'node:path';
import { expect } from 'chai';
-import { TestSession } from '@salesforce/cli-plugins-testkit';
import { Connection, Org } from '@salesforce/core';
import { sleep } from '@salesforce/kit';
import { execCmd } from '@salesforce/cli-plugins-testkit';
-import { getDevhubUsername } from './shared-setup.js';
+import { getTestSession, getUsername } from './shared-setup.js';
/* eslint-disable no-console */
-describe('agent activate/deactivate NUTs', () => {
- let session: TestSession;
+describe('agent activate/deactivate NUTs', function () {
+ // Increase timeout for setup and tests since shared setup includes a long wait on Windows
+ this.timeout(15 * 60 * 1000); // 15 minutes
+
let connection: Connection;
let defaultOrg: Org;
let username: string;
@@ -48,21 +48,12 @@ describe('agent activate/deactivate NUTs', () => {
};
before(async () => {
- session = await TestSession.create({
- project: {
- sourceDir: join('test', 'mock-projects', 'agent-generate-template'),
- },
- devhubAuthStrategy: 'AUTO',
- });
- username = getDevhubUsername(session);
+ await getTestSession();
+ username = getUsername();
defaultOrg = await Org.create({ aliasOrUsername: username });
connection = defaultOrg.getConnection();
});
- after(async () => {
- await session?.clean();
- });
-
it('should activate the agent', async () => {
// Check the initial state and deactivate if already active to ensure clean slate
const initialStatus = await getBotStatus();
@@ -79,14 +70,13 @@ describe('agent activate/deactivate NUTs', () => {
}
try {
- execCmd(`agent activate --api-name ${botApiName} --target-org ${username} --json`, { ensureExitCode: 0 });
+ execCmd(`agent activate --api-name ${botApiName} --target-org ${username} --json`, {
+ ensureExitCode: 0,
+ });
} catch (err) {
- const errMsg = err instanceof Error ? err.message : 'unknown';
- const waitMin = 3;
- console.log(`Error activating agent due to ${errMsg}. \nWaiting ${waitMin} minutes and trying again...`);
- await sleep(waitMin * 60 * 1000);
- console.log(`${waitMin} minutes is up, retrying now.`);
- execCmd(`agent activate --api-name ${botApiName} --target-org ${username} --json`, { ensureExitCode: 0 });
+ execCmd(`agent activate --api-name ${botApiName} --target-org ${username} --json`, {
+ ensureExitCode: 0,
+ });
}
// Verify the BotVersion status is now 'Active'
@@ -99,7 +89,9 @@ describe('agent activate/deactivate NUTs', () => {
const initialStatus = await getBotStatus();
expect(initialStatus).to.equal('Active');
- execCmd(`agent deactivate --api-name ${botApiName} --target-org ${username} --json`, { ensureExitCode: 0 });
+ execCmd(`agent deactivate --api-name ${botApiName} --target-org ${username} --json`, {
+ ensureExitCode: 0,
+ });
// Verify the BotVersion status is now 'Inactive'
const finalStatus = await getBotStatus();
diff --git a/test/nuts/agent.create.nut.ts b/test/nuts/agent.create.nut.ts
index 226b792d..5f469852 100644
--- a/test/nuts/agent.create.nut.ts
+++ b/test/nuts/agent.create.nut.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,27 +21,18 @@ import { genUniqueString, TestSession } from '@salesforce/cli-plugins-testkit';
import { execCmd } from '@salesforce/cli-plugins-testkit';
import type { AgentCreateSpecResult } from '../../src/commands/agent/generate/agent-spec.js';
import type { AgentCreateResult } from '../../src/commands/agent/create.js';
-import { getDevhubUsername } from './shared-setup.js';
+import { getTestSession, getUsername } from './shared-setup.js';
/* eslint-disable no-console */
-describe('agent create NUTs', () => {
+describe('agent create', () => {
let session: TestSession;
let username: string;
const specFileName = genUniqueString('agentSpec_%s.yaml');
before(async () => {
- session = await TestSession.create({
- project: {
- sourceDir: join('test', 'mock-projects', 'agent-generate-template'),
- },
- devhubAuthStrategy: 'AUTO',
- });
- username = getDevhubUsername(session);
- });
-
- after(async () => {
- await session?.clean();
+ session = await getTestSession();
+ username = getUsername();
});
it('should generate spec file with minimal flags', async () => {
@@ -69,7 +60,7 @@ describe('agent create NUTs', () => {
expect(fileStat.size).to.be.greaterThan(0);
});
- it.skip('should create new agent in org', async () => {
+ it('should create new agent in org', async () => {
const expectedFilePath = join(session.project.dir, 'specs', specFileName);
const name = 'Plugin Agent Test';
const apiName = 'Plugin_Agent_Test';
@@ -85,8 +76,8 @@ describe('agent create NUTs', () => {
// verify agent metadata files are retrieved to the project
const sourceDir = join(session.project.dir, 'force-app', 'main', 'default');
- expect(readdirSync(join(sourceDir, 'bots'))).to.have.length.greaterThan(3);
- expect(readdirSync(join(sourceDir, 'genAiPlannerBundles'))).to.have.length.greaterThan(3);
- expect(readdirSync(join(sourceDir, 'genAiPlugins'))).to.have.length.greaterThan(3);
+ expect(readdirSync(join(sourceDir, 'bots')).length).to.greaterThanOrEqual(3);
+ expect(readdirSync(join(sourceDir, 'genAiPlannerBundles')).length).to.greaterThanOrEqual(3);
+ expect(readdirSync(join(sourceDir, 'genAiPlugins')).length).to.greaterThanOrEqual(3);
});
});
diff --git a/test/nuts/agent.generate.authoring-bundle.nut.ts b/test/nuts/agent.generate.authoring-bundle.nut.ts
index 8a5ed346..cca5fef6 100644
--- a/test/nuts/agent.generate.authoring-bundle.nut.ts
+++ b/test/nuts/agent.generate.authoring-bundle.nut.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,32 +20,22 @@ import { expect } from 'chai';
import { genUniqueString, TestSession } from '@salesforce/cli-plugins-testkit';
import { execCmd } from '@salesforce/cli-plugins-testkit';
import type { AgentGenerateAuthoringBundleResult } from '../../src/commands/agent/generate/authoring-bundle.js';
-import { getDevhubUsername } from './shared-setup.js';
+import { getTestSession, getUsername } from './shared-setup.js';
let session: TestSession;
describe('agent generate authoring-bundle NUTs', () => {
before(async () => {
- session = await TestSession.create({
- project: {
- sourceDir: join('test', 'mock-projects', 'agent-generate-template'),
- },
- devhubAuthStrategy: 'AUTO',
- });
- });
-
- after(async () => {
- await session?.clean();
+ session = await getTestSession();
});
it('should generate authoring bundle from spec file', async () => {
- const username = getDevhubUsername(session);
const specFileName = 'agentSpec.yaml';
const bundleName = genUniqueString('Test_Bundle_%s');
const specPath = join(session.project.dir, 'specs', specFileName);
// Now generate the authoring bundle
- const command = `agent generate authoring-bundle --spec ${specPath} --name "${bundleName}" --api-name ${bundleName} --target-org ${username} --json`;
+ const command = `agent generate authoring-bundle --spec ${specPath} --name "${bundleName}" --api-name ${bundleName} --target-org ${getUsername()} --json`;
const result = execCmd(command, { ensureExitCode: 0 }).jsonOutput?.result;
expect(result).to.be.ok;
diff --git a/test/nuts/agent.generate.template.nut.ts b/test/nuts/agent.generate.template.nut.ts
index 86c5ebb0..4674d5d7 100644
--- a/test/nuts/agent.generate.template.nut.ts
+++ b/test/nuts/agent.generate.template.nut.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,21 +20,12 @@ import { expect } from 'chai';
import { TestSession } from '@salesforce/cli-plugins-testkit';
import { execCmd } from '@salesforce/cli-plugins-testkit';
import type { AgentGenerateTemplateResult } from '../../src/commands/agent/generate/template.js';
+import { getTestSession } from './shared-setup.js';
describe('agent generate template NUTs', () => {
let session: TestSession;
-
before(async () => {
- session = await TestSession.create({
- project: {
- sourceDir: join('test', 'mock-projects', 'agent-generate-template'),
- },
- devhubAuthStrategy: 'AUTO',
- });
- });
-
- after(async () => {
- await session?.clean();
+ session = await getTestSession();
});
it('should generate template from agent file', () => {
diff --git a/test/nuts/agent.generate.test-spec.nut.ts b/test/nuts/agent.generate.test-spec.nut.ts
index bd097591..7f5b72ee 100644
--- a/test/nuts/agent.generate.test-spec.nut.ts
+++ b/test/nuts/agent.generate.test-spec.nut.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,21 +19,12 @@ import { existsSync } from 'node:fs';
import { expect } from 'chai';
import { genUniqueString, TestSession } from '@salesforce/cli-plugins-testkit';
import { execCmd } from '@salesforce/cli-plugins-testkit';
+import { getTestSession } from './shared-setup.js';
describe('agent generate test-spec NUTs', () => {
let session: TestSession;
-
before(async () => {
- session = await TestSession.create({
- project: {
- sourceDir: join('test', 'mock-projects', 'agent-generate-template'),
- },
- devhubAuthStrategy: 'AUTO',
- });
- });
-
- after(async () => {
- await session?.clean();
+ session = await getTestSession();
});
it('should generate test spec from existing aiEvaluationDefinition', () => {
diff --git a/test/nuts/agent.publish.nut.ts b/test/nuts/agent.publish.nut.ts
deleted file mode 100644
index 2910ad5e..00000000
--- a/test/nuts/agent.publish.nut.ts
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright 2025, Salesforce, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-import { readFileSync, writeFileSync } from 'node:fs';
-import { join } from 'node:path';
-import { expect } from 'chai';
-import { genUniqueString, TestSession } from '@salesforce/cli-plugins-testkit';
-import { execCmd } from '@salesforce/cli-plugins-testkit';
-import { Org } from '@salesforce/core';
-import type { AgentPublishAuthoringBundleResult } from '../../src/commands/agent/publish/authoring-bundle.js';
-import type { AgentGenerateAuthoringBundleResult } from '../../src/commands/agent/generate/authoring-bundle.js';
-import { getDevhubUsername } from './shared-setup.js';
-
-describe('agent publish authoring-bundle NUTs', () => {
- let session: TestSession;
- const bundleApiName = 'Willie_Resort_Manager';
-
- before(async () => {
- session = await TestSession.create({
- project: {
- sourceDir: join('test', 'mock-projects', 'agent-generate-template'),
- },
- devhubAuthStrategy: 'AUTO',
- });
- });
-
- after(async () => {
- await session?.clean();
- });
-
- it.skip('should publish a new agent (first version)', async () => {
- const username = getDevhubUsername(session);
-
- // Generate a unique bundle name to ensure it's a new agent
- const bundleName = genUniqueString('Test_Agent_%s');
- const newBundleApiName = genUniqueString('Test_Agent_%s');
- const specFileName = genUniqueString('agentSpec_%s.yaml');
- const specPath = join(session.project.dir, 'specs', specFileName);
-
- // Step 1: Generate an agent spec
- const specCommand = `agent generate agent-spec --target-org ${username} --type customer --role "test agent role" --company-name "Test Company" --company-description "Test Description" --output-file ${specPath} --json`;
- execCmd(specCommand, { ensureExitCode: 0 });
-
- // Step 2: Generate the authoring bundle from the spec
- const generateCommand = `agent generate authoring-bundle --spec ${specPath} --name "${bundleName}" --api-name ${newBundleApiName} --target-org ${username} --json`;
- const generateResult = execCmd(generateCommand, {
- ensureExitCode: 0,
- }).jsonOutput?.result;
- expect(generateResult).to.be.ok;
-
- // Step 2.5: Update default_agent_user in the generated .agent file
- if (generateResult?.agentPath) {
- const agentContent = readFileSync(generateResult.agentPath, 'utf8');
- // Replace default_agent_user with the devhub username
- const updatedContent = agentContent.replace(
- /default_agent_user:\s*"[^"]*"/,
- 'default_agent_user: "ge.agent@afdx-usa1000-02.testorg"'
- );
- writeFileSync(generateResult.agentPath, updatedContent, 'utf8');
- }
-
- // Step 3: Publish the authoring bundle (first version)
- const publishResult = execCmd(
- `agent publish authoring-bundle --api-name ${newBundleApiName} --target-org ${username} --json`,
- { ensureExitCode: 0 }
- ).jsonOutput?.result;
-
- expect(publishResult).to.be.ok;
- expect(publishResult?.success).to.be.true;
- expect(publishResult?.botDeveloperName).to.be.a('string');
- expect(publishResult?.errors).to.be.undefined;
-
- // Cleanup: Delete the created metadata
- if (!publishResult?.botDeveloperName) {
- throw new Error('botDeveloperName not found in publish result');
- }
-
- const org = await Org.create({ aliasOrUsername: username });
- const connection = org.getConnection();
- const botDeveloperName = publishResult.botDeveloperName;
-
- // Query for Bot and BotVersions
- type BotDefinitionWithVersions = {
- Id: string;
- DeveloperName: string;
- BotVersions: {
- records: Array<{ Id: string }>;
- };
- };
-
- // Query for Bot and BotVersions
- const botResult = await connection.singleRecordQuery(
- `SELECT Id, DeveloperName, (SELECT Id FROM BotVersions) FROM BotDefinition WHERE DeveloperName = '${botDeveloperName}' LIMIT 1`
- );
-
- // Delete in correct order to handle dependencies:
- // 1. AiAuthoringBundle (references BotVersion)
- // 2. BotVersions (references Bot)
- // 3. Bot (BotDefinition)
- // 4. GenAiPlannerBundle
-
- // Step 1: Delete AiAuthoringBundle first (it references BotVersion)
- type AiAuthoringBundleResult = {
- Id: string;
- DeveloperName: string;
- };
-
- const authoringBundleResult = await connection.query(
- `SELECT Id, DeveloperName FROM AiAuthoringBundle WHERE DeveloperName = '${newBundleApiName}' LIMIT 1`
- );
-
- if (authoringBundleResult.records && authoringBundleResult.records.length > 0) {
- await connection.sobject('AiAuthoringBundle').destroy(authoringBundleResult.records[0].Id);
- }
-
- // Step 2: Delete BotVersions (must delete before Bot)
- if (botResult.BotVersions?.records && botResult.BotVersions.records.length > 0) {
- const botVersionIds = botResult.BotVersions.records.map((bv) => bv.Id);
- // Delete all BotVersions in parallel
- await Promise.all(botVersionIds.map((id) => connection.sobject('BotVersion').destroy(id)));
- }
-
- // Step 3: Delete Bot
- await connection.sobject('BotDefinition').destroy(botResult.Id);
-
- // Step 4: Query and delete GenAiPlannerBundle
- type GenAiPlannerBundleResult = {
- Id: string;
- DeveloperName: string;
- };
-
- const plannerBundleResult = await connection.query(
- `SELECT Id, DeveloperName FROM GenAiPlannerBundle WHERE DeveloperName = '${botDeveloperName}' LIMIT 1`
- );
-
- if (plannerBundleResult.records && plannerBundleResult.records.length > 0) {
- await connection.sobject('GenAiPlannerBundle').destroy(plannerBundleResult.records[0].Id);
- }
- });
-
- it.skip('should publish a new version of an existing agent', async () => {
- const username = getDevhubUsername(session);
-
- // Publish the existing Willie_Resort_Manager authoring bundle
- const result = execCmd(
- `agent publish authoring-bundle --api-name ${bundleApiName} --target-org ${username} --json`,
- { ensureExitCode: 0 }
- ).jsonOutput?.result;
-
- expect(result).to.be.ok;
- expect(result?.success).to.be.true;
- expect(result?.botDeveloperName).to.be.a('string');
- expect(result?.errors).to.be.undefined;
- });
-
- it('should fail for invalid bundle api-name', async () => {
- const username = getDevhubUsername(session);
- const invalidApiName = 'Invalid_Bundle_Name_That_Does_Not_Exist';
-
- execCmd(
- `agent publish authoring-bundle --api-name ${invalidApiName} --target-org ${username} --json`,
- { ensureExitCode: 1 }
- );
- });
-});
diff --git a/test/nuts/agent.test.create.nut.ts b/test/nuts/agent.test.create.nut.ts
index cd2cb22d..0f5272e6 100644
--- a/test/nuts/agent.test.create.nut.ts
+++ b/test/nuts/agent.test.create.nut.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,42 +16,31 @@
import { join, normalize } from 'node:path';
import { existsSync } from 'node:fs';
+import * as os from 'node:os';
import { expect } from 'chai';
import { genUniqueString, TestSession } from '@salesforce/cli-plugins-testkit';
import { execCmd } from '@salesforce/cli-plugins-testkit';
import type { AgentTestCreateResult } from '../../src/commands/agent/test/create.js';
-import { getDevhubUsername } from './shared-setup.js';
+import { getTestSession, getUsername } from './shared-setup.js';
-const isWindows = process.platform === 'win32';
-
-describe('agent test create NUTs', () => {
+describe('agent test create', () => {
let session: TestSession;
-
before(async () => {
- session = await TestSession.create({
- project: {
- sourceDir: join('test', 'mock-projects', 'agent-generate-template'),
- },
- devhubAuthStrategy: 'AUTO',
- });
+ session = await getTestSession();
});
-
- after(async () => {
- await session?.clean();
- });
-
- (isWindows ? it.skip : it)('should create test from test spec file', async () => {
- const username = getDevhubUsername(session);
+ // this NUT is failing on windows due to an invalid api name, but it seems valid to me, passes on unix
+ // Error: Unexpected exit code for command: agent test create --api-name Test_Agent_5096f046f91f34e7 --spec "...\agent-generate-template\specs\testSpec.yaml" --target-org test-relsveqne0do@example.com --json. Expected: 0 Actual: 1
+ // Message: "Name: The AI Evaluation Definition API Name can only contain underscores and alphanumeric characters. It must be unique, begin with a letter, not include spaces, not end with an underscore, and not contain two consecutive underscores.",
+ // Test_Agent_5096f046f91f34e7 only contains underscores, and alphanumeric characters...
+ (os.platform() === 'win32' ? it.skip : it)('should create test from test spec file', async function () {
+ // Increase timeout to 30 minutes since deployment can take a long time
+ this.timeout(30 * 60 * 1000);
const testApiName = genUniqueString('Test_Agent_%s');
// Use the existing test spec file from the mock project
const specPath = join(session.project.dir, 'specs', 'testSpec.yaml');
- // Normalize path for cross-platform compatibility (Windows uses backslashes)
- const normalizedSpecPath = normalize(specPath).replace(/\\/g, '/');
- // Don't quote --api-name on Windows - it can cause parsing issues
- // Only quote --spec path since it may contain spaces
const commandResult = execCmd(
- `agent test create --api-name ${testApiName} --spec "${normalizedSpecPath}" --target-org ${username} --json`,
+ `agent test create --api-name "${testApiName}" --spec "${specPath}" --target-org ${getUsername()} --json`,
{ ensureExitCode: 0 }
);
@@ -71,27 +60,29 @@ describe('agent test create NUTs', () => {
});
it('should fail when spec file does not exist', async () => {
- const username = getDevhubUsername(session);
const testApiName = genUniqueString('Test_Agent_%s');
const invalidSpecPath = join(session.project.dir, 'invalid', 'testSpec.yaml');
const normalizedInvalidSpecPath = normalize(invalidSpecPath).replace(/\\/g, '/');
execCmd(
- `agent test create --api-name ${testApiName} --spec "${normalizedInvalidSpecPath}" --target-org ${username} --json`,
+ `agent test create --api-name "${testApiName}" --spec "${normalizedInvalidSpecPath}" --target-org ${getUsername()} --json`,
{ ensureExitCode: 1 }
);
});
it('should fail when required flags are missing in JSON mode', async () => {
- const username = getDevhubUsername(session);
-
// Missing --api-name
- execCmd(`agent test create --target-org ${username} --json`, { ensureExitCode: 1 });
+ execCmd(`agent test create --target-org ${getUsername()} --json`, {
+ ensureExitCode: 1,
+ });
// Missing --spec
const testApiName = genUniqueString('Test_Agent_%s');
- execCmd(`agent test create --api-name ${testApiName} --target-org ${username} --json`, {
- ensureExitCode: 1,
- });
+ execCmd(
+ `agent test create --api-name "${testApiName}" --target-org ${getUsername()} --json`,
+ {
+ ensureExitCode: 1,
+ }
+ );
});
});
diff --git a/test/nuts/agent.test.nut.ts b/test/nuts/agent.test.nut.ts
index 5b7cbb0c..f7c96d71 100644
--- a/test/nuts/agent.test.nut.ts
+++ b/test/nuts/agent.test.nut.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,40 +14,26 @@
* limitations under the License.
*/
-import { join } from 'node:path';
import { expect } from 'chai';
-import { TestSession } from '@salesforce/cli-plugins-testkit';
import { execCmd } from '@salesforce/cli-plugins-testkit';
import { AgentTestCache } from '../../src/agentTestCache.js';
import type { AgentTestListResult } from '../../src/commands/agent/test/list.js';
import type { AgentTestResultsResult } from '../../src/commands/agent/test/results.js';
import type { AgentTestRunResult } from '../../src/flags.js';
-import { getDevhubUsername } from './shared-setup.js';
+import { getTestSession, getUsername } from './shared-setup.js';
/* eslint-disable no-console */
-describe('agent test NUTs', () => {
- let session: TestSession;
- let devhubUsername: string;
+describe('agent test', () => {
const agentTestName = 'Local_Info_Agent_Test';
before(async () => {
- session = await TestSession.create({
- project: {
- sourceDir: join('test', 'mock-projects', 'agent-generate-template'),
- },
- devhubAuthStrategy: 'AUTO',
- });
- devhubUsername = getDevhubUsername(session);
- });
-
- after(async () => {
- await session?.clean();
+ await getTestSession();
});
describe('agent test list', () => {
it('should list agent tests in org', async () => {
- const result = execCmd(`agent test list --target-org ${devhubUsername} --json`, {
+ const result = execCmd(`agent test list --target-org ${getUsername()} --json`, {
ensureExitCode: 0,
}).jsonOutput?.result;
expect(result).to.be.ok;
@@ -58,7 +44,7 @@ describe('agent test NUTs', () => {
describe('agent test run', () => {
it('should start async test run', async () => {
- const command = `agent test run --api-name ${agentTestName} --target-org ${devhubUsername} --json`;
+ const command = `agent test run --api-name ${agentTestName} --target-org ${getUsername()} --json`;
const output = execCmd(command, {
ensureExitCode: 0,
}).jsonOutput;
@@ -73,7 +59,7 @@ describe('agent test NUTs', () => {
});
it('should poll for test run completion when --wait is used', async () => {
- const command = `agent test run --api-name ${agentTestName} --target-org ${devhubUsername} --wait 5 --json`;
+ const command = `agent test run --api-name ${agentTestName} --target-org ${getUsername()} --wait 5 --json`;
const output = execCmd(command, {
ensureExitCode: 0,
}).jsonOutput;
@@ -90,7 +76,7 @@ describe('agent test NUTs', () => {
cache.clear();
const runResult = execCmd(
- `agent test run --api-name ${agentTestName} --target-org ${devhubUsername} --wait 5 --json`,
+ `agent test run --api-name ${agentTestName} --target-org ${getUsername()} --wait 5 --json`,
{
ensureExitCode: 0,
}
@@ -100,7 +86,7 @@ describe('agent test NUTs', () => {
expect(runResult?.result.status.toLowerCase()).to.equal('completed');
const output = execCmd(
- `agent test results --job-id ${runResult?.result.runId} --target-org ${devhubUsername} --json`,
+ `agent test results --job-id ${runResult?.result.runId} --target-org ${getUsername()} --json`,
{
ensureExitCode: 0,
}
@@ -121,7 +107,7 @@ describe('agent test NUTs', () => {
cache.clear();
const runResult = execCmd(
- `agent test run --api-name ${agentTestName} --target-org ${devhubUsername} --json`,
+ `agent test run --api-name ${agentTestName} --target-org ${getUsername()} --json`,
{
ensureExitCode: 0,
}
@@ -130,7 +116,7 @@ describe('agent test NUTs', () => {
expect(runResult?.result.runId).to.be.ok;
const output = execCmd(
- `agent test resume --job-id ${runResult?.result.runId} --target-org ${devhubUsername} --json`,
+ `agent test resume --job-id ${runResult?.result.runId} --target-org ${getUsername()} --json`,
{
ensureExitCode: 0,
}
diff --git a/test/nuts/shared-setup.ts b/test/nuts/shared-setup.ts
index 41cac0f7..ca880b6a 100644
--- a/test/nuts/shared-setup.ts
+++ b/test/nuts/shared-setup.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,56 +15,180 @@
*/
import { join } from 'node:path';
-import { Connection } from '@salesforce/core';
+import { Duration, TestSession } from '@salesforce/cli-plugins-testkit';
import { ComponentSetBuilder } from '@salesforce/source-deploy-retrieve';
-import { expect } from 'chai';
-import type { TestSession } from '@salesforce/cli-plugins-testkit';
+import { Org, User } from '@salesforce/core';
+import { sleep } from '@salesforce/kit';
/* eslint-disable no-console */
+// Module-level variables to ensure only one TestSession is created
+let testSession: TestSession | undefined;
+let testSessionPromise: Promise | undefined;
+let agentUsername: string | undefined;
+
/**
- * Gets the devhub username from the test session.
+ * Gets the shared TestSession with a scratch org. This ensures only one TestSession
+ * is created per test run, even if called from multiple test files simultaneously.
+ * All callers will wait for the same creation promise.
*/
-export function getDevhubUsername(session: TestSession): string {
- // First try environment variable
- if (process.env.TESTKIT_HUB_USERNAME) {
- return process.env.TESTKIT_HUB_USERNAME;
+export async function getTestSession(): Promise {
+ // If already created, return it immediately
+ if (testSession) {
+ return testSession;
}
- // Use session.hubOrg which TestKit keeps authenticated
- if (session.hubOrg?.username) {
- return session.hubOrg.username;
+ // If creation is in progress, wait for the same promise
+ if (testSessionPromise) {
+ return testSessionPromise;
}
- throw new Error('Devhub username not found. Ensure TESTKIT_HUB_USERNAME is set or devhub is properly authenticated.');
+ // Create the TestSession (only once, even if called from multiple test files simultaneously)
+ testSessionPromise = (async (): Promise => {
+ console.log('Creating shared TestSession with scratch org...');
+ const session = await TestSession.create({
+ project: {
+ sourceDir: join('test', 'mock-projects', 'agent-generate-template'),
+ },
+ devhubAuthStrategy: 'AUTO',
+ scratchOrgs: [
+ {
+ alias: 'default',
+ setDefault: true,
+ config: 'config/project-scratch-def.json',
+ },
+ ],
+ });
+
+ testSession = session;
+ console.log('TestSession created successfully');
+
+ // Get the scratch org username and assign permission set
+ const orgs = session.orgs;
+ const defaultOrg = orgs.get('default');
+
+ if (orgs && orgs.size > 0) {
+ if (defaultOrg?.username) {
+ console.log(`Using scratch org: ${defaultOrg.username}`);
+ const org = await Org.create({ aliasOrUsername: defaultOrg.username });
+ const connection = org.getConnection();
+
+ // assign the EinsteinGPTPromptTemplateManager to the scratch org admin user
+ const queryResult = await connection.singleRecordQuery<{ Id: string; Name: string }>(
+ `SELECT Id, Name FROM User WHERE Username='${defaultOrg.username}'`
+ );
+ const user = await User.create({ org });
+ await user.assignPermissionSets(queryResult.Id, ['EinsteinGPTPromptTemplateManager']);
+ console.log(`Permission set assigned to scratch org user: ${queryResult.Name}`);
+ // Create a new agent user with required permission sets
+ console.log('Creating agent user...');
+
+ // Get the 'Einstein Agent User' profile
+ const profileResult = await connection.singleRecordQuery<{ Id: string }>(
+ "SELECT Id FROM Profile WHERE Name='Einstein Agent User'"
+ );
+
+ // Generate a unique username using timestamp to avoid duplicates
+ const timestamp = Date.now();
+ const domain = defaultOrg.username.split('@')[1];
+ agentUsername = `agent.user.${timestamp}@${domain}`;
+ const agentUserRecord = await connection.sobject('User').create({
+ FirstName: 'Agent',
+ LastName: 'User',
+ Alias: 'agentusr',
+ Email: agentUsername,
+ Username: agentUsername,
+ ProfileId: profileResult.Id,
+ TimeZoneSidKey: 'America/Los_Angeles',
+ LocaleSidKey: 'en_US',
+ EmailEncodingKey: 'UTF-8',
+ LanguageLocaleKey: 'en_US',
+ });
+
+ if (!agentUserRecord.success || !agentUserRecord.id) {
+ throw new Error(`Failed to create agent user: ${agentUserRecord.errors?.join(', ')}`);
+ }
+
+ const agentUserId = agentUserRecord.id;
+ console.log(`Agent user created: ${agentUsername} (${agentUserId})`);
+
+ // Assign permission sets to the agent user individually to identify any failures
+ const permissionSets = [
+ 'AgentforceServiceAgentBase',
+ 'AgentforceServiceAgentUser',
+ 'EinsteinGPTPromptTemplateUser',
+ ];
+
+ // I had issues assigning all permission sets in one pass, assign individually for now
+ for (const permissionSet of permissionSets) {
+ // eslint-disable-next-line no-await-in-loop
+ await user.assignPermissionSets(agentUserId, [permissionSet]);
+ console.log(`Permission set assigned: ${permissionSet}`);
+ }
+ console.log('Permission set assignment completed');
+
+ // Set environment variable for string replacement
+ process.env.AGENT_USER_USERNAME = agentUsername;
+
+ console.log('deploying metadata (no AiEvaluationDefinition)');
+
+ const cs1 = await ComponentSetBuilder.build({
+ manifest: {
+ manifestPath: join(testSession.project.dir, 'noTest.xml'),
+ directoryPaths: [testSession.homeDir],
+ },
+ });
+ const deploy1 = await cs1.deploy({ usernameOrConnection: defaultOrg.username });
+ await deploy1.pollStatus({ frequency: Duration.seconds(10) });
+
+ console.log('deploying metadata (AiEvaluationDefinition)');
+
+ const cs2 = await ComponentSetBuilder.build({
+ manifest: {
+ manifestPath: join(testSession.project.dir, 'test.xml'),
+ directoryPaths: [testSession.homeDir],
+ },
+ });
+ const deploy2 = await cs2.deploy({ usernameOrConnection: defaultOrg.username });
+ await deploy2.pollStatus({ frequency: Duration.seconds(10) });
+ }
+ }
+
+ // Wait for org to be ready - longer wait on Windows CI where things can be slower
+ const isWindows = process.platform === 'win32';
+ const waitTime = isWindows ? 10 * 60 * 1000 : 5 * 60 * 1000; // 10 minutes on Windows, 5 minutes otherwise
+ console.log(`waiting ${waitTime / 1000 / 60} minutes for org to be ready (platform: ${process.platform})`);
+ await sleep(waitTime);
+ return session;
+ })();
+
+ return testSessionPromise;
}
-export async function deployMetadata(connection: Connection, session: TestSession): Promise {
- // deploy Local_Info_Agent to scratch org
- const compSet1 = await ComponentSetBuilder.build({
- metadata: {
- metadataEntries: ['Agent:Local_Info_Agent'],
- directoryPaths: [join(session.project.dir, 'force-app', 'main', 'default')],
- },
- });
- const deploy1 = await compSet1.deploy({ usernameOrConnection: connection });
- const deployResult1 = await deploy1.pollStatus();
- if (!deployResult1.response.success) {
- console.dir(deployResult1.response, { depth: 10 });
+/**
+ * Gets the scratch org username from the shared test session.
+ * Throws an error if the session hasn't been created yet.
+ */
+export function getUsername(): string {
+ if (!testSession) {
+ throw new Error('Test session not available. Call getTestSession() first.');
}
- expect(deployResult1.response.success, 'expected Agent deploy to succeed').to.equal(true);
-
- // deploy Local_Info_Agent_Test to scratch org
- const compSet2 = await ComponentSetBuilder.build({
- metadata: {
- metadataEntries: ['AiEvaluationDefinition:Local_Info_Agent_Test'],
- directoryPaths: [join(session.project.dir, 'force-app', 'main', 'default')],
- },
- });
- const deploy2 = await compSet2.deploy({ usernameOrConnection: connection });
- const deployResult2 = await deploy2.pollStatus();
- if (!deployResult2.response.success) {
- console.dir(deployResult2.response, { depth: 10 });
+
+ const orgs = testSession.orgs;
+ if (!orgs || orgs.size === 0) {
+ throw new Error('No orgs found in test session.');
+ }
+
+ return testSession.orgs.get('default')!.username!;
+}
+
+/**
+ * Gets the agent user, username, from the shared test session.
+ * Throws an error if the session hasn't been created yet.
+ */
+export function getAgentUsername(): string | undefined {
+ if (!testSession) {
+ throw new Error('Test session not available. Call getTestSession() first.');
}
- expect(deployResult2.response.success, 'expected Agent Test deploy to succeed').to.equal(true);
+ return agentUsername;
}
diff --git a/test/commands/agent/generate/template.nut.ts b/test/nuts/template.nut.ts
similarity index 93%
rename from test/commands/agent/generate/template.nut.ts
rename to test/nuts/template.nut.ts
index cf96615f..c695b18c 100644
--- a/test/commands/agent/generate/template.nut.ts
+++ b/test/nuts/template.nut.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,20 +22,14 @@ import {
AgentGenerateTemplateResult,
BotTemplateExt,
GenAiPlannerBundleExt,
-} from '../../../../src/commands/agent/generate/template.js';
+} from '../../src/commands/agent/generate/template.js';
+import { getTestSession } from './shared-setup.js';
describe('agent generate template NUTs', () => {
let session: TestSession;
before(async () => {
- session = await TestSession.create({
- devhubAuthStrategy: 'NONE',
- project: { sourceDir: join('test', 'mock-projects', 'agent-generate-template') },
- });
- });
-
- after(async () => {
- await session?.clean();
+ session = await getTestSession();
});
it('throws an error if Bot "type" is equal to "Bot"', async () => {
diff --git a/test/nuts/agent.validate.nut.ts b/test/nuts/z1.agent.validate.nut.ts
similarity index 59%
rename from test/nuts/agent.validate.nut.ts
rename to test/nuts/z1.agent.validate.nut.ts
index c7be4b63..36984943 100644
--- a/test/nuts/agent.validate.nut.ts
+++ b/test/nuts/z1.agent.validate.nut.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,35 +13,33 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { join } from 'node:path';
import { expect } from 'chai';
-import { TestSession } from '@salesforce/cli-plugins-testkit';
import { execCmd } from '@salesforce/cli-plugins-testkit';
+import { sleep } from '@salesforce/kit';
import type { AgentValidateAuthoringBundleResult } from '../../src/commands/agent/validate/authoring-bundle.js';
-import { getDevhubUsername } from './shared-setup.js';
+import { getTestSession, getUsername } from './shared-setup.js';
-describe('agent validate authoring-bundle NUTs', () => {
- let session: TestSession;
+describe('agent validate authoring-bundle NUTs', function () {
+ // Increase timeout for setup since shared setup includes a long wait on Windows
+ this.timeout(15 * 60 * 1000); // 15 minutes
before(async () => {
- session = await TestSession.create({
- project: {
- sourceDir: join('test', 'mock-projects', 'agent-generate-template'),
- },
- devhubAuthStrategy: 'AUTO',
- });
+ await getTestSession();
});
- after(async () => {
- await session?.clean();
- });
+ it('should validate a valid authoring bundle', async function () {
+ // Retry up to 3 times total (1 initial + 2 retries) to handle transient failures
+ // Windows CI can be slower, so retries help handle timing issues
+ this.retries(2);
- it('should validate a valid authoring bundle', async () => {
- const username = getDevhubUsername(session);
+ // Add a small delay on Windows before running the test to ensure API is ready
+ if (process.platform === 'win32') {
+ await sleep(30 * 1000); // Wait 30 seconds on Windows
+ }
// Use the existing Willie_Resort_Manager authoring bundle
const result = execCmd(
- `agent validate authoring-bundle --api-name Willie_Resort_Manager --target-org ${username} --json`,
+ `agent validate authoring-bundle --api-name Willie_Resort_Manager --target-org ${getUsername()} --json`,
{ ensureExitCode: 0 }
).jsonOutput?.result;
@@ -50,12 +48,13 @@ describe('agent validate authoring-bundle NUTs', () => {
expect(result?.errors).to.be.undefined;
});
- it('should fail validation for invalid authoring bundle', async () => {
- const username = getDevhubUsername(session);
+ it('should fail validation for invalid authoring bundle', async function () {
+ // Retry up to 3 times total (1 initial + 2 retries) to handle transient failures
+ this.retries(2);
// Use the invalid authoring bundle (expects exit code 2 for compilation errors)
execCmd(
- `agent validate authoring-bundle --api-name invalid --target-org ${username} --json`,
+ `agent validate authoring-bundle --api-name invalid --target-org ${getUsername()} --json`,
{ ensureExitCode: 2 }
);
});
diff --git a/test/nuts/z2.agent.publish.nut.ts b/test/nuts/z2.agent.publish.nut.ts
new file mode 100644
index 00000000..13b4465f
--- /dev/null
+++ b/test/nuts/z2.agent.publish.nut.ts
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2026, Salesforce, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { readFileSync, writeFileSync } from 'node:fs';
+import { join } from 'node:path';
+import { expect } from 'chai';
+import { genUniqueString, TestSession } from '@salesforce/cli-plugins-testkit';
+import { execCmd } from '@salesforce/cli-plugins-testkit';
+import type { AgentPublishAuthoringBundleResult } from '../../src/commands/agent/publish/authoring-bundle.js';
+import type { AgentGenerateAuthoringBundleResult } from '../../src/commands/agent/generate/authoring-bundle.js';
+import { getAgentUsername, getTestSession, getUsername } from './shared-setup.js';
+
+describe('agent publish authoring-bundle NUTs', function () {
+ // Increase timeout for setup since shared setup includes a long wait on Windows
+ this.timeout(15 * 60 * 1000); // 15 minutes
+
+ let session: TestSession;
+ const bundleApiName = genUniqueString('Test_Agent_%s');
+ before(async () => {
+ session = await getTestSession();
+ });
+
+ it('should publish a new agent (first version)', async function () {
+ // Increase timeout to 30 minutes since deployment can take a long time
+ this.timeout(30 * 60 * 1000); // 30 minutes
+ // Retry up to 3 times total (1 initial + 2 retries) to handle transient failures
+ this.retries(2);
+ const specFileName = genUniqueString('agentSpec_%s.yaml');
+ const specPath = join(session.project.dir, 'specs', specFileName);
+
+ // Step 1: Generate an agent spec
+ const specCommand = `agent generate agent-spec --target-org ${getUsername()} --type customer --role "test agent role" --company-name "Test Company" --company-description "Test Description" --output-file ${specPath} --json`;
+ execCmd(specCommand, { ensureExitCode: 0 });
+
+ // Step 2: Generate the authoring bundle from the spec
+ const generateCommand = `agent generate authoring-bundle --spec ${specPath} --name "${bundleApiName}" --api-name ${bundleApiName} --target-org ${getUsername()} --json`;
+ const generateResult = execCmd(generateCommand, {
+ ensureExitCode: 0,
+ }).jsonOutput?.result;
+ expect(generateResult).to.be.ok;
+
+ // Step 2.5: Update default_agent_user in the generated .agent file to the 'agent user' we created in shared setup
+ if (generateResult?.agentPath) {
+ const agentContent = readFileSync(generateResult.agentPath, 'utf8');
+ // Replace default_agent_user with the devhub username
+ const updatedContent = agentContent.replace(
+ /default_agent_user:\s*"[^"]*"/,
+ `default_agent_user: "${getAgentUsername()!}"`
+ );
+ writeFileSync(generateResult.agentPath, updatedContent, 'utf8');
+ }
+
+ // Step 3: Publish the authoring bundle (first version)
+ const publishResult = execCmd(
+ `agent publish authoring-bundle --api-name ${bundleApiName} --target-org ${getUsername()} --json`,
+ { ensureExitCode: 0 }
+ ).jsonOutput?.result;
+
+ expect(publishResult).to.be.ok;
+ expect(publishResult?.success).to.be.true;
+ expect(publishResult?.botDeveloperName).to.be.a('string');
+ expect(publishResult?.errors).to.be.undefined;
+ });
+
+ it('should publish a new version of an existing agent', async function () {
+ // Increase timeout to 30 minutes since deployment can take a long time
+ this.timeout(30 * 60 * 1000); // 30 minutes
+ // Retry up to 2 times total (1 initial + 1 retries) to handle transient failures
+ this.retries(1);
+ // Publish the existing Willie_Resort_Manager authoring bundle
+ const result = execCmd(
+ `agent publish authoring-bundle --api-name ${bundleApiName} --target-org ${getUsername()} --json`,
+ { ensureExitCode: 0 }
+ ).jsonOutput?.result;
+
+ expect(result).to.be.ok;
+ expect(result?.success).to.be.true;
+ expect(result?.botDeveloperName).to.be.a('string');
+ expect(result?.errors).to.be.undefined;
+ });
+
+ it('should fail for invalid bundle api-name', async () => {
+ const invalidApiName = 'Invalid_Bundle_Name_That_Does_Not_Exist';
+
+ execCmd(
+ `agent publish authoring-bundle --api-name ${invalidApiName} --target-org ${getUsername()} --json`,
+ { ensureExitCode: 1 }
+ );
+ });
+});
diff --git a/test/testData.ts b/test/testData.ts
index d910afab..f9e199df 100644
--- a/test/testData.ts
+++ b/test/testData.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2025, Salesforce, Inc.
+ * Copyright 2026, Salesforce, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
diff --git a/test/utils/assignAgentforcePermset.ts b/test/utils/assignAgentforcePermset.ts
deleted file mode 100644
index 2b6066bd..00000000
--- a/test/utils/assignAgentforcePermset.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2025, Salesforce, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import { Org, User } from '@salesforce/core';
-
-export async function assignAgentforcePermset(username: string) {
- // const username = session.orgs.get('default')!.username as string;
- const org = await Org.create({ aliasOrUsername: username });
- const connection = org.getConnection();
-
- // assign the EinsteinGPTPromptTemplateManager to the scratch org admin user
- const queryResult = await connection.singleRecordQuery<{ Id: string }>(
- `SELECT Id FROM User WHERE Username='${username}'`
- );
- const user = await User.create({ org });
- await user.assignPermissionSets(queryResult.Id, ['EinsteinGPTPromptTemplateManager']);
-}