@salesforce/afv-skills 1.31.0 → 1.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/agentforce-bot-upgrade/SKILL.md +217 -0
- package/skills/agentforce-bot-upgrade/references/extraction-blueprint.md +242 -0
- package/skills/agentforce-bot-upgrade/references/generate-agent-spec.md +128 -0
- package/skills/agentforce-bot-upgrade/references/handoff-output-format.md +208 -0
- package/skills/agentforce-bot-upgrade/references/input-contract.md +101 -0
- package/skills/agentforce-bot-upgrade/references/mapping-rules.md +113 -0
- package/skills/agentforce-bot-upgrade/references/planner-workflow-reference.md +78 -0
- package/skills/agentforce-bot-upgrade/references/post-conversion-enhancements-reference.md +67 -0
- package/skills/agentforce-bot-upgrade/references/quality-checklist.md +33 -0
- package/skills/agentforce-bot-upgrade/references/sf-cli-bot-reference.md +116 -0
- package/skills/dx-devops-work-item-manage/SKILL.md +270 -0
- package/skills/dx-devops-work-item-manage/examples/common-workflows.md +479 -0
- package/skills/dx-devops-work-item-manage/references/cli-commands.md +476 -0
- package/skills/dx-org-manage/SKILL.md +8 -5
- package/skills/dx-org-trial-expiration-check/SKILL.md +239 -0
- package/skills/dx-org-trial-expiration-check/scripts/check_expiration.sh +588 -0
- package/skills/experience-ui-bundle-app-coordinate/SKILL.md +12 -9
- package/skills/experience-ui-bundle-custom-app-generate/SKILL.md +29 -5
- package/skills/experience-ui-bundle-custom-app-generate/references/configure-metadata-custom-application.md +1 -1
- package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.sh +30 -0
- package/skills/experience-ui-bundle-features-generate/SKILL.md +86 -11
- package/skills/experience-ui-bundle-features-generate/references/conflict-resolution-schema.json +20 -0
- package/skills/experience-ui-bundle-features-generate/scripts/verify-react-bundle.sh +14 -0
- package/skills/experience-ui-bundle-frontend-generate/SKILL.md +6 -1
- package/skills/experience-ui-bundle-frontend-generate/references/component.md +34 -1
- package/skills/experience-ui-bundle-frontend-generate/references/page.md +1 -1
- package/skills/experience-ui-bundle-project-generate/SKILL.md +111 -0
- package/skills/experience-ui-bundle-project-generate/scripts/flatten-project.mjs +33 -0
- package/skills/platform-custom-lightning-type-generate/SKILL.md +9 -14
- package/skills/platform-custom-lightning-type-generate/references/widget-rendition.md +27 -111
- package/skills/platform-lightning-type-widget-coordinate/SKILL.md +214 -0
- package/skills/platform-lightning-type-widget-coordinate/examples/existing-lightning-type-with-widget-prompt.md +80 -0
- package/skills/platform-lightning-type-widget-coordinate/examples/new-lightning-type-with-widget-prompt.md +75 -0
- package/skills/platform-lightning-type-widget-coordinate/references/build-plan-format.md +67 -0
- package/skills/platform-lightning-type-widget-coordinate/references/lightning-type-discovery.md +124 -0
- package/skills/platform-lightning-type-widget-coordinate/references/validation-gates.md +130 -0
- package/skills/platform-sharing-owd-configure/SKILL.md +142 -0
- package/skills/platform-sharing-owd-configure/examples/get_owd_output.md +38 -0
- package/skills/platform-sharing-owd-configure/examples/update_owd_output.md +44 -0
- package/skills/platform-sharing-owd-configure/references/access_levels.md +49 -0
- package/skills/platform-sharing-owd-configure/references/metadata_api_approach.md +69 -0
- package/skills/platform-sharing-rules-generate/SKILL.md +89 -19
- package/skills/platform-sharing-rules-generate/examples/test-cases.md +381 -0
- package/skills/platform-widget-generate/SKILL.md +241 -0
- package/skills/platform-widget-generate/examples/conditional.json +73 -0
- package/skills/platform-widget-generate/examples/list-with-foreach.json +66 -0
- package/skills/platform-widget-generate/examples/single-object.json +64 -0
- package/skills/platform-widget-generate/references/schema-from-lightning-type.md +76 -0
- package/skills/platform-widget-generate/references/widget-bundle-layout.md +116 -0
- package/skills/platform-widget-generate/references/widget-meta-directives.md +130 -0
- package/skills/sales-agentforce-pipeline-management-configure/SKILL.md +268 -0
- package/skills/sales-agentforce-pipeline-management-configure/assets/field-completion-template.genAiPromptTemplate-meta.xml +141 -0
- package/skills/sales-agentforce-pipeline-management-configure/assets/pipeline_management_flow.flow-meta.xml +548 -0
- package/skills/sales-agentforce-pipeline-management-configure/assets/sales_management_agent.agent +2938 -0
- package/skills/sales-agentforce-pipeline-management-configure/assets/sales_management_agent.bundle-meta.xml +4 -0
- package/skills/sales-agentforce-pipeline-management-configure/assets/sfdx-project.json +12 -0
- package/skills/sales-agentforce-pipeline-management-configure/assets/stage-descriptions/bant.txt +11 -0
- package/skills/sales-agentforce-pipeline-management-configure/assets/stage-descriptions/meddic.txt +11 -0
- package/skills/sales-agentforce-pipeline-management-configure/assets/stage-descriptions/spiced.txt +11 -0
- package/skills/sales-agentforce-pipeline-management-configure/examples/custom-prompt-instructions.md +317 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/admin-communication.md +355 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/agent-creation.md +383 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/auth-and-cli.md +146 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/automation-matrix.md +23 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/autonomous-updates.md +215 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/canonical-agent-path.md +75 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/data-sources.md +155 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/field-completion-prompt-template.md +120 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/field-completion-prompts.md +149 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/flags.md +13 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/flow-clone-from-template.md +447 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/metadata-inventory.md +330 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/opportunity-stages.md +246 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/repair-diagnostics.md +265 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/setup-order.md +263 -0
- package/skills/sales-agentforce-pipeline-management-configure/references/soap-api-enablement.md +528 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/CHANGES.md +180 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/README.md +56 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/add-field-suggestion.sh +679 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/create-agent.sh +302 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/create-flow.sh +250 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/define-agent-access.sh +430 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/deploy-settings.sh +77 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/enable-deal-agent.sh +241 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/enable-prerequisites.sh +538 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/flow-debug-and-verify.sh +385 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/retrieve-settings.sh +131 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/setup-all.sh +2791 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/agent-bundle-publish.sh +189 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/agent-detection.sh +239 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/flow-builder.sh +238 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/psg.sh +48 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/soap.sh +140 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/stage-descriptions.sh +448 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/shared/test-opp.sh +166 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/verify-all.sh +636 -0
- package/skills/sales-agentforce-pipeline-management-configure/scripts/verify-prompt-generation.sh +346 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Verify and ensure Pipeline Management agent is functional.
|
|
4
|
+
#
|
|
5
|
+
# CRITICAL: BotDefinition:SalesAgent is REQUIRED for a functional Pipeline Management agent.
|
|
6
|
+
# Users need an interactive Sales Agent they can chat with, which requires the BotDefinition.
|
|
7
|
+
# The agent user + PSG provision the backend identity, but without the BotDefinition,
|
|
8
|
+
# users CANNOT interact with the Sales Agent via chat/conversation interface.
|
|
9
|
+
#
|
|
10
|
+
# This script ensures:
|
|
11
|
+
# Step 1: Agent user exists with SalesManagementAgentUserPsg assigned
|
|
12
|
+
# Step 2: BotDefinition:SalesAgent is created and activated (via authoring bundle)
|
|
13
|
+
# Step 3: Both are verified functional (backend + user-facing)
|
|
14
|
+
#
|
|
15
|
+
# If the agent user exists but BotDefinition is missing, the script CREATES it.
|
|
16
|
+
# If BotDefinition creation fails, the script EXITS 1 (setup incomplete).
|
|
17
|
+
#
|
|
18
|
+
# Usage: ./create-agent.sh <org-alias>
|
|
19
|
+
|
|
20
|
+
set -euo pipefail
|
|
21
|
+
|
|
22
|
+
# sf CLI can emit ANSI color codes inside --json stdout, breaking jq parsing.
|
|
23
|
+
# 2>/dev/null only strips stderr; these env vars are the reliable fix (see PM notes).
|
|
24
|
+
export NO_COLOR=1
|
|
25
|
+
export FORCE_COLOR=0
|
|
26
|
+
|
|
27
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
28
|
+
|
|
29
|
+
# Source shared library
|
|
30
|
+
source "$SCRIPT_DIR/shared/agent-bundle-publish.sh"
|
|
31
|
+
|
|
32
|
+
# Define Agent Access (W-23242378) so human users holding SalesManagementUserPsg
|
|
33
|
+
# can launch the agent. Idempotent; exits gracefully if no active bot exists.
|
|
34
|
+
define_agent_access() {
|
|
35
|
+
local org="$1"
|
|
36
|
+
if [[ -f "$SCRIPT_DIR/define-agent-access.sh" ]]; then
|
|
37
|
+
echo ""
|
|
38
|
+
echo "=== Defining Agent Access (W-23242378) ==="
|
|
39
|
+
local rc=0
|
|
40
|
+
bash "$SCRIPT_DIR/define-agent-access.sh" "$org" || rc=$?
|
|
41
|
+
if [[ $rc -ne 0 ]]; then
|
|
42
|
+
echo " Warning: Agent Access definition failed (exit $rc) — see above"
|
|
43
|
+
return $rc
|
|
44
|
+
fi
|
|
45
|
+
fi
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
ORG_ALIAS="${1:-}"
|
|
49
|
+
|
|
50
|
+
if [[ -z "$ORG_ALIAS" ]]; then
|
|
51
|
+
echo "Error: Missing org alias"
|
|
52
|
+
echo "Usage: $0 <org-alias>"
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
echo "Verifying Pipeline Management agent setup"
|
|
57
|
+
echo ""
|
|
58
|
+
|
|
59
|
+
# --- Step 1: Check functional indicators (agent user + PSG) ---
|
|
60
|
+
echo "=== Step 1: Checking agent user (primary functional indicator) ==="
|
|
61
|
+
AGENT_USER=$(sf data query \
|
|
62
|
+
--query "SELECT Id, Username FROM User WHERE Username LIKE '%salesmanagementagentuser%'" \
|
|
63
|
+
--target-org "$ORG_ALIAS" \
|
|
64
|
+
--json 2>/dev/null | jq -r '.result.records[0] // empty' 2>/dev/null || echo "")
|
|
65
|
+
|
|
66
|
+
if [[ -n "$AGENT_USER" ]]; then
|
|
67
|
+
AGENT_USERNAME=$(echo "$AGENT_USER" | jq -r '.Username')
|
|
68
|
+
AGENT_USER_ID=$(echo "$AGENT_USER" | jq -r '.Id')
|
|
69
|
+
echo " Agent user found: $AGENT_USERNAME"
|
|
70
|
+
echo ""
|
|
71
|
+
|
|
72
|
+
# Check PSG assignment
|
|
73
|
+
PSG_ASSIGNED=$(sf data query \
|
|
74
|
+
--query "SELECT PermissionSetGroup.DeveloperName FROM PermissionSetAssignment WHERE AssigneeId = '${AGENT_USER_ID}' AND PermissionSetGroup.DeveloperName = 'SalesManagementAgentUserPsg'" \
|
|
75
|
+
--target-org "$ORG_ALIAS" \
|
|
76
|
+
--json 2>/dev/null | jq -r '.result.records[0] // empty' 2>/dev/null || echo "")
|
|
77
|
+
|
|
78
|
+
if [[ -n "$PSG_ASSIGNED" ]]; then
|
|
79
|
+
echo " PSG assigned: SalesManagementAgentUserPsg ✓"
|
|
80
|
+
else
|
|
81
|
+
echo " Warning: SalesManagementAgentUserPsg not assigned — attempting assignment..."
|
|
82
|
+
PSG_ID=$(sf data query \
|
|
83
|
+
--query "SELECT Id FROM PermissionSetGroup WHERE DeveloperName = 'SalesManagementAgentUserPsg'" \
|
|
84
|
+
--target-org "$ORG_ALIAS" \
|
|
85
|
+
--json 2>/dev/null | jq -r '.result.records[0].Id // empty')
|
|
86
|
+
if [[ -n "$PSG_ID" ]]; then
|
|
87
|
+
sf data create record --sobject PermissionSetAssignment \
|
|
88
|
+
--values "AssigneeId='${AGENT_USER_ID}' PermissionSetGroupId='${PSG_ID}'" \
|
|
89
|
+
--target-org "$ORG_ALIAS" --json 2>/dev/null >/dev/null \
|
|
90
|
+
&& echo " PSG assigned successfully ✓" \
|
|
91
|
+
|| echo " Assignment failed (may already be assigned)"
|
|
92
|
+
fi
|
|
93
|
+
fi
|
|
94
|
+
echo ""
|
|
95
|
+
|
|
96
|
+
# Determine architecture — match the bot by AgentTemplate (the field the
|
|
97
|
+
# scheduled flow uses), not by hardcoded DeveloperName.
|
|
98
|
+
echo "=== Architecture Detection ==="
|
|
99
|
+
EXISTING_BOT=$(pm_bot_developer_name "$ORG_ALIAS")
|
|
100
|
+
|
|
101
|
+
if [[ -n "$EXISTING_BOT" ]]; then
|
|
102
|
+
echo " Architecture: Standalone Bot (BotDefinition:$EXISTING_BOT matched by AgentTemplate)"
|
|
103
|
+
echo ""
|
|
104
|
+
|
|
105
|
+
# A BotDefinition can exist yet have no ACTIVE version — the state
|
|
106
|
+
# auto-provisioning leaves it in. Without an active version the scheduled
|
|
107
|
+
# flow never adds the agent user to opportunity teams (no suggestions) and
|
|
108
|
+
# Agent Access can't be defined. Activate the latest version if needed.
|
|
109
|
+
BOT_ACTIVE_COUNT=$(pm_bot_active_version_count "$ORG_ALIAS")
|
|
110
|
+
if [[ "$BOT_ACTIVE_COUNT" -ge 1 ]]; then
|
|
111
|
+
echo " BotVersion: active ✓"
|
|
112
|
+
else
|
|
113
|
+
echo " BotVersion: no active version — activating (auto-provisioned bots land Inactive)..."
|
|
114
|
+
if ! activate_pm_bot_if_inactive "$ORG_ALIAS"; then
|
|
115
|
+
echo ""
|
|
116
|
+
echo " BLOCKER: BotDefinition:$EXISTING_BOT exists but has no active version and activation failed."
|
|
117
|
+
echo " The scheduled flow will not generate suggestions until the agent is active."
|
|
118
|
+
echo " Resolve via Setup → Agents → $EXISTING_BOT → activate, then re-run: $0 $ORG_ALIAS"
|
|
119
|
+
exit 1
|
|
120
|
+
fi
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
echo ""
|
|
124
|
+
echo "Agent setup is FUNCTIONAL."
|
|
125
|
+
echo " - Agent user: $AGENT_USERNAME"
|
|
126
|
+
echo " - PSG: SalesManagementAgentUserPsg"
|
|
127
|
+
echo " - BotDefinition: $EXISTING_BOT (active)"
|
|
128
|
+
echo " - Schedule-triggered flow will run as this user"
|
|
129
|
+
echo ""
|
|
130
|
+
echo "No further agent creation/deployment needed."
|
|
131
|
+
define_agent_access "$ORG_ALIAS"
|
|
132
|
+
exit $?
|
|
133
|
+
else
|
|
134
|
+
echo " Architecture: Platform Copilot (no standalone BotDefinition found)"
|
|
135
|
+
echo " Attempting to create Sales Agent BotDefinition for user interaction..."
|
|
136
|
+
echo ""
|
|
137
|
+
|
|
138
|
+
# Use shared library function to publish and activate agent
|
|
139
|
+
if publish_and_activate_agent "$ORG_ALIAS" "exit" "plain"; then
|
|
140
|
+
echo ""
|
|
141
|
+
echo "Agent setup is COMPLETE."
|
|
142
|
+
echo " - Agent user: $AGENT_USERNAME"
|
|
143
|
+
echo " - PSG: SalesManagementAgentUserPsg"
|
|
144
|
+
echo " - BotDefinition: ${AGENT_API_NAME:-SalesAgent} (ACTIVE, version $AGENT_VERSION)"
|
|
145
|
+
echo " - Schedule-triggered flow will run as this user"
|
|
146
|
+
define_agent_access "$ORG_ALIAS"
|
|
147
|
+
exit $?
|
|
148
|
+
fi
|
|
149
|
+
# If function returned non-zero, it already exited (on-error="exit")
|
|
150
|
+
fi
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
# --- Step 2: No agent user found — need remediation ---
|
|
154
|
+
echo " Agent user NOT found."
|
|
155
|
+
echo ""
|
|
156
|
+
echo "=== Step 2: Attempting SOAP toggle to re-provision agent user + PSGs ==="
|
|
157
|
+
echo " (The toggle re-creates the agent user and permission set groups only."
|
|
158
|
+
echo " It does NOT create BotDefinition:SalesAgent — that comes from the bundle"
|
|
159
|
+
echo " publish in Step 3 below.)"
|
|
160
|
+
|
|
161
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
162
|
+
AUTH_INFO=$(sf org display --target-org "$ORG_ALIAS" --json 2>/dev/null)
|
|
163
|
+
ACCESS_TOKEN=$(echo "$AUTH_INFO" | jq -r '.result.accessToken')
|
|
164
|
+
INSTANCE_URL=$(echo "$AUTH_INFO" | jq -r '.result.instanceUrl')
|
|
165
|
+
|
|
166
|
+
# Newer CLI versions redact accessToken — use show-access-token fallback
|
|
167
|
+
if [[ -z "$ACCESS_TOKEN" || "$ACCESS_TOKEN" == "null" || "$ACCESS_TOKEN" == *"REDACTED"* ]]; then
|
|
168
|
+
ACCESS_TOKEN=$(echo "y" | sf org auth show-access-token --target-org "$ORG_ALIAS" --no-prompt --json 2>/dev/null | jq -r '.result.accessToken // empty')
|
|
169
|
+
fi
|
|
170
|
+
|
|
171
|
+
if [[ -z "$ACCESS_TOKEN" || "$ACCESS_TOKEN" == "null" ]]; then
|
|
172
|
+
echo "Error: Could not retrieve org credentials. Is the org authenticated?"
|
|
173
|
+
exit 1
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
# Pre-check: Is org in "partially enabled" state (PSGs exist but enableDealAgent=false)?
|
|
177
|
+
# In that state, the toggle is harmful — disable may succeed but re-enable will fail.
|
|
178
|
+
PM_READ=$(curl -s "${INSTANCE_URL}/services/Soap/m/64.0" \
|
|
179
|
+
-H "Content-Type: text/xml; charset=UTF-8" \
|
|
180
|
+
-H "SOAPAction: readMetadata" \
|
|
181
|
+
-d "<?xml version='1.0' encoding='utf-8'?>
|
|
182
|
+
<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:met='http://soap.sforce.com/2006/04/metadata'>
|
|
183
|
+
<soapenv:Header><met:SessionHeader><met:sessionId>${ACCESS_TOKEN}</met:sessionId></met:SessionHeader></soapenv:Header>
|
|
184
|
+
<soapenv:Body><met:readMetadata><met:type>SalesDealAgentSettings</met:type><met:fullNames>SalesDealAgent</met:fullNames></met:readMetadata></soapenv:Body>
|
|
185
|
+
</soapenv:Envelope>" 2>/dev/null | grep -o "<enableDealAgent>[^<]*" | grep -o "true\|false" || echo "")
|
|
186
|
+
|
|
187
|
+
# PSG existence does NOT count as a partial signal — SalesManagementUserPsg /
|
|
188
|
+
# SalesManagementAgentUserPsg ship with the Agentforce-for-Sales license and exist
|
|
189
|
+
# in never-configured orgs. The real partial signals (with enableDealAgent=false)
|
|
190
|
+
# are a cloned scheduled flow or a PM BotDefinition. (The agent user was already
|
|
191
|
+
# ruled out in Step 1 above.)
|
|
192
|
+
PM_FLOW_EXISTS=$(pm_flow_clone_exists "$ORG_ALIAS")
|
|
193
|
+
PM_BOT_EXISTS=$(pm_bot_count "$ORG_ALIAS")
|
|
194
|
+
|
|
195
|
+
if [[ "$PM_READ" != "true" && ( "${PM_FLOW_EXISTS:-0}" -ge 1 || "${PM_BOT_EXISTS:-0}" -ge 1 ) ]]; then
|
|
196
|
+
echo "Detected partial-enablement state: enableDealAgent reads false but PM components exist (flow=$PM_FLOW_EXISTS bot=$PM_BOT_EXISTS)."
|
|
197
|
+
echo ""
|
|
198
|
+
echo " The SOAP toggle is NOT safe in this state (re-enable may fail mid-provisioning)."
|
|
199
|
+
echo " This org was likely provisioned via org template."
|
|
200
|
+
echo ""
|
|
201
|
+
echo " To resolve:"
|
|
202
|
+
echo " 1. Open: ${INSTANCE_URL}/lightning/setup/PipelineManagement/home"
|
|
203
|
+
echo " 2. Enable Pipeline Management in the Setup UI"
|
|
204
|
+
echo " 3. Wait 2-5 minutes for agent user provisioning"
|
|
205
|
+
echo " 4. Re-run this script"
|
|
206
|
+
exit 0
|
|
207
|
+
fi
|
|
208
|
+
|
|
209
|
+
echo " Using SOAP toggle to re-provision agent user + PSGs (NOT the BotDefinition)..."
|
|
210
|
+
echo " WARNING: This will temporarily disable Pipeline Management (~40 seconds)."
|
|
211
|
+
echo ""
|
|
212
|
+
|
|
213
|
+
# Disable Pipeline Management
|
|
214
|
+
echo " Disabling Pipeline Management..."
|
|
215
|
+
DISABLE_RESPONSE=$(curl -s -X POST "${INSTANCE_URL}/services/Soap/m/64.0" \
|
|
216
|
+
-H "Content-Type: text/xml; charset=utf-8" \
|
|
217
|
+
-H "SOAPAction: update" \
|
|
218
|
+
-d "<?xml version='1.0' encoding='utf-8'?>
|
|
219
|
+
<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:met='http://soap.sforce.com/2006/04/metadata'>
|
|
220
|
+
<soapenv:Header><met:SessionHeader><met:sessionId>${ACCESS_TOKEN}</met:sessionId></met:SessionHeader></soapenv:Header>
|
|
221
|
+
<soapenv:Body><met:updateMetadata>
|
|
222
|
+
<met:metadata xsi:type='met:SalesDealAgentSettings' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
|
|
223
|
+
<met:fullName>SalesDealAgent</met:fullName>
|
|
224
|
+
<met:enableDealAgent>false</met:enableDealAgent>
|
|
225
|
+
</met:metadata>
|
|
226
|
+
</met:updateMetadata></soapenv:Body>
|
|
227
|
+
</soapenv:Envelope>")
|
|
228
|
+
|
|
229
|
+
if echo "$DISABLE_RESPONSE" | grep -q "<success>true</success>"; then
|
|
230
|
+
echo " Disabled successfully. Waiting 10 seconds..."
|
|
231
|
+
sleep 10
|
|
232
|
+
|
|
233
|
+
# Re-enable Pipeline Management
|
|
234
|
+
echo " Re-enabling Pipeline Management..."
|
|
235
|
+
ENABLE_RESPONSE=$(curl -s -X POST "${INSTANCE_URL}/services/Soap/m/64.0" \
|
|
236
|
+
-H "Content-Type: text/xml; charset=utf-8" \
|
|
237
|
+
-H "SOAPAction: update" \
|
|
238
|
+
-d "<?xml version='1.0' encoding='utf-8'?>
|
|
239
|
+
<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:met='http://soap.sforce.com/2006/04/metadata'>
|
|
240
|
+
<soapenv:Header><met:SessionHeader><met:sessionId>${ACCESS_TOKEN}</met:sessionId></met:SessionHeader></soapenv:Header>
|
|
241
|
+
<soapenv:Body><met:updateMetadata>
|
|
242
|
+
<met:metadata xsi:type='met:SalesDealAgentSettings' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
|
|
243
|
+
<met:fullName>SalesDealAgent</met:fullName>
|
|
244
|
+
<met:enableDealAgent>true</met:enableDealAgent>
|
|
245
|
+
<met:enableDealAgentAutoApproveAllTasks>false</met:enableDealAgentAutoApproveAllTasks>
|
|
246
|
+
</met:metadata>
|
|
247
|
+
</met:updateMetadata></soapenv:Body>
|
|
248
|
+
</soapenv:Envelope>")
|
|
249
|
+
|
|
250
|
+
if echo "$ENABLE_RESPONSE" | grep -q "<success>true</success>"; then
|
|
251
|
+
echo " Re-enabled successfully. Waiting 30 seconds for provisioning..."
|
|
252
|
+
sleep 30
|
|
253
|
+
else
|
|
254
|
+
echo " Error: Failed to re-enable Pipeline Management"
|
|
255
|
+
echo "$ENABLE_RESPONSE" | grep -o '<message>[^<]*</message>' | sed 's/<[^>]*>//g' | head -1 || true
|
|
256
|
+
exit 1
|
|
257
|
+
fi
|
|
258
|
+
else
|
|
259
|
+
ERR_MSG=$(echo "$DISABLE_RESPONSE" | grep -o '<message>[^<]*</message>' | sed 's/<[^>]*>//g' | head -1 || echo "unknown error")
|
|
260
|
+
echo " SOAP toggle failed: $ERR_MSG"
|
|
261
|
+
echo ""
|
|
262
|
+
fi
|
|
263
|
+
|
|
264
|
+
# Check if agent user was provisioned
|
|
265
|
+
AGENT_USER_CHECK=$(sf data query \
|
|
266
|
+
--query "SELECT Id, Username FROM User WHERE Username LIKE '%salesmanagementagentuser%'" \
|
|
267
|
+
--target-org "$ORG_ALIAS" \
|
|
268
|
+
--json 2>/dev/null | jq -r '.result.records[0].Username // empty' 2>/dev/null || echo "")
|
|
269
|
+
|
|
270
|
+
if [[ -n "$AGENT_USER_CHECK" ]]; then
|
|
271
|
+
echo ""
|
|
272
|
+
echo " Agent user provisioned: $AGENT_USER_CHECK"
|
|
273
|
+
echo " BotDefinition:SalesAgent is still missing — the toggle does not create it."
|
|
274
|
+
echo " Proceeding to Step 3 to publish the authoring bundle."
|
|
275
|
+
fi
|
|
276
|
+
|
|
277
|
+
# --- Step 3: Last resort — authoring bundle deployment ---
|
|
278
|
+
echo ""
|
|
279
|
+
echo "=== Step 3: Attempting authoring bundle deployment (last resort) ==="
|
|
280
|
+
|
|
281
|
+
# Use shared library function with return-on-error behavior
|
|
282
|
+
if publish_and_activate_agent "$ORG_ALIAS" "return" "plain"; then
|
|
283
|
+
echo " Agent deployed and activated via authoring bundle"
|
|
284
|
+
define_agent_access "$ORG_ALIAS"
|
|
285
|
+
exit $?
|
|
286
|
+
else
|
|
287
|
+
echo " Authoring bundle publish/activate failed"
|
|
288
|
+
fi
|
|
289
|
+
|
|
290
|
+
# --- All approaches failed ---
|
|
291
|
+
echo ""
|
|
292
|
+
echo "=== BLOCKER: Agent provisioning failed ==="
|
|
293
|
+
echo ""
|
|
294
|
+
echo " No agent user was created via any automated method."
|
|
295
|
+
echo " Suggestions cannot generate without the agent user."
|
|
296
|
+
echo ""
|
|
297
|
+
echo " Manual resolution:"
|
|
298
|
+
echo " 1. Open: ${INSTANCE_URL}/lightning/setup/PipelineManagement/home"
|
|
299
|
+
echo " 2. Disable Pipeline Management, wait 30 seconds, re-enable"
|
|
300
|
+
echo " 3. Wait 2-5 minutes for agent user provisioning"
|
|
301
|
+
echo " 4. Re-run: $0 $ORG_ALIAS"
|
|
302
|
+
exit 1
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Detect, create/deploy, and activate Pipeline Management suggestion processing flow
|
|
4
|
+
#
|
|
5
|
+
# Strategy (in order of preference):
|
|
6
|
+
# 1. Check if flow clone already exists (by SourceTemplateId or naming convention)
|
|
7
|
+
# 2. If missing: deploy from pre-retrieved template (assets/pipeline_management_flow.flow-meta.xml)
|
|
8
|
+
# 3. If deploy fails: instruct user to perform Setup UI "Save As" from managed template
|
|
9
|
+
# 4. If exists but inactive: activate via retrieve → transform → deploy
|
|
10
|
+
#
|
|
11
|
+
# The template (assets/) was retrieved from a live org with Pipeline Management enabled.
|
|
12
|
+
# It contains the complete flow logic including sourceTemplate reference, so the deployed
|
|
13
|
+
# flow registers as a proper clone of sales_pipe_mgmt__OppSuggGenSchFlow.
|
|
14
|
+
#
|
|
15
|
+
# Usage: ./create-flow.sh <org-alias>
|
|
16
|
+
|
|
17
|
+
set -euo pipefail
|
|
18
|
+
|
|
19
|
+
# sf CLI can emit ANSI color codes inside --json stdout, breaking jq parsing.
|
|
20
|
+
# 2>/dev/null only strips stderr; these env vars are the reliable fix (see PM notes).
|
|
21
|
+
export NO_COLOR=1
|
|
22
|
+
export FORCE_COLOR=0
|
|
23
|
+
|
|
24
|
+
# Cross-platform sed -i (macOS requires '' arg, GNU does not)
|
|
25
|
+
sed_inplace() {
|
|
26
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
27
|
+
sed -i '' "$@"
|
|
28
|
+
else
|
|
29
|
+
sed -i "$@"
|
|
30
|
+
fi
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
ORG_ALIAS="${1:-}"
|
|
34
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
35
|
+
|
|
36
|
+
if [[ -z "$ORG_ALIAS" ]]; then
|
|
37
|
+
echo "Error: Missing org alias"
|
|
38
|
+
echo "Usage: $0 <org-alias>"
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
echo "Pipeline Management Flow: Detect + Deploy + Activate"
|
|
43
|
+
echo ""
|
|
44
|
+
|
|
45
|
+
TEMPLATE_NAME="sales_pipe_mgmt__OppSuggGenSchFlow"
|
|
46
|
+
FLOW_API_NAME="Process_Field_Update_Suggestions"
|
|
47
|
+
|
|
48
|
+
# --- Detection ---
|
|
49
|
+
echo -n "Checking if flow clone exists... "
|
|
50
|
+
|
|
51
|
+
# Attempt 1: Query by SourceTemplateId (verified field on FlowDefinitionView in API v67.0)
|
|
52
|
+
EXISTING_QUERY=$(sf data query \
|
|
53
|
+
--query "SELECT Id, ApiName, IsActive, SourceTemplateId FROM FlowDefinitionView WHERE SourceTemplateId = '${TEMPLATE_NAME}' AND IsTemplate = false" \
|
|
54
|
+
--target-org "$ORG_ALIAS" \
|
|
55
|
+
--json 2>/dev/null)
|
|
56
|
+
|
|
57
|
+
EXISTING_FLOW=$(echo "$EXISTING_QUERY" | jq -r '.result.records[0].ApiName // empty' 2>/dev/null || echo "")
|
|
58
|
+
IS_ACTIVE=$(echo "$EXISTING_QUERY" | jq -r '.result.records[0].IsActive // empty' 2>/dev/null || echo "")
|
|
59
|
+
|
|
60
|
+
# Attempt 2: Fallback to naming convention match
|
|
61
|
+
if [[ -z "$EXISTING_FLOW" ]]; then
|
|
62
|
+
EXISTING_QUERY=$(sf data query \
|
|
63
|
+
--query "SELECT Id, ApiName, IsActive FROM FlowDefinitionView WHERE ApiName LIKE '%OppSuggGen%' AND IsTemplate = false" \
|
|
64
|
+
--target-org "$ORG_ALIAS" \
|
|
65
|
+
--json 2>/dev/null)
|
|
66
|
+
|
|
67
|
+
EXISTING_FLOW=$(echo "$EXISTING_QUERY" | jq -r '.result.records[0].ApiName // empty' 2>/dev/null || echo "")
|
|
68
|
+
IS_ACTIVE=$(echo "$EXISTING_QUERY" | jq -r '.result.records[0].IsActive // empty' 2>/dev/null || echo "")
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Attempt 3: Check by standard API name
|
|
72
|
+
if [[ -z "$EXISTING_FLOW" ]]; then
|
|
73
|
+
EXISTING_QUERY=$(sf data query \
|
|
74
|
+
--query "SELECT Id, ApiName, IsActive FROM FlowDefinitionView WHERE ApiName = '${FLOW_API_NAME}'" \
|
|
75
|
+
--target-org "$ORG_ALIAS" \
|
|
76
|
+
--json 2>/dev/null)
|
|
77
|
+
|
|
78
|
+
EXISTING_FLOW=$(echo "$EXISTING_QUERY" | jq -r '.result.records[0].ApiName // empty' 2>/dev/null || echo "")
|
|
79
|
+
IS_ACTIVE=$(echo "$EXISTING_QUERY" | jq -r '.result.records[0].IsActive // empty' 2>/dev/null || echo "")
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
# --- Flow Not Found: Deploy from Template ---
|
|
83
|
+
if [[ -z "$EXISTING_FLOW" ]]; then
|
|
84
|
+
echo "not found"
|
|
85
|
+
echo ""
|
|
86
|
+
|
|
87
|
+
TEMPLATE_FILE="$SCRIPT_DIR/../assets/pipeline_management_flow.flow-meta.xml"
|
|
88
|
+
|
|
89
|
+
if [[ -f "$TEMPLATE_FILE" ]]; then
|
|
90
|
+
echo "Deploying flow from pre-retrieved template..."
|
|
91
|
+
echo " Template: assets/pipeline_management_flow.flow-meta.xml"
|
|
92
|
+
echo " API Name: $FLOW_API_NAME"
|
|
93
|
+
echo ""
|
|
94
|
+
|
|
95
|
+
# Ensure sfdx-project.json exists
|
|
96
|
+
if [[ ! -f "sfdx-project.json" ]]; then
|
|
97
|
+
cat > sfdx-project.json << 'EOF'
|
|
98
|
+
{"packageDirectories": [{"path": "force-app", "default": true}], "sourceApiVersion": "67.0"}
|
|
99
|
+
EOF
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
FLOW_DIR="force-app/main/default/flows"
|
|
103
|
+
mkdir -p "$FLOW_DIR"
|
|
104
|
+
FLOW_FILE="${FLOW_DIR}/${FLOW_API_NAME}.flow-meta.xml"
|
|
105
|
+
cp "$TEMPLATE_FILE" "$FLOW_FILE"
|
|
106
|
+
|
|
107
|
+
# Update startDate to today
|
|
108
|
+
TODAY=$(date +%Y-%m-%d)
|
|
109
|
+
sed_inplace "s|<startDate>[^<]*</startDate>|<startDate>${TODAY}</startDate>|g" "$FLOW_FILE"
|
|
110
|
+
|
|
111
|
+
echo " Schedule start: $TODAY (daily at 11:55 UTC)"
|
|
112
|
+
echo " Status: Active"
|
|
113
|
+
echo ""
|
|
114
|
+
|
|
115
|
+
# Deploy
|
|
116
|
+
echo " Deploying..."
|
|
117
|
+
DEPLOY_RESULT=$(sf project deploy start --source-dir "$FLOW_FILE" --target-org "$ORG_ALIAS" --json 2>/dev/null || echo '{"status":1}')
|
|
118
|
+
|
|
119
|
+
if echo "$DEPLOY_RESULT" | jq -e '.status == 0' >/dev/null 2>&1; then
|
|
120
|
+
EXISTING_FLOW="$FLOW_API_NAME"
|
|
121
|
+
IS_ACTIVE="true"
|
|
122
|
+
echo " Deploy SUCCEEDED"
|
|
123
|
+
echo ""
|
|
124
|
+
echo "Flow '$FLOW_API_NAME' deployed and activated."
|
|
125
|
+
echo "Suggestions will generate daily at 11:55 UTC."
|
|
126
|
+
else
|
|
127
|
+
DEPLOY_ERR=$(echo "$DEPLOY_RESULT" | jq -r '.result.details.componentFailures[0].problem // .message // "unknown"' 2>/dev/null || echo "unknown")
|
|
128
|
+
echo " Deploy FAILED: $DEPLOY_ERR"
|
|
129
|
+
echo ""
|
|
130
|
+
echo "Falling back to manual Setup UI clone..."
|
|
131
|
+
echo ""
|
|
132
|
+
fi
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
# If still no flow, guide user through UI
|
|
136
|
+
if [[ -z "$EXISTING_FLOW" ]]; then
|
|
137
|
+
echo "ACTION REQUIRED: Clone the template manually via Setup UI."
|
|
138
|
+
echo ""
|
|
139
|
+
echo " The template flow is in the 'sales_pipe_mgmt' managed namespace."
|
|
140
|
+
echo ""
|
|
141
|
+
echo " Steps:"
|
|
142
|
+
echo " 1. Open Setup -> Flows"
|
|
143
|
+
echo " 2. Find 'Process Field Update Suggestions' (marked with template icon)"
|
|
144
|
+
echo " 3. Open the flow -> click 'Save As'"
|
|
145
|
+
echo " 4. Label: 'Process Field Update Suggestions' -> Save"
|
|
146
|
+
echo " 5. Click 'Activate' on the new flow"
|
|
147
|
+
echo " 6. Re-run this script to verify"
|
|
148
|
+
echo ""
|
|
149
|
+
exit 1
|
|
150
|
+
fi
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
# --- Flow Found ---
|
|
154
|
+
if [[ -n "$EXISTING_FLOW" ]]; then
|
|
155
|
+
echo "found: $EXISTING_FLOW (active: $IS_ACTIVE)"
|
|
156
|
+
echo ""
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
# --- Already Active ---
|
|
160
|
+
if [[ "$IS_ACTIVE" == "true" ]]; then
|
|
161
|
+
echo "Flow '$EXISTING_FLOW' is ACTIVE."
|
|
162
|
+
echo "Suggestions will generate on schedule. No action needed."
|
|
163
|
+
echo ""
|
|
164
|
+
echo "Done."
|
|
165
|
+
exit 0
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
# --- Exists But Inactive: Activate ---
|
|
169
|
+
echo "Flow '$EXISTING_FLOW' exists but is INACTIVE. Activating..."
|
|
170
|
+
echo ""
|
|
171
|
+
|
|
172
|
+
# Ensure sfdx-project.json exists for retrieve/deploy
|
|
173
|
+
if [[ ! -f "sfdx-project.json" ]]; then
|
|
174
|
+
cat > sfdx-project.json << 'EOF'
|
|
175
|
+
{"packageDirectories": [{"path": "force-app", "default": true}], "sourceApiVersion": "67.0"}
|
|
176
|
+
EOF
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
FLOW_DIR="force-app/main/default/flows"
|
|
180
|
+
mkdir -p "$FLOW_DIR"
|
|
181
|
+
|
|
182
|
+
# Retrieve the CLONE (not the template — the clone is in the org's namespace and IS retrievable)
|
|
183
|
+
echo " Retrieving flow metadata..."
|
|
184
|
+
sf project retrieve start \
|
|
185
|
+
--metadata "Flow:${EXISTING_FLOW}" \
|
|
186
|
+
--target-org "$ORG_ALIAS" \
|
|
187
|
+
--json 2>/dev/null >/dev/null || true
|
|
188
|
+
|
|
189
|
+
FLOW_FILE="${FLOW_DIR}/${EXISTING_FLOW}.flow-meta.xml"
|
|
190
|
+
|
|
191
|
+
if [[ ! -f "$FLOW_FILE" ]]; then
|
|
192
|
+
echo " Warning: Could not retrieve flow file."
|
|
193
|
+
echo " Activate manually: Setup -> Flows -> ${EXISTING_FLOW} -> Activate"
|
|
194
|
+
exit 1
|
|
195
|
+
fi
|
|
196
|
+
|
|
197
|
+
echo " Retrieved successfully."
|
|
198
|
+
|
|
199
|
+
# Transform status to Active
|
|
200
|
+
echo " Setting status to Active..."
|
|
201
|
+
sed_inplace 's|<status>Draft</status>|<status>Active</status>|g' "$FLOW_FILE"
|
|
202
|
+
sed_inplace 's|<status>Obsolete</status>|<status>Active</status>|g' "$FLOW_FILE"
|
|
203
|
+
|
|
204
|
+
# Deploy
|
|
205
|
+
echo " Deploying activated flow..."
|
|
206
|
+
DEPLOY_RESULT=$(sf project deploy start \
|
|
207
|
+
--metadata "Flow:${EXISTING_FLOW}" \
|
|
208
|
+
--target-org "$ORG_ALIAS" \
|
|
209
|
+
--json 2>/dev/null)
|
|
210
|
+
|
|
211
|
+
if echo "$DEPLOY_RESULT" | jq -e '.status == 0' >/dev/null 2>&1; then
|
|
212
|
+
echo " Deployed successfully."
|
|
213
|
+
else
|
|
214
|
+
ERROR_MSG=$(echo "$DEPLOY_RESULT" | jq -r '.message // .result.details.componentFailures[0].problem // "unknown error"' 2>/dev/null || echo "unknown error")
|
|
215
|
+
echo " Warning: Deploy may have failed: $ERROR_MSG"
|
|
216
|
+
echo " Activate manually: Setup -> Flows -> ${EXISTING_FLOW} -> Activate"
|
|
217
|
+
fi
|
|
218
|
+
|
|
219
|
+
echo ""
|
|
220
|
+
|
|
221
|
+
# --- Final Verification ---
|
|
222
|
+
echo "Verifying final state..."
|
|
223
|
+
sleep 2 # Brief propagation wait
|
|
224
|
+
|
|
225
|
+
VERIFY_RESULT=$(sf data query \
|
|
226
|
+
--query "SELECT ApiName, IsActive FROM FlowDefinitionView WHERE ApiName = '${EXISTING_FLOW}'" \
|
|
227
|
+
--target-org "$ORG_ALIAS" \
|
|
228
|
+
--json 2>/dev/null)
|
|
229
|
+
|
|
230
|
+
FINAL_ACTIVE=$(echo "$VERIFY_RESULT" | jq -r '.result.records[0].IsActive // "unknown"' 2>/dev/null || echo "unknown")
|
|
231
|
+
|
|
232
|
+
if [[ "$FINAL_ACTIVE" == "true" ]]; then
|
|
233
|
+
echo " Flow: $EXISTING_FLOW"
|
|
234
|
+
echo " Status: ACTIVE"
|
|
235
|
+
echo ""
|
|
236
|
+
echo "Flow activated successfully. Suggestions will generate on schedule."
|
|
237
|
+
else
|
|
238
|
+
echo " Flow: $EXISTING_FLOW"
|
|
239
|
+
echo " Status: $FINAL_ACTIVE"
|
|
240
|
+
echo ""
|
|
241
|
+
echo " Flow may need manual activation via Setup UI."
|
|
242
|
+
fi
|
|
243
|
+
|
|
244
|
+
echo ""
|
|
245
|
+
echo "Done."
|
|
246
|
+
echo ""
|
|
247
|
+
echo "Next steps:"
|
|
248
|
+
echo " 1. Verify agent is active (./create-agent.sh $ORG_ALIAS)"
|
|
249
|
+
echo " 2. Configure opportunity stages (see references/opportunity-stages.md)"
|
|
250
|
+
echo " 3. Wait for schedule to trigger, or test with manual notes/emails"
|