From c06d6386b8840a757147713ca518cf174ecf9523 Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Thu, 5 Feb 2026 15:03:19 -0700 Subject: [PATCH 01/25] fix: add agent preview start,send,end commands --- messages/agent.preview.end.md | 29 +++++++++++ messages/agent.preview.send.md | 29 +++++++++++ messages/agent.preview.start.md | 33 +++++++++++++ schemas/agent-preview-end.json | 19 +++++++ schemas/agent-preview-send.json | 23 +++++++++ schemas/agent-preview-start.json | 16 ++++++ src/commands/agent/preview/end.ts | 76 ++++++++++++++++++++++++++++ src/commands/agent/preview/send.ts | 75 ++++++++++++++++++++++++++++ src/commands/agent/preview/start.ts | 77 +++++++++++++++++++++++++++++ 9 files changed, 377 insertions(+) create mode 100644 messages/agent.preview.end.md create mode 100644 messages/agent.preview.send.md create mode 100644 messages/agent.preview.start.md create mode 100644 schemas/agent-preview-end.json create mode 100644 schemas/agent-preview-send.json create mode 100644 schemas/agent-preview-start.json create mode 100644 src/commands/agent/preview/end.ts create mode 100644 src/commands/agent/preview/send.ts create mode 100644 src/commands/agent/preview/start.ts diff --git a/messages/agent.preview.end.md b/messages/agent.preview.end.md new file mode 100644 index 00000000..9435ea38 --- /dev/null +++ b/messages/agent.preview.end.md @@ -0,0 +1,29 @@ +# summary + +End a preview session and get trace location (beta). + +# description + +End an existing preview session and print the local path where session traces are stored (.sfdx/agents/). Use the session ID returned by "agent preview start". Specify the same agent with --api-name or --authoring-bundle as used when starting the session; one is required. + +# flags.session-id.summary + +Session ID from "agent preview start" (required). + +# flags.api-name.summary + +API name or ID of the published agent. + +# flags.authoring-bundle.summary + +API name of the authoring bundle (Agent Script). + +# output.tracesPath + +Session traces: %s + +# examples + +- End a preview session: + + <%= config.bin %> <%= command.id %> --session-id --target-org my-dev-org diff --git a/messages/agent.preview.send.md b/messages/agent.preview.send.md new file mode 100644 index 00000000..b75bc787 --- /dev/null +++ b/messages/agent.preview.send.md @@ -0,0 +1,29 @@ +# summary + +Send a message in a preview session (beta). + +# description + +Send an utterance to an existing preview session and get the agent response. Use the session ID returned by "agent preview start". Specify the same agent with --api-name or --authoring-bundle as used when starting the session; one is required. + +# flags.session-id.summary + +Session ID from "agent preview start" (required). + +# flags.utterance.summary + +Utterance to send to the agent. + +# flags.api-name.summary + +API name or ID of the published agent. + +# flags.authoring-bundle.summary + +API name of the authoring bundle (Agent Script). + +# examples + +- Send a message to a preview session: + + <%= config.bin %> <%= command.id %> --session-id --utterance "What can you help me with?" --target-org my-dev-org diff --git a/messages/agent.preview.start.md b/messages/agent.preview.start.md new file mode 100644 index 00000000..e7f6a856 --- /dev/null +++ b/messages/agent.preview.start.md @@ -0,0 +1,33 @@ +# summary + +Start a programmatic preview session (beta). + +# description + +Start an agent preview session and get a session ID. Use the session ID with "agent preview send" and "agent preview end". Specify the agent with --api-name (published agent) or --authoring-bundle (Agent Script); one is required. Use --use-live-actions for live mode; otherwise preview uses mock (simulated) actions. + +# flags.api-name.summary + +API name or ID of the published agent. + +# flags.authoring-bundle.summary + +API name of the authoring bundle (Agent Script) to preview. + +# flags.use-live-actions.summary + +Use real actions in the org; if not specified, preview uses mock (simulated) actions. + +# output.sessionId + +Session ID: %s + +# examples + +- Start a preview session with an authoring bundle and use mock actions: + + <%= config.bin %> <%= command.id %> --authoring-bundle My_Agent_Bundle --target-org my-dev-org + +- Start a preview session with a published agent in live mode: + + <%= config.bin %> <%= command.id %> --api-name My_Published_Agent --use-live-actions --target-org my-dev-org diff --git a/schemas/agent-preview-end.json b/schemas/agent-preview-end.json new file mode 100644 index 00000000..96827c55 --- /dev/null +++ b/schemas/agent-preview-end.json @@ -0,0 +1,19 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/AgentPreviewEndResult", + "definitions": { + "AgentPreviewEndResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "sessionId": { + "type": "string" + }, + "tracesPath": { + "type": "string" + } + }, + "required": ["sessionId", "tracesPath"] + } + } +} diff --git a/schemas/agent-preview-send.json b/schemas/agent-preview-send.json new file mode 100644 index 00000000..baa4db99 --- /dev/null +++ b/schemas/agent-preview-send.json @@ -0,0 +1,23 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/AgentPreviewSendResult", + "definitions": { + "AgentPreviewSendResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "messages": { + "type": "array", + "items": { + "type": "object", + "properties": { + "message": { "type": "string" }, + "role": { "type": "string" } + } + } + } + }, + "required": ["messages"] + } + } +} diff --git a/schemas/agent-preview-start.json b/schemas/agent-preview-start.json new file mode 100644 index 00000000..b50b7b8b --- /dev/null +++ b/schemas/agent-preview-start.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/AgentPreviewStartResult", + "definitions": { + "AgentPreviewStartResult": { + "type": "object", + "additionalProperties": false, + "properties": { + "sessionId": { + "type": "string" + } + }, + "required": ["sessionId"] + } + } +} diff --git a/src/commands/agent/preview/end.ts b/src/commands/agent/preview/end.ts new file mode 100644 index 00000000..b17302e4 --- /dev/null +++ b/src/commands/agent/preview/end.ts @@ -0,0 +1,76 @@ +/* + * 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 { join } from 'node:path'; +import { Flags, SfCommand } from '@salesforce/sf-plugins-core'; +import { Messages } from '@salesforce/core'; +import { Agent, ProductionAgent, ScriptAgent } from '@salesforce/agents'; + +Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); +const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.preview.end'); + +export type AgentPreviewEndResult = { + sessionId: string; + tracesPath: string; +}; + +export default class AgentPreviewEnd extends SfCommand { + public static readonly summary = messages.getMessage('summary'); + public static readonly description = messages.getMessage('description'); + public static readonly examples = messages.getMessages('examples'); + public static readonly state = 'beta'; + public static readonly requiresProject = true; + + public static readonly flags = { + 'target-org': Flags.requiredOrg(), + 'api-version': Flags.orgApiVersion(), + 'session-id': Flags.string({ + summary: messages.getMessage('flags.session-id.summary'), + required: true, + }), + 'api-name': Flags.string({ + summary: messages.getMessage('flags.api-name.summary'), + char: 'n', + exactlyOne: ['api-name', 'authoring-bundle'], + }), + 'authoring-bundle': Flags.string({ + summary: messages.getMessage('flags.authoring-bundle.summary'), + exactlyOne: ['api-name', 'authoring-bundle'], + }), + }; + + public async run(): Promise { + const { flags } = await this.parse(AgentPreviewEnd); + const sessionId = flags['session-id']; + const projectPath = this.project!.getPath(); + + const conn = flags['target-org'].getConnection(flags['api-version']); + const agent = flags['authoring-bundle'] + ? await Agent.init({ connection: conn, project: this.project!, aabName: flags['authoring-bundle'] }) + : await Agent.init({ connection: conn, project: this.project!, apiNameOrId: flags['api-name']! }); + + if (agent instanceof ScriptAgent) { + await agent.preview.end(); + } else if (agent instanceof ProductionAgent) { + await agent.preview.end('UserRequest'); + } + + const tracesPath = join(projectPath, '.sfdx', 'agents', agent.getAgentIdForStorage(), 'sessions', sessionId); + const result = { sessionId, tracesPath }; + this.log(messages.getMessage('output.tracesPath', [tracesPath])); + return result; + } +} diff --git a/src/commands/agent/preview/send.ts b/src/commands/agent/preview/send.ts new file mode 100644 index 00000000..4836897d --- /dev/null +++ b/src/commands/agent/preview/send.ts @@ -0,0 +1,75 @@ +/* + * 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 { Flags, SfCommand } from '@salesforce/sf-plugins-core'; +import { Messages } from '@salesforce/core'; +import { Agent, ScriptAgent } from '@salesforce/agents'; + +Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); +const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.preview.send'); + +export type AgentPreviewSendResult = { + messages: Array<{ message?: string; role?: string }>; +}; + +export default class AgentPreviewSend extends SfCommand { + public static readonly summary = messages.getMessage('summary'); + public static readonly description = messages.getMessage('description'); + public static readonly examples = messages.getMessages('examples'); + public static readonly state = 'beta'; + public static readonly requiresProject = true; + + public static readonly flags = { + 'target-org': Flags.requiredOrg(), + 'api-version': Flags.orgApiVersion(), + 'session-id': Flags.string({ + summary: messages.getMessage('flags.session-id.summary'), + required: true, + }), + utterance: Flags.string({ + summary: messages.getMessage('flags.utterance.summary'), + required: true, + char: 'u', + }), + 'api-name': Flags.string({ + summary: messages.getMessage('flags.api-name.summary'), + char: 'n', + exactlyOne: ['api-name', 'authoring-bundle'], + }), + 'authoring-bundle': Flags.string({ + summary: messages.getMessage('flags.authoring-bundle.summary'), + exactlyOne: ['api-name', 'authoring-bundle'], + }), + }; + + public async run(): Promise { + const { flags } = await this.parse(AgentPreviewSend); + + const conn = flags['target-org'].getConnection(flags['api-version']); + const agent = flags['authoring-bundle'] + ? await Agent.init({ connection: conn, project: this.project!, aabName: flags['authoring-bundle'] }) + : await Agent.init({ connection: conn, project: this.project!, apiNameOrId: flags['api-name']! }); + if (agent instanceof ScriptAgent) { + agent.preview.setMockMode('Mock'); + } + + agent.setSessionId(flags['session-id']); + + const response = await agent.preview.send(flags.utterance); + this.log(response.messages[0].message); + return { messages: response.messages ?? [] }; + } +} diff --git a/src/commands/agent/preview/start.ts b/src/commands/agent/preview/start.ts new file mode 100644 index 00000000..2c3fbd9b --- /dev/null +++ b/src/commands/agent/preview/start.ts @@ -0,0 +1,77 @@ +/* + * 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 { Flags, SfCommand } from '@salesforce/sf-plugins-core'; +import { Lifecycle, Messages } from '@salesforce/core'; +import { Agent, ProductionAgent, ScriptAgent } from '@salesforce/agents'; + +Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); +const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.preview.start'); + +export type AgentPreviewStartResult = { + sessionId: string; +}; + +export default class AgentPreviewStart extends SfCommand { + public static readonly summary = messages.getMessage('summary'); + public static readonly description = messages.getMessage('description'); + public static readonly examples = messages.getMessages('examples'); + public static readonly state = 'beta'; + public static readonly requiresProject = true; + + public static readonly flags = { + 'target-org': Flags.requiredOrg(), + 'api-version': Flags.orgApiVersion(), + 'api-name': Flags.string({ + summary: messages.getMessage('flags.api-name.summary'), + char: 'n', + exactlyOne: ['api-name', 'authoring-bundle'], + }), + 'authoring-bundle': Flags.string({ + summary: messages.getMessage('flags.authoring-bundle.summary'), + exactlyOne: ['api-name', 'authoring-bundle'], + }), + 'use-live-actions': Flags.boolean({ + summary: messages.getMessage('flags.use-live-actions.summary'), + default: false, + }), + }; + + public async run(): Promise { + const { flags } = await this.parse(AgentPreviewStart); + const conn = flags['target-org'].getConnection(flags['api-version']); + const useLiveActions = flags['use-live-actions']; + + const agent = flags['authoring-bundle'] + ? await Agent.init({ connection: conn, project: this.project!, aabName: flags['authoring-bundle'] }) + : await Agent.init({ connection: conn, project: this.project!, apiNameOrId: flags['api-name']! }); + if (agent instanceof ScriptAgent) { + agent.preview.setMockMode(useLiveActions ? 'Live Test' : 'Mock'); + } + + if (useLiveActions && agent instanceof ProductionAgent) { + void Lifecycle.getInstance().emitWarning( + 'Published agents always use real actions; --use-live-actions has no effect for published agents.' + ); + } + + const session = await agent.preview.start(); + + const result: AgentPreviewStartResult = { sessionId: session.sessionId }; + this.log(messages.getMessage('output.sessionId', [session.sessionId])); + return result; + } +} From 4af0cf34f3a3169f15b53f1203846ad5a27b05a5 Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Thu, 5 Feb 2026 15:04:03 -0700 Subject: [PATCH 02/25] chore: snapshots and schemas --- command-snapshot.json | 33 ++++++++++++++++++++++++++++++++ schemas/agent-preview-end.json | 4 ++-- schemas/agent-preview-send.json | 15 ++++++++++----- schemas/agent-preview-start.json | 4 ++-- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/command-snapshot.json b/command-snapshot.json index bc0fe751..6ac3ec55 100644 --- a/command-snapshot.json +++ b/command-snapshot.json @@ -92,6 +92,39 @@ ], "plugin": "@salesforce/plugin-agent" }, + { + "alias": [], + "command": "agent:preview:end", + "flagAliases": [], + "flagChars": ["n", "o"], + "flags": ["api-name", "api-version", "authoring-bundle", "flags-dir", "json", "session-id", "target-org"], + "plugin": "@salesforce/plugin-agent" + }, + { + "alias": [], + "command": "agent:preview:send", + "flagAliases": [], + "flagChars": ["n", "o", "u"], + "flags": [ + "api-name", + "api-version", + "authoring-bundle", + "flags-dir", + "json", + "session-id", + "target-org", + "utterance" + ], + "plugin": "@salesforce/plugin-agent" + }, + { + "alias": [], + "command": "agent:preview:start", + "flagAliases": [], + "flagChars": ["n", "o"], + "flags": ["api-name", "api-version", "authoring-bundle", "flags-dir", "json", "target-org", "use-live-actions"], + "plugin": "@salesforce/plugin-agent" + }, { "alias": [], "command": "agent:publish:authoring-bundle", diff --git a/schemas/agent-preview-end.json b/schemas/agent-preview-end.json index 96827c55..9ce8737d 100644 --- a/schemas/agent-preview-end.json +++ b/schemas/agent-preview-end.json @@ -4,7 +4,6 @@ "definitions": { "AgentPreviewEndResult": { "type": "object", - "additionalProperties": false, "properties": { "sessionId": { "type": "string" @@ -13,7 +12,8 @@ "type": "string" } }, - "required": ["sessionId", "tracesPath"] + "required": ["sessionId", "tracesPath"], + "additionalProperties": false } } } diff --git a/schemas/agent-preview-send.json b/schemas/agent-preview-send.json index baa4db99..ad6d5d9a 100644 --- a/schemas/agent-preview-send.json +++ b/schemas/agent-preview-send.json @@ -4,20 +4,25 @@ "definitions": { "AgentPreviewSendResult": { "type": "object", - "additionalProperties": false, "properties": { "messages": { "type": "array", "items": { "type": "object", "properties": { - "message": { "type": "string" }, - "role": { "type": "string" } - } + "message": { + "type": "string" + }, + "role": { + "type": "string" + } + }, + "additionalProperties": false } } }, - "required": ["messages"] + "required": ["messages"], + "additionalProperties": false } } } diff --git a/schemas/agent-preview-start.json b/schemas/agent-preview-start.json index b50b7b8b..f608d52f 100644 --- a/schemas/agent-preview-start.json +++ b/schemas/agent-preview-start.json @@ -4,13 +4,13 @@ "definitions": { "AgentPreviewStartResult": { "type": "object", - "additionalProperties": false, "properties": { "sessionId": { "type": "string" } }, - "required": ["sessionId"] + "required": ["sessionId"], + "additionalProperties": false } } } From b6b86ccf82f62bb9243f9d17315229d6df072311 Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Thu, 5 Feb 2026 15:42:51 -0700 Subject: [PATCH 03/25] chore: add cache to valid session/agent combo for send/end --- src/commands/agent/preview/end.ts | 7 +++ src/commands/agent/preview/send.ts | 7 +++ src/commands/agent/preview/start.ts | 8 +++ src/previewSessionStore.ts | 95 +++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 src/previewSessionStore.ts diff --git a/src/commands/agent/preview/end.ts b/src/commands/agent/preview/end.ts index b17302e4..9d73b134 100644 --- a/src/commands/agent/preview/end.ts +++ b/src/commands/agent/preview/end.ts @@ -18,6 +18,7 @@ import { join } from 'node:path'; import { Flags, SfCommand } from '@salesforce/sf-plugins-core'; import { Messages } from '@salesforce/core'; import { Agent, ProductionAgent, ScriptAgent } from '@salesforce/agents'; +import { validatePreviewSession } from '../../../previewSessionStore.js'; Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.preview.end'); @@ -57,6 +58,12 @@ export default class AgentPreviewEnd extends SfCommand { const sessionId = flags['session-id']; const projectPath = this.project!.getPath(); + await validatePreviewSession(projectPath, sessionId, { + apiNameOrId: flags['api-name'], + aabName: flags['authoring-bundle'], + orgUsername: flags['target-org'].getUsername() ?? '', + }); + const conn = flags['target-org'].getConnection(flags['api-version']); const agent = flags['authoring-bundle'] ? await Agent.init({ connection: conn, project: this.project!, aabName: flags['authoring-bundle'] }) diff --git a/src/commands/agent/preview/send.ts b/src/commands/agent/preview/send.ts index 4836897d..87df0246 100644 --- a/src/commands/agent/preview/send.ts +++ b/src/commands/agent/preview/send.ts @@ -17,6 +17,7 @@ import { Flags, SfCommand } from '@salesforce/sf-plugins-core'; import { Messages } from '@salesforce/core'; import { Agent, ScriptAgent } from '@salesforce/agents'; +import { validatePreviewSession } from '../../../previewSessionStore.js'; Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.preview.send'); @@ -58,6 +59,12 @@ export default class AgentPreviewSend extends SfCommand public async run(): Promise { const { flags } = await this.parse(AgentPreviewSend); + await validatePreviewSession(this.project!.getPath(), flags['session-id'], { + apiNameOrId: flags['api-name'], + aabName: flags['authoring-bundle'], + orgUsername: flags['target-org'].getUsername() ?? '', + }); + const conn = flags['target-org'].getConnection(flags['api-version']); const agent = flags['authoring-bundle'] ? await Agent.init({ connection: conn, project: this.project!, aabName: flags['authoring-bundle'] }) diff --git a/src/commands/agent/preview/start.ts b/src/commands/agent/preview/start.ts index 2c3fbd9b..2cb9ffc1 100644 --- a/src/commands/agent/preview/start.ts +++ b/src/commands/agent/preview/start.ts @@ -17,6 +17,7 @@ import { Flags, SfCommand } from '@salesforce/sf-plugins-core'; import { Lifecycle, Messages } from '@salesforce/core'; import { Agent, ProductionAgent, ScriptAgent } from '@salesforce/agents'; +import { createCache } from '../../../previewSessionStore.js'; Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.preview.start'); @@ -70,6 +71,13 @@ export default class AgentPreviewStart extends SfCommand>; + +function getStorePath(projectPath: string): string { + return join(projectPath, CACHE_DIR, AGENTS_DIR, SESSIONS_FILE); +} + +/** + * Save a preview session so send/end can validate that the session was started with the same agent and org. + */ +export async function createCache(projectPath: string, entry: PreviewSessionEntry): Promise { + const dir = join(projectPath, CACHE_DIR, AGENTS_DIR); + await mkdir(dir, { recursive: true }); + const path = getStorePath(projectPath); + let store: SessionsStore = {}; + try { + const data = await readFile(path, 'utf-8'); + store = JSON.parse(data) as SessionsStore; + } catch { + // file missing or invalid + } + const { sessionId, ...rest } = entry; + store[sessionId] = rest; + await writeFile(path, JSON.stringify(store, null, 2), 'utf-8'); +} + +/** + * Validate that the given session was started with the specified agent and org. + * Throws SfError if the session is unknown or does not match. + */ +export async function validatePreviewSession( + projectPath: string, + sessionId: string, + agentAndOrg: { apiNameOrId?: string; aabName?: string; orgUsername: string } +): Promise { + const data = await readFile(getStorePath(projectPath), 'utf-8'); + const store = JSON.parse(data) as SessionsStore; + const entry = store[sessionId]; + if (!entry) { + throw new SfError( + `No preview session found for session ID "${sessionId}". Run "sf agent preview start" first.`, + 'PreviewSessionNotFound' + ); + } + if (entry.orgUsername !== agentAndOrg.orgUsername) { + throw new SfError( + `Session ${sessionId} was started with a different target org. Use --target-org ${entry.orgUsername} for this session.`, + 'PreviewSessionOrgMismatch' + ); + } + const entryAgent = entry.aabName ? `--authoring-bundle ${entry.aabName}` : `--api-name ${entry.apiNameOrId ?? ''}`; + if (entry.aabName) { + if (agentAndOrg.aabName !== entry.aabName) { + throw new SfError( + `Session ${sessionId} was started with ${entryAgent}. Use the same agent for send/end.`, + 'PreviewSessionAgentMismatch' + ); + } + } else if (agentAndOrg.apiNameOrId !== entry.apiNameOrId) { + throw new SfError( + `Session ${sessionId} was started with ${entryAgent}. Use the same agent for send/end.`, + 'PreviewSessionAgentMismatch' + ); + } +} From 08278c29fd0677fe46a3948cf4ef7c14e6e7f46e Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Thu, 5 Feb 2026 16:12:12 -0700 Subject: [PATCH 04/25] test: add UT/NUT --- src/previewSessionStore.ts | 10 +- test/nuts/z3.agent.preview.nut.ts | 154 +++++++++----------- test/previewSessionStore.test.ts | 235 ++++++++++++++++++++++++++++++ 3 files changed, 316 insertions(+), 83 deletions(-) create mode 100644 test/previewSessionStore.test.ts diff --git a/src/previewSessionStore.ts b/src/previewSessionStore.ts index 02d6e150..8c5e4ed9 100644 --- a/src/previewSessionStore.ts +++ b/src/previewSessionStore.ts @@ -63,7 +63,15 @@ export async function validatePreviewSession( sessionId: string, agentAndOrg: { apiNameOrId?: string; aabName?: string; orgUsername: string } ): Promise { - const data = await readFile(getStorePath(projectPath), 'utf-8'); + let data: string; + try { + data = await readFile(getStorePath(projectPath), 'utf-8'); + } catch { + throw new SfError( + `No preview session found for session ID "${sessionId}". Run "sf agent preview start" first.`, + 'PreviewSessionNotFound' + ); + } const store = JSON.parse(data) as SessionsStore; const entry = store[sessionId]; if (!entry) { diff --git a/test/nuts/z3.agent.preview.nut.ts b/test/nuts/z3.agent.preview.nut.ts index dc7b15da..cd1f251c 100644 --- a/test/nuts/z3.agent.preview.nut.ts +++ b/test/nuts/z3.agent.preview.nut.ts @@ -17,7 +17,10 @@ import { expect } from 'chai'; import { execCmd, TestSession } from '@salesforce/cli-plugins-testkit'; import { Agent } from '@salesforce/agents'; -import { Org, SfProject } from '@salesforce/core'; +import { Org } from '@salesforce/core'; +import type { AgentPreviewStartResult } from '../../src/commands/agent/preview/start.js'; +import type { AgentPreviewSendResult } from '../../src/commands/agent/preview/send.js'; +import type { AgentPreviewEndResult } from '../../src/commands/agent/preview/end.js'; import { getTestSession, getUsername } from './shared-setup.js'; /* eslint-disable no-console */ @@ -42,110 +45,97 @@ describe('agent preview', function () { execCmd(`agent preview --api-name ${invalidApiName} --target-org ${getUsername()}`, { ensureExitCode: 1 }); }); - describe('using agent library directly', function () { - it("should start,send,end a preview (AgentScript, preview API, mockMode = 'Mock'", async () => { + describe('using preview start/send/end commands', () => { + it('should start, send, end a preview (Agent Script, mock mode)', async function () { this.timeout(5 * 60 * 1000); // 5 minutes for this test const bundleApiName = 'Willie_Resort_Manager'; - const projectPath = session.project.dir; - - const org = await Org.create({ aliasOrUsername: getUsername() }); - const connection = org.getConnection(); - const project = await SfProject.resolve(projectPath); - - const agent = await Agent.init({ - connection, - project, - aabName: bundleApiName, - }); - - agent.preview.setMockMode('Mock'); - - // Start session - const previewSession = await agent.preview.start(); - expect(previewSession.sessionId).to.be.a('string'); - - // Send first message - const response1 = await agent.preview.send('What can you help me with?'); - expect(response1.messages).to.be.an('array').with.length.greaterThan(0); - - // Send second message - const response2 = await agent.preview.send('Tell me more'); - expect(response2.messages).to.be.an('array').with.length.greaterThan(0); - - // End session - await agent.preview.end(); + const targetOrg = getUsername(); + + const startResult = execCmd( + `agent preview start --authoring-bundle ${bundleApiName} --target-org ${targetOrg} --json` + ).jsonOutput?.result; + expect(startResult?.sessionId).to.be.a('string'); + const sessionId = startResult!.sessionId; + + const sendResult1 = execCmd( + `agent preview send --session-id ${sessionId} --authoring-bundle ${bundleApiName} --utterance "What can you help me with?" --target-org ${targetOrg} --json` + ).jsonOutput?.result; + expect(sendResult1?.messages).to.be.an('array').with.length.greaterThan(0); + + const sendResult2 = execCmd( + `agent preview send --session-id ${sessionId} --authoring-bundle ${bundleApiName} --utterance "Tell me more" --target-org ${targetOrg} --json` + ).jsonOutput?.result; + expect(sendResult2?.messages).to.be.an('array').with.length.greaterThan(0); + + const endResult = execCmd( + `agent preview end --session-id ${sessionId} --authoring-bundle ${bundleApiName} --target-org ${targetOrg} --json` + ).jsonOutput?.result; + expect(endResult?.sessionId).to.equal(sessionId); + expect(endResult?.tracesPath).to.be.a('string').and.include('.sfdx').and.include('agents'); }); - it("should start,send,end a preview (AgentScript, preview API, mockMode = 'Live Test'", async () => { + + it('should start, send, end a preview (Agent Script, live mode)', async function () { this.timeout(5 * 60 * 1000); // 5 minutes for this test const bundleApiName = 'Willie_Resort_Manager'; - const projectPath = session.project.dir; - - const org = await Org.create({ aliasOrUsername: getUsername() }); - const connection = org.getConnection(); - const project = await SfProject.resolve(projectPath); - - const agent = await Agent.init({ - connection, - project, - aabName: bundleApiName, - }); - - // Start session - const previewSession = await agent.preview.start(); - expect(previewSession.sessionId).to.be.a('string'); + const targetOrg = getUsername(); - // Send first message - const response1 = await agent.preview.send('What can you help me with?'); - expect(response1.messages).to.be.an('array').with.length.greaterThan(0); + const startResult = execCmd( + `agent preview start --authoring-bundle ${bundleApiName} --use-live-actions --target-org ${targetOrg} --json` + ).jsonOutput?.result; + expect(startResult?.sessionId).to.be.a('string'); + const sessionId = startResult!.sessionId; - // Send second message - const response2 = await agent.preview.send('Tell me more'); - expect(response2.messages).to.be.an('array').with.length.greaterThan(0); + const sendResult1 = execCmd( + `agent preview send --session-id ${sessionId} --authoring-bundle ${bundleApiName} --utterance "What can you help me with?" --target-org ${targetOrg} --json` + ).jsonOutput?.result; + expect(sendResult1?.messages).to.be.an('array').with.length.greaterThan(0); - // End session - await agent.preview.end(); + execCmd( + `agent preview end --session-id ${sessionId} --authoring-bundle ${bundleApiName} --target-org ${targetOrg} --json` + ); }); - it('should start,send,end a preview (Published) session', async () => { + it('should start, send, end a preview (Published agent)', async function () { this.timeout(5 * 60 * 1000); // 5 minutes for this test const org = await Org.create({ aliasOrUsername: getUsername() }); const connection = org.getConnection(); - const project = await SfProject.resolve(session.project.dir); - // Find the published agent from the publish test (starts with "Test_Agent_") const publishedAgents = await Agent.listRemote(connection); - const publishedAgent = publishedAgents.find((agent) => agent.DeveloperName?.startsWith('Test_Agent_')); - + const publishedAgent = publishedAgents.find((a) => a.DeveloperName?.startsWith('Test_Agent_')); expect(publishedAgent).to.not.be.undefined; expect(publishedAgent?.DeveloperName).to.be.a('string'); - // Query the Bot object to get the Id - const botResult = await connection.singleRecordQuery<{ Id: string }>( - `SELECT ID FROM BotDefinition WHERE DeveloperName = '${publishedAgent!.DeveloperName}'` - ); - - expect(botResult).to.not.be.undefined; - expect(botResult.Id).to.be.a('string').and.not.be.empty; - - // Initialize the published agent using its Bot Id - const agent = await Agent.init({ - connection, - project, - apiNameOrId: botResult.Id, + // Activate published agent before previewing + execCmd(`agent activate --api-name ${publishedAgent!.DeveloperName} --target-org ${getUsername()} --json`, { + ensureExitCode: 0, + cwd: session.project.dir, }); - // gotta activate published agents before previewing - await agent.activate(); - - // Start session - const previewSession = await agent.preview.start(); - expect(previewSession.sessionId).to.be.a('string'); - - const response = await agent.preview.send('What can you help me with?'); - expect(response.messages).to.be.an('array').with.length.greaterThan(0); + const targetOrg = getUsername(); + + const startResult = execCmd( + `agent preview start --api-name ${publishedAgent!.DeveloperName} --target-org ${targetOrg} --json` + ).jsonOutput?.result; + expect(startResult?.sessionId).to.be.a('string'); + const sessionId = startResult!.sessionId; + + const sendResult = execCmd( + `agent preview send --session-id ${sessionId} --api-name ${ + publishedAgent!.DeveloperName + } --utterance "What can you help me with?" --target-org ${targetOrg} --json` + ).jsonOutput?.result; + expect(sendResult?.messages).to.be.an('array').with.length.greaterThan(0); + + const endResult = execCmd( + `agent preview end --session-id ${sessionId} --api-name ${ + publishedAgent!.DeveloperName + } --target-org ${targetOrg} --json` + ).jsonOutput?.result; + expect(endResult?.sessionId).to.equal(sessionId); + expect(endResult?.tracesPath).to.be.a('string'); }); }); }); diff --git a/test/previewSessionStore.test.ts b/test/previewSessionStore.test.ts new file mode 100644 index 00000000..d33bf1a0 --- /dev/null +++ b/test/previewSessionStore.test.ts @@ -0,0 +1,235 @@ +/* + * 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 { mkdtempSync, rmSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { expect } from 'chai'; +import { SfError } from '@salesforce/core'; +import { createCache, validatePreviewSession } from '../src/previewSessionStore.js'; + +describe('previewSessionStore', () => { + let projectPath: string; + + beforeEach(() => { + projectPath = mkdtempSync(join(tmpdir(), 'preview-session-store-')); + }); + + afterEach(() => { + rmSync(projectPath, { recursive: true, force: true }); + }); + + describe('createCache', () => { + it('saves session with authoring-bundle', async () => { + await createCache(projectPath, { + sessionId: 'sess-1', + orgUsername: 'user@org.com', + aabName: 'My_Bundle', + }); + await validatePreviewSession(projectPath, 'sess-1', { + aabName: 'My_Bundle', + orgUsername: 'user@org.com', + }); + }); + + it('saves session with api-name', async () => { + await createCache(projectPath, { + sessionId: 'sess-2', + orgUsername: 'user@org.com', + apiNameOrId: 'My_Published_Agent', + }); + await validatePreviewSession(projectPath, 'sess-2', { + apiNameOrId: 'My_Published_Agent', + orgUsername: 'user@org.com', + }); + }); + + it('allows multiple sessions in same store', async () => { + await createCache(projectPath, { + sessionId: 'sess-a', + orgUsername: 'user@org.com', + aabName: 'Bundle_A', + }); + await createCache(projectPath, { + sessionId: 'sess-b', + orgUsername: 'user@org.com', + apiNameOrId: 'Agent_B', + }); + await validatePreviewSession(projectPath, 'sess-a', { + aabName: 'Bundle_A', + orgUsername: 'user@org.com', + }); + await validatePreviewSession(projectPath, 'sess-b', { + apiNameOrId: 'Agent_B', + orgUsername: 'user@org.com', + }); + }); + }); + + describe('validatePreviewSession', () => { + it('throws PreviewSessionNotFound when store file does not exist', async () => { + try { + await validatePreviewSession(projectPath, 'unknown-sess', { + aabName: 'My_Bundle', + orgUsername: 'user@org.com', + }); + expect.fail('Expected validatePreviewSession to throw'); + } catch (e) { + expect(e).to.be.instanceOf(SfError); + expect((e as SfError).name).to.equal('PreviewSessionNotFound'); + expect((e as SfError).message).to.include('No preview session found'); + expect((e as SfError).message).to.include('unknown-sess'); + } + }); + + it('throws PreviewSessionNotFound when session id not in store', async () => { + await createCache(projectPath, { + sessionId: 'sess-1', + orgUsername: 'user@org.com', + aabName: 'My_Bundle', + }); + try { + await validatePreviewSession(projectPath, 'other-sess', { + aabName: 'My_Bundle', + orgUsername: 'user@org.com', + }); + expect.fail('Expected validatePreviewSession to throw'); + } catch (e) { + expect(e).to.be.instanceOf(SfError); + expect((e as SfError).name).to.equal('PreviewSessionNotFound'); + } + }); + + it('throws PreviewSessionOrgMismatch when org differs', async () => { + await createCache(projectPath, { + sessionId: 'sess-1', + orgUsername: 'user@org-a.com', + aabName: 'My_Bundle', + }); + try { + await validatePreviewSession(projectPath, 'sess-1', { + aabName: 'My_Bundle', + orgUsername: 'user@org-b.com', + }); + expect.fail('Expected validatePreviewSession to throw'); + } catch (e) { + expect(e).to.be.instanceOf(SfError); + expect((e as SfError).name).to.equal('PreviewSessionOrgMismatch'); + expect((e as SfError).message).to.include('different target org'); + expect((e as SfError).message).to.include('user@org-a.com'); + } + }); + + it('throws PreviewSessionAgentMismatch when authoring-bundle differs', async () => { + await createCache(projectPath, { + sessionId: 'sess-1', + orgUsername: 'user@org.com', + aabName: 'Bundle_A', + }); + try { + await validatePreviewSession(projectPath, 'sess-1', { + aabName: 'Bundle_B', + orgUsername: 'user@org.com', + }); + expect.fail('Expected validatePreviewSession to throw'); + } catch (e) { + expect(e).to.be.instanceOf(SfError); + expect((e as SfError).name).to.equal('PreviewSessionAgentMismatch'); + expect((e as SfError).message).to.include('Session sess-1 was started with'); + expect((e as SfError).message).to.include('Bundle_A'); + } + }); + + it('throws PreviewSessionAgentMismatch when api-name differs', async () => { + await createCache(projectPath, { + sessionId: 'sess-1', + orgUsername: 'user@org.com', + apiNameOrId: 'Agent_A', + }); + try { + await validatePreviewSession(projectPath, 'sess-1', { + apiNameOrId: 'Agent_B', + orgUsername: 'user@org.com', + }); + expect.fail('Expected validatePreviewSession to throw'); + } catch (e) { + expect(e).to.be.instanceOf(SfError); + expect((e as SfError).name).to.equal('PreviewSessionAgentMismatch'); + expect((e as SfError).message).to.include('Agent_A'); + } + }); + + it('throws when session was started with authoring-bundle but send uses api-name', async () => { + await createCache(projectPath, { + sessionId: 'sess-1', + orgUsername: 'user@org.com', + aabName: 'My_Bundle', + }); + try { + await validatePreviewSession(projectPath, 'sess-1', { + apiNameOrId: 'Some_Agent', + orgUsername: 'user@org.com', + }); + expect.fail('Expected validatePreviewSession to throw'); + } catch (e) { + expect(e).to.be.instanceOf(SfError); + expect((e as SfError).name).to.equal('PreviewSessionAgentMismatch'); + } + }); + + it('throws when session was started with api-name but send uses authoring-bundle', async () => { + await createCache(projectPath, { + sessionId: 'sess-1', + orgUsername: 'user@org.com', + apiNameOrId: 'My_Agent', + }); + try { + await validatePreviewSession(projectPath, 'sess-1', { + aabName: 'Some_Bundle', + orgUsername: 'user@org.com', + }); + expect.fail('Expected validatePreviewSession to throw'); + } catch (e) { + expect(e).to.be.instanceOf(SfError); + expect((e as SfError).name).to.equal('PreviewSessionAgentMismatch'); + } + }); + + it('succeeds when agent and org match (authoring-bundle)', async () => { + await createCache(projectPath, { + sessionId: 'sess-1', + orgUsername: 'user@org.com', + aabName: 'My_Bundle', + }); + await validatePreviewSession(projectPath, 'sess-1', { + aabName: 'My_Bundle', + orgUsername: 'user@org.com', + }); + }); + + it('succeeds when agent and org match (api-name)', async () => { + await createCache(projectPath, { + sessionId: 'sess-1', + orgUsername: 'user@org.com', + apiNameOrId: 'My_Agent', + }); + await validatePreviewSession(projectPath, 'sess-1', { + apiNameOrId: 'My_Agent', + orgUsername: 'user@org.com', + }); + }); + }); +}); From d4d876e7e4fa49d0f83be53a4dae2dabbb5a5563 Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Thu, 5 Feb 2026 16:47:58 -0700 Subject: [PATCH 05/25] chore: refactor cache, src only --- src/commands/agent/preview/end.ts | 15 ++--- src/commands/agent/preview/send.ts | 7 +-- src/commands/agent/preview/start.ts | 8 +-- src/previewSessionStore.ts | 87 ++++++----------------------- 4 files changed, 24 insertions(+), 93 deletions(-) diff --git a/src/commands/agent/preview/end.ts b/src/commands/agent/preview/end.ts index 9d73b134..4a047cfc 100644 --- a/src/commands/agent/preview/end.ts +++ b/src/commands/agent/preview/end.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { join } from 'node:path'; import { Flags, SfCommand } from '@salesforce/sf-plugins-core'; import { Messages } from '@salesforce/core'; import { Agent, ProductionAgent, ScriptAgent } from '@salesforce/agents'; @@ -56,26 +55,22 @@ export default class AgentPreviewEnd extends SfCommand { public async run(): Promise { const { flags } = await this.parse(AgentPreviewEnd); const sessionId = flags['session-id']; - const projectPath = this.project!.getPath(); - - await validatePreviewSession(projectPath, sessionId, { - apiNameOrId: flags['api-name'], - aabName: flags['authoring-bundle'], - orgUsername: flags['target-org'].getUsername() ?? '', - }); const conn = flags['target-org'].getConnection(flags['api-version']); const agent = flags['authoring-bundle'] ? await Agent.init({ connection: conn, project: this.project!, aabName: flags['authoring-bundle'] }) : await Agent.init({ connection: conn, project: this.project!, apiNameOrId: flags['api-name']! }); + agent.setSessionId(sessionId); + await validatePreviewSession(agent); + + const tracesPath = await (agent as unknown as { getHistoryDir(): Promise }).getHistoryDir(); + if (agent instanceof ScriptAgent) { await agent.preview.end(); } else if (agent instanceof ProductionAgent) { await agent.preview.end('UserRequest'); } - - const tracesPath = join(projectPath, '.sfdx', 'agents', agent.getAgentIdForStorage(), 'sessions', sessionId); const result = { sessionId, tracesPath }; this.log(messages.getMessage('output.tracesPath', [tracesPath])); return result; diff --git a/src/commands/agent/preview/send.ts b/src/commands/agent/preview/send.ts index 87df0246..e604d811 100644 --- a/src/commands/agent/preview/send.ts +++ b/src/commands/agent/preview/send.ts @@ -59,12 +59,6 @@ export default class AgentPreviewSend extends SfCommand public async run(): Promise { const { flags } = await this.parse(AgentPreviewSend); - await validatePreviewSession(this.project!.getPath(), flags['session-id'], { - apiNameOrId: flags['api-name'], - aabName: flags['authoring-bundle'], - orgUsername: flags['target-org'].getUsername() ?? '', - }); - const conn = flags['target-org'].getConnection(flags['api-version']); const agent = flags['authoring-bundle'] ? await Agent.init({ connection: conn, project: this.project!, aabName: flags['authoring-bundle'] }) @@ -74,6 +68,7 @@ export default class AgentPreviewSend extends SfCommand } agent.setSessionId(flags['session-id']); + await validatePreviewSession(agent); const response = await agent.preview.send(flags.utterance); this.log(response.messages[0].message); diff --git a/src/commands/agent/preview/start.ts b/src/commands/agent/preview/start.ts index 2cb9ffc1..36c4e2f0 100644 --- a/src/commands/agent/preview/start.ts +++ b/src/commands/agent/preview/start.ts @@ -70,13 +70,7 @@ export default class AgentPreviewStart extends SfCommand>; - -function getStorePath(projectPath: string): string { - return join(projectPath, CACHE_DIR, AGENTS_DIR, SESSIONS_FILE); -} +const SESSION_META_FILE = 'session-meta.json'; /** - * Save a preview session so send/end can validate that the session was started with the same agent and org. + * Save a marker so send/end can validate that the session was started for this agent. + * Caller must have started the session (agent has sessionId set). Uses agent.getHistoryDir() for the path. */ -export async function createCache(projectPath: string, entry: PreviewSessionEntry): Promise { - const dir = join(projectPath, CACHE_DIR, AGENTS_DIR); - await mkdir(dir, { recursive: true }); - const path = getStorePath(projectPath); - let store: SessionsStore = {}; - try { - const data = await readFile(path, 'utf-8'); - store = JSON.parse(data) as SessionsStore; - } catch { - // file missing or invalid - } - const { sessionId, ...rest } = entry; - store[sessionId] = rest; - await writeFile(path, JSON.stringify(store, null, 2), 'utf-8'); +export async function createCache(agent: AgentInstance): Promise { + const historyDir = await agent.getHistoryDir(); + const path = join(historyDir, SESSION_META_FILE); + await writeFile(path, JSON.stringify({}), 'utf-8'); } /** - * Validate that the given session was started with the specified agent and org. - * Throws SfError if the session is unknown or does not match. + * Validate that the session was started for this agent (marker file exists in agent's history dir for current sessionId). + * Caller must set sessionId on the agent (agent.setSessionId) before calling. + * Throws SfError if the session marker is not found. */ -export async function validatePreviewSession( - projectPath: string, - sessionId: string, - agentAndOrg: { apiNameOrId?: string; aabName?: string; orgUsername: string } -): Promise { - let data: string; +export async function validatePreviewSession(agent: AgentInstance): Promise { + const historyDir = await agent.getHistoryDir(); + const path = join(historyDir, SESSION_META_FILE); try { - data = await readFile(getStorePath(projectPath), 'utf-8'); + await readFile(path, 'utf-8'); } catch { throw new SfError( - `No preview session found for session ID "${sessionId}". Run "sf agent preview start" first.`, + 'No preview session found for this session ID. Run "sf agent preview start" first.', 'PreviewSessionNotFound' ); } - const store = JSON.parse(data) as SessionsStore; - const entry = store[sessionId]; - if (!entry) { - throw new SfError( - `No preview session found for session ID "${sessionId}". Run "sf agent preview start" first.`, - 'PreviewSessionNotFound' - ); - } - if (entry.orgUsername !== agentAndOrg.orgUsername) { - throw new SfError( - `Session ${sessionId} was started with a different target org. Use --target-org ${entry.orgUsername} for this session.`, - 'PreviewSessionOrgMismatch' - ); - } - const entryAgent = entry.aabName ? `--authoring-bundle ${entry.aabName}` : `--api-name ${entry.apiNameOrId ?? ''}`; - if (entry.aabName) { - if (agentAndOrg.aabName !== entry.aabName) { - throw new SfError( - `Session ${sessionId} was started with ${entryAgent}. Use the same agent for send/end.`, - 'PreviewSessionAgentMismatch' - ); - } - } else if (agentAndOrg.apiNameOrId !== entry.apiNameOrId) { - throw new SfError( - `Session ${sessionId} was started with ${entryAgent}. Use the same agent for send/end.`, - 'PreviewSessionAgentMismatch' - ); - } } From b1dbad7b1efb1aeffe4574ab0ad41c43b4268f71 Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Thu, 5 Feb 2026 16:51:17 -0700 Subject: [PATCH 06/25] test: fix UT --- test/previewSessionStore.test.ts | 224 +++++++------------------------ 1 file changed, 50 insertions(+), 174 deletions(-) diff --git a/test/previewSessionStore.test.ts b/test/previewSessionStore.test.ts index d33bf1a0..bd594833 100644 --- a/test/previewSessionStore.test.ts +++ b/test/previewSessionStore.test.ts @@ -21,6 +21,23 @@ import { expect } from 'chai'; import { SfError } from '@salesforce/core'; import { createCache, validatePreviewSession } from '../src/previewSessionStore.js'; +function makeMockAgent(baseDir: string, agentId: string) { + let sessionId: string | undefined; + const agent = { + setSessionId(id: string) { + sessionId = id; + }, + async getHistoryDir(): Promise { + if (!sessionId) throw new Error('sessionId not set'); + const dir = join(baseDir, 'agents', agentId, 'sessions', sessionId); + const { mkdir } = await import('node:fs/promises'); + await mkdir(dir, { recursive: true }); + return dir; + }, + }; + return agent; +} + describe('previewSessionStore', () => { let projectPath: string; @@ -33,79 +50,49 @@ describe('previewSessionStore', () => { }); describe('createCache', () => { - it('saves session with authoring-bundle', async () => { - await createCache(projectPath, { - sessionId: 'sess-1', - orgUsername: 'user@org.com', - aabName: 'My_Bundle', - }); - await validatePreviewSession(projectPath, 'sess-1', { - aabName: 'My_Bundle', - orgUsername: 'user@org.com', - }); - }); - - it('saves session with api-name', async () => { - await createCache(projectPath, { - sessionId: 'sess-2', - orgUsername: 'user@org.com', - apiNameOrId: 'My_Published_Agent', - }); - await validatePreviewSession(projectPath, 'sess-2', { - apiNameOrId: 'My_Published_Agent', - orgUsername: 'user@org.com', - }); + it('saves session and validates with same agent', async () => { + const agent = makeMockAgent(projectPath, 'agent-1'); + agent.setSessionId('sess-1'); + await createCache(agent as never); + agent.setSessionId('sess-1'); + await validatePreviewSession(agent as never); }); - it('allows multiple sessions in same store', async () => { - await createCache(projectPath, { - sessionId: 'sess-a', - orgUsername: 'user@org.com', - aabName: 'Bundle_A', - }); - await createCache(projectPath, { - sessionId: 'sess-b', - orgUsername: 'user@org.com', - apiNameOrId: 'Agent_B', - }); - await validatePreviewSession(projectPath, 'sess-a', { - aabName: 'Bundle_A', - orgUsername: 'user@org.com', - }); - await validatePreviewSession(projectPath, 'sess-b', { - apiNameOrId: 'Agent_B', - orgUsername: 'user@org.com', - }); + it('allows multiple sessions for same agent', async () => { + const agent = makeMockAgent(projectPath, 'agent-1'); + agent.setSessionId('sess-a'); + await createCache(agent as never); + agent.setSessionId('sess-b'); + await createCache(agent as never); + agent.setSessionId('sess-a'); + await validatePreviewSession(agent as never); + agent.setSessionId('sess-b'); + await validatePreviewSession(agent as never); }); }); describe('validatePreviewSession', () => { - it('throws PreviewSessionNotFound when store file does not exist', async () => { + it('throws PreviewSessionNotFound when session file does not exist', async () => { + const agent = makeMockAgent(projectPath, 'agent-1'); + agent.setSessionId('unknown-sess'); try { - await validatePreviewSession(projectPath, 'unknown-sess', { - aabName: 'My_Bundle', - orgUsername: 'user@org.com', - }); + await validatePreviewSession(agent as never); expect.fail('Expected validatePreviewSession to throw'); } catch (e) { expect(e).to.be.instanceOf(SfError); expect((e as SfError).name).to.equal('PreviewSessionNotFound'); expect((e as SfError).message).to.include('No preview session found'); - expect((e as SfError).message).to.include('unknown-sess'); } }); - it('throws PreviewSessionNotFound when session id not in store', async () => { - await createCache(projectPath, { - sessionId: 'sess-1', - orgUsername: 'user@org.com', - aabName: 'My_Bundle', - }); + it('throws PreviewSessionNotFound when session id is for different agent', async () => { + const agentA = makeMockAgent(projectPath, 'agent-a'); + const agentB = makeMockAgent(projectPath, 'agent-b'); + (agentA as { setSessionId: (id: string) => void }).setSessionId('sess-1'); + await createCache(agentA as never); + (agentB as { setSessionId: (id: string) => void }).setSessionId('sess-1'); try { - await validatePreviewSession(projectPath, 'other-sess', { - aabName: 'My_Bundle', - orgUsername: 'user@org.com', - }); + await validatePreviewSession(agentB as never); expect.fail('Expected validatePreviewSession to throw'); } catch (e) { expect(e).to.be.instanceOf(SfError); @@ -113,123 +100,12 @@ describe('previewSessionStore', () => { } }); - it('throws PreviewSessionOrgMismatch when org differs', async () => { - await createCache(projectPath, { - sessionId: 'sess-1', - orgUsername: 'user@org-a.com', - aabName: 'My_Bundle', - }); - try { - await validatePreviewSession(projectPath, 'sess-1', { - aabName: 'My_Bundle', - orgUsername: 'user@org-b.com', - }); - expect.fail('Expected validatePreviewSession to throw'); - } catch (e) { - expect(e).to.be.instanceOf(SfError); - expect((e as SfError).name).to.equal('PreviewSessionOrgMismatch'); - expect((e as SfError).message).to.include('different target org'); - expect((e as SfError).message).to.include('user@org-a.com'); - } - }); - - it('throws PreviewSessionAgentMismatch when authoring-bundle differs', async () => { - await createCache(projectPath, { - sessionId: 'sess-1', - orgUsername: 'user@org.com', - aabName: 'Bundle_A', - }); - try { - await validatePreviewSession(projectPath, 'sess-1', { - aabName: 'Bundle_B', - orgUsername: 'user@org.com', - }); - expect.fail('Expected validatePreviewSession to throw'); - } catch (e) { - expect(e).to.be.instanceOf(SfError); - expect((e as SfError).name).to.equal('PreviewSessionAgentMismatch'); - expect((e as SfError).message).to.include('Session sess-1 was started with'); - expect((e as SfError).message).to.include('Bundle_A'); - } - }); - - it('throws PreviewSessionAgentMismatch when api-name differs', async () => { - await createCache(projectPath, { - sessionId: 'sess-1', - orgUsername: 'user@org.com', - apiNameOrId: 'Agent_A', - }); - try { - await validatePreviewSession(projectPath, 'sess-1', { - apiNameOrId: 'Agent_B', - orgUsername: 'user@org.com', - }); - expect.fail('Expected validatePreviewSession to throw'); - } catch (e) { - expect(e).to.be.instanceOf(SfError); - expect((e as SfError).name).to.equal('PreviewSessionAgentMismatch'); - expect((e as SfError).message).to.include('Agent_A'); - } - }); - - it('throws when session was started with authoring-bundle but send uses api-name', async () => { - await createCache(projectPath, { - sessionId: 'sess-1', - orgUsername: 'user@org.com', - aabName: 'My_Bundle', - }); - try { - await validatePreviewSession(projectPath, 'sess-1', { - apiNameOrId: 'Some_Agent', - orgUsername: 'user@org.com', - }); - expect.fail('Expected validatePreviewSession to throw'); - } catch (e) { - expect(e).to.be.instanceOf(SfError); - expect((e as SfError).name).to.equal('PreviewSessionAgentMismatch'); - } - }); - - it('throws when session was started with api-name but send uses authoring-bundle', async () => { - await createCache(projectPath, { - sessionId: 'sess-1', - orgUsername: 'user@org.com', - apiNameOrId: 'My_Agent', - }); - try { - await validatePreviewSession(projectPath, 'sess-1', { - aabName: 'Some_Bundle', - orgUsername: 'user@org.com', - }); - expect.fail('Expected validatePreviewSession to throw'); - } catch (e) { - expect(e).to.be.instanceOf(SfError); - expect((e as SfError).name).to.equal('PreviewSessionAgentMismatch'); - } - }); - - it('succeeds when agent and org match (authoring-bundle)', async () => { - await createCache(projectPath, { - sessionId: 'sess-1', - orgUsername: 'user@org.com', - aabName: 'My_Bundle', - }); - await validatePreviewSession(projectPath, 'sess-1', { - aabName: 'My_Bundle', - orgUsername: 'user@org.com', - }); - }); - - it('succeeds when agent and org match (api-name)', async () => { - await createCache(projectPath, { - sessionId: 'sess-1', - orgUsername: 'user@org.com', - apiNameOrId: 'My_Agent', - }); - await validatePreviewSession(projectPath, 'sess-1', { - apiNameOrId: 'My_Agent', - orgUsername: 'user@org.com', - }); + it('succeeds when session exists for this agent', async () => { + const agent = makeMockAgent(projectPath, 'agent-1'); + agent.setSessionId('sess-1'); + await createCache(agent as never); + agent.setSessionId('sess-1'); + await validatePreviewSession(agent as never); }); }); }); From e4e2a308f527cd8dffe36f64eb63cd263913fb85 Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Fri, 6 Feb 2026 10:39:15 -0700 Subject: [PATCH 07/25] chore: caching sessionid flag for send/end --- messages/agent.preview.end.md | 16 +++- messages/agent.preview.send.md | 14 +++- src/commands/agent/preview/end.ts | 23 ++++-- src/commands/agent/preview/send.ts | 28 +++++-- src/previewSessionStore.ts | 64 ++++++++++++++-- test/previewSessionStore.test.ts | 114 ++++++++++++++++++++++++----- 6 files changed, 215 insertions(+), 44 deletions(-) diff --git a/messages/agent.preview.end.md b/messages/agent.preview.end.md index 9435ea38..6e2b8a29 100644 --- a/messages/agent.preview.end.md +++ b/messages/agent.preview.end.md @@ -8,7 +8,7 @@ End an existing preview session and print the local path where session traces ar # flags.session-id.summary -Session ID from "agent preview start" (required). +Session ID from "agent preview start". Omit when the agent has exactly one active session. # flags.api-name.summary @@ -18,12 +18,24 @@ API name or ID of the published agent. API name of the authoring bundle (Agent Script). +# error.noSession + +No preview session found. Run "sf agent preview start" first. + +# error.multipleSessions + +Multiple preview sessions found for this agent. Specify --session-id. Sessions: %s + # output.tracesPath Session traces: %s # examples -- End a preview session: +- End the single active preview session: + + <%= config.bin %> <%= command.id %> --target-org my-dev-org + +- End a specific session when multiple exist: <%= config.bin %> <%= command.id %> --session-id --target-org my-dev-org diff --git a/messages/agent.preview.send.md b/messages/agent.preview.send.md index b75bc787..a38c50c9 100644 --- a/messages/agent.preview.send.md +++ b/messages/agent.preview.send.md @@ -8,7 +8,7 @@ Send an utterance to an existing preview session and get the agent response. Use # flags.session-id.summary -Session ID from "agent preview start" (required). +Session ID from "agent preview start". Omit when the agent has exactly one active session. # flags.utterance.summary @@ -22,8 +22,20 @@ API name or ID of the published agent. API name of the authoring bundle (Agent Script). +# error.noSession + +No preview session found. Run "sf agent preview start" first. + +# error.multipleSessions + +Multiple preview sessions found for this agent. Specify --session-id. Sessions: %s + # examples - Send a message to a preview session: + <%= config.bin %> <%= command.id %> --utterance "What can you help me with?" --target-org my-dev-org + +- Send to a specific session when multiple exist: + <%= config.bin %> <%= command.id %> --session-id --utterance "What can you help me with?" --target-org my-dev-org diff --git a/src/commands/agent/preview/end.ts b/src/commands/agent/preview/end.ts index 4a047cfc..a4c78cab 100644 --- a/src/commands/agent/preview/end.ts +++ b/src/commands/agent/preview/end.ts @@ -15,9 +15,9 @@ */ import { Flags, SfCommand } from '@salesforce/sf-plugins-core'; -import { Messages } from '@salesforce/core'; +import { Messages, SfError } from '@salesforce/core'; import { Agent, ProductionAgent, ScriptAgent } from '@salesforce/agents'; -import { validatePreviewSession } from '../../../previewSessionStore.js'; +import { getCachedSessionIds, validatePreviewSession } from '../../../previewSessionStore.js'; Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.preview.end'); @@ -39,7 +39,7 @@ export default class AgentPreviewEnd extends SfCommand { 'api-version': Flags.orgApiVersion(), 'session-id': Flags.string({ summary: messages.getMessage('flags.session-id.summary'), - required: true, + required: false, }), 'api-name': Flags.string({ summary: messages.getMessage('flags.api-name.summary'), @@ -54,17 +54,30 @@ export default class AgentPreviewEnd extends SfCommand { public async run(): Promise { const { flags } = await this.parse(AgentPreviewEnd); - const sessionId = flags['session-id']; const conn = flags['target-org'].getConnection(flags['api-version']); const agent = flags['authoring-bundle'] ? await Agent.init({ connection: conn, project: this.project!, aabName: flags['authoring-bundle'] }) : await Agent.init({ connection: conn, project: this.project!, apiNameOrId: flags['api-name']! }); + let sessionId = flags['session-id']; + if (sessionId === undefined) { + const cached = await getCachedSessionIds(this.project!, agent); + if (cached.length === 0) { + throw new SfError(messages.getMessage('error.noSession'), 'PreviewSessionNotFound'); + } + if (cached.length > 1) { + throw new SfError( + messages.getMessage('error.multipleSessions', [cached.join(', ')]), + 'PreviewSessionAmbiguous' + ); + } + sessionId = cached[0]; + } agent.setSessionId(sessionId); await validatePreviewSession(agent); - const tracesPath = await (agent as unknown as { getHistoryDir(): Promise }).getHistoryDir(); + const tracesPath = await agent.getHistoryDir(); if (agent instanceof ScriptAgent) { await agent.preview.end(); diff --git a/src/commands/agent/preview/send.ts b/src/commands/agent/preview/send.ts index e604d811..a87dc959 100644 --- a/src/commands/agent/preview/send.ts +++ b/src/commands/agent/preview/send.ts @@ -15,9 +15,9 @@ */ import { Flags, SfCommand } from '@salesforce/sf-plugins-core'; -import { Messages } from '@salesforce/core'; -import { Agent, ScriptAgent } from '@salesforce/agents'; -import { validatePreviewSession } from '../../../previewSessionStore.js'; +import { Messages, SfError } from '@salesforce/core'; +import { Agent } from '@salesforce/agents'; +import { getCachedSessionIds, validatePreviewSession } from '../../../previewSessionStore.js'; Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.preview.send'); @@ -38,7 +38,7 @@ export default class AgentPreviewSend extends SfCommand 'api-version': Flags.orgApiVersion(), 'session-id': Flags.string({ summary: messages.getMessage('flags.session-id.summary'), - required: true, + required: false, }), utterance: Flags.string({ summary: messages.getMessage('flags.utterance.summary'), @@ -60,14 +60,26 @@ export default class AgentPreviewSend extends SfCommand const { flags } = await this.parse(AgentPreviewSend); const conn = flags['target-org'].getConnection(flags['api-version']); + const agent = flags['authoring-bundle'] ? await Agent.init({ connection: conn, project: this.project!, aabName: flags['authoring-bundle'] }) : await Agent.init({ connection: conn, project: this.project!, apiNameOrId: flags['api-name']! }); - if (agent instanceof ScriptAgent) { - agent.preview.setMockMode('Mock'); - } - agent.setSessionId(flags['session-id']); + let sessionId = flags['session-id']; + if (sessionId === undefined) { + const cached = await getCachedSessionIds(this.project!, agent); + if (cached.length === 0) { + throw new SfError(messages.getMessage('error.noSession'), 'PreviewSessionNotFound'); + } + if (cached.length > 1) { + throw new SfError( + messages.getMessage('error.multipleSessions', [cached.join(', ')]), + 'PreviewSessionAmbiguous' + ); + } + sessionId = cached[0]; + } + agent.setSessionId(sessionId); await validatePreviewSession(agent); const response = await agent.preview.send(flags.utterance); diff --git a/src/previewSessionStore.ts b/src/previewSessionStore.ts index 6651b035..8d78659f 100644 --- a/src/previewSessionStore.ts +++ b/src/previewSessionStore.ts @@ -14,10 +14,11 @@ * limitations under the License. */ -import { readFile, writeFile } from 'node:fs/promises'; +import { readdir, readFile, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; import { SfError } from '@salesforce/core'; -import type { AgentInstance } from '@salesforce/agents'; +import type { SfProject } from '@salesforce/core'; +import type { ProductionAgent, ScriptAgent } from '@salesforce/agents'; const SESSION_META_FILE = 'session-meta.json'; @@ -25,10 +26,12 @@ const SESSION_META_FILE = 'session-meta.json'; * Save a marker so send/end can validate that the session was started for this agent. * Caller must have started the session (agent has sessionId set). Uses agent.getHistoryDir() for the path. */ -export async function createCache(agent: AgentInstance): Promise { +export async function createCache(agent: ScriptAgent | ProductionAgent): Promise { + /* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument */ const historyDir = await agent.getHistoryDir(); - const path = join(historyDir, SESSION_META_FILE); - await writeFile(path, JSON.stringify({}), 'utf-8'); + const metaPath = join(historyDir, SESSION_META_FILE); + /* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument */ + await writeFile(metaPath, JSON.stringify({}), 'utf-8'); } /** @@ -36,11 +39,13 @@ export async function createCache(agent: AgentInstance): Promise { * Caller must set sessionId on the agent (agent.setSessionId) before calling. * Throws SfError if the session marker is not found. */ -export async function validatePreviewSession(agent: AgentInstance): Promise { +export async function validatePreviewSession(agent: ScriptAgent | ProductionAgent): Promise { + /* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument */ const historyDir = await agent.getHistoryDir(); - const path = join(historyDir, SESSION_META_FILE); + const metaPath = join(historyDir, SESSION_META_FILE); + /* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument */ try { - await readFile(path, 'utf-8'); + await readFile(metaPath, 'utf-8'); } catch { throw new SfError( 'No preview session found for this session ID. Run "sf agent preview start" first.', @@ -48,3 +53,46 @@ export async function validatePreviewSession(agent: AgentInstance): Promise/sessions//session-meta.json. + */ +export async function getCachedSessionIds(project: SfProject, agent: ScriptAgent | ProductionAgent): Promise { + const agentId = agent.getAgentIdForStorage(); + const base = join(project.getPath(), '.sfdx'); + const sessionsDir = join(base, 'agents', agentId, 'sessions'); + const sessionIds: string[] = []; + try { + const entries = await readdir(sessionsDir, { withFileTypes: true }); + const dirs = entries.filter((e) => e.isDirectory()).map((e) => e.name); + const hasMarker = await Promise.all( + dirs.map(async (name) => { + try { + await readFile(join(sessionsDir, name, SESSION_META_FILE), 'utf-8'); + return true; + } catch { + return false; + } + }) + ); + dirs.forEach((name, i) => { + if (hasMarker[i]) sessionIds.push(name); + }); + } catch { + // sessions dir missing or unreadable + } + return sessionIds; +} + +/** + * Return the single "current" session ID when safe: exactly one cached session for this agent. + * Returns undefined when there are zero or multiple sessions (caller should require --session-id). + */ +export async function getCurrentSessionId( + project: SfProject, + agent: ScriptAgent | ProductionAgent +): Promise { + const ids = await getCachedSessionIds(project, agent); + return ids.length === 1 ? ids[0] : undefined; +} diff --git a/test/previewSessionStore.test.ts b/test/previewSessionStore.test.ts index bd594833..26b1bb27 100644 --- a/test/previewSessionStore.test.ts +++ b/test/previewSessionStore.test.ts @@ -18,24 +18,36 @@ import { mkdtempSync, rmSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { expect } from 'chai'; -import { SfError } from '@salesforce/core'; -import { createCache, validatePreviewSession } from '../src/previewSessionStore.js'; +import { SfError, SfProject } from '@salesforce/core'; +import type { ProductionAgent, ScriptAgent } from '@salesforce/agents'; +import { + createCache, + getCachedSessionIds, + getCurrentSessionId, + validatePreviewSession, +} from '../src/previewSessionStore.js'; -function makeMockAgent(baseDir: string, agentId: string) { +function makeMockProject(getPath: () => string): SfProject { + return { getPath } as SfProject; +} + +function makeMockAgent(projectDir: string, agentId: string): ScriptAgent | ProductionAgent { let sessionId: string | undefined; - const agent = { + return { setSessionId(id: string) { sessionId = id; }, + getAgentIdForStorage(): string { + return agentId; + }, async getHistoryDir(): Promise { if (!sessionId) throw new Error('sessionId not set'); - const dir = join(baseDir, 'agents', agentId, 'sessions', sessionId); + const dir = join(projectDir, '.sfdx', 'agents', agentId, 'sessions', sessionId); const { mkdir } = await import('node:fs/promises'); await mkdir(dir, { recursive: true }); return dir; }, - }; - return agent; + } as ScriptAgent | ProductionAgent; } describe('previewSessionStore', () => { @@ -53,21 +65,21 @@ describe('previewSessionStore', () => { it('saves session and validates with same agent', async () => { const agent = makeMockAgent(projectPath, 'agent-1'); agent.setSessionId('sess-1'); - await createCache(agent as never); + await createCache(agent); agent.setSessionId('sess-1'); - await validatePreviewSession(agent as never); + await validatePreviewSession(agent); }); it('allows multiple sessions for same agent', async () => { const agent = makeMockAgent(projectPath, 'agent-1'); agent.setSessionId('sess-a'); - await createCache(agent as never); + await createCache(agent); agent.setSessionId('sess-b'); - await createCache(agent as never); + await createCache(agent); agent.setSessionId('sess-a'); - await validatePreviewSession(agent as never); + await validatePreviewSession(agent); agent.setSessionId('sess-b'); - await validatePreviewSession(agent as never); + await validatePreviewSession(agent); }); }); @@ -76,7 +88,7 @@ describe('previewSessionStore', () => { const agent = makeMockAgent(projectPath, 'agent-1'); agent.setSessionId('unknown-sess'); try { - await validatePreviewSession(agent as never); + await validatePreviewSession(agent); expect.fail('Expected validatePreviewSession to throw'); } catch (e) { expect(e).to.be.instanceOf(SfError); @@ -88,11 +100,11 @@ describe('previewSessionStore', () => { it('throws PreviewSessionNotFound when session id is for different agent', async () => { const agentA = makeMockAgent(projectPath, 'agent-a'); const agentB = makeMockAgent(projectPath, 'agent-b'); - (agentA as { setSessionId: (id: string) => void }).setSessionId('sess-1'); - await createCache(agentA as never); - (agentB as { setSessionId: (id: string) => void }).setSessionId('sess-1'); + agentA.setSessionId('sess-1'); + await createCache(agentA); + agentB.setSessionId('sess-1'); try { - await validatePreviewSession(agentB as never); + await validatePreviewSession(agentB); expect.fail('Expected validatePreviewSession to throw'); } catch (e) { expect(e).to.be.instanceOf(SfError); @@ -103,9 +115,71 @@ describe('previewSessionStore', () => { it('succeeds when session exists for this agent', async () => { const agent = makeMockAgent(projectPath, 'agent-1'); agent.setSessionId('sess-1'); - await createCache(agent as never); + await createCache(agent); + agent.setSessionId('sess-1'); + await validatePreviewSession(agent); + }); + }); + + describe('getCachedSessionIds', () => { + it('returns empty when no sessions', async () => { + const project = makeMockProject(() => projectPath); + const agent = makeMockAgent(projectPath, 'agent-1'); + const ids = await getCachedSessionIds(project, agent); + expect(ids).to.deep.equal([]); + }); + + it('returns session ids that have session-meta.json', async () => { + const project = makeMockProject(() => projectPath); + const agent = makeMockAgent(projectPath, 'agent-1'); + agent.setSessionId('sess-1'); + await createCache(agent); + agent.setSessionId('sess-2'); + await createCache(agent); + const ids = await getCachedSessionIds(project, agent); + expect(ids).to.have.members(['sess-1', 'sess-2']); + }); + + it('does not return session dirs without session-meta.json', async () => { + const project = makeMockProject(() => projectPath); + const agent = makeMockAgent(projectPath, 'agent-1'); agent.setSessionId('sess-1'); - await validatePreviewSession(agent as never); + await createCache(agent); + const { mkdir } = await import('node:fs/promises'); + await mkdir(join(projectPath, '.sfdx', 'agents', 'agent-1', 'sessions', 'other-dir'), { + recursive: true, + }); + const ids = await getCachedSessionIds(project, agent); + expect(ids).to.deep.equal(['sess-1']); + }); + }); + + describe('getCurrentSessionId', () => { + it('returns undefined when no sessions', async () => { + const project = makeMockProject(() => projectPath); + const agent = makeMockAgent(projectPath, 'agent-1'); + const id = await getCurrentSessionId(project, agent); + expect(id).to.be.undefined; + }); + + it('returns session id when exactly one session', async () => { + const project = makeMockProject(() => projectPath); + const agent = makeMockAgent(projectPath, 'agent-1'); + agent.setSessionId('sess-1'); + await createCache(agent); + const id = await getCurrentSessionId(project, agent); + expect(id).to.equal('sess-1'); + }); + + it('returns undefined when multiple sessions', async () => { + const project = makeMockProject(() => projectPath); + const agent = makeMockAgent(projectPath, 'agent-1'); + agent.setSessionId('sess-a'); + await createCache(agent); + agent.setSessionId('sess-b'); + await createCache(agent); + const id = await getCurrentSessionId(project, agent); + expect(id).to.be.undefined; }); }); }); From 085e742cce1349a29a40f069f6817cfb0e536334 Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Fri, 6 Feb 2026 10:49:15 -0700 Subject: [PATCH 08/25] chore: cache cleanup --- src/commands/agent/preview/end.ts | 4 +++- src/previewSessionStore.ts | 16 +++++++++++++++- test/previewSessionStore.test.ts | 31 +++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/commands/agent/preview/end.ts b/src/commands/agent/preview/end.ts index a4c78cab..6d66cae7 100644 --- a/src/commands/agent/preview/end.ts +++ b/src/commands/agent/preview/end.ts @@ -17,7 +17,7 @@ import { Flags, SfCommand } from '@salesforce/sf-plugins-core'; import { Messages, SfError } from '@salesforce/core'; import { Agent, ProductionAgent, ScriptAgent } from '@salesforce/agents'; -import { getCachedSessionIds, validatePreviewSession } from '../../../previewSessionStore.js'; +import { getCachedSessionIds, removeCache, validatePreviewSession } from '../../../previewSessionStore.js'; Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.preview.end'); @@ -79,6 +79,8 @@ export default class AgentPreviewEnd extends SfCommand { const tracesPath = await agent.getHistoryDir(); + await removeCache(agent); + if (agent instanceof ScriptAgent) { await agent.preview.end(); } else if (agent instanceof ProductionAgent) { diff --git a/src/previewSessionStore.ts b/src/previewSessionStore.ts index 8d78659f..e72b8887 100644 --- a/src/previewSessionStore.ts +++ b/src/previewSessionStore.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { readdir, readFile, writeFile } from 'node:fs/promises'; +import { readdir, readFile, unlink, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; import { SfError } from '@salesforce/core'; import type { SfProject } from '@salesforce/core'; @@ -54,6 +54,20 @@ export async function validatePreviewSession(agent: ScriptAgent | ProductionAgen } } +/** + * Remove the session marker so this session is no longer considered "active" for send/end without --session-id. + * Call after ending the session. Caller must set sessionId on the agent before calling. + */ +export async function removeCache(agent: ScriptAgent | ProductionAgent): Promise { + const historyDir = await agent.getHistoryDir(); + const metaPath = join(historyDir, SESSION_META_FILE); + try { + await unlink(metaPath); + } catch { + // already removed or never created + } +} + /** * List session IDs that have a cache marker (started via "agent preview start") for this agent. * Uses project path and agent's storage ID to find .sfdx/agents//sessions//session-meta.json. diff --git a/test/previewSessionStore.test.ts b/test/previewSessionStore.test.ts index 26b1bb27..1b23151d 100644 --- a/test/previewSessionStore.test.ts +++ b/test/previewSessionStore.test.ts @@ -24,6 +24,7 @@ import { createCache, getCachedSessionIds, getCurrentSessionId, + removeCache, validatePreviewSession, } from '../src/previewSessionStore.js'; @@ -154,6 +155,36 @@ describe('previewSessionStore', () => { }); }); + describe('removeCache', () => { + it('removes session from cache so getCachedSessionIds no longer includes it', async () => { + const project = makeMockProject(() => projectPath); + const agent = makeMockAgent(projectPath, 'agent-1'); + agent.setSessionId('sess-1'); + await createCache(agent); + agent.setSessionId('sess-2'); + await createCache(agent); + let ids = await getCachedSessionIds(project, agent); + expect(ids).to.have.members(['sess-1', 'sess-2']); + agent.setSessionId('sess-1'); + await removeCache(agent); + ids = await getCachedSessionIds(project, agent); + expect(ids).to.deep.equal(['sess-2']); + }); + + it('after removing one of two sessions, getCurrentSessionId returns the remaining session', async () => { + const project = makeMockProject(() => projectPath); + const agent = makeMockAgent(projectPath, 'agent-1'); + agent.setSessionId('sess-a'); + await createCache(agent); + agent.setSessionId('sess-b'); + await createCache(agent); + expect(await getCurrentSessionId(project, agent)).to.be.undefined; + agent.setSessionId('sess-a'); + await removeCache(agent); + expect(await getCurrentSessionId(project, agent)).to.equal('sess-b'); + }); + }); + describe('getCurrentSessionId', () => { it('returns undefined when no sessions', async () => { const project = makeMockProject(() => projectPath); From 8d3e80734a1cd6eaeaffac37532634f06c6cd7af Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Fri, 6 Feb 2026 11:15:52 -0700 Subject: [PATCH 09/25] feat: add 'agent preview sessions' to list sessions' --- command-snapshot.json | 8 ++++ messages/agent.preview.sessions.md | 25 +++++++++++ package.json | 2 +- schemas/agent-preview-sessions.json | 22 +++++++++ src/commands/agent/preview/sessions.ts | 62 ++++++++++++++++++++++++++ src/previewSessionStore.ts | 49 ++++++++++++++++++++ test/previewSessionStore.test.ts | 26 +++++++++++ yarn.lock | 8 ++-- 8 files changed, 197 insertions(+), 5 deletions(-) create mode 100644 messages/agent.preview.sessions.md create mode 100644 schemas/agent-preview-sessions.json create mode 100644 src/commands/agent/preview/sessions.ts diff --git a/command-snapshot.json b/command-snapshot.json index 6ac3ec55..768826f3 100644 --- a/command-snapshot.json +++ b/command-snapshot.json @@ -117,6 +117,14 @@ ], "plugin": "@salesforce/plugin-agent" }, + { + "alias": [], + "command": "agent:preview:sessions", + "flagAliases": [], + "flagChars": [], + "flags": ["flags-dir", "json"], + "plugin": "@salesforce/plugin-agent" + }, { "alias": [], "command": "agent:preview:start", diff --git a/messages/agent.preview.sessions.md b/messages/agent.preview.sessions.md new file mode 100644 index 00000000..66e7cb1e --- /dev/null +++ b/messages/agent.preview.sessions.md @@ -0,0 +1,25 @@ +# summary + +List cached preview sessions (beta). + +# description + +List preview sessions that were started with "agent preview start" and are still in the cache. Use this to see which sessions exist so you can end them with "agent preview end" (e.g. to clean up or resolve "multiple sessions" when using send without --session-id). Agent ID is the authoring bundle name for Agent Script agents, or the agent ID for published agents. + +# output.empty + +No cached preview sessions found. + +# output.tableHeader.agentId + +Agent ID (authoring bundle or agent) + +# output.tableHeader.sessionId + +Session ID + +# examples + +- List all cached preview sessions: + + <%= config.bin %> <%= command.id %> diff --git a/package.json b/package.json index 73654f3b..7f228432 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "@inquirer/prompts": "^7.10.1", "@oclif/core": "^4", "@oclif/multi-stage-output": "^0.8.29", - "@salesforce/agents": "^0.22.1", + "@salesforce/agents": "^0.22.4", "@salesforce/core": "^8.24.3", "@salesforce/kit": "^3.2.4", "@salesforce/sf-plugins-core": "^12.2.6", diff --git a/schemas/agent-preview-sessions.json b/schemas/agent-preview-sessions.json new file mode 100644 index 00000000..2e50b4e5 --- /dev/null +++ b/schemas/agent-preview-sessions.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$ref": "#/definitions/AgentPreviewSessionsResult", + "definitions": { + "AgentPreviewSessionsResult": { + "type": "array", + "items": { + "type": "object", + "properties": { + "agentId": { + "type": "string" + }, + "sessionId": { + "type": "string" + } + }, + "required": ["agentId", "sessionId"], + "additionalProperties": false + } + } + } +} diff --git a/src/commands/agent/preview/sessions.ts b/src/commands/agent/preview/sessions.ts new file mode 100644 index 00000000..b123262f --- /dev/null +++ b/src/commands/agent/preview/sessions.ts @@ -0,0 +1,62 @@ +/* + * 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 { SfCommand } from '@salesforce/sf-plugins-core'; +import { Messages } from '@salesforce/core'; +import { listCachedSessions } from '../../../previewSessionStore.js'; + +Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); +const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.preview.sessions'); + +export type AgentPreviewSessionsResult = Array<{ agentId: string; sessionId: string }>; + +export default class AgentPreviewSessions extends SfCommand { + public static readonly summary = messages.getMessage('summary'); + public static readonly description = messages.getMessage('description'); + public static readonly examples = messages.getMessages('examples'); + public static readonly state = 'beta'; + public static readonly requiresProject = true; + + public async run(): Promise { + const entries = await listCachedSessions(this.project!); + const rows: AgentPreviewSessionsResult = []; + for (const { agentId, sessionIds } of entries) { + for (const sessionId of sessionIds) { + rows.push({ agentId, sessionId }); + } + } + + if (rows.length === 0) { + this.log(messages.getMessage('output.empty')); + return []; + } + + if (this.jsonEnabled()) { + return rows; + } + + const agentIdHeader = messages.getMessage('output.tableHeader.agentId'); + const sessionIdHeader = messages.getMessage('output.tableHeader.sessionId'); + this.table({ + data: rows, + columns: [ + { key: 'agentId', name: agentIdHeader }, + { key: 'sessionId', name: sessionIdHeader }, + ], + }); + return rows; + } +} diff --git a/src/previewSessionStore.ts b/src/previewSessionStore.ts index e72b8887..e52f8a18 100644 --- a/src/previewSessionStore.ts +++ b/src/previewSessionStore.ts @@ -59,8 +59,10 @@ export async function validatePreviewSession(agent: ScriptAgent | ProductionAgen * Call after ending the session. Caller must set sessionId on the agent before calling. */ export async function removeCache(agent: ScriptAgent | ProductionAgent): Promise { + /* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument */ const historyDir = await agent.getHistoryDir(); const metaPath = join(historyDir, SESSION_META_FILE); + /* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument */ try { await unlink(metaPath); } catch { @@ -110,3 +112,50 @@ export async function getCurrentSessionId( const ids = await getCachedSessionIds(project, agent); return ids.length === 1 ? ids[0] : undefined; } + +export type CachedSessionEntry = { agentId: string; sessionIds: string[] }; + +/** + * List all cached preview sessions in the project, grouped by agent ID. + * Agent ID is the authoring bundle name (for script agents) or agent ID (for published agents). + * Use this to show users which sessions exist so they can end or clean up. + */ +export async function listCachedSessions(project: SfProject): Promise { + const base = join(project.getPath(), '.sfdx', 'agents'); + const result: CachedSessionEntry[] = []; + try { + const agentDirs = await readdir(base, { withFileTypes: true }); + const entries = await Promise.all( + agentDirs + .filter((ent) => ent.isDirectory()) + .map(async (ent) => { + const agentId = ent.name; + const sessionsDir = join(base, agentId, 'sessions'); + let sessionIds: string[] = []; + try { + const sessionDirs = await readdir(sessionsDir, { withFileTypes: true }); + const withMarker = await Promise.all( + sessionDirs + .filter((s) => s.isDirectory()) + .map(async (s) => { + try { + await readFile(join(sessionsDir, s.name, SESSION_META_FILE), 'utf-8'); + return s.name; + } catch { + return null; + } + }) + ); + sessionIds = withMarker.filter((id): id is string => id !== null); + } catch { + // no sessions dir or unreadable + } + return { agentId, sessionIds }; + }) + ); + result.push(...entries.filter((e) => e.sessionIds.length > 0)); + } catch { + // no agents dir or unreadable + } + return result; +} diff --git a/test/previewSessionStore.test.ts b/test/previewSessionStore.test.ts index 1b23151d..90ab87a4 100644 --- a/test/previewSessionStore.test.ts +++ b/test/previewSessionStore.test.ts @@ -24,6 +24,7 @@ import { createCache, getCachedSessionIds, getCurrentSessionId, + listCachedSessions, removeCache, validatePreviewSession, } from '../src/previewSessionStore.js'; @@ -185,6 +186,31 @@ describe('previewSessionStore', () => { }); }); + describe('listCachedSessions', () => { + it('returns empty when no cached sessions', async () => { + const project = makeMockProject(() => projectPath); + const list = await listCachedSessions(project); + expect(list).to.deep.equal([]); + }); + + it('returns agent ids and session ids for all cached sessions', async () => { + const project = makeMockProject(() => projectPath); + const agent1 = makeMockAgent(projectPath, 'bundle-a'); + agent1.setSessionId('s1'); + await createCache(agent1); + agent1.setSessionId('s2'); + await createCache(agent1); + const agent2 = makeMockAgent(projectPath, 'bundle-b'); + agent2.setSessionId('s3'); + await createCache(agent2); + const list = await listCachedSessions(project); + expect(list).to.have.lengthOf(2); + const byAgent = Object.fromEntries(list.map((e) => [e.agentId, e.sessionIds])); + expect(byAgent['bundle-a']).to.have.members(['s1', 's2']); + expect(byAgent['bundle-b']).to.deep.equal(['s3']); + }); + }); + describe('getCurrentSessionId', () => { it('returns undefined when no sessions', async () => { const project = makeMockProject(() => projectPath); diff --git a/yarn.lock b/yarn.lock index 8d68f93a..65e661dd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1719,10 +1719,10 @@ resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== -"@salesforce/agents@^0.22.1": - version "0.22.2" - resolved "https://registry.yarnpkg.com/@salesforce/agents/-/agents-0.22.2.tgz#b9c6612040938c37cfa85f250cb6ee5a0a055135" - integrity sha512-TF/hvrM2wv3rSLWkBbLCjBGax6y5EaO5t6cevM+i/VMX140M+ls63O/8AaoXAwjNo3udorNUhm0wbs1HE3QfRw== +"@salesforce/agents@^0.22.4": + version "0.22.4" + resolved "https://registry.yarnpkg.com/@salesforce/agents/-/agents-0.22.4.tgz#a9fe2beb94bd12e1f941bb22fc3c00ed24888662" + integrity sha512-Oe5LApwpEFm+VeOtatQPvyfcJlYIP6ixpJo/CbAIX0M9TI9UP7E/oLmQfkxylaiqYQzNtK+B21x7+Lwr6cPgxg== dependencies: "@salesforce/core" "^8.24.0" "@salesforce/kit" "^3.2.4" From 370f2e7f9905443b6e23846b5327c9f313316627 Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Fri, 6 Feb 2026 11:20:52 -0700 Subject: [PATCH 10/25] chore: fix end typing extra --- src/components/agent-preview-react.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/agent-preview-react.tsx b/src/components/agent-preview-react.tsx index a6095b3c..2221f5ee 100644 --- a/src/components/agent-preview-react.tsx +++ b/src/components/agent-preview-react.tsx @@ -125,7 +125,7 @@ export function AgentPreviewReact(props: { if (isLocalAgent) { await agent.end(); } else { - await (agent as ProductionAgentPreview).end('UserRequest'); + await agent.end('UserRequest'); } process.exit(0); } catch (e) { From fe7a3d5052372257d839a3591aab128af1c66265 Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Fri, 6 Feb 2026 11:28:21 -0700 Subject: [PATCH 11/25] chore: save api-name, not id --- messages/agent.preview.sessions.md | 4 ++-- src/commands/agent/preview/sessions.ts | 16 +++++++++------ src/commands/agent/preview/start.ts | 3 ++- src/previewSessionStore.ts | 27 +++++++++++++++++++++----- test/previewSessionStore.test.ts | 12 ++++++++++++ 5 files changed, 48 insertions(+), 14 deletions(-) diff --git a/messages/agent.preview.sessions.md b/messages/agent.preview.sessions.md index 66e7cb1e..ac064d1f 100644 --- a/messages/agent.preview.sessions.md +++ b/messages/agent.preview.sessions.md @@ -10,9 +10,9 @@ List preview sessions that were started with "agent preview start" and are still No cached preview sessions found. -# output.tableHeader.agentId +# output.tableHeader.agent -Agent ID (authoring bundle or agent) +Agent (authoring bundle or API name) # output.tableHeader.sessionId diff --git a/src/commands/agent/preview/sessions.ts b/src/commands/agent/preview/sessions.ts index b123262f..dac20a41 100644 --- a/src/commands/agent/preview/sessions.ts +++ b/src/commands/agent/preview/sessions.ts @@ -21,7 +21,7 @@ import { listCachedSessions } from '../../../previewSessionStore.js'; Messages.importMessagesDirectoryFromMetaUrl(import.meta.url); const messages = Messages.loadMessages('@salesforce/plugin-agent', 'agent.preview.sessions'); -export type AgentPreviewSessionsResult = Array<{ agentId: string; sessionId: string }>; +export type AgentPreviewSessionsResult = Array<{ agentId: string; displayName?: string; sessionId: string }>; export default class AgentPreviewSessions extends SfCommand { public static readonly summary = messages.getMessage('summary'); @@ -33,9 +33,9 @@ export default class AgentPreviewSessions extends SfCommand { const entries = await listCachedSessions(this.project!); const rows: AgentPreviewSessionsResult = []; - for (const { agentId, sessionIds } of entries) { + for (const { agentId, displayName, sessionIds } of entries) { for (const sessionId of sessionIds) { - rows.push({ agentId, sessionId }); + rows.push({ agentId, displayName, sessionId }); } } @@ -48,12 +48,16 @@ export default class AgentPreviewSessions extends SfCommand ({ + agent: r.displayName ?? r.agentId, + sessionId: r.sessionId, + })); this.table({ - data: rows, + data: tableData, columns: [ - { key: 'agentId', name: agentIdHeader }, + { key: 'agent', name: agentColumnHeader }, { key: 'sessionId', name: sessionIdHeader }, ], }); diff --git a/src/commands/agent/preview/start.ts b/src/commands/agent/preview/start.ts index 36c4e2f0..6b638f29 100644 --- a/src/commands/agent/preview/start.ts +++ b/src/commands/agent/preview/start.ts @@ -70,7 +70,8 @@ export default class AgentPreviewStart extends SfCommand { +export async function createCache( + agent: ScriptAgent | ProductionAgent, + options?: { displayName?: string } +): Promise { /* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument */ const historyDir = await agent.getHistoryDir(); const metaPath = join(historyDir, SESSION_META_FILE); /* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument */ - await writeFile(metaPath, JSON.stringify({}), 'utf-8'); + const meta: SessionMeta = { displayName: options?.displayName }; + await writeFile(metaPath, JSON.stringify(meta), 'utf-8'); } /** @@ -113,11 +120,11 @@ export async function getCurrentSessionId( return ids.length === 1 ? ids[0] : undefined; } -export type CachedSessionEntry = { agentId: string; sessionIds: string[] }; +export type CachedSessionEntry = { agentId: string; displayName?: string; sessionIds: string[] }; /** * List all cached preview sessions in the project, grouped by agent ID. - * Agent ID is the authoring bundle name (for script agents) or agent ID (for published agents). + * displayName (when present in session-meta.json) is the authoring bundle name or production agent API name for display. * Use this to show users which sessions exist so they can end or clean up. */ export async function listCachedSessions(project: SfProject): Promise { @@ -132,6 +139,7 @@ export async function listCachedSessions(project: SfProject): Promise id !== null); + if (sessionIds.length > 0) { + try { + const raw = await readFile(join(sessionsDir, sessionIds[0], SESSION_META_FILE), 'utf-8'); + const meta = JSON.parse(raw) as SessionMeta; + displayName = meta.displayName; + } catch { + // ignore + } + } } catch { // no sessions dir or unreadable } - return { agentId, sessionIds }; + return { agentId, displayName, sessionIds }; }) ); result.push(...entries.filter((e) => e.sessionIds.length > 0)); diff --git a/test/previewSessionStore.test.ts b/test/previewSessionStore.test.ts index 90ab87a4..a1a52e53 100644 --- a/test/previewSessionStore.test.ts +++ b/test/previewSessionStore.test.ts @@ -209,6 +209,18 @@ describe('previewSessionStore', () => { expect(byAgent['bundle-a']).to.have.members(['s1', 's2']); expect(byAgent['bundle-b']).to.deep.equal(['s3']); }); + + it('returns displayName from session-meta when createCache was called with displayName', async () => { + const project = makeMockProject(() => projectPath); + const agent = makeMockAgent(projectPath, 'some-id'); + agent.setSessionId('s1'); + await createCache(agent, { displayName: 'My_Production_Agent' }); + const list = await listCachedSessions(project); + expect(list).to.have.lengthOf(1); + expect(list[0].agentId).to.equal('some-id'); + expect(list[0].displayName).to.equal('My_Production_Agent'); + expect(list[0].sessionIds).to.deep.equal(['s1']); + }); }); describe('getCurrentSessionId', () => { From 48cda5c81bc0c5598f33920dd2d0b141de58edee Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Fri, 6 Feb 2026 11:49:32 -0700 Subject: [PATCH 12/25] docs: update help/examples --- messages/agent.preview.end.md | 10 +++++++--- messages/agent.preview.send.md | 8 ++++++-- messages/agent.preview.start.md | 8 ++++++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/messages/agent.preview.end.md b/messages/agent.preview.end.md index 6e2b8a29..ad25725d 100644 --- a/messages/agent.preview.end.md +++ b/messages/agent.preview.end.md @@ -4,7 +4,7 @@ End a preview session and get trace location (beta). # description -End an existing preview session and print the local path where session traces are stored (.sfdx/agents/). Use the session ID returned by "agent preview start". Specify the same agent with --api-name or --authoring-bundle as used when starting the session; one is required. +End an existing preview session and print the local path where session traces are stored. Use the session ID returned by "agent preview start". Specify the same agent with --api-name or --authoring-bundle as used when starting the session; one is required. # flags.session-id.summary @@ -32,9 +32,13 @@ Session traces: %s # examples -- End the single active preview session: +- End the single active preview session for a simulated agent: - <%= config.bin %> <%= command.id %> --target-org my-dev-org + <%= config.bin %> <%= command.id %> --target-org my-dev-org --authoring-bundle My_Local + +- End the single active preview session for a published agent: + +<%= config.bin %> <%= command.id %> --target-org my-dev-org --api-name My_Published_Agent - End a specific session when multiple exist: diff --git a/messages/agent.preview.send.md b/messages/agent.preview.send.md index a38c50c9..187d4fca 100644 --- a/messages/agent.preview.send.md +++ b/messages/agent.preview.send.md @@ -32,9 +32,13 @@ Multiple preview sessions found for this agent. Specify --session-id. Sessions: # examples -- Send a message to a preview session: +- Send a message to a simulated Agent: - <%= config.bin %> <%= command.id %> --utterance "What can you help me with?" --target-org my-dev-org + <%= config.bin %> <%= command.id %> --utterance "What can you help me with?" --authoring-bundle My_Agent + +Send a message to a published Agent: + +<%= config.bin %> <%= command.id %> --utterance "What can you help me with?" --api-name My_Published_Agent - Send to a specific session when multiple exist: diff --git a/messages/agent.preview.start.md b/messages/agent.preview.start.md index e7f6a856..4a70b001 100644 --- a/messages/agent.preview.start.md +++ b/messages/agent.preview.start.md @@ -28,6 +28,10 @@ Session ID: %s <%= config.bin %> <%= command.id %> --authoring-bundle My_Agent_Bundle --target-org my-dev-org -- Start a preview session with a published agent in live mode: +- Start a preview session with an authoring bundle and use real actions: - <%= config.bin %> <%= command.id %> --api-name My_Published_Agent --use-live-actions --target-org my-dev-org + <%= config.bin %> <%= command.id %> --authoring-bundle My_Agent_Bundle --use-live-actions --target-org my-dev-org + +- Start a preview session with a published agent: + + <%= config.bin %> <%= command.id %> --api-name My_Published_Agent From 8c2f89445934d6f83400fb8359ffded59260f7b3 Mon Sep 17 00:00:00 2001 From: Willie Ruemmele Date: Fri, 6 Feb 2026 12:04:15 -0700 Subject: [PATCH 13/25] chore: schemas and snapshots --- schemas/agent-preview-sessions.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/schemas/agent-preview-sessions.json b/schemas/agent-preview-sessions.json index 2e50b4e5..37c008c0 100644 --- a/schemas/agent-preview-sessions.json +++ b/schemas/agent-preview-sessions.json @@ -10,6 +10,9 @@ "agentId": { "type": "string" }, + "displayName": { + "type": "string" + }, "sessionId": { "type": "string" } From 2a2d74ab453d98b77c55f365e80809542e38d08a Mon Sep 17 00:00:00 2001 From: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:20:18 -0800 Subject: [PATCH 14/25] fix: teeny edit to existing "agent preview" messages file --- messages/agent.preview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/messages/agent.preview.md b/messages/agent.preview.md index 0e62bfae..d4d38ea8 100644 --- a/messages/agent.preview.md +++ b/messages/agent.preview.md @@ -21,7 +21,7 @@ When the session concludes, the command asks if you want to save the API respons # flags.api-name.summary -API name of the published and active agent you want to interact with. +API name of the activated published agent you want to interact with. # flags.authoring-bundle.summary From 90c924e977613d5be9697e72734d7cccd174a9de Mon Sep 17 00:00:00 2001 From: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:22:43 -0800 Subject: [PATCH 15/25] fix: edit --- messages/agent.preview.end.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/messages/agent.preview.end.md b/messages/agent.preview.end.md index ad25725d..967d1230 100644 --- a/messages/agent.preview.end.md +++ b/messages/agent.preview.end.md @@ -1,30 +1,32 @@ # summary -End a preview session and get trace location (beta). +End an existing programmatic agent preview session and get trace location. # description -End an existing preview session and print the local path where session traces are stored. Use the session ID returned by "agent preview start". Specify the same agent with --api-name or --authoring-bundle as used when starting the session; one is required. +You must have previously started a programmatic agent preview session with the "agent preview start" command to then use this command to end it. This command also displays the local directory where the session trace files are stored. + +The original "agent preview start" command outputs a session ID which you then use with this command. Alternatively, you can use the --authoring-bundle or --api-name flags to specify the API name of the authoring bundle, or the agent itself, as long as the agent has only one active preview session. If it has multiple sessions, then you must instead use --session-id to identify the exact one you want to end. # flags.session-id.summary -Session ID from "agent preview start". Omit when the agent has exactly one active session. +Session ID outputted by "agent preview start". Not required when the agent has exactly one active session. Run "agent preview sessions" to see the list of all sessions. # flags.api-name.summary -API name or ID of the published agent. +API name of the activated published agent you want to preview. # flags.authoring-bundle.summary -API name of the authoring bundle (Agent Script). +API name of the authoring bundle metadata component that contains the agent's Agent Script file. # error.noSession -No preview session found. Run "sf agent preview start" first. +No agent preview session found. Run "sf agent preview start" to start a new agent preview session. # error.multipleSessions -Multiple preview sessions found for this agent. Specify --session-id. Sessions: %s +Multiple preview sessions found for this agent. Use the --session-id flag to identify a specific session. Sessions: %s # output.tracesPath @@ -32,14 +34,14 @@ Session traces: %s # examples -- End the single active preview session for a simulated agent: +- End an agent preview session by specifying its session ID; use the default org: - <%= config.bin %> <%= command.id %> --target-org my-dev-org --authoring-bundle My_Local + <%= config.bin %> <%= command.id %> --session-id -- End the single active preview session for a published agent: +- End an agent preview session using the API name of the published agent; you get an error if the agent has more than one active session. Use the org with alias "my-dev-org": -<%= config.bin %> <%= command.id %> --target-org my-dev-org --api-name My_Published_Agent + <%= config.bin %> <%= command.id %> --api-name My_Published_Agent --target-org my-dev-org -- End a specific session when multiple exist: +- End an agent preview session using its authoring bundle API name; you get an error if the agent has more than one active session. - <%= config.bin %> <%= command.id %> --session-id --target-org my-dev-org + <%= config.bin %> <%= command.id %> --authoring-bundle My_Local_Agent From 47040f0bfd74bdcc6c805765af67f5e70987f439 Mon Sep 17 00:00:00 2001 From: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:23:36 -0800 Subject: [PATCH 16/25] Update agent preview send command documentation --- messages/agent.preview.send.md | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/messages/agent.preview.send.md b/messages/agent.preview.send.md index 187d4fca..1ca76a64 100644 --- a/messages/agent.preview.send.md +++ b/messages/agent.preview.send.md @@ -1,45 +1,47 @@ # summary -Send a message in a preview session (beta). +Send a message to an existing agent preview session. # description -Send an utterance to an existing preview session and get the agent response. Use the session ID returned by "agent preview start". Specify the same agent with --api-name or --authoring-bundle as used when starting the session; one is required. +You must have previously started a programmatic agent preview session with the "agent preview start" command to then use this command to send the agent a message (utterance). This command then displays the agent's response. + +The original "agent preview start" command outputs a session ID which you then use with this command. Alternatively, you can use the --authoring-bundle or --api-name flags to specify the API name of the authoring bundle, or the agent itself, as long as the agent has only one active preview session. If it has multiple sessions, then you must instead use --session-id to identify the exact one you want to send a message to. # flags.session-id.summary -Session ID from "agent preview start". Omit when the agent has exactly one active session. +Session ID outputted by "agent preview start". Not required when the agent has exactly one active session. Run "agent preview sessions" to see list of all sessions. # flags.utterance.summary -Utterance to send to the agent. +Utterance to send to the agent, enclosed in double quotes. # flags.api-name.summary -API name or ID of the published agent. +API name of the activated published agent you want to preview. # flags.authoring-bundle.summary -API name of the authoring bundle (Agent Script). +API name of the authoring bundle metadata component that contains the agent's Agent Script file. # error.noSession -No preview session found. Run "sf agent preview start" first. +No agent preview session found. Run "sf agent preview start" to start a new agent preview session. # error.multipleSessions -Multiple preview sessions found for this agent. Specify --session-id. Sessions: %s +Multiple preview sessions found for this agent. Use the --session-id flag to identify a specific session. Sessions: %s # examples -- Send a message to a simulated Agent: +- Send a message to an agent identified by its session ID; use the default org: - <%= config.bin %> <%= command.id %> --utterance "What can you help me with?" --authoring-bundle My_Agent + <%= config.bin %> <%= command.id %> --utterance "What can you help me with?" --session-id -Send a message to a published Agent: +- Send a message to an activated published agent using its API name; you get an error if the agent has more than one active session. Use the org with alias "my-dev-org": -<%= config.bin %> <%= command.id %> --utterance "What can you help me with?" --api-name My_Published_Agent + <%= config.bin %> <%= command.id %> --utterance "What can you help me with?" --api-name My_Published_Agent --target-org my-dev-org -- Send to a specific session when multiple exist: +- Send a message to an agent using its authoring bundle API name; you get an error if the agent has more than one active session: - <%= config.bin %> <%= command.id %> --session-id --utterance "What can you help me with?" --target-org my-dev-org + <%= config.bin %> <%= command.id %> --utterance "what can you help me with?" --authoring-bundle My_Local_Agent From d5b27f581ba45a83ffe460cff872bfb37dea1b31 Mon Sep 17 00:00:00 2001 From: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:24:59 -0800 Subject: [PATCH 17/25] Clarify agent preview sessions documentation Updated documentation to clarify that the command lists all known programmatic agent preview sessions and provides more details on usage. --- messages/agent.preview.sessions.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/messages/agent.preview.sessions.md b/messages/agent.preview.sessions.md index ac064d1f..8a79790a 100644 --- a/messages/agent.preview.sessions.md +++ b/messages/agent.preview.sessions.md @@ -1,14 +1,16 @@ # summary -List cached preview sessions (beta). +List all known programmatic agent preview sessions. # description -List preview sessions that were started with "agent preview start" and are still in the cache. Use this to see which sessions exist so you can end them with "agent preview end" (e.g. to clean up or resolve "multiple sessions" when using send without --session-id). Agent ID is the authoring bundle name for Agent Script agents, or the agent ID for published agents. +This command lists the agent preview sessions that were started with the "agent preview start" command and are still in the local cache. Use this command to discover specific session IDs that you can pass to the "agent preview send" or "agent preview end" commands with the --session-id flag. + +Programmatic agent preview sessions can be started for published activated agents and by using an agent's local authoring bundle, which contains its Agent Script file. In this command's output table, the Agent column contains either the API name of the authoring bundle or published agent, whichever was used when starting the session. # output.empty -No cached preview sessions found. +No cached agent preview sessions found. # output.tableHeader.agent @@ -20,6 +22,6 @@ Session ID # examples -- List all cached preview sessions: +- List all cached agent preview sessions: - <%= config.bin %> <%= command.id %> + <%= config.bin %> <%= command.id %> From 5f929dbbe9907ebcbffb1b0aa9ac1b095ac6d471 Mon Sep 17 00:00:00 2001 From: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:25:53 -0800 Subject: [PATCH 18/25] Revise agent preview session documentation Updated the documentation for starting a programmatic agent preview session, clarifying the use of flags and examples. --- messages/agent.preview.start.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/messages/agent.preview.start.md b/messages/agent.preview.start.md index 4a70b001..a6f08789 100644 --- a/messages/agent.preview.start.md +++ b/messages/agent.preview.start.md @@ -1,22 +1,24 @@ # summary -Start a programmatic preview session (beta). +Start a programmatic agent preview session. # description -Start an agent preview session and get a session ID. Use the session ID with "agent preview send" and "agent preview end". Specify the agent with --api-name (published agent) or --authoring-bundle (Agent Script); one is required. Use --use-live-actions for live mode; otherwise preview uses mock (simulated) actions. +This command outputs a session ID that you then use with the "agent preview send" command to send an utterance to the agent. Use the "agent preview sessions" command to list all active sessions and the "agent preview end" command to end a specific session. + +Identify the agent you want to start previewing with either the --authoring-bundle flag to specify a local authoring bundle's API name or --api-name to specify an activated published agent's API name. When using the authoring bundle, which contains the agent's Agent Script file, the preview uses mocked actions by default. Specify --use-live-actions for live mode, which uses the real Apex classes, flows, etc, in the org for the actions. # flags.api-name.summary -API name or ID of the published agent. +API name of the activated published agent you want to preview. # flags.authoring-bundle.summary -API name of the authoring bundle (Agent Script) to preview. +API name of the authoring bundle metadata component that contains the agent's Agent Script file. # flags.use-live-actions.summary -Use real actions in the org; if not specified, preview uses mock (simulated) actions. +Use real actions in the org; if not specified, preview uses AI to simulate (mock) actions. # output.sessionId @@ -24,14 +26,14 @@ Session ID: %s # examples -- Start a preview session with an authoring bundle and use mock actions: +- Start a programmatic agent preview session by specifying an authoring bundle; uses mocked actions by default. Use the org with alias "my-dev-org": - <%= config.bin %> <%= command.id %> --authoring-bundle My_Agent_Bundle --target-org my-dev-org + <%= config.bin %> <%= command.id %> --authoring-bundle My_Agent_Bundle --target-org my-dev-org -- Start a preview session with an authoring bundle and use real actions: +- Similar to previous example but use live actions and the default org: - <%= config.bin %> <%= command.id %> --authoring-bundle My_Agent_Bundle --use-live-actions --target-org my-dev-org + <%= config.bin %> <%= command.id %> --authoring-bundle My_Agent_Bundle --use-live-actions -- Start a preview session with a published agent: +- Start a preview session with an activated published agent: - <%= config.bin %> <%= command.id %> --api-name My_Published_Agent + <%= config.bin %> <%= command.id %> --api-name My_Published_Agent From c1e047f2eacc55baa42ef9591ebd9fbd577aa74c Mon Sep 17 00:00:00 2001 From: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:46:02 -0800 Subject: [PATCH 19/25] Update agent preview sessions documentation Clarified the description of programmatic agent preview sessions and their output. --- messages/agent.preview.sessions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/messages/agent.preview.sessions.md b/messages/agent.preview.sessions.md index 8a79790a..27dc69c8 100644 --- a/messages/agent.preview.sessions.md +++ b/messages/agent.preview.sessions.md @@ -6,7 +6,7 @@ List all known programmatic agent preview sessions. This command lists the agent preview sessions that were started with the "agent preview start" command and are still in the local cache. Use this command to discover specific session IDs that you can pass to the "agent preview send" or "agent preview end" commands with the --session-id flag. -Programmatic agent preview sessions can be started for published activated agents and by using an agent's local authoring bundle, which contains its Agent Script file. In this command's output table, the Agent column contains either the API name of the authoring bundle or published agent, whichever was used when starting the session. +Programmatic agent preview sessions can be started for both published activated agents and by using an agent's local authoring bundle, which contains its Agent Script file. In this command's output table, the Agent column contains either the API name of the authoring bundle or the published agent, whichever was used when starting the session. In the table, if the same API name has multiple rows with different session IDs, then it means that you previously started multiple preview sessions with the associated agent. # output.empty From 7d23b41a0cf7d11b881fda372bb3e6b0f9d892f7 Mon Sep 17 00:00:00 2001 From: Esteban Romero Date: Mon, 9 Feb 2026 19:10:46 -0300 Subject: [PATCH 20/25] chore: bump agents lib --- package.json | 2 +- yarn.lock | 597 ++++++++++++++++++++++++++------------------------- 2 files changed, 311 insertions(+), 288 deletions(-) diff --git a/package.json b/package.json index 7f228432..82623291 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "@inquirer/prompts": "^7.10.1", "@oclif/core": "^4", "@oclif/multi-stage-output": "^0.8.29", - "@salesforce/agents": "^0.22.4", + "@salesforce/agents": "^0.22.6", "@salesforce/core": "^8.24.3", "@salesforce/kit": "^3.2.4", "@salesforce/sf-plugins-core": "^12.2.6", diff --git a/yarn.lock b/yarn.lock index 65e661dd..bbf4aa41 100644 --- a/yarn.lock +++ b/yarn.lock @@ -78,81 +78,81 @@ "@smithy/util-utf8" "^2.0.0" tslib "^2.6.2" -"@aws-sdk/client-cloudfront@^3.980.0": - version "3.982.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudfront/-/client-cloudfront-3.982.0.tgz#309db3fe254f729bb14f28169853a11a7dc5662d" - integrity sha512-AbDbqc5UJ8A+3MOHqMv76n3PNXWQ2kVKFxcuGjNyKGYFocWJx3uQuP14VyeOh3pUnCEIV16eSKspfhUOuyFmuw== +"@aws-sdk/client-cloudfront@^3.985.0": + version "3.986.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-cloudfront/-/client-cloudfront-3.986.0.tgz#0d3aac516a53e67dfb41154686502efd543ec25a" + integrity sha512-/3rhUiTvzCxDawuSWObqXJ+V0OAwKxlsFOTerfV8UKPt0D1OrLXpAwT3im7iPRyVSBfv/15cI4Mwj5AqtWHgDg== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "^3.973.6" - "@aws-sdk/credential-provider-node" "^3.972.5" + "@aws-sdk/core" "^3.973.7" + "@aws-sdk/credential-provider-node" "^3.972.6" "@aws-sdk/middleware-host-header" "^3.972.3" "@aws-sdk/middleware-logger" "^3.972.3" "@aws-sdk/middleware-recursion-detection" "^3.972.3" - "@aws-sdk/middleware-user-agent" "^3.972.6" + "@aws-sdk/middleware-user-agent" "^3.972.7" "@aws-sdk/region-config-resolver" "^3.972.3" "@aws-sdk/types" "^3.973.1" - "@aws-sdk/util-endpoints" "3.982.0" + "@aws-sdk/util-endpoints" "3.986.0" "@aws-sdk/util-user-agent-browser" "^3.972.3" - "@aws-sdk/util-user-agent-node" "^3.972.4" + "@aws-sdk/util-user-agent-node" "^3.972.5" "@smithy/config-resolver" "^4.4.6" - "@smithy/core" "^3.22.0" + "@smithy/core" "^3.22.1" "@smithy/fetch-http-handler" "^5.3.9" "@smithy/hash-node" "^4.2.8" "@smithy/invalid-dependency" "^4.2.8" "@smithy/middleware-content-length" "^4.2.8" - "@smithy/middleware-endpoint" "^4.4.12" - "@smithy/middleware-retry" "^4.4.29" + "@smithy/middleware-endpoint" "^4.4.13" + "@smithy/middleware-retry" "^4.4.30" "@smithy/middleware-serde" "^4.2.9" "@smithy/middleware-stack" "^4.2.8" "@smithy/node-config-provider" "^4.3.8" - "@smithy/node-http-handler" "^4.4.8" + "@smithy/node-http-handler" "^4.4.9" "@smithy/protocol-http" "^5.3.8" - "@smithy/smithy-client" "^4.11.1" + "@smithy/smithy-client" "^4.11.2" "@smithy/types" "^4.12.0" "@smithy/url-parser" "^4.2.8" "@smithy/util-base64" "^4.3.0" "@smithy/util-body-length-browser" "^4.2.0" "@smithy/util-body-length-node" "^4.2.1" - "@smithy/util-defaults-mode-browser" "^4.3.28" - "@smithy/util-defaults-mode-node" "^4.2.31" + "@smithy/util-defaults-mode-browser" "^4.3.29" + "@smithy/util-defaults-mode-node" "^4.2.32" "@smithy/util-endpoints" "^3.2.8" "@smithy/util-middleware" "^4.2.8" "@smithy/util-retry" "^4.2.8" - "@smithy/util-stream" "^4.5.10" + "@smithy/util-stream" "^4.5.11" "@smithy/util-utf8" "^4.2.0" "@smithy/util-waiter" "^4.2.8" tslib "^2.6.2" -"@aws-sdk/client-s3@^3.980.0": - version "3.982.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.982.0.tgz#a4646be026b46de356e486fcf232a6072d2ee236" - integrity sha512-k0ANYAtPiON9BwLXcDgJXkmmCAGEuSk2pZOvrMej2kNhs3xTXoPshIUR5UMCD9apYiWtXJJfXMZSgaME+iWNaQ== +"@aws-sdk/client-s3@^3.985.0": + version "3.986.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.986.0.tgz#38ecea36c41b36748b7c703ba09d77ce95c7d6ee" + integrity sha512-IcDJ8shVVvbxgMe8+dLWcv6uhSwmX65PHTVGX81BhWAElPnp3CL8w/5uzOPRo4n4/bqIk9eskGVEIicw2o+SrA== dependencies: "@aws-crypto/sha1-browser" "5.2.0" "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "^3.973.6" - "@aws-sdk/credential-provider-node" "^3.972.5" + "@aws-sdk/core" "^3.973.7" + "@aws-sdk/credential-provider-node" "^3.972.6" "@aws-sdk/middleware-bucket-endpoint" "^3.972.3" "@aws-sdk/middleware-expect-continue" "^3.972.3" - "@aws-sdk/middleware-flexible-checksums" "^3.972.4" + "@aws-sdk/middleware-flexible-checksums" "^3.972.5" "@aws-sdk/middleware-host-header" "^3.972.3" "@aws-sdk/middleware-location-constraint" "^3.972.3" "@aws-sdk/middleware-logger" "^3.972.3" "@aws-sdk/middleware-recursion-detection" "^3.972.3" - "@aws-sdk/middleware-sdk-s3" "^3.972.6" + "@aws-sdk/middleware-sdk-s3" "^3.972.7" "@aws-sdk/middleware-ssec" "^3.972.3" - "@aws-sdk/middleware-user-agent" "^3.972.6" + "@aws-sdk/middleware-user-agent" "^3.972.7" "@aws-sdk/region-config-resolver" "^3.972.3" - "@aws-sdk/signature-v4-multi-region" "3.982.0" + "@aws-sdk/signature-v4-multi-region" "3.986.0" "@aws-sdk/types" "^3.973.1" - "@aws-sdk/util-endpoints" "3.982.0" + "@aws-sdk/util-endpoints" "3.986.0" "@aws-sdk/util-user-agent-browser" "^3.972.3" - "@aws-sdk/util-user-agent-node" "^3.972.4" + "@aws-sdk/util-user-agent-node" "^3.972.5" "@smithy/config-resolver" "^4.4.6" - "@smithy/core" "^3.22.0" + "@smithy/core" "^3.22.1" "@smithy/eventstream-serde-browser" "^4.2.8" "@smithy/eventstream-serde-config-resolver" "^4.3.8" "@smithy/eventstream-serde-node" "^4.2.8" @@ -163,86 +163,86 @@ "@smithy/invalid-dependency" "^4.2.8" "@smithy/md5-js" "^4.2.8" "@smithy/middleware-content-length" "^4.2.8" - "@smithy/middleware-endpoint" "^4.4.12" - "@smithy/middleware-retry" "^4.4.29" + "@smithy/middleware-endpoint" "^4.4.13" + "@smithy/middleware-retry" "^4.4.30" "@smithy/middleware-serde" "^4.2.9" "@smithy/middleware-stack" "^4.2.8" "@smithy/node-config-provider" "^4.3.8" - "@smithy/node-http-handler" "^4.4.8" + "@smithy/node-http-handler" "^4.4.9" "@smithy/protocol-http" "^5.3.8" - "@smithy/smithy-client" "^4.11.1" + "@smithy/smithy-client" "^4.11.2" "@smithy/types" "^4.12.0" "@smithy/url-parser" "^4.2.8" "@smithy/util-base64" "^4.3.0" "@smithy/util-body-length-browser" "^4.2.0" "@smithy/util-body-length-node" "^4.2.1" - "@smithy/util-defaults-mode-browser" "^4.3.28" - "@smithy/util-defaults-mode-node" "^4.2.31" + "@smithy/util-defaults-mode-browser" "^4.3.29" + "@smithy/util-defaults-mode-node" "^4.2.32" "@smithy/util-endpoints" "^3.2.8" "@smithy/util-middleware" "^4.2.8" "@smithy/util-retry" "^4.2.8" - "@smithy/util-stream" "^4.5.10" + "@smithy/util-stream" "^4.5.11" "@smithy/util-utf8" "^4.2.0" "@smithy/util-waiter" "^4.2.8" tslib "^2.6.2" -"@aws-sdk/client-sso@3.982.0": - version "3.982.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.982.0.tgz#36ea3868045c6d0ade03bf7a0119ac3a1abf79a8" - integrity sha512-qJrIiivmvujdGqJ0ldSUvhN3k3N7GtPesoOI1BSt0fNXovVnMz4C/JmnkhZihU7hJhDvxJaBROLYTU+lpild4w== +"@aws-sdk/client-sso@3.985.0": + version "3.985.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.985.0.tgz#67287e255389c73d45f8b3b6b55ba7b57a5f73f0" + integrity sha512-81J8iE8MuXhdbMfIz4sWFj64Pe41bFi/uqqmqOC5SlGv+kwoyLsyKS/rH2tW2t5buih4vTUxskRjxlqikTD4oQ== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "^3.973.6" + "@aws-sdk/core" "^3.973.7" "@aws-sdk/middleware-host-header" "^3.972.3" "@aws-sdk/middleware-logger" "^3.972.3" "@aws-sdk/middleware-recursion-detection" "^3.972.3" - "@aws-sdk/middleware-user-agent" "^3.972.6" + "@aws-sdk/middleware-user-agent" "^3.972.7" "@aws-sdk/region-config-resolver" "^3.972.3" "@aws-sdk/types" "^3.973.1" - "@aws-sdk/util-endpoints" "3.982.0" + "@aws-sdk/util-endpoints" "3.985.0" "@aws-sdk/util-user-agent-browser" "^3.972.3" - "@aws-sdk/util-user-agent-node" "^3.972.4" + "@aws-sdk/util-user-agent-node" "^3.972.5" "@smithy/config-resolver" "^4.4.6" - "@smithy/core" "^3.22.0" + "@smithy/core" "^3.22.1" "@smithy/fetch-http-handler" "^5.3.9" "@smithy/hash-node" "^4.2.8" "@smithy/invalid-dependency" "^4.2.8" "@smithy/middleware-content-length" "^4.2.8" - "@smithy/middleware-endpoint" "^4.4.12" - "@smithy/middleware-retry" "^4.4.29" + "@smithy/middleware-endpoint" "^4.4.13" + "@smithy/middleware-retry" "^4.4.30" "@smithy/middleware-serde" "^4.2.9" "@smithy/middleware-stack" "^4.2.8" "@smithy/node-config-provider" "^4.3.8" - "@smithy/node-http-handler" "^4.4.8" + "@smithy/node-http-handler" "^4.4.9" "@smithy/protocol-http" "^5.3.8" - "@smithy/smithy-client" "^4.11.1" + "@smithy/smithy-client" "^4.11.2" "@smithy/types" "^4.12.0" "@smithy/url-parser" "^4.2.8" "@smithy/util-base64" "^4.3.0" "@smithy/util-body-length-browser" "^4.2.0" "@smithy/util-body-length-node" "^4.2.1" - "@smithy/util-defaults-mode-browser" "^4.3.28" - "@smithy/util-defaults-mode-node" "^4.2.31" + "@smithy/util-defaults-mode-browser" "^4.3.29" + "@smithy/util-defaults-mode-node" "^4.2.32" "@smithy/util-endpoints" "^3.2.8" "@smithy/util-middleware" "^4.2.8" "@smithy/util-retry" "^4.2.8" "@smithy/util-utf8" "^4.2.0" tslib "^2.6.2" -"@aws-sdk/core@^3.973.6": - version "3.973.6" - resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.973.6.tgz#dd7ff2af60034da3e1af7926d2ce7efe0341ea64" - integrity sha512-pz4ZOw3BLG0NdF25HoB9ymSYyPbMiIjwQJ2aROXRhAzt+b+EOxStfFv8s5iZyP6Kiw7aYhyWxj5G3NhmkoOTKw== +"@aws-sdk/core@^3.973.7": + version "3.973.7" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.973.7.tgz#b2b3e8f272ba283ff8c066560e15b26238fdb410" + integrity sha512-wNZZQQNlJ+hzD49cKdo+PY6rsTDElO8yDImnrI69p2PLBa7QomeUKAJWYp9xnaR38nlHqWhMHZuYLCQ3oSX+xg== dependencies: "@aws-sdk/types" "^3.973.1" "@aws-sdk/xml-builder" "^3.972.4" - "@smithy/core" "^3.22.0" + "@smithy/core" "^3.22.1" "@smithy/node-config-provider" "^4.3.8" "@smithy/property-provider" "^4.2.8" "@smithy/protocol-http" "^5.3.8" "@smithy/signature-v4" "^5.3.8" - "@smithy/smithy-client" "^4.11.1" + "@smithy/smithy-client" "^4.11.2" "@smithy/types" "^4.12.0" "@smithy/util-base64" "^4.3.0" "@smithy/util-middleware" "^4.2.8" @@ -257,46 +257,46 @@ "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@aws-sdk/credential-provider-env@^3.972.4": - version "3.972.4" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.4.tgz#33b5ad1169ce5b7ac313ce2c27b939277795b9d0" - integrity sha512-/8dnc7+XNMmViEom2xsNdArQxQPSgy4Z/lm6qaFPTrMFesT1bV3PsBhb19n09nmxHdrtQskYmViddUIjUQElXg== +"@aws-sdk/credential-provider-env@^3.972.5": + version "3.972.5" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.5.tgz#33ccf5df157a2e14a502e2295996f830547b6346" + integrity sha512-LxJ9PEO4gKPXzkufvIESUysykPIdrV7+Ocb9yAhbhJLE4TiAYqbCVUE+VuKP1leGR1bBfjWjYgSV5MxprlX3mQ== dependencies: - "@aws-sdk/core" "^3.973.6" + "@aws-sdk/core" "^3.973.7" "@aws-sdk/types" "^3.973.1" "@smithy/property-provider" "^4.2.8" "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@aws-sdk/credential-provider-http@^3.972.6": - version "3.972.6" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.6.tgz#3a6720826cff7620690fc4fdf522a81e299a2ebf" - integrity sha512-5ERWqRljiZv44AIdvIRQ3k+EAV0Sq2WeJHvXuK7gL7bovSxOf8Al7MLH7Eh3rdovH4KHFnlIty7J71mzvQBl5Q== +"@aws-sdk/credential-provider-http@^3.972.7": + version "3.972.7" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.7.tgz#089412221a6ca6769e9fe9af95c12b0fbebcce93" + integrity sha512-L2uOGtvp2x3bTcxFTpSM+GkwFIPd8pHfGWO1764icMbo7e5xJh0nfhx1UwkXLnwvocTNEf8A7jISZLYjUSNaTg== dependencies: - "@aws-sdk/core" "^3.973.6" + "@aws-sdk/core" "^3.973.7" "@aws-sdk/types" "^3.973.1" "@smithy/fetch-http-handler" "^5.3.9" - "@smithy/node-http-handler" "^4.4.8" + "@smithy/node-http-handler" "^4.4.9" "@smithy/property-provider" "^4.2.8" "@smithy/protocol-http" "^5.3.8" - "@smithy/smithy-client" "^4.11.1" + "@smithy/smithy-client" "^4.11.2" "@smithy/types" "^4.12.0" - "@smithy/util-stream" "^4.5.10" + "@smithy/util-stream" "^4.5.11" tslib "^2.6.2" -"@aws-sdk/credential-provider-ini@^3.972.4": - version "3.972.4" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.4.tgz#77df2d72984b51f51307914a543514414f780e19" - integrity sha512-eRUg+3HaUKuXWn/lEMirdiA5HOKmEl8hEHVuszIDt2MMBUKgVX5XNGmb3XmbgU17h6DZ+RtjbxQpjhz3SbTjZg== - dependencies: - "@aws-sdk/core" "^3.973.6" - "@aws-sdk/credential-provider-env" "^3.972.4" - "@aws-sdk/credential-provider-http" "^3.972.6" - "@aws-sdk/credential-provider-login" "^3.972.4" - "@aws-sdk/credential-provider-process" "^3.972.4" - "@aws-sdk/credential-provider-sso" "^3.972.4" - "@aws-sdk/credential-provider-web-identity" "^3.972.4" - "@aws-sdk/nested-clients" "3.982.0" +"@aws-sdk/credential-provider-ini@^3.972.5": + version "3.972.5" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.5.tgz#520754da94d91e801ea16303806c93b86ef11444" + integrity sha512-SdDTYE6jkARzOeL7+kudMIM4DaFnP5dZVeatzw849k4bSXDdErDS188bgeNzc/RA2WGrlEpsqHUKP6G7sVXhZg== + dependencies: + "@aws-sdk/core" "^3.973.7" + "@aws-sdk/credential-provider-env" "^3.972.5" + "@aws-sdk/credential-provider-http" "^3.972.7" + "@aws-sdk/credential-provider-login" "^3.972.5" + "@aws-sdk/credential-provider-process" "^3.972.5" + "@aws-sdk/credential-provider-sso" "^3.972.5" + "@aws-sdk/credential-provider-web-identity" "^3.972.5" + "@aws-sdk/nested-clients" "3.985.0" "@aws-sdk/types" "^3.973.1" "@smithy/credential-provider-imds" "^4.2.8" "@smithy/property-provider" "^4.2.8" @@ -304,13 +304,13 @@ "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@aws-sdk/credential-provider-login@^3.972.4": - version "3.972.4" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.4.tgz#dc656fbcb3206e5bebbdc44a571503a5ba4e0e6d" - integrity sha512-nLGjXuvWWDlQAp505xIONI7Gam0vw2p7Qu3P6on/W2q7rjJXtYjtpHbcsaOjJ/pAju3eTvEQuSuRedcRHVQIAQ== +"@aws-sdk/credential-provider-login@^3.972.5": + version "3.972.5" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.5.tgz#5677d7a829e5b9a14e37d5784f944cb2c513e082" + integrity sha512-uYq1ILyTSI6ZDCMY5+vUsRM0SOCVI7kaW4wBrehVVkhAxC6y+e9rvGtnoZqCOWL1gKjTMouvsf4Ilhc5NCg1Aw== dependencies: - "@aws-sdk/core" "^3.973.6" - "@aws-sdk/nested-clients" "3.982.0" + "@aws-sdk/core" "^3.973.7" + "@aws-sdk/nested-clients" "3.985.0" "@aws-sdk/types" "^3.973.1" "@smithy/property-provider" "^4.2.8" "@smithy/protocol-http" "^5.3.8" @@ -318,17 +318,17 @@ "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@aws-sdk/credential-provider-node@^3.972.5": - version "3.972.5" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.5.tgz#2f16620eee963c445a727d4a7b5e000df41fa7b6" - integrity sha512-VWXKgSISQCI2GKN3zakTNHSiZ0+mux7v6YHmmbLQp/o3fvYUQJmKGcLZZzg2GFA+tGGBStplra9VFNf/WwxpYg== - dependencies: - "@aws-sdk/credential-provider-env" "^3.972.4" - "@aws-sdk/credential-provider-http" "^3.972.6" - "@aws-sdk/credential-provider-ini" "^3.972.4" - "@aws-sdk/credential-provider-process" "^3.972.4" - "@aws-sdk/credential-provider-sso" "^3.972.4" - "@aws-sdk/credential-provider-web-identity" "^3.972.4" +"@aws-sdk/credential-provider-node@^3.972.6": + version "3.972.6" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.6.tgz#ac44d928df3e4598263d8b35a6ad6785f65a3ecd" + integrity sha512-DZ3CnAAtSVtVz+G+ogqecaErMLgzph4JH5nYbHoBMgBkwTUV+SUcjsjOJwdBJTHu3Dm6l5LBYekZoU2nDqQk2A== + dependencies: + "@aws-sdk/credential-provider-env" "^3.972.5" + "@aws-sdk/credential-provider-http" "^3.972.7" + "@aws-sdk/credential-provider-ini" "^3.972.5" + "@aws-sdk/credential-provider-process" "^3.972.5" + "@aws-sdk/credential-provider-sso" "^3.972.5" + "@aws-sdk/credential-provider-web-identity" "^3.972.5" "@aws-sdk/types" "^3.973.1" "@smithy/credential-provider-imds" "^4.2.8" "@smithy/property-provider" "^4.2.8" @@ -336,39 +336,39 @@ "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@aws-sdk/credential-provider-process@^3.972.4": - version "3.972.4" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.4.tgz#4918ba11b88e0bc96e488f199e6d5605f2449c49" - integrity sha512-TCZpWUnBQN1YPk6grvd5x419OfXjHvhj5Oj44GYb84dOVChpg/+2VoEj+YVA4F4E/6huQPNnX7UYbTtxJqgihw== +"@aws-sdk/credential-provider-process@^3.972.5": + version "3.972.5" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.5.tgz#6851a7170a1625e661600f5954b1cbe21dcf1eb4" + integrity sha512-HDKF3mVbLnuqGg6dMnzBf1VUOywE12/N286msI9YaK9mEIzdsGCtLTvrDhe3Up0R9/hGFbB+9l21/TwF5L1C6g== dependencies: - "@aws-sdk/core" "^3.973.6" + "@aws-sdk/core" "^3.973.7" "@aws-sdk/types" "^3.973.1" "@smithy/property-provider" "^4.2.8" "@smithy/shared-ini-file-loader" "^4.4.3" "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@aws-sdk/credential-provider-sso@^3.972.4": - version "3.972.4" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.4.tgz#0a945243e26e76c7460e20ae6725e07aa03d75fb" - integrity sha512-wzsGwv9mKlwJ3vHLyembBvGE/5nPUIwRR2I51B1cBV4Cb4ql9nIIfpmHzm050XYTY5fqTOKJQnhLj7zj89VG8g== +"@aws-sdk/credential-provider-sso@^3.972.5": + version "3.972.5" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.5.tgz#a2ee1952f045ccfdef7527cf0f763533a23ba8ab" + integrity sha512-8urj3AoeNeQisjMmMBhFeiY2gxt6/7wQQbEGun0YV/OaOOiXrIudTIEYF8ZfD+NQI6X1FY5AkRsx6O/CaGiybA== dependencies: - "@aws-sdk/client-sso" "3.982.0" - "@aws-sdk/core" "^3.973.6" - "@aws-sdk/token-providers" "3.982.0" + "@aws-sdk/client-sso" "3.985.0" + "@aws-sdk/core" "^3.973.7" + "@aws-sdk/token-providers" "3.985.0" "@aws-sdk/types" "^3.973.1" "@smithy/property-provider" "^4.2.8" "@smithy/shared-ini-file-loader" "^4.4.3" "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@aws-sdk/credential-provider-web-identity@^3.972.4": - version "3.972.4" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.4.tgz#8dd394a0d1e1663fe0dec5ae9f2688cc5d3de410" - integrity sha512-hIzw2XzrG8jzsUSEatehmpkd5rWzASg5IHUfA+m01k/RtvfAML7ZJVVohuKdhAYx+wV2AThLiQJVzqn7F0khrw== +"@aws-sdk/credential-provider-web-identity@^3.972.5": + version "3.972.5" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.5.tgz#c9aaaa412382802418d610828034b77051e98370" + integrity sha512-OK3cULuJl6c+RcDZfPpaK5o3deTOnKZbxm7pzhFNGA3fI2hF9yDih17fGRazJzGGWaDVlR9ejZrpDef4DJCEsw== dependencies: - "@aws-sdk/core" "^3.973.6" - "@aws-sdk/nested-clients" "3.982.0" + "@aws-sdk/core" "^3.973.7" + "@aws-sdk/nested-clients" "3.985.0" "@aws-sdk/types" "^3.973.1" "@smithy/property-provider" "^4.2.8" "@smithy/shared-ini-file-loader" "^4.4.3" @@ -398,15 +398,15 @@ "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@aws-sdk/middleware-flexible-checksums@^3.972.4": - version "3.972.4" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.972.4.tgz#3d43d12a11a07a6660093d10b16d8e65bf242050" - integrity sha512-xOxsUkF3O3BtIe3tf54OpPo94eZepjFm3z0Dd2TZKbsPxMiRTFXurC04wJ58o/wPW9YHVO9VqZik3MfoPfrKlw== +"@aws-sdk/middleware-flexible-checksums@^3.972.5": + version "3.972.5" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.972.5.tgz#08391e6a407a6894e105dca37126dac1f969c107" + integrity sha512-SF/1MYWx67OyCrLA4icIpWUfCkdlOi8Y1KecQ9xYxkL10GMjVdPTGPnYhAg0dw5U43Y9PVUWhAV2ezOaG+0BLg== dependencies: "@aws-crypto/crc32" "5.2.0" "@aws-crypto/crc32c" "5.2.0" "@aws-crypto/util" "5.2.0" - "@aws-sdk/core" "^3.973.6" + "@aws-sdk/core" "^3.973.7" "@aws-sdk/crc64-nvme" "3.972.0" "@aws-sdk/types" "^3.973.1" "@smithy/is-array-buffer" "^4.2.0" @@ -414,7 +414,7 @@ "@smithy/protocol-http" "^5.3.8" "@smithy/types" "^4.12.0" "@smithy/util-middleware" "^4.2.8" - "@smithy/util-stream" "^4.5.10" + "@smithy/util-stream" "^4.5.11" "@smithy/util-utf8" "^4.2.0" tslib "^2.6.2" @@ -457,23 +457,23 @@ "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@aws-sdk/middleware-sdk-s3@^3.972.6": - version "3.972.6" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.6.tgz#d3ca2f65298c6a1076f0244833f11019f5766cb2" - integrity sha512-Xq7wM6kbgJN1UO++8dvH/efPb1nTwWqFCpZCR7RCLOETP7xAUAhVo7JmsCnML5Di/iC4Oo5VrJ4QmkYcMZniLw== +"@aws-sdk/middleware-sdk-s3@^3.972.7": + version "3.972.7" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.7.tgz#eb77744a4533fb289e7278b8e0fa40816f53c309" + integrity sha512-VtZ7tMIw18VzjG+I6D6rh2eLkJfTtByiFoCIauGDtTTPBEUMQUiGaJ/zZrPlCY6BsvLLeFKz3+E5mntgiOWmIg== dependencies: - "@aws-sdk/core" "^3.973.6" + "@aws-sdk/core" "^3.973.7" "@aws-sdk/types" "^3.973.1" "@aws-sdk/util-arn-parser" "^3.972.2" - "@smithy/core" "^3.22.0" + "@smithy/core" "^3.22.1" "@smithy/node-config-provider" "^4.3.8" "@smithy/protocol-http" "^5.3.8" "@smithy/signature-v4" "^5.3.8" - "@smithy/smithy-client" "^4.11.1" + "@smithy/smithy-client" "^4.11.2" "@smithy/types" "^4.12.0" "@smithy/util-config-provider" "^4.2.0" "@smithy/util-middleware" "^4.2.8" - "@smithy/util-stream" "^4.5.10" + "@smithy/util-stream" "^4.5.11" "@smithy/util-utf8" "^4.2.0" tslib "^2.6.2" @@ -486,57 +486,57 @@ "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@aws-sdk/middleware-user-agent@^3.972.6": - version "3.972.6" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.6.tgz#8abf3fae980f80834460d3345937e5843a59082d" - integrity sha512-TehLN8W/kivl0U9HcS+keryElEWORROpghDXZBLfnb40DXM7hx/i+7OOjkogXQOF3QtUraJVRkHQ07bPhrWKlw== +"@aws-sdk/middleware-user-agent@^3.972.7": + version "3.972.7" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.7.tgz#3c49e740d6e7b594952a5e340925e0a0bfde4777" + integrity sha512-HUD+geASjXSCyL/DHPQc/Ua7JhldTcIglVAoCV8kiVm99IaFSlAbTvEnyhZwdE6bdFyTL+uIaWLaCFSRsglZBQ== dependencies: - "@aws-sdk/core" "^3.973.6" + "@aws-sdk/core" "^3.973.7" "@aws-sdk/types" "^3.973.1" - "@aws-sdk/util-endpoints" "3.982.0" - "@smithy/core" "^3.22.0" + "@aws-sdk/util-endpoints" "3.985.0" + "@smithy/core" "^3.22.1" "@smithy/protocol-http" "^5.3.8" "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@aws-sdk/nested-clients@3.982.0": - version "3.982.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/nested-clients/-/nested-clients-3.982.0.tgz#b7d50bb7c273ed688fab0e52d5430dc6b0167d6d" - integrity sha512-VVkaH27digrJfdVrT64rjkllvOp4oRiZuuJvrylLXAKl18ujToJR7AqpDldL/LS63RVne3QWIpkygIymxFtliQ== +"@aws-sdk/nested-clients@3.985.0": + version "3.985.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/nested-clients/-/nested-clients-3.985.0.tgz#b67ee7500dc3e2306e06ff7fa02badae154c3231" + integrity sha512-TsWwKzb/2WHafAY0CE7uXgLj0FmnkBTgfioG9HO+7z/zCPcl1+YU+i7dW4o0y+aFxFgxTMG+ExBQpqT/k2ao8g== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "^3.973.6" + "@aws-sdk/core" "^3.973.7" "@aws-sdk/middleware-host-header" "^3.972.3" "@aws-sdk/middleware-logger" "^3.972.3" "@aws-sdk/middleware-recursion-detection" "^3.972.3" - "@aws-sdk/middleware-user-agent" "^3.972.6" + "@aws-sdk/middleware-user-agent" "^3.972.7" "@aws-sdk/region-config-resolver" "^3.972.3" "@aws-sdk/types" "^3.973.1" - "@aws-sdk/util-endpoints" "3.982.0" + "@aws-sdk/util-endpoints" "3.985.0" "@aws-sdk/util-user-agent-browser" "^3.972.3" - "@aws-sdk/util-user-agent-node" "^3.972.4" + "@aws-sdk/util-user-agent-node" "^3.972.5" "@smithy/config-resolver" "^4.4.6" - "@smithy/core" "^3.22.0" + "@smithy/core" "^3.22.1" "@smithy/fetch-http-handler" "^5.3.9" "@smithy/hash-node" "^4.2.8" "@smithy/invalid-dependency" "^4.2.8" "@smithy/middleware-content-length" "^4.2.8" - "@smithy/middleware-endpoint" "^4.4.12" - "@smithy/middleware-retry" "^4.4.29" + "@smithy/middleware-endpoint" "^4.4.13" + "@smithy/middleware-retry" "^4.4.30" "@smithy/middleware-serde" "^4.2.9" "@smithy/middleware-stack" "^4.2.8" "@smithy/node-config-provider" "^4.3.8" - "@smithy/node-http-handler" "^4.4.8" + "@smithy/node-http-handler" "^4.4.9" "@smithy/protocol-http" "^5.3.8" - "@smithy/smithy-client" "^4.11.1" + "@smithy/smithy-client" "^4.11.2" "@smithy/types" "^4.12.0" "@smithy/url-parser" "^4.2.8" "@smithy/util-base64" "^4.3.0" "@smithy/util-body-length-browser" "^4.2.0" "@smithy/util-body-length-node" "^4.2.1" - "@smithy/util-defaults-mode-browser" "^4.3.28" - "@smithy/util-defaults-mode-node" "^4.2.31" + "@smithy/util-defaults-mode-browser" "^4.3.29" + "@smithy/util-defaults-mode-node" "^4.2.32" "@smithy/util-endpoints" "^3.2.8" "@smithy/util-middleware" "^4.2.8" "@smithy/util-retry" "^4.2.8" @@ -554,25 +554,25 @@ "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@aws-sdk/signature-v4-multi-region@3.982.0": - version "3.982.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.982.0.tgz#d11cae61faf8e63428246b4bd32d4ed962827c26" - integrity sha512-AWqjMAH848aNwnLCtIKM3WO00eHuUoYVfQMP4ccrUHhnEduGOusVgdHQ5mLNQZZNZzREuBwnPPhIP55cy0gFSg== +"@aws-sdk/signature-v4-multi-region@3.986.0": + version "3.986.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.986.0.tgz#bd34f23daee028905640023c483fdc12eda9a4e6" + integrity sha512-Upw+rw7wCH93E6QWxqpAqJLrUmJYVUAWrk4tCOBnkeuwzGERZvJFL5UQ6TAJFj9T18Ih+vNFaACh8J5aP4oTBw== dependencies: - "@aws-sdk/middleware-sdk-s3" "^3.972.6" + "@aws-sdk/middleware-sdk-s3" "^3.972.7" "@aws-sdk/types" "^3.973.1" "@smithy/protocol-http" "^5.3.8" "@smithy/signature-v4" "^5.3.8" "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@aws-sdk/token-providers@3.982.0": - version "3.982.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.982.0.tgz#c7a65d4f286c69ef10918fe7758bbe8dc7a064e9" - integrity sha512-v3M0KYp2TVHYHNBT7jHD9lLTWAdS9CaWJ2jboRKt0WAB65bA7iUEpR+k4VqKYtpQN4+8kKSc4w+K6kUNZkHKQw== +"@aws-sdk/token-providers@3.985.0": + version "3.985.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.985.0.tgz#bd700b624093352d25ff564457000ee3efdc6522" + integrity sha512-+hwpHZyEq8k+9JL2PkE60V93v2kNhUIv7STFt+EAez1UJsJOQDhc5LpzEX66pNjclI5OTwBROs/DhJjC/BtMjQ== dependencies: - "@aws-sdk/core" "^3.973.6" - "@aws-sdk/nested-clients" "3.982.0" + "@aws-sdk/core" "^3.973.7" + "@aws-sdk/nested-clients" "3.985.0" "@aws-sdk/types" "^3.973.1" "@smithy/property-provider" "^4.2.8" "@smithy/shared-ini-file-loader" "^4.4.3" @@ -594,10 +594,21 @@ dependencies: tslib "^2.6.2" -"@aws-sdk/util-endpoints@3.982.0": - version "3.982.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.982.0.tgz#65674c566a8aa2d35b27dcd4132873e75f58dc76" - integrity sha512-M27u8FJP7O0Of9hMWX5dipp//8iglmV9jr7R8SR8RveU+Z50/8TqH68Tu6wUWBGMfXjzbVwn1INIAO5lZrlxXQ== +"@aws-sdk/util-endpoints@3.985.0": + version "3.985.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.985.0.tgz#a6393811e86aaf71e17aa3313551c19e54ed59f8" + integrity sha512-vth7UfGSUR3ljvaq8V4Rc62FsM7GUTH/myxPWkaEgOrprz1/Pc72EgTXxj+cPPPDAfHFIpjhkB7T7Td0RJx+BA== + dependencies: + "@aws-sdk/types" "^3.973.1" + "@smithy/types" "^4.12.0" + "@smithy/url-parser" "^4.2.8" + "@smithy/util-endpoints" "^3.2.8" + tslib "^2.6.2" + +"@aws-sdk/util-endpoints@3.986.0": + version "3.986.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.986.0.tgz#16d3bd7227e5c3797a10a95d37898e511e75a72a" + integrity sha512-Mqi79L38qi1gCG3adlVdbNrSxvcm1IPDLiJPA3OBypY5ewxUyWbaA3DD4goG+EwET6LSFgZJcRSIh6KBNpP5pA== dependencies: "@aws-sdk/types" "^3.973.1" "@smithy/types" "^4.12.0" @@ -622,12 +633,12 @@ bowser "^2.11.0" tslib "^2.6.2" -"@aws-sdk/util-user-agent-node@^3.972.4": - version "3.972.4" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.972.4.tgz#35cf669fa3e77973422da5a1df50b79b41d460b3" - integrity sha512-3WFCBLiM8QiHDfosQq3Py+lIMgWlFWwFQliUHUqwEiRqLnKyhgbU3AKa7AWJF7lW2Oc/2kFNY4MlAYVnVc0i8A== +"@aws-sdk/util-user-agent-node@^3.972.5": + version "3.972.5" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.972.5.tgz#fccbe3b707a9d9bb7a755f7164f4f87dbeb81f84" + integrity sha512-GsUDF+rXyxDZkkJxUsDxnA67FG+kc5W1dnloCFLl6fWzceevsCYzJpASBzT+BPjwUgREE6FngfJYYYMQUY5fZQ== dependencies: - "@aws-sdk/middleware-user-agent" "^3.972.6" + "@aws-sdk/middleware-user-agent" "^3.972.7" "@aws-sdk/types" "^3.973.1" "@smithy/node-config-provider" "^4.3.8" "@smithy/types" "^4.12.0" @@ -683,9 +694,9 @@ semver "^6.3.1" "@babel/generator@^7.29.0": - version "7.29.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.29.0.tgz#4cba5a76b3c71d8be31761b03329d5dc7768447f" - integrity sha512-vSH118/wwM/pLR38g/Sgk05sNtro6TlTJKuiMXDaZqPUfjTFcudpCOt00IhOfj+1BFAX+UFAlzCU+6WXr3GLFQ== + version "7.29.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.29.1.tgz#d09876290111abbb00ef962a7b83a5307fba0d50" + integrity sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw== dependencies: "@babel/parser" "^7.29.0" "@babel/types" "^7.29.0" @@ -1324,6 +1335,11 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" +"@isaacs/cliui@^9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-9.0.0.tgz#4d0a3f127058043bf2e7ee169eaf30ed901302f3" + integrity sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1398,30 +1414,30 @@ node-fetch "^2.6.1" xml2js "^0.6.2" -"@jsonjoy.com/base64@17.65.0": - version "17.65.0" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/base64/-/base64-17.65.0.tgz#ba3b023c69ab311e5b706289414a44ee46117824" - integrity sha512-Xrh7Fm/M0QAYpekSgmskdZYnFdSGnsxJ/tHaolA4bNwWdG9i65S8m83Meh7FOxyJyQAdo4d4J97NOomBLEfkDQ== +"@jsonjoy.com/base64@17.67.0": + version "17.67.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/base64/-/base64-17.67.0.tgz#7eeda3cb41138d77a90408fd2e42b2aba10576d7" + integrity sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw== "@jsonjoy.com/base64@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@jsonjoy.com/base64/-/base64-1.1.2.tgz#cf8ea9dcb849b81c95f14fc0aaa151c6b54d2578" integrity sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA== -"@jsonjoy.com/buffers@17.65.0", "@jsonjoy.com/buffers@^17.65.0": - version "17.65.0" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/buffers/-/buffers-17.65.0.tgz#d6890737d9cbc49c17e2c5d1a2d796c57205152c" - integrity sha512-eBrIXd0/Ld3p9lpDDlMaMn6IEfWqtHMD+z61u0JrIiPzsV1r7m6xDZFRxJyvIFTEO+SWdYF9EiQbXZGd8BzPfA== +"@jsonjoy.com/buffers@17.67.0", "@jsonjoy.com/buffers@^17.65.0": + version "17.67.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/buffers/-/buffers-17.67.0.tgz#5c58dbcdeea8824ce296bd1cfce006c2eb167b3d" + integrity sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw== "@jsonjoy.com/buffers@^1.0.0", "@jsonjoy.com/buffers@^1.2.0": version "1.2.1" resolved "https://registry.yarnpkg.com/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz#8d99c7f67eaf724d3428dfd9826c6455266a5c83" integrity sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA== -"@jsonjoy.com/codegen@17.65.0": - version "17.65.0" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/codegen/-/codegen-17.65.0.tgz#531524f37fd3e1d1189de18fef346e998eee8952" - integrity sha512-7MXcRYe7n3BG+fo3jicvjB0+6ypl2Y/bQp79Sp7KeSiiCgLqw4Oled6chVv07/xLVTdo3qa1CD0VCCnPaw+RGA== +"@jsonjoy.com/codegen@17.67.0": + version "17.67.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/codegen/-/codegen-17.67.0.tgz#3635fd8769d77e19b75dc5574bc9756019b2e591" + integrity sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q== "@jsonjoy.com/codegen@^1.0.0": version "1.0.0" @@ -1514,25 +1530,25 @@ tree-dump "^1.1.0" "@jsonjoy.com/json-pack@^17.65.0": - version "17.65.0" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/json-pack/-/json-pack-17.65.0.tgz#4ea06dd0aee1c29954bd978c4f107401dbf713fb" - integrity sha512-e0SG/6qUCnVhHa0rjDJHgnXnbsacooHVqQHxspjvlYQSkHm+66wkHw6Gql+3u/WxI/b1VsOdUi0M+fOtkgKGdQ== - dependencies: - "@jsonjoy.com/base64" "17.65.0" - "@jsonjoy.com/buffers" "17.65.0" - "@jsonjoy.com/codegen" "17.65.0" - "@jsonjoy.com/json-pointer" "17.65.0" - "@jsonjoy.com/util" "17.65.0" + version "17.67.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/json-pack/-/json-pack-17.67.0.tgz#8dd8ff65dd999c5d4d26df46c63915c7bdec093a" + integrity sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w== + dependencies: + "@jsonjoy.com/base64" "17.67.0" + "@jsonjoy.com/buffers" "17.67.0" + "@jsonjoy.com/codegen" "17.67.0" + "@jsonjoy.com/json-pointer" "17.67.0" + "@jsonjoy.com/util" "17.67.0" hyperdyperid "^1.2.0" thingies "^2.5.0" tree-dump "^1.1.0" -"@jsonjoy.com/json-pointer@17.65.0": - version "17.65.0" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/json-pointer/-/json-pointer-17.65.0.tgz#4bad42d86c9ee0ad1758c082b065bd5e16f8dc36" - integrity sha512-uhTe+XhlIZpWOxgPcnO+iSCDgKKBpwkDVTyYiXX9VayGV8HSFVJM67M6pUE71zdnXF1W0Da21AvnhlmdwYPpow== +"@jsonjoy.com/json-pointer@17.67.0": + version "17.67.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/json-pointer/-/json-pointer-17.67.0.tgz#74439573dc046e0c9a3a552fb94b391bc75313b8" + integrity sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA== dependencies: - "@jsonjoy.com/util" "17.65.0" + "@jsonjoy.com/util" "17.67.0" "@jsonjoy.com/json-pointer@^1.0.2": version "1.0.2" @@ -1542,13 +1558,13 @@ "@jsonjoy.com/codegen" "^1.0.0" "@jsonjoy.com/util" "^1.9.0" -"@jsonjoy.com/util@17.65.0", "@jsonjoy.com/util@^17.65.0": - version "17.65.0" - resolved "https://registry.yarnpkg.com/@jsonjoy.com/util/-/util-17.65.0.tgz#b27832bdf7aeaf4a36f9cb8721cb4ffb086f06a1" - integrity sha512-cWiEHZccQORf96q2y6zU3wDeIVPeidmGqd9cNKJRYoVHTV0S1eHPy5JTbHpMnGfDvtvujQwQozOqgO9ABu6h0w== +"@jsonjoy.com/util@17.67.0", "@jsonjoy.com/util@^17.65.0": + version "17.67.0" + resolved "https://registry.yarnpkg.com/@jsonjoy.com/util/-/util-17.67.0.tgz#7c4288fc3808233e55c7610101e7bb4590cddd3f" + integrity sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew== dependencies: - "@jsonjoy.com/buffers" "17.65.0" - "@jsonjoy.com/codegen" "17.65.0" + "@jsonjoy.com/buffers" "17.67.0" + "@jsonjoy.com/codegen" "17.67.0" "@jsonjoy.com/util@^1.9.0": version "1.9.0" @@ -1617,9 +1633,9 @@ wrap-ansi "^9.0.2" "@oclif/plugin-command-snapshot@^5.3.8": - version "5.3.8" - resolved "https://registry.yarnpkg.com/@oclif/plugin-command-snapshot/-/plugin-command-snapshot-5.3.8.tgz#b952a270bfdfaea941f244363c4bcf781398d9b9" - integrity sha512-pxuW6kVAkAJBZzk7w2xUy32D+EQGeef15Kyjz13LYazHNXcVdrzP/5726VGfMnK3U4W1QyJ7CalzZxRLVvxQcg== + version "5.3.9" + resolved "https://registry.yarnpkg.com/@oclif/plugin-command-snapshot/-/plugin-command-snapshot-5.3.9.tgz#a687cd53c17e1faeb8381a0b46121f498e4f09b5" + integrity sha512-1l/uOKbRefdRQzyOLwqlOq+CUtvuqFNnEi8c7vYEE3eCnlSk3th2LZXoC/Na3y8eIEJU1mhEa6FX8UumCcVzzg== dependencies: "@oclif/core" "^4" ansis "^3.17.0" @@ -1628,10 +1644,10 @@ lodash.difference "^4.5.0" lodash.get "^4.4.2" lodash.sortby "^4.7.0" - semver "^7.7.3" + semver "^7.7.4" ts-json-schema-generator "^1.5.1" -"@oclif/plugin-help@^6.2.36": +"@oclif/plugin-help@^6.2.37": version "6.2.37" resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-6.2.37.tgz#93c7a37241a48f32517f41199a3bd56954a9d68c" integrity sha512-5N/X/FzlJaYfpaHwDC0YHzOzKDWa41s9t+4FpCDu4f9OMReds4JeNBaaWk9rlIzdKjh2M6AC5Q18ORfECRkHGA== @@ -1719,16 +1735,16 @@ resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== -"@salesforce/agents@^0.22.4": - version "0.22.4" - resolved "https://registry.yarnpkg.com/@salesforce/agents/-/agents-0.22.4.tgz#a9fe2beb94bd12e1f941bb22fc3c00ed24888662" - integrity sha512-Oe5LApwpEFm+VeOtatQPvyfcJlYIP6ixpJo/CbAIX0M9TI9UP7E/oLmQfkxylaiqYQzNtK+B21x7+Lwr6cPgxg== +"@salesforce/agents@^0.22.6": + version "0.22.6" + resolved "https://registry.yarnpkg.com/@salesforce/agents/-/agents-0.22.6.tgz#35ea2ec80b3da6489b6ff18c63a9a7c4f2ca6e96" + integrity sha512-FOJFNVPsJeDEZ9TBk1YL0O0iwovDhXCdk+gw0+Ow1XB2h0eAY4FFOWWzexTXnYKflsVVvA+1lgEeFQS4bwgJSw== dependencies: - "@salesforce/core" "^8.24.0" + "@salesforce/core" "^8.25.1" "@salesforce/kit" "^3.2.4" - "@salesforce/source-deploy-retrieve" "^12.31.6" - "@salesforce/types" "^1.5.0" - fast-xml-parser "^5.3.4" + "@salesforce/source-deploy-retrieve" "^12.31.10" + "@salesforce/types" "^1.6.0" + fast-xml-parser "^5.3.5" nock "^13.5.6" yaml "^2.8.2" @@ -1748,7 +1764,7 @@ strip-ansi "6.0.1" ts-retry-promise "^0.8.1" -"@salesforce/core@^8.18.7", "@salesforce/core@^8.23.1", "@salesforce/core@^8.23.3", "@salesforce/core@^8.24.0", "@salesforce/core@^8.24.3", "@salesforce/core@^8.5.1", "@salesforce/core@^8.8.0": +"@salesforce/core@^8.18.7", "@salesforce/core@^8.23.1", "@salesforce/core@^8.23.3", "@salesforce/core@^8.24.0", "@salesforce/core@^8.24.3", "@salesforce/core@^8.25.1", "@salesforce/core@^8.5.1", "@salesforce/core@^8.8.0": version "8.25.1" resolved "https://registry.yarnpkg.com/@salesforce/core/-/core-8.25.1.tgz#7646025598bb59b6f95b3656baf8eb0b63a43052" integrity sha512-Jon0a9uZpp+mNa5PiY+y8dTjaPcsMaxXEkswdzWotrdrZ4g84MmPKSEv+Q/LtXw3uc9i4RmqBJBUXSIvZhgrjg== @@ -1870,7 +1886,7 @@ cli-progress "^3.12.0" terminal-link "^3.0.0" -"@salesforce/source-deploy-retrieve@^12.31.10", "@salesforce/source-deploy-retrieve@^12.31.6": +"@salesforce/source-deploy-retrieve@^12.31.10": version "12.31.10" resolved "https://registry.yarnpkg.com/@salesforce/source-deploy-retrieve/-/source-deploy-retrieve-12.31.10.tgz#612886356d81c87eb9053bbc9173546556fd5f36" integrity sha512-kUdJicJUd3/lzNQOvDW1Sc5iBl8PVv2Tz7L59YA/Le0fzZCYM72oyKwdbl/f6kc+MzJpMVia2+AxrvVZir8oJw== @@ -2056,7 +2072,7 @@ "@smithy/util-middleware" "^4.2.8" tslib "^2.6.2" -"@smithy/core@^3.22.0", "@smithy/core@^3.22.1": +"@smithy/core@^3.22.1": version "3.22.1" resolved "https://registry.yarnpkg.com/@smithy/core/-/core-3.22.1.tgz#c34180d541c9dc5d29412809a6aa497ea47d74f8" integrity sha512-x3ie6Crr58MWrm4viHqqy2Du2rHYZjwu8BekasrQx4ca+Y24dzVAwq3yErdqIbc2G3I0kLQA13PQ+/rde+u65g== @@ -2208,7 +2224,7 @@ "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@smithy/middleware-endpoint@^4.4.12", "@smithy/middleware-endpoint@^4.4.13": +"@smithy/middleware-endpoint@^4.4.13": version "4.4.13" resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.13.tgz#8a5dda67cbf8e63155a908a724e7ae09b763baad" integrity sha512-x6vn0PjYmGdNuKh/juUJJewZh7MoQ46jYaJ2mvekF4EesMuFfrl4LaW/k97Zjf8PTCPQmPgMvwewg7eNoH9n5w== @@ -2222,7 +2238,7 @@ "@smithy/util-middleware" "^4.2.8" tslib "^2.6.2" -"@smithy/middleware-retry@^4.4.29": +"@smithy/middleware-retry@^4.4.30": version "4.4.30" resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-4.4.30.tgz#a0548803044069b53a332606d4b4f803f07f8963" integrity sha512-CBGyFvN0f8hlnqKH/jckRDz78Snrp345+PVk8Ux7pnkUCW97Iinse59lY78hBt04h1GZ6hjBN94BRwZy1xC8Bg== @@ -2264,7 +2280,7 @@ "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@smithy/node-http-handler@^4.4.8", "@smithy/node-http-handler@^4.4.9": +"@smithy/node-http-handler@^4.4.9": version "4.4.9" resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-4.4.9.tgz#c167e5b8aed33c5edaf25b903ed9866858499c93" integrity sha512-KX5Wml5mF+luxm1szW4QDz32e3NObgJ4Fyw+irhph4I/2geXwUy4jkIMUs5ZPGflRBeR6BUkC2wqIab4Llgm3w== @@ -2337,7 +2353,7 @@ "@smithy/util-utf8" "^4.2.0" tslib "^2.6.2" -"@smithy/smithy-client@^4.11.1", "@smithy/smithy-client@^4.11.2": +"@smithy/smithy-client@^4.11.2": version "4.11.2" resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-4.11.2.tgz#1f6a4d75625dbaa16bafbe9b10cf6a41c98fe3da" integrity sha512-SCkGmFak/xC1n7hKRsUr6wOnBTJ3L22Qd4e8H1fQIuKTAjntwgU8lrdMe7uHdiT2mJAOWA/60qaW9tiMu69n1A== @@ -2412,7 +2428,7 @@ dependencies: tslib "^2.6.2" -"@smithy/util-defaults-mode-browser@^4.3.28": +"@smithy/util-defaults-mode-browser@^4.3.29": version "4.3.29" resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.29.tgz#fd4f9563ffd1fb49d092e5b86bacc7796170763e" integrity sha512-nIGy3DNRmOjaYaaKcQDzmWsro9uxlaqUOhZDHQed9MW/GmkBZPtnU70Pu1+GT9IBmUXwRdDuiyaeiy9Xtpn3+Q== @@ -2422,7 +2438,7 @@ "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@smithy/util-defaults-mode-node@^4.2.31": +"@smithy/util-defaults-mode-node@^4.2.32": version "4.2.32" resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.32.tgz#bc3e9ee1711a9ac3b1c29ea0bef0e785c1da30da" integrity sha512-7dtFff6pu5fsjqrVve0YMhrnzJtccCWDacNKOkiZjJ++fmjGExmmSu341x+WU6Oc1IccL7lDuaUj7SfrHpWc5Q== @@ -2468,7 +2484,7 @@ "@smithy/types" "^4.12.0" tslib "^2.6.2" -"@smithy/util-stream@^4.5.10", "@smithy/util-stream@^4.5.11": +"@smithy/util-stream@^4.5.11": version "4.5.11" resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-4.5.11.tgz#69bf0816c2a396b389a48a64455dacdb57893984" integrity sha512-lKmZ0S/3Qj2OF5H1+VzvDLb6kRxGzZHq6f3rAsoSu5cTLGsn3v3VQBA8czkNNXlLjoFEtVu3OQT2jEeOtOE2CA== @@ -2522,12 +2538,12 @@ tslib "^2.6.2" "@stylistic/eslint-plugin@^5.2.3": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@stylistic/eslint-plugin/-/eslint-plugin-5.7.1.tgz#bb108186a0133071b38be5fa705cd262260be8a8" - integrity sha512-zjTUwIsEfT+k9BmXwq1QEFYsb4afBlsI1AXFyWQBgggMzwBFOuu92pGrE5OFx90IOjNl+lUbQoTG7f8S0PkOdg== + version "5.8.0" + resolved "https://registry.yarnpkg.com/@stylistic/eslint-plugin/-/eslint-plugin-5.8.0.tgz#e3986833ebb9476310eb9d03a7483c046b0f57ad" + integrity sha512-WNPVF/FfBAjyi3OA7gok8swRiImNLKI4dmV3iK/GC/0xSJR7eCzBFsw9hLZVgb1+MYNLy7aDsjohxN1hA/FIfQ== dependencies: "@eslint-community/eslint-utils" "^4.9.1" - "@typescript-eslint/types" "^8.53.1" + "@typescript-eslint/types" "^8.54.0" eslint-visitor-keys "^4.2.1" espree "^10.4.0" estraverse "^5.3.0" @@ -2656,9 +2672,9 @@ "@types/node" "*" "@types/node@*": - version "25.2.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-25.2.0.tgz#015b7d228470c1dcbfc17fe9c63039d216b4d782" - integrity sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w== + version "25.2.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-25.2.2.tgz#0ddfe326c326afcb3422d32bfe5eb2938e1cb5db" + integrity sha512-BkmoP5/FhRYek5izySdkOneRyXYN35I860MFAGupTdebyE66uZaR+bXLHq8k4DirE5DwQi3NuhvRU1jqTVwUrQ== dependencies: undici-types "~7.16.0" @@ -2675,16 +2691,16 @@ undici-types "~5.26.4" "@types/node@^20.4.8": - version "20.19.31" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.31.tgz#762ddf4088b3ac2389077cf1fb5336800a1fb4d5" - integrity sha512-5jsi0wpncvTD33Sh1UCgacK37FFwDn+EG7wCmEvs62fCvBL+n8/76cAYDok21NF6+jaVWIqKwCZyX7Vbu8eB3A== + version "20.19.33" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.33.tgz#ac8364c623b72d43125f0e7dd722bbe968f0c65e" + integrity sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw== dependencies: undici-types "~6.21.0" "@types/node@^22.5.5": - version "22.19.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.19.8.tgz#b0c7812df8a98a001570950f4275f0c10fcad101" - integrity sha512-ebO/Yl+EAvVe8DnMfi+iaAyIqYdK0q/q0y0rw82INWEKJOBe6b/P3YWE8NW7oOlF/nXFNrHwhARrN/hdgDkraA== + version "22.19.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.19.10.tgz#a802d3cc6bdc190ec2b0cbf6958bf127c0ec2926" + integrity sha512-tF5VOugLS/EuDlTBijk0MqABfP8UxgYazTLo3uIn3b4yJgg26QRbVYJYsDtHrjdDUIRfP70+VfhTTc+CE1yskw== dependencies: undici-types "~6.21.0" @@ -2699,9 +2715,9 @@ integrity sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw== "@types/react@^18.3.12", "@types/react@^18.3.3": - version "18.3.27" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.27.tgz#74a3b590ea183983dc65a474dc17553ae1415c34" - integrity sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w== + version "18.3.28" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.28.tgz#0a85b1a7243b4258d9f626f43797ba18eb5f8781" + integrity sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw== dependencies: "@types/prop-types" "*" csstype "^3.2.2" @@ -2819,10 +2835,10 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.18.0.tgz#b90a57ccdea71797ffffa0321e744f379ec838c9" integrity sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ== -"@typescript-eslint/types@^8.53.1": - version "8.54.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.54.0.tgz#c12d41f67a2e15a8a96fbc5f2d07b17331130889" - integrity sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA== +"@typescript-eslint/types@^8.54.0": + version "8.55.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.55.0.tgz#8449c5a7adac61184cac92dbf6315733569708c2" + integrity sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w== "@typescript-eslint/typescript-estree@6.21.0": version "6.21.0" @@ -2988,9 +3004,9 @@ ansi-escapes@^5.0.0: type-fest "^1.0.2" ansi-escapes@^7.0.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.2.0.tgz#31b25afa3edd3efc09d98c2fee831d460ff06b49" - integrity sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw== + version "7.3.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-7.3.0.tgz#5395bb74b2150a4a1d6e3c2565f4aeca78d28627" + integrity sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg== dependencies: environment "^1.0.0" @@ -3261,9 +3277,9 @@ binary-extensions@^2.0.0: integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== bowser@^2.11.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.13.1.tgz#5a4c652de1d002f847dd011819f5fc729f308a7e" - integrity sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw== + version "2.14.1" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.14.1.tgz#4ea39bf31e305184522d7ad7bfd91389e4f0cb79" + integrity sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg== brace-expansion@^1.1.7: version "1.1.12" @@ -3438,9 +3454,9 @@ camelcase@^6.0.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001759: - version "1.0.30001767" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001767.tgz#0279c498e862efb067938bba0a0aabafe8d0b730" - integrity sha512-34+zUAMhSH+r+9eKmYG+k2Rpt8XttfE4yXAjoZvkAPs15xcYQhyBYdalJ65BzivAvGRMViEjy6oKr/S91loekQ== + version "1.0.30001769" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz#1ad91594fad7dc233777c2781879ab5409f7d9c2" + integrity sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg== capital-case@^1.0.4: version "1.0.4" @@ -4692,13 +4708,20 @@ fast-uri@^3.0.1: resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== -fast-xml-parser@5.3.4, fast-xml-parser@^5.3.4: +fast-xml-parser@5.3.4: version "5.3.4" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.3.4.tgz#06f39aafffdbc97bef0321e626c7ddd06a043ecf" integrity sha512-EFd6afGmXlCx8H8WTZHhAoDaWaGyuIBoZJ2mknrNxug+aZKjkp0a0dlars9Izl+jF+7Gu1/5f/2h68cQpe0IiA== dependencies: strnum "^2.1.0" +fast-xml-parser@^5.3.4, fast-xml-parser@^5.3.5: + version "5.3.5" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.3.5.tgz#3e914cb852e636923cb555deaa356f7366e18b49" + integrity sha512-JeaA2Vm9ffQKp9VjvfzObuMCjUYAp5WDYhRYL5LrBPY/jUDlUtOvDfot0vKSkB9tuX885BDHjtw4fZadD95wnA== + dependencies: + strnum "^2.1.2" + fastest-levenshtein@^1.0.7: version "1.0.16" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" @@ -5987,11 +6010,11 @@ jackspeak@^3.1.2: "@pkgjs/parseargs" "^0.11.0" jackspeak@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.1.1.tgz#96876030f450502047fc7e8c7fcf8ce8124e43ae" - integrity sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ== + version "4.2.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.2.3.tgz#27ef80f33b93412037c3bea4f8eddf80e1931483" + integrity sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg== dependencies: - "@isaacs/cliui" "^8.0.2" + "@isaacs/cliui" "^9.0.0" jake@^10.8.5: version "10.9.4" @@ -6999,17 +7022,17 @@ object.values@^1.1.6, object.values@^1.2.1: es-object-atoms "^1.0.0" oclif@^4.22.70: - version "4.22.73" - resolved "https://registry.yarnpkg.com/oclif/-/oclif-4.22.73.tgz#a2b75aa0279d6eac70d123d0908b8f6e35858159" - integrity sha512-nyODp0FrwdKc/jBPFeloGmAQA49Y6nC7ZANHwPZjok09RUCJpaJkuoe7EH6EOeMrS1Qsb+muYsV4fBa6bkVjIg== + version "4.22.77" + resolved "https://registry.yarnpkg.com/oclif/-/oclif-4.22.77.tgz#325621695aa760a7d807fb457fd2ece376c2562d" + integrity sha512-H0iVdnKNItaNV9xU0fDAqEy3o82BRTpps9ePoqVEctrqMCqKnKS5VpNSLZCJN/WiY85fXD496llwGqoizBBVrw== dependencies: - "@aws-sdk/client-cloudfront" "^3.980.0" - "@aws-sdk/client-s3" "^3.980.0" + "@aws-sdk/client-cloudfront" "^3.985.0" + "@aws-sdk/client-s3" "^3.985.0" "@inquirer/confirm" "^3.1.22" "@inquirer/input" "^2.2.4" "@inquirer/select" "^2.5.0" "@oclif/core" "^4.8.0" - "@oclif/plugin-help" "^6.2.36" + "@oclif/plugin-help" "^6.2.37" "@oclif/plugin-not-found" "^3.2.74" "@oclif/plugin-warn-if-update-available" "^3.1.55" ansis "^3.16.0" @@ -7023,7 +7046,7 @@ oclif@^4.22.70: got "^13" lodash "^4.17.23" normalize-package-data "^6" - semver "^7.7.3" + semver "^7.7.4" sort-package-json "^2.15.1" tiny-jsonc "^1.0.2" validate-npm-package-name "^5.0.1" @@ -7893,10 +7916,10 @@ semver@^6.0.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.4, semver@^7.3.5, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.7.3: - version "7.7.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" - integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== +semver@^7.3.4, semver@^7.3.5, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.7.3, semver@^7.7.4: + version "7.7.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.4.tgz#28464e36060e991fa7a11d0279d2d3f3b57a7e8a" + integrity sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA== sentence-case@^3.0.4: version "3.0.4" @@ -8427,7 +8450,7 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strnum@^2.1.0: +strnum@^2.1.0, strnum@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.1.2.tgz#a5e00ba66ab25f9cafa3726b567ce7a49170937a" integrity sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ== @@ -8523,17 +8546,17 @@ tinyglobby@^0.2.14, tinyglobby@^0.2.9: fdir "^6.5.0" picomatch "^4.0.3" -tldts-core@^7.0.22: - version "7.0.22" - resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-7.0.22.tgz#c446174555a1f38c166740934e5809a092b1d4c8" - integrity sha512-KgbTDC5wzlL6j/x6np6wCnDSMUq4kucHNm00KXPbfNzmllCmtmvtykJHfmgdHntwIeupW04y8s1N/43S1PkQDw== +tldts-core@^7.0.23: + version "7.0.23" + resolved "https://registry.yarnpkg.com/tldts-core/-/tldts-core-7.0.23.tgz#47bf18282a44641304a399d247703413b5d3e309" + integrity sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ== tldts@^7.0.5: - version "7.0.22" - resolved "https://registry.yarnpkg.com/tldts/-/tldts-7.0.22.tgz#1ace3cf67ee9ca197636da1b410dff8ba837d84f" - integrity sha512-nqpKFC53CgopKPjT6Wfb6tpIcZXHcI6G37hesvikhx0EmUGPkZrujRyAjgnmp1SHNgpQfKVanZ+KfpANFt2Hxw== + version "7.0.23" + resolved "https://registry.yarnpkg.com/tldts/-/tldts-7.0.23.tgz#444f0f0720fa777839a23ea665e04f61ee57217a" + integrity sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw== dependencies: - tldts-core "^7.0.22" + tldts-core "^7.0.23" to-regex-range@^5.0.1: version "5.0.1" From 0d8f5b9af69ef37bfd80f811607674bfbdbf579e Mon Sep 17 00:00:00 2001 From: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> Date: Mon, 9 Feb 2026 14:11:56 -0800 Subject: [PATCH 21/25] Clarify usage of session ID and API name flags --- messages/agent.preview.end.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/messages/agent.preview.end.md b/messages/agent.preview.end.md index 967d1230..8de9e790 100644 --- a/messages/agent.preview.end.md +++ b/messages/agent.preview.end.md @@ -6,7 +6,7 @@ End an existing programmatic agent preview session and get trace location. You must have previously started a programmatic agent preview session with the "agent preview start" command to then use this command to end it. This command also displays the local directory where the session trace files are stored. -The original "agent preview start" command outputs a session ID which you then use with this command. Alternatively, you can use the --authoring-bundle or --api-name flags to specify the API name of the authoring bundle, or the agent itself, as long as the agent has only one active preview session. If it has multiple sessions, then you must instead use --session-id to identify the exact one you want to end. +The original "agent preview start" command outputs a session ID which you then use with the --session-id flag of this command. You don't have to specify the --session-id flag if an agent has only one active preview session. You must also specify either the --authoring-bundle or --api-name flag to specify the API name of the authoring bundle or the published agent, respecitvely. To find either API name, navigate to your package directory in your DX project. The API name of an authoring bundle is the same as its directory name under the "aiAuthoringBundles" metadata directory. Similarly, the published agent's API name is the same as its directory name under the "Bots" metadata directory. # flags.session-id.summary @@ -14,7 +14,7 @@ Session ID outputted by "agent preview start". Not required when the agent has e # flags.api-name.summary -API name of the activated published agent you want to preview. +API name of the activated published agent you want to preview. # flags.authoring-bundle.summary @@ -34,11 +34,11 @@ Session traces: %s # examples -- End an agent preview session by specifying its session ID; use the default org: +- End an agent preview session by specifying its session ID and the API name of the published agent; use the default org: - <%= config.bin %> <%= command.id %> --session-id + <%= config.bin %> <%= command.id %> --session-id --api-name My_Published_Agent -- End an agent preview session using the API name of the published agent; you get an error if the agent has more than one active session. Use the org with alias "my-dev-org": +- Similar to previous example, but don't specify a session ID; you get an error if the agent has more than one active session. Use the org with alias "my-dev-org": <%= config.bin %> <%= command.id %> --api-name My_Published_Agent --target-org my-dev-org From a15af70575f84358d773588d132057cd9b805530 Mon Sep 17 00:00:00 2001 From: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> Date: Mon, 9 Feb 2026 14:16:04 -0800 Subject: [PATCH 22/25] Clarify agent message sending command usage Updated command usage instructions for sending messages to agents, clarifying the use of session ID and API name flags. --- messages/agent.preview.send.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/messages/agent.preview.send.md b/messages/agent.preview.send.md index 1ca76a64..428ce765 100644 --- a/messages/agent.preview.send.md +++ b/messages/agent.preview.send.md @@ -6,7 +6,7 @@ Send a message to an existing agent preview session. You must have previously started a programmatic agent preview session with the "agent preview start" command to then use this command to send the agent a message (utterance). This command then displays the agent's response. -The original "agent preview start" command outputs a session ID which you then use with this command. Alternatively, you can use the --authoring-bundle or --api-name flags to specify the API name of the authoring bundle, or the agent itself, as long as the agent has only one active preview session. If it has multiple sessions, then you must instead use --session-id to identify the exact one you want to send a message to. +The original "agent preview start" command outputs a session ID which you then use with the --session-id flag of this command to send a message. You don't have to specify the --session-id flag if an agent has only one active preview session. You must also use either the --authoring-bundle or --api-name flag to specify the API name of the authoring bundle or the published agent, respecitvely. To find either API name, navigate to your package directory in your DX project. The API name of an authoring bundle is the same as its directory name under the "aiAuthoringBundles" metadata directory. Similarly, the published agent's API name is the same as its directory name under the "Bots" metadata directory. # flags.session-id.summary @@ -34,11 +34,11 @@ Multiple preview sessions found for this agent. Use the --session-id flag to ide # examples -- Send a message to an agent identified by its session ID; use the default org: +- Send a message to an activated published agent using its API name and session ID; use the default org: - <%= config.bin %> <%= command.id %> --utterance "What can you help me with?" --session-id + <%= config.bin %> <%= command.id %> --utterance "What can you help me with?" --api-name My_Published_Agent --session-id -- Send a message to an activated published agent using its API name; you get an error if the agent has more than one active session. Use the org with alias "my-dev-org": +- Similar to previous example, but don't specify a session ID; you get an error if the agent has more than one active session. Use the org with alias "my-dev-org": <%= config.bin %> <%= command.id %> --utterance "What can you help me with?" --api-name My_Published_Agent --target-org my-dev-org From 2a8866d80006b5138836c594402fd0ae0494ec79 Mon Sep 17 00:00:00 2001 From: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> Date: Mon, 9 Feb 2026 14:16:57 -0800 Subject: [PATCH 23/25] Fix wording for session ID usage in agent preview end --- messages/agent.preview.end.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/messages/agent.preview.end.md b/messages/agent.preview.end.md index 8de9e790..79cd7e74 100644 --- a/messages/agent.preview.end.md +++ b/messages/agent.preview.end.md @@ -6,7 +6,7 @@ End an existing programmatic agent preview session and get trace location. You must have previously started a programmatic agent preview session with the "agent preview start" command to then use this command to end it. This command also displays the local directory where the session trace files are stored. -The original "agent preview start" command outputs a session ID which you then use with the --session-id flag of this command. You don't have to specify the --session-id flag if an agent has only one active preview session. You must also specify either the --authoring-bundle or --api-name flag to specify the API name of the authoring bundle or the published agent, respecitvely. To find either API name, navigate to your package directory in your DX project. The API name of an authoring bundle is the same as its directory name under the "aiAuthoringBundles" metadata directory. Similarly, the published agent's API name is the same as its directory name under the "Bots" metadata directory. +The original "agent preview start" command outputs a session ID which you then use with the --session-id flag of this command to end the session. You don't have to specify the --session-id flag if an agent has only one active preview session. You must also use either the --authoring-bundle or --api-name flag to specify the API name of the authoring bundle or the published agent, respecitvely. To find either API name, navigate to your package directory in your DX project. The API name of an authoring bundle is the same as its directory name under the "aiAuthoringBundles" metadata directory. Similarly, the published agent's API name is the same as its directory name under the "Bots" metadata directory. # flags.session-id.summary From 8fffc2e7daf3b90149858eb3597a680cf63dcd8f Mon Sep 17 00:00:00 2001 From: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> Date: Mon, 9 Feb 2026 14:18:57 -0800 Subject: [PATCH 24/25] Enhance agent preview session instructions Clarify instructions for identifying agent API names and using live actions. --- messages/agent.preview.start.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/messages/agent.preview.start.md b/messages/agent.preview.start.md index a6f08789..3d840163 100644 --- a/messages/agent.preview.start.md +++ b/messages/agent.preview.start.md @@ -6,7 +6,9 @@ Start a programmatic agent preview session. This command outputs a session ID that you then use with the "agent preview send" command to send an utterance to the agent. Use the "agent preview sessions" command to list all active sessions and the "agent preview end" command to end a specific session. -Identify the agent you want to start previewing with either the --authoring-bundle flag to specify a local authoring bundle's API name or --api-name to specify an activated published agent's API name. When using the authoring bundle, which contains the agent's Agent Script file, the preview uses mocked actions by default. Specify --use-live-actions for live mode, which uses the real Apex classes, flows, etc, in the org for the actions. +Identify the agent you want to start previewing with either the --authoring-bundle flag to specify a local authoring bundle's API name or --api-name to specify an activated published agent's API name. To find either API name, navigate to your package directory in your DX project. The API name of an authoring bundle is the same as its directory name under the "aiAuthoringBundles" metadata directory. Similarly, the published agent's API name is the same as its directory name under the "Bots" metadata directory. + +When starting a preview session using the authoring bundle, which contains the agent's Agent Script file, the preview uses mocked actions by default. Specify --use-live-actions for live mode, which uses the real Apex classes, flows, etc, in the org for the actions. # flags.api-name.summary From 4dd5e0c6e3832b9e59e1d9e6e396b820e0709d02 Mon Sep 17 00:00:00 2001 From: Juliet Shackell <63259011+jshackell-sfdc@users.noreply.github.com> Date: Mon, 9 Feb 2026 14:22:04 -0800 Subject: [PATCH 25/25] Clarify language in agent preview session instructions --- messages/agent.preview.end.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/messages/agent.preview.end.md b/messages/agent.preview.end.md index 79cd7e74..09a4d2f5 100644 --- a/messages/agent.preview.end.md +++ b/messages/agent.preview.end.md @@ -34,14 +34,14 @@ Session traces: %s # examples -- End an agent preview session by specifying its session ID and the API name of the published agent; use the default org: +- End a preview session of a published agent by specifying its session ID and API name ; use the default org: <%= config.bin %> <%= command.id %> --session-id --api-name My_Published_Agent -- Similar to previous example, but don't specify a session ID; you get an error if the agent has more than one active session. Use the org with alias "my-dev-org": +- Similar to previous example, but don't specify a session ID; you get an error if the published agent has more than one active session. Use the org with alias "my-dev-org": <%= config.bin %> <%= command.id %> --api-name My_Published_Agent --target-org my-dev-org -- End an agent preview session using its authoring bundle API name; you get an error if the agent has more than one active session. +- End a preview session of an agent using its authoring bundle API name; you get an error if the agent has more than one active session. <%= config.bin %> <%= command.id %> --authoring-bundle My_Local_Agent