From d3123d6c8667790bce7163d0691a2b71bcda3314 Mon Sep 17 00:00:00 2001 From: Jesse Turner Date: Wed, 4 Mar 2026 15:18:57 +0000 Subject: [PATCH 01/10] feat: add `agentcore traces` command and trace link in invoke TUI Add traces support with three features: 1. `agentcore traces list` - Lists recent traces for a deployed agent by querying CloudWatch Logs Insights. Supports --agent, --target, and --limit options. Displays trace ID, timestamp, and session ID. 2. `agentcore traces get ` - Downloads a full trace to a JSON file from CloudWatch Logs. Supports --agent, --target, and --output options. Saves OpenTelemetry span data to agentcore/.cli/traces/. 3. Trace console link in invoke TUI header - Shows the CloudWatch console URL for viewing traces alongside the existing log link. Both commands also print the CloudWatch console URL for quick access to the trace dashboard. New dependency: @aws-sdk/client-cloudwatch-logs --- package-lock.json | 18 -- src/cli/cli.ts | 2 + src/cli/commands/index.ts | 1 + src/cli/commands/traces/action.ts | 174 ++++++++++++++++++++ src/cli/commands/traces/command.tsx | 127 ++++++++++++++ src/cli/commands/traces/index.ts | 2 + src/cli/commands/traces/types.ts | 11 ++ src/cli/operations/index.ts | 1 + src/cli/operations/traces/get-trace.ts | 116 +++++++++++++ src/cli/operations/traces/index.ts | 3 + src/cli/operations/traces/list-traces.ts | 108 ++++++++++++ src/cli/operations/traces/trace-url.ts | 37 +++++ src/cli/tui/copy.ts | 1 + src/cli/tui/screens/invoke/InvokeScreen.tsx | 18 ++ 14 files changed, 601 insertions(+), 18 deletions(-) create mode 100644 src/cli/commands/traces/action.ts create mode 100644 src/cli/commands/traces/command.tsx create mode 100644 src/cli/commands/traces/index.ts create mode 100644 src/cli/commands/traces/types.ts create mode 100644 src/cli/operations/traces/get-trace.ts create mode 100644 src/cli/operations/traces/index.ts create mode 100644 src/cli/operations/traces/list-traces.ts create mode 100644 src/cli/operations/traces/trace-url.ts diff --git a/package-lock.json b/package-lock.json index dd07aff7..afe6fa1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13098,24 +13098,6 @@ } } }, - "node_modules/vitest/node_modules/yaml": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", - "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/src/cli/cli.ts b/src/cli/cli.ts index bf9477f5..f49112a4 100644 --- a/src/cli/cli.ts +++ b/src/cli/cli.ts @@ -8,6 +8,7 @@ import { registerLogs } from './commands/logs'; import { registerPackage } from './commands/package'; import { registerRemove } from './commands/remove'; import { registerStatus } from './commands/status'; +import { registerTraces } from './commands/traces'; import { registerUpdate } from './commands/update'; import { registerValidate } from './commands/validate'; import { PACKAGE_VERSION } from './constants'; @@ -134,6 +135,7 @@ export function registerCommands(program: Command) { registerPackage(program); registerRemove(program); registerStatus(program); + registerTraces(program); registerUpdate(program); registerValidate(program); } diff --git a/src/cli/commands/index.ts b/src/cli/commands/index.ts index 6234fe63..3e1fd854 100644 --- a/src/cli/commands/index.ts +++ b/src/cli/commands/index.ts @@ -7,4 +7,5 @@ export { registerInvoke } from './invoke'; export { registerPackage } from './package'; export { registerRemove } from './remove'; export { registerStatus } from './status'; +export { registerTraces } from './traces'; export { registerUpdate } from './update'; diff --git a/src/cli/commands/traces/action.ts b/src/cli/commands/traces/action.ts new file mode 100644 index 00000000..578ed932 --- /dev/null +++ b/src/cli/commands/traces/action.ts @@ -0,0 +1,174 @@ +import { ConfigIO } from '../../../lib'; +import type { AgentCoreProjectSpec, AwsDeploymentTargets, DeployedState } from '../../../schema'; +import { buildTraceConsoleUrl, getTrace, listTraces, parseRuntimeArn } from '../../operations/traces'; +import type { TracesGetOptions, TracesListOptions } from './types'; + +export interface TracesContext { + project: AgentCoreProjectSpec; + deployedState: DeployedState; + awsTargets: AwsDeploymentTargets; +} + +export async function loadTracesConfig(configIO: ConfigIO = new ConfigIO()): Promise { + return { + project: await configIO.readProjectSpec(), + deployedState: await configIO.readDeployedState(), + awsTargets: await configIO.readAWSDeploymentTargets(), + }; +} + +interface ResolvedAgent { + agentName: string; + region: string; + accountId: string; + runtimeId: string; + targetName: string; +} + +function resolveAgent( + context: TracesContext, + options: { agent?: string; target?: string } +): ResolvedAgent | { error: string } { + const { project, deployedState, awsTargets } = context; + + const targetNames = Object.keys(deployedState.targets); + if (targetNames.length === 0) { + return { error: 'No deployed targets found. Run `agentcore deploy` first.' }; + } + + const selectedTargetName = options.target ?? targetNames[0]!; + if (options.target && !targetNames.includes(options.target)) { + return { error: `Target '${options.target}' not found. Available: ${targetNames.join(', ')}` }; + } + + const targetState = deployedState.targets[selectedTargetName]; + const targetConfig = awsTargets.find(t => t.name === selectedTargetName); + if (!targetConfig) { + return { error: `Target config '${selectedTargetName}' not found in aws-targets` }; + } + + if (project.agents.length === 0) { + return { error: 'No agents defined in configuration' }; + } + + const agentNames = project.agents.map(a => a.name); + if (!options.agent && project.agents.length > 1) { + return { error: `Multiple agents found. Use --agent to specify one: ${agentNames.join(', ')}` }; + } + + const agentSpec = options.agent ? project.agents.find(a => a.name === options.agent) : project.agents[0]; + if (options.agent && !agentSpec) { + return { error: `Agent '${options.agent}' not found. Available: ${agentNames.join(', ')}` }; + } + if (!agentSpec) { + return { error: 'No agents defined in configuration' }; + } + + const agentState = targetState?.resources?.agents?.[agentSpec.name]; + if (!agentState) { + return { error: `Agent '${agentSpec.name}' is not deployed to target '${selectedTargetName}'` }; + } + + const parsed = parseRuntimeArn(agentState.runtimeArn); + if (!parsed) { + return { error: `Could not parse runtime ARN: ${agentState.runtimeArn}` }; + } + + return { + agentName: agentSpec.name, + region: targetConfig.region, + accountId: parsed.accountId, + runtimeId: parsed.runtimeId, + targetName: selectedTargetName, + }; +} + +export interface TracesListResult { + success: boolean; + agentName?: string; + targetName?: string; + consoleUrl?: string; + traces?: { traceId: string; timestamp: string; sessionId?: string }[]; + error?: string; +} + +export async function handleTracesList(context: TracesContext, options: TracesListOptions): Promise { + const resolved = resolveAgent(context, options); + if ('error' in resolved) { + return { success: false, error: resolved.error }; + } + + const consoleUrl = buildTraceConsoleUrl({ + region: resolved.region, + accountId: resolved.accountId, + runtimeId: resolved.runtimeId, + agentName: resolved.agentName, + }); + + const limit = options.limit ? parseInt(options.limit, 10) : 20; + const result = await listTraces({ + region: resolved.region, + runtimeId: resolved.runtimeId, + agentName: resolved.agentName, + limit, + }); + + if (!result.success) { + return { success: false, error: result.error, consoleUrl }; + } + + return { + success: true, + agentName: resolved.agentName, + targetName: resolved.targetName, + consoleUrl, + traces: result.traces, + }; +} + +export interface TracesGetResult { + success: boolean; + agentName?: string; + targetName?: string; + consoleUrl?: string; + filePath?: string; + error?: string; +} + +export async function handleTracesGet( + context: TracesContext, + traceId: string, + options: TracesGetOptions +): Promise { + const resolved = resolveAgent(context, options); + if ('error' in resolved) { + return { success: false, error: resolved.error }; + } + + const consoleUrl = buildTraceConsoleUrl({ + region: resolved.region, + accountId: resolved.accountId, + runtimeId: resolved.runtimeId, + agentName: resolved.agentName, + }); + + const result = await getTrace({ + region: resolved.region, + runtimeId: resolved.runtimeId, + agentName: resolved.agentName, + traceId, + outputPath: options.output, + }); + + if (!result.success) { + return { success: false, error: result.error, consoleUrl }; + } + + return { + success: true, + agentName: resolved.agentName, + targetName: resolved.targetName, + consoleUrl, + filePath: result.filePath, + }; +} diff --git a/src/cli/commands/traces/command.tsx b/src/cli/commands/traces/command.tsx new file mode 100644 index 00000000..5195e547 --- /dev/null +++ b/src/cli/commands/traces/command.tsx @@ -0,0 +1,127 @@ +import { getErrorMessage } from '../../errors'; +import { COMMAND_DESCRIPTIONS } from '../../tui/copy'; +import { requireProject } from '../../tui/guards'; +import { handleTracesGet, handleTracesList, loadTracesConfig } from './action'; +import type { TracesGetOptions, TracesListOptions } from './types'; +import type { Command } from '@commander-js/extra-typings'; +import { Box, Text, render } from 'ink'; + +function formatTimestamp(ts: string): string { + const num = Number(ts); + if (isNaN(num)) return ts; + // Epoch ms → human-readable + return new Date(num) + .toISOString() + .replace('T', ' ') + .replace(/\.\d+Z$/, 'Z'); +} + +export const registerTraces = (program: Command) => { + const traces = program.command('traces').alias('t').description(COMMAND_DESCRIPTIONS.traces); + + traces + .command('list') + .description('List recent traces for a deployed agent') + .option('--agent ', 'Select specific agent') + .option('--target ', 'Select deployment target') + .option('--limit ', 'Maximum number of traces to display', '20') + .action(async (cliOptions: TracesListOptions) => { + requireProject(); + + try { + const context = await loadTracesConfig(); + const result = await handleTracesList(context, cliOptions); + + if (!result.success) { + render( + + Error: {result.error} + {result.consoleUrl && Console: {result.consoleUrl}} + + ); + process.exit(1); + return; + } + + render( + + + Traces for {result.agentName} (target: {result.targetName}) + + + {result.traces && result.traces.length > 0 ? ( + <> + + + Trace ID + + + Timestamp + + + Session ID + + + {result.traces.map((trace, i) => ( + + + {trace.traceId.slice(0, 32)} + + + {formatTimestamp(trace.timestamp)} + + + {trace.sessionId?.slice(0, 36) ?? '-'} + + + ))} + + ) : ( + No traces found in the last 12 hours. + )} + + {result.consoleUrl && Console: {result.consoleUrl}} + + ); + } catch (error) { + render(Error: {getErrorMessage(error)}); + process.exit(1); + } + }); + + traces + .command('get ') + .description('Download a trace to a JSON file') + .option('--agent ', 'Select specific agent') + .option('--target ', 'Select deployment target') + .option('--output ', 'Output file path') + .action(async (traceId: string, cliOptions: TracesGetOptions) => { + requireProject(); + + try { + const context = await loadTracesConfig(); + const result = await handleTracesGet(context, traceId, cliOptions); + + if (!result.success) { + render( + + Error: {result.error} + {result.consoleUrl && Console: {result.consoleUrl}} + + ); + process.exit(1); + return; + } + + render( + + Trace saved to: {result.filePath} + {result.consoleUrl && Console: {result.consoleUrl}} + + ); + } catch (error) { + render(Error: {getErrorMessage(error)}); + process.exit(1); + } + }); +}; diff --git a/src/cli/commands/traces/index.ts b/src/cli/commands/traces/index.ts new file mode 100644 index 00000000..59de20ed --- /dev/null +++ b/src/cli/commands/traces/index.ts @@ -0,0 +1,2 @@ +export { registerTraces } from './command'; +export { handleTracesList, handleTracesGet, loadTracesConfig, type TracesContext } from './action'; diff --git a/src/cli/commands/traces/types.ts b/src/cli/commands/traces/types.ts new file mode 100644 index 00000000..083f59f0 --- /dev/null +++ b/src/cli/commands/traces/types.ts @@ -0,0 +1,11 @@ +export interface TracesListOptions { + agent?: string; + target?: string; + limit?: string; +} + +export interface TracesGetOptions { + agent?: string; + target?: string; + output?: string; +} diff --git a/src/cli/operations/index.ts b/src/cli/operations/index.ts index 1af97a2c..ae1c84c1 100644 --- a/src/cli/operations/index.ts +++ b/src/cli/operations/index.ts @@ -6,3 +6,4 @@ export * from './mcp'; export * from './python'; export * from './remove'; export * from './session'; +export * from './traces'; diff --git a/src/cli/operations/traces/get-trace.ts b/src/cli/operations/traces/get-trace.ts new file mode 100644 index 00000000..817456c6 --- /dev/null +++ b/src/cli/operations/traces/get-trace.ts @@ -0,0 +1,116 @@ +import { getCredentialProvider } from '../../aws'; +import { CloudWatchLogsClient, GetQueryResultsCommand, StartQueryCommand } from '@aws-sdk/client-cloudwatch-logs'; +import fs from 'node:fs'; +import path from 'node:path'; + +export interface GetTraceOptions { + region: string; + runtimeId: string; + agentName: string; + traceId: string; + outputPath?: string; +} + +export interface GetTraceResult { + success: boolean; + filePath?: string; + error?: string; +} + +/** + * Fetches a full trace from CloudWatch Logs and writes it to a JSON file. + * + * Log group naming convention: /aws/bedrock-agentcore/runtimes/{runtimeId}-DEFAULT + * Trace ID is stored in the @message JSON body as "traceId". + */ +export async function getTrace(options: GetTraceOptions): Promise { + const { region, runtimeId, agentName, traceId, outputPath } = options; + + const client = new CloudWatchLogsClient({ + credentials: getCredentialProvider(), + region, + }); + + const logGroupName = `/aws/bedrock-agentcore/runtimes/${runtimeId}-DEFAULT`; + + const now = Date.now(); + const startTime = now - 24 * 60 * 60 * 1000; // last 24 hours + + try { + const startQuery = await client.send( + new StartQueryCommand({ + logGroupName, + startTime: Math.floor(startTime / 1000), + endTime: Math.floor(now / 1000), + queryString: `fields @timestamp, @message +| filter traceId = '${traceId}' +| sort @timestamp asc +| limit 1000`, + }) + ); + + if (!startQuery.queryId) { + return { success: false, error: 'Failed to start CloudWatch Logs Insights query' }; + } + + // Poll for results + let traceData: Record[] = []; + + for (let i = 0; i < 30; i++) { + await new Promise(resolve => setTimeout(resolve, 1000)); + + const queryResults = await client.send(new GetQueryResultsCommand({ queryId: startQuery.queryId })); + + const status = queryResults.status ?? 'Unknown'; + + if (status === 'Complete' || status === 'Failed' || status === 'Cancelled') { + if (status !== 'Complete') { + return { success: false, error: `Query ${status.toLowerCase()}` }; + } + + traceData = (queryResults.results ?? []).map(row => { + const fields: Record = {}; + for (const field of row) { + if (field.field && field.value) { + fields[field.field] = field.value; + } + } + return fields; + }); + break; + } + } + + if (traceData.length === 0) { + return { success: false, error: `No trace data found for trace ID: ${traceId}` }; + } + + // Parse @message fields as JSON where possible + const parsedTrace = traceData.map(entry => { + try { + const parsed: unknown = JSON.parse(entry['@message'] ?? '{}'); + return { ...entry, '@message': parsed }; + } catch { + return entry; + } + }); + + // Write to file + const filePath = outputPath ?? path.join('agentcore', '.cli', 'traces', `${agentName}-${traceId}.json`); + + const dir = path.dirname(filePath); + fs.mkdirSync(dir, { recursive: true }); + fs.writeFileSync(filePath, JSON.stringify(parsedTrace, null, 2)); + + return { success: true, filePath: path.resolve(filePath) }; + } catch (error: unknown) { + const err = error as Error; + if (err.name === 'ResourceNotFoundException') { + return { + success: false, + error: `Log group '${logGroupName}' not found. The agent may not have been invoked yet, or traces may not be enabled.`, + }; + } + return { success: false, error: err.message ?? String(error) }; + } +} diff --git a/src/cli/operations/traces/index.ts b/src/cli/operations/traces/index.ts new file mode 100644 index 00000000..0507e35e --- /dev/null +++ b/src/cli/operations/traces/index.ts @@ -0,0 +1,3 @@ +export { buildTraceConsoleUrl, parseRuntimeArn } from './trace-url'; +export { listTraces, type TraceEntry, type ListTracesOptions, type ListTracesResult } from './list-traces'; +export { getTrace, type GetTraceOptions, type GetTraceResult } from './get-trace'; diff --git a/src/cli/operations/traces/list-traces.ts b/src/cli/operations/traces/list-traces.ts new file mode 100644 index 00000000..05f2eb2b --- /dev/null +++ b/src/cli/operations/traces/list-traces.ts @@ -0,0 +1,108 @@ +import { getCredentialProvider } from '../../aws'; +import { CloudWatchLogsClient, GetQueryResultsCommand, StartQueryCommand } from '@aws-sdk/client-cloudwatch-logs'; + +export interface TraceEntry { + traceId: string; + timestamp: string; + sessionId?: string; + spanCount?: string; +} + +export interface ListTracesOptions { + region: string; + runtimeId: string; + agentName: string; + limit?: number; +} + +export interface ListTracesResult { + success: boolean; + traces?: TraceEntry[]; + error?: string; +} + +/** + * Lists recent traces for a deployed agent by querying CloudWatch Logs Insights. + * + * Log group naming convention: /aws/bedrock-agentcore/runtimes/{runtimeId}-DEFAULT + * Trace data is in the @message JSON body with fields like traceId, spanId, etc. + */ +export async function listTraces(options: ListTracesOptions): Promise { + const { region, runtimeId, limit = 20 } = options; + + const client = new CloudWatchLogsClient({ + credentials: getCredentialProvider(), + region, + }); + + const logGroupName = `/aws/bedrock-agentcore/runtimes/${runtimeId}-DEFAULT`; + + const now = Date.now(); + const startTime = now - 12 * 60 * 60 * 1000; // last 12 hours + + try { + const startQuery = await client.send( + new StartQueryCommand({ + logGroupName, + startTime: Math.floor(startTime / 1000), + endTime: Math.floor(now / 1000), + queryString: `stats earliest(@timestamp) as firstSeen, latest(@timestamp) as lastSeen, count(*) as spanCount, earliest(attributes.session.id) as sessionId by traceId +| sort lastSeen desc +| limit ${limit}`, + }) + ); + + if (!startQuery.queryId) { + return { success: false, error: 'Failed to start CloudWatch Logs Insights query' }; + } + + // Poll for results + let status = 'Running'; + let results: TraceEntry[] = []; + + for (let i = 0; i < 30; i++) { + await new Promise(resolve => setTimeout(resolve, 1000)); + + const queryResults = await client.send(new GetQueryResultsCommand({ queryId: startQuery.queryId })); + + status = queryResults.status ?? 'Unknown'; + + if (status === 'Complete' || status === 'Failed' || status === 'Cancelled') { + if (status !== 'Complete') { + return { success: false, error: `Query ${status.toLowerCase()}` }; + } + + results = (queryResults.results ?? []).map(row => { + const fields: Record = {}; + for (const field of row) { + if (field.field && field.value) { + fields[field.field] = field.value; + } + } + return { + traceId: fields.traceId ?? 'unknown', + timestamp: fields.lastSeen ?? fields.firstSeen ?? 'unknown', + sessionId: fields.sessionId, + spanCount: fields.spanCount, + }; + }); + break; + } + } + + if (status === 'Running') { + return { success: false, error: 'Query timed out after 30 seconds' }; + } + + return { success: true, traces: results }; + } catch (error: unknown) { + const err = error as Error; + if (err.name === 'ResourceNotFoundException') { + return { + success: false, + error: `Log group '${logGroupName}' not found. The agent may not have been invoked yet, or traces may not be enabled.`, + }; + } + return { success: false, error: err.message ?? String(error) }; + } +} diff --git a/src/cli/operations/traces/trace-url.ts b/src/cli/operations/traces/trace-url.ts new file mode 100644 index 00000000..f977f743 --- /dev/null +++ b/src/cli/operations/traces/trace-url.ts @@ -0,0 +1,37 @@ +/** + * Builds the CloudWatch console URL for viewing agent traces. + */ +export function buildTraceConsoleUrl(params: { + region: string; + accountId: string; + runtimeId: string; + agentName: string; +}): string { + const { region, accountId, runtimeId, agentName } = params; + const resourceId = encodeURIComponent( + `arn:aws:bedrock-agentcore:${region}:${accountId}:runtime/${runtimeId}/runtime-endpoint/DEFAULT:DEFAULT` + ); + return `https://${region}.console.aws.amazon.com/cloudwatch/home?region=${region}#/gen-ai-observability/agent-core/agent-alias/${runtimeId}/endpoint/DEFAULT/agent/${agentName}?start=-43200000&resourceId=${resourceId}&serviceName=${agentName}.DEFAULT&tabId=traces`; +} + +/** + * Parses an AgentCore runtime ARN to extract region, account ID, and runtime ID. + * + * ARN format: arn:aws:bedrock:REGION:ACCOUNT_ID:agent-runtime/RUNTIME_ID + * Also supports: arn:aws:bedrock-agentcore:REGION:ACCOUNT_ID:runtime/RUNTIME_ID/... + */ +export function parseRuntimeArn(arn: string): { region: string; accountId: string; runtimeId: string } | null { + // arn:aws:bedrock:us-east-1:123456789012:agent-runtime/rt-xxx + const parts = arn.split(':'); + if (parts.length < 6) return null; + + const region = parts[3]!; + const accountId = parts[4]!; + + // Extract runtime ID from the resource part + const resource = parts.slice(5).join(':'); + const runtimeMatch = /(?:agent-runtime|runtime)\/([^/]+)/.exec(resource); + if (!runtimeMatch) return null; + + return { region, accountId, runtimeId: runtimeMatch[1]! }; +} diff --git a/src/cli/tui/copy.ts b/src/cli/tui/copy.ts index 775a423d..507365da 100644 --- a/src/cli/tui/copy.ts +++ b/src/cli/tui/copy.ts @@ -39,6 +39,7 @@ export const COMMAND_DESCRIPTIONS = { package: 'Package Bedrock AgentCore runtime artifacts.', remove: 'Remove AgentCore resources and project', status: 'Retrieve details of deployed AgentCore resources.', + traces: 'View and download agent traces.', update: 'Check for and install CLI updates', validate: 'Validate agentcore/ config files.', } as const; diff --git a/src/cli/tui/screens/invoke/InvokeScreen.tsx b/src/cli/tui/screens/invoke/InvokeScreen.tsx index b1f1accb..547a2209 100644 --- a/src/cli/tui/screens/invoke/InvokeScreen.tsx +++ b/src/cli/tui/screens/invoke/InvokeScreen.tsx @@ -1,3 +1,4 @@ +import { buildTraceConsoleUrl, parseRuntimeArn } from '../../../operations/traces'; import { GradientText, LogLink, Panel, Screen, SelectList, TextInput } from '../../components'; import { useInvokeFlow } from './useInvokeFlow'; import { Box, Text, useInput, useStdout } from 'ink'; @@ -321,6 +322,23 @@ export function InvokeScreen({ )} {logFilePath && } + {mode !== 'select-agent' && + agent && + (() => { + const parsed = parseRuntimeArn(agent.state.runtimeArn); + if (!parsed) return null; + const traceUrl = buildTraceConsoleUrl({ + region: config.target.region, + accountId: parsed.accountId, + runtimeId: parsed.runtimeId, + agentName: agent.name, + }); + return ( + + Traces: {traceUrl} + + ); + })()} ); From 94675e423808b56dfce65e4e151441813ba3c93b Mon Sep 17 00:00:00 2001 From: Jesse Turner Date: Wed, 4 Mar 2026 15:50:02 +0000 Subject: [PATCH 02/10] chore: remove --target option from traces commands Multiple targets are not currently supported, so remove the --target flag from both `traces list` and `traces get` to avoid exposing an unsupported concept. The commands now always use the single deployed target. Co-Authored-By: Claude Opus 4.6 --- src/cli/commands/traces/action.ts | 11 ++--------- src/cli/commands/traces/command.tsx | 2 -- src/cli/commands/traces/types.ts | 2 -- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/cli/commands/traces/action.ts b/src/cli/commands/traces/action.ts index 578ed932..66333fb8 100644 --- a/src/cli/commands/traces/action.ts +++ b/src/cli/commands/traces/action.ts @@ -25,10 +25,7 @@ interface ResolvedAgent { targetName: string; } -function resolveAgent( - context: TracesContext, - options: { agent?: string; target?: string } -): ResolvedAgent | { error: string } { +function resolveAgent(context: TracesContext, options: { agent?: string }): ResolvedAgent | { error: string } { const { project, deployedState, awsTargets } = context; const targetNames = Object.keys(deployedState.targets); @@ -36,11 +33,7 @@ function resolveAgent( return { error: 'No deployed targets found. Run `agentcore deploy` first.' }; } - const selectedTargetName = options.target ?? targetNames[0]!; - if (options.target && !targetNames.includes(options.target)) { - return { error: `Target '${options.target}' not found. Available: ${targetNames.join(', ')}` }; - } - + const selectedTargetName = targetNames[0]!; const targetState = deployedState.targets[selectedTargetName]; const targetConfig = awsTargets.find(t => t.name === selectedTargetName); if (!targetConfig) { diff --git a/src/cli/commands/traces/command.tsx b/src/cli/commands/traces/command.tsx index 5195e547..b18ae9e9 100644 --- a/src/cli/commands/traces/command.tsx +++ b/src/cli/commands/traces/command.tsx @@ -23,7 +23,6 @@ export const registerTraces = (program: Command) => { .command('list') .description('List recent traces for a deployed agent') .option('--agent ', 'Select specific agent') - .option('--target ', 'Select deployment target') .option('--limit ', 'Maximum number of traces to display', '20') .action(async (cliOptions: TracesListOptions) => { requireProject(); @@ -93,7 +92,6 @@ export const registerTraces = (program: Command) => { .command('get ') .description('Download a trace to a JSON file') .option('--agent ', 'Select specific agent') - .option('--target ', 'Select deployment target') .option('--output ', 'Output file path') .action(async (traceId: string, cliOptions: TracesGetOptions) => { requireProject(); diff --git a/src/cli/commands/traces/types.ts b/src/cli/commands/traces/types.ts index 083f59f0..4e4bf230 100644 --- a/src/cli/commands/traces/types.ts +++ b/src/cli/commands/traces/types.ts @@ -1,11 +1,9 @@ export interface TracesListOptions { agent?: string; - target?: string; limit?: string; } export interface TracesGetOptions { agent?: string; - target?: string; output?: string; } From 064732c2f8741316f65207227efad54d0fae5136 Mon Sep 17 00:00:00 2001 From: Jesse Turner Date: Wed, 4 Mar 2026 18:59:11 +0000 Subject: [PATCH 03/10] fix: increase get-trace query timeout to 60s and add timeout detection The polling loop only waited 30 seconds and silently fell through to a misleading "No trace data found" error on timeout. Increase to 60s and add an explicit timeout check matching the pattern in list-traces.ts. Co-Authored-By: Claude Opus 4.6 --- src/cli/operations/traces/get-trace.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/cli/operations/traces/get-trace.ts b/src/cli/operations/traces/get-trace.ts index 817456c6..e0c7b525 100644 --- a/src/cli/operations/traces/get-trace.ts +++ b/src/cli/operations/traces/get-trace.ts @@ -55,17 +55,18 @@ export async function getTrace(options: GetTraceOptions): Promise[] = []; + let queryStatus = 'Running'; - for (let i = 0; i < 30; i++) { + for (let i = 0; i < 60; i++) { await new Promise(resolve => setTimeout(resolve, 1000)); const queryResults = await client.send(new GetQueryResultsCommand({ queryId: startQuery.queryId })); - const status = queryResults.status ?? 'Unknown'; + queryStatus = queryResults.status ?? 'Unknown'; - if (status === 'Complete' || status === 'Failed' || status === 'Cancelled') { - if (status !== 'Complete') { - return { success: false, error: `Query ${status.toLowerCase()}` }; + if (queryStatus === 'Complete' || queryStatus === 'Failed' || queryStatus === 'Cancelled') { + if (queryStatus !== 'Complete') { + return { success: false, error: `Query ${queryStatus.toLowerCase()}` }; } traceData = (queryResults.results ?? []).map(row => { @@ -81,6 +82,10 @@ export async function getTrace(options: GetTraceOptions): Promise Date: Wed, 4 Mar 2026 18:59:39 +0000 Subject: [PATCH 04/10] fix: increase list-traces query timeout to 60s Match the get-trace timeout increase for consistency. Large log groups may need more than 30 seconds for CWL Insights queries to complete. Co-Authored-By: Claude Opus 4.6 --- src/cli/operations/traces/list-traces.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cli/operations/traces/list-traces.ts b/src/cli/operations/traces/list-traces.ts index 05f2eb2b..4c19afce 100644 --- a/src/cli/operations/traces/list-traces.ts +++ b/src/cli/operations/traces/list-traces.ts @@ -60,7 +60,7 @@ export async function listTraces(options: ListTracesOptions): Promise setTimeout(resolve, 1000)); const queryResults = await client.send(new GetQueryResultsCommand({ queryId: startQuery.queryId })); @@ -91,7 +91,7 @@ export async function listTraces(options: ListTracesOptions): Promise Date: Wed, 4 Mar 2026 18:59:58 +0000 Subject: [PATCH 05/10] fix: show full trace ID and session ID in traces list output Truncating IDs made them unusable as input to `traces get`. Display the full values so users can copy-paste trace IDs directly. Co-Authored-By: Claude Opus 4.6 --- src/cli/commands/traces/command.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cli/commands/traces/command.tsx b/src/cli/commands/traces/command.tsx index b18ae9e9..796cb013 100644 --- a/src/cli/commands/traces/command.tsx +++ b/src/cli/commands/traces/command.tsx @@ -64,13 +64,13 @@ export const registerTraces = (program: Command) => { {result.traces.map((trace, i) => ( - {trace.traceId.slice(0, 32)} + {trace.traceId} {formatTimestamp(trace.timestamp)} - {trace.sessionId?.slice(0, 36) ?? '-'} + {trace.sessionId ?? '-'} ))} From 838c36b90b0ca62f3800f34d489135ac0a6d4145 Mon Sep 17 00:00:00 2001 From: Jesse Turner Date: Wed, 4 Mar 2026 16:15:50 -0500 Subject: [PATCH 06/10] refactor: extract shared agent resolution + add --since/--until to traces list Extract duplicate agent resolution logic into a shared resolve-agent utility (src/cli/operations/resolve-agent.ts) used by both logs and traces commands. Move time-parser to shared utils (src/lib/utils/time-parser.ts). Add --since and --until flags to `traces list` for custom time range queries instead of the hardcoded 12h window. Co-Authored-By: Claude Opus 4.6 --- package-lock.json | 618 +++++++++--------- .../commands/logs/__tests__/action.test.ts | 4 +- .../logs/__tests__/time-parser.test.ts | 2 +- src/cli/commands/logs/action.ts | 95 +-- src/cli/commands/traces/action.ts | 156 ++--- src/cli/commands/traces/command.tsx | 13 +- src/cli/commands/traces/index.ts | 2 +- src/cli/commands/traces/types.ts | 4 + src/cli/operations/index.ts | 1 + src/cli/operations/resolve-agent.ts | 99 +++ src/cli/operations/traces/get-trace.ts | 7 +- src/cli/operations/traces/index.ts | 2 +- src/cli/operations/traces/list-traces.ts | 7 +- src/cli/operations/traces/trace-url.ts | 22 - src/cli/tui/screens/invoke/InvokeScreen.tsx | 8 +- src/lib/utils/index.ts | 1 + .../logs => lib/utils}/time-parser.ts | 0 17 files changed, 522 insertions(+), 519 deletions(-) create mode 100644 src/cli/operations/resolve-agent.ts rename src/{cli/commands/logs => lib/utils}/time-parser.ts (100%) diff --git a/package-lock.json b/package-lock.json index afe6fa1a..449678e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -112,19 +112,19 @@ "license": "Apache-2.0" }, "node_modules/@aws-cdk/aws-service-spec": { - "version": "0.1.158", - "resolved": "https://registry.npmjs.org/@aws-cdk/aws-service-spec/-/aws-service-spec-0.1.158.tgz", - "integrity": "sha512-lzqqZgJfm+iR+pDZ6t4PijTcvSZ0w1LC9u2eAxf3p9ACSXj00fn/3yDF/trIOVNbUNz2yzRHJFy3Ob4D6JXvxg==", + "version": "0.1.159", + "resolved": "https://registry.npmjs.org/@aws-cdk/aws-service-spec/-/aws-service-spec-0.1.159.tgz", + "integrity": "sha512-IgdIOREfGNWwSac1Y2XpsP8WL9CkoolS2ixfGC3VJFDifkni5rmc+ADeFuD+egujAnjHUIz7MZP/67gIHru3mA==", "license": "Apache-2.0", "dependencies": { - "@aws-cdk/service-spec-types": "^0.0.224", + "@aws-cdk/service-spec-types": "^0.0.225", "@cdklabs/tskb": "^0.0.4" } }, "node_modules/@aws-cdk/aws-service-spec/node_modules/@aws-cdk/service-spec-types": { - "version": "0.0.224", - "resolved": "https://registry.npmjs.org/@aws-cdk/service-spec-types/-/service-spec-types-0.0.224.tgz", - "integrity": "sha512-yQu2EnQvMihN3zcLhKaS0R72yXw1nCcoOZppCrR9SC1PLwlUarlomS3IEgbcUzMUYuet7prwVlBy8oz+1BPRLA==", + "version": "0.0.225", + "resolved": "https://registry.npmjs.org/@aws-cdk/service-spec-types/-/service-spec-types-0.0.225.tgz", + "integrity": "sha512-y7+D/NwFxzopYB4jlSH+ES/p8OyI4JWZIMPjE20RFCWdWRNukxevGPCSM5T6YS0eWHjLUIECaMhOqVLyyFemvQ==", "license": "Apache-2.0", "dependencies": { "@cdklabs/tskb": "^0.0.4" @@ -206,9 +206,9 @@ } }, "node_modules/@aws-cdk/cloud-assembly-schema": { - "version": "53.0.0", - "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-53.0.0.tgz", - "integrity": "sha512-8DbZLaBeKM+i+tqujr/oQc/+3cDJoVhlXEkVyf152rkl6gnmfOZniRYjd+JsrOPrzwpcNoq05bo9KHME1EhMVQ==", + "version": "53.1.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-53.1.0.tgz", + "integrity": "sha512-G5baT6PU8dqJWtHJ64Q2L7C4JSIQRo0WmqmSkR/BEpwnV2MhbsGxCfeKDqg9Gj7gUVzJAeIrBDPdZjdPR+Frww==", "bundleDependencies": [ "jsonschema", "semver" @@ -341,14 +341,14 @@ } }, "node_modules/@aws-cdk/toolkit-lib": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@aws-cdk/toolkit-lib/-/toolkit-lib-1.16.1.tgz", - "integrity": "sha512-1hBMYBHrioX5JV0oShwTDT2vwE5XjuY0PzOe5j34xc2ZQutwrSYMmCEyq6jDJKn8QvsXUg8yM13ZN8zaBeaLcg==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/toolkit-lib/-/toolkit-lib-1.17.0.tgz", + "integrity": "sha512-6FXAB4bDw9NQ9j151Wm3JkqGTGfpCfVHUCZaj8i3GFGHQ2eGdUiryGD8kkgicT9R8cEal71X+BPbGxylZnDsRA==", "license": "Apache-2.0", "dependencies": { "@aws-cdk/cdk-assets-lib": "^1", "@aws-cdk/cloud-assembly-api": "2.2.0", - "@aws-cdk/cloud-assembly-schema": ">=53.0.0", + "@aws-cdk/cloud-assembly-schema": ">=53.1.0", "@aws-cdk/cloudformation-diff": "^2", "@aws-cdk/cx-api": "^2", "@aws-sdk/client-appsync": "^3", @@ -379,7 +379,7 @@ "@smithy/util-retry": "^4", "@smithy/util-waiter": "^4", "archiver": "^7.0.1", - "cdk-from-cfn": "^0.283.0", + "cdk-from-cfn": "^0.286.0", "chalk": "^4", "chokidar": "^4", "fast-deep-equal": "^3.1.3", @@ -603,24 +603,24 @@ } }, "node_modules/@aws-sdk/client-appsync": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-appsync/-/client-appsync-3.1001.0.tgz", - "integrity": "sha512-xLT74VnXu2OlAgLbG6UPGwWh/oQEpdbQeWmhctP+8cECepJ4Bst4W6fES/cxZkjqizqdDkuaQye6beHiHG22pg==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-appsync/-/client-appsync-3.1002.0.tgz", + "integrity": "sha512-aTo6abHnap7jFbAi1c6l5OoUne94KjgOxxhoyEPGIxjy77Nt43q4eXN1AqE1jRJJOaW9elcpyd6UIFn+s1OpeQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -654,24 +654,24 @@ } }, "node_modules/@aws-sdk/client-bedrock-agentcore": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-agentcore/-/client-bedrock-agentcore-3.1001.0.tgz", - "integrity": "sha512-NHQcYpLZ+YgINcJMdlZk5IPKd70Z59qs10OHhhj914w8FX2WznVX2tXT7SINb6y5MWrvLgtnufslbt8XlpIGiQ==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-agentcore/-/client-bedrock-agentcore-3.1002.0.tgz", + "integrity": "sha512-Cfuu+mqZdU/l1UnUZLqGk/yFg0Kjbv3Lckm9oB2f8fG1QIu9uJKJqJMrFifzQu3iruN887BVQzX+EudAEol2lQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/eventstream-serde-browser": "^4.2.10", @@ -708,24 +708,24 @@ } }, "node_modules/@aws-sdk/client-bedrock-agentcore-control": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-agentcore-control/-/client-bedrock-agentcore-control-3.1001.0.tgz", - "integrity": "sha512-5BM5A7Qs8ZXJOzTPVXVTxoY7KcyBp7ArNWKxX+18OsecanVvb+tmdAsQuqzre48692iIgzeqcgMUV/fzbw5rQw==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-agentcore-control/-/client-bedrock-agentcore-control-3.1002.0.tgz", + "integrity": "sha512-dYhADpzZg5AgWx0ow8egwD00qgudG8x7KBCnBXlSi74aSwcVSBQ8qcJe8D8uO1fK2B4IwV9ibXVhhq8l4n2v9A==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -759,28 +759,28 @@ } }, "node_modules/@aws-sdk/client-bedrock-runtime": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.1001.0.tgz", - "integrity": "sha512-wmrVqR0QvzvDejVnwf4jOJCobzOC89MU/B3zeI6PeFygc2XOScalmlDZ6WhW5nklR1DOvRRq0SuKPG3iRebdPA==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.1002.0.tgz", + "integrity": "sha512-xUmzgTvTeQFVxBqla8U4nXpZNXLcZ0xszfZ4yxdTUNyChQQb7JLaH4E8pAbl7ulg0RoJ4ChNWtOqMJC/N3+qcQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/eventstream-handler-node": "^3.972.9", "@aws-sdk/middleware-eventstream": "^3.972.6", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/middleware-websocket": "^3.972.11", "@aws-sdk/region-config-resolver": "^3.972.6", - "@aws-sdk/token-providers": "3.1001.0", + "@aws-sdk/token-providers": "3.1002.0", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/eventstream-serde-browser": "^4.2.10", @@ -817,24 +817,24 @@ } }, "node_modules/@aws-sdk/client-cloudcontrol": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudcontrol/-/client-cloudcontrol-3.1001.0.tgz", - "integrity": "sha512-IYYp84vAlw/tOwgZGc4P6dDGYnNujLQN2M5+TXx4bkJWrm2goSmpvP1eAkbnQHU1r+5Nh2pCxqspFIoO5vUClA==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudcontrol/-/client-cloudcontrol-3.1002.0.tgz", + "integrity": "sha512-2MesTcG9YyHk8HStm3zWNNi4pvYbRo3mECDljfYUA93dkZTF3FwN5veiAx/MgaIJ6XXQRqXoiIaDSJTHoiTeKw==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -868,24 +868,24 @@ } }, "node_modules/@aws-sdk/client-cloudformation": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudformation/-/client-cloudformation-3.1001.0.tgz", - "integrity": "sha512-9SuAsg+KeGNPrmNsS2eA5yQWgSMXHtpyTKvPe2NNwrSoLLaxA3CdIQgByKVGUvoP8lry/dF78k8DN3pTphWX6A==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudformation/-/client-cloudformation-3.1002.0.tgz", + "integrity": "sha512-03UzXmKaXSfa8+BtePs0xdbPpuek+r5ghwcRntegHSTeMngTLKBfswyEwX3evL0DffX1nmxjxorDWHJJcOTqhQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -919,24 +919,24 @@ } }, "node_modules/@aws-sdk/client-cloudwatch-logs": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.1001.0.tgz", - "integrity": "sha512-o8wHfVuDDsOpnhcLOKnOg/ryqlZhvP9k8HPqGv6mjC+9OAdQt1gXgUqEKOL8jCzClOOKzSfrML4KtdIz3ap1dw==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.1002.0.tgz", + "integrity": "sha512-O0ov4W+IiMla4HhB3eAey5MxwjdGvVkhDne9wdLRD+2H2Ba8qtSq/FwdeyCUYha93E2T813orYaxppcYemiNjg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/eventstream-serde-browser": "^4.2.10", @@ -972,24 +972,24 @@ } }, "node_modules/@aws-sdk/client-codebuild": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-codebuild/-/client-codebuild-3.1001.0.tgz", - "integrity": "sha512-9T84U8PRANnfHBADxrS15lIMEEw9SS2toLr0THWLEFRC1zxomPyz9pkrIxYjeJKtdccHU1O0XTkvTuD0t4WSzw==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-codebuild/-/client-codebuild-3.1002.0.tgz", + "integrity": "sha512-Aqd28f/qYgATvwfZnFOVPhglFQgX0cx6rRKBfFUPM3XhUimnisI+tCro7jooapxKOyD1xlNuroVgnD5SpI0Uow==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1022,24 +1022,24 @@ } }, "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.1001.0.tgz", - "integrity": "sha512-eQSkLtI5DbYoUQfrlz9iKIE+qgfsyqToufhkqXeaiegV8lz99hh8DbKc7WitKo5NSQumf+GS8B6VzmsrWH0gFg==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.1002.0.tgz", + "integrity": "sha512-tWopjShTQyg0/KIdOiUHWQAb7Ef26X7voDIRinxL9oql90qRMSEbSw050OzXM0pwpF0TapyMsed4V8V/Z5k+Cg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1072,25 +1072,25 @@ } }, "node_modules/@aws-sdk/client-ec2": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ec2/-/client-ec2-3.1001.0.tgz", - "integrity": "sha512-yROJVvWStAno73KbmurBNIp/9iITAPEJNMv6l9TN7R2Vrq3nEYPfd2/sgAy3Woe75fjKONHFHyE5gXmvcSpVzw==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ec2/-/client-ec2-3.1002.0.tgz", + "integrity": "sha512-KyhUr/IBfy5sgkF6WWNrb5rc7Osb6gp5IVAO76IWUPnhzGnFweMnmerasTd0GXQKyoxJYuJbKEvJE2eIiFYsSg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", "@aws-sdk/middleware-sdk-ec2": "^3.972.12", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1124,24 +1124,24 @@ } }, "node_modules/@aws-sdk/client-ecr": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ecr/-/client-ecr-3.1001.0.tgz", - "integrity": "sha512-nz2//TUpIijghQa3PVJl5uPAFAb/31ZBcDadZdv1y5C5jApHgAusixVjNMqgykxgS/i4fqp4XKhDOe7XcyEuDg==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ecr/-/client-ecr-3.1002.0.tgz", + "integrity": "sha512-HsCQjKd65MtleWMhBk07brizAZrOUEGNXMQnLqSZNvKKlxeOB0a2+zQGb4oJkXsNl2TXiCSUyQ7ziQ7aTEIQZg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1175,24 +1175,24 @@ } }, "node_modules/@aws-sdk/client-ecs": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ecs/-/client-ecs-3.1001.0.tgz", - "integrity": "sha512-6NOp4cpl8fOxwV9s22nskBpuKxIBZxhaegeM1qDujhpZNhzvTUEySy1JI0qkOLmt99Xy9V7YE/eWT+Euceyizg==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ecs/-/client-ecs-3.1002.0.tgz", + "integrity": "sha512-7MtbcsJhPXLih+PXf61ovsj1M3LCiC+BFHTWMHIBO4V5lRhE3GmFmb+bW1hkMhSRWg1sT/YDqAGHCcB7v1p6OQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1226,24 +1226,24 @@ } }, "node_modules/@aws-sdk/client-elastic-load-balancing-v2": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-elastic-load-balancing-v2/-/client-elastic-load-balancing-v2-3.1001.0.tgz", - "integrity": "sha512-CXmeSyl+yttMpwYPvnT9msL+8fkiNVUIZB523y5GhaMXsvleD5vtVLb8g5cIB3A1Tfknv6evdt/RZXesFFCuYg==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-elastic-load-balancing-v2/-/client-elastic-load-balancing-v2-3.1002.0.tgz", + "integrity": "sha512-3XMbmYCKYzoRbMpFKRr8R9bGq9UETvwVrhl9YT1VY0mlrWY2SL3mOX2A6BQvWFdK+qUuhF3PT1MtcWb/tPV7GA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1277,24 +1277,24 @@ } }, "node_modules/@aws-sdk/client-iam": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-iam/-/client-iam-3.1001.0.tgz", - "integrity": "sha512-+ascrJmif0lrKgO8zBhi/4QGsHS6SAEoG3MFWCzdB4+bDEGCKAV77s48gTbGqMTEWnSyiHdudCBjhxvsZhcPZw==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-iam/-/client-iam-3.1002.0.tgz", + "integrity": "sha512-gtWLZngHw5hgegxe9/sdAYGBcdLMhdc/05lPXudH8W/vaUC8OO0weAoiyLaIvUcP6w3WA/zYKMU7QwFeWj8P5g==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1328,24 +1328,24 @@ } }, "node_modules/@aws-sdk/client-kms": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-kms/-/client-kms-3.1001.0.tgz", - "integrity": "sha512-wfaFP5H3RUZ8E77ZaVskax2trS0vviWsXbvcsEfPjS6PmCJBy5AezfLsv1aoypCgd3IyPbWR+yV8zGaJ5vMPvw==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-kms/-/client-kms-3.1002.0.tgz", + "integrity": "sha512-J0UN301gkKT95ANzIRCDiEaoJkVi22uBBpwv6wTgyMn7BaS2ISUWe01itZ5wQdS541V8NIiyJEjc9hlYWBHb5Q==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1378,24 +1378,24 @@ } }, "node_modules/@aws-sdk/client-lambda": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.1001.0.tgz", - "integrity": "sha512-YR3ntp0YY0f/Fdx9UNmRLa5PVOik0J1dIHGrTRRC241QjL2Le9b1DkDordto2QtvGQeK5LNPMbuxiGZqQ594Tg==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.1002.0.tgz", + "integrity": "sha512-b4043kyufHP48gja3UYl+/V7m+DoVaMmQAB6xe1NdYNsbTljU64qlxrv77tEtkt2J1og/sLe4Ppma9+q1yamDg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/eventstream-serde-browser": "^4.2.10", @@ -1433,24 +1433,24 @@ } }, "node_modules/@aws-sdk/client-resource-groups-tagging-api": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-resource-groups-tagging-api/-/client-resource-groups-tagging-api-3.1001.0.tgz", - "integrity": "sha512-4/7tDkh/G0l9sjGLV4Ndt1ovjZTooTtljenvA8X9CrDHjtoTh16xdGHxsNfvF65+fA6ItO/QL2aH9hBWb9vN6g==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-resource-groups-tagging-api/-/client-resource-groups-tagging-api-3.1002.0.tgz", + "integrity": "sha512-dl41eUbZW1IrFrOIjoJoF3TzWezznuaafaDj+DJfO2aITRA1nfo/lf9CcN70nk3UvBmCtxTXbV9JJRfLZ8f+og==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1483,25 +1483,25 @@ } }, "node_modules/@aws-sdk/client-route-53": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-route-53/-/client-route-53-3.1001.0.tgz", - "integrity": "sha512-jCyFEooFQdGalWpIXszvr8KcOA632qmaToNdqiicKbXpsbi4Jli9SOvRjeaQzO9qbpWahIbLvpjs8/wvrB4Byw==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-route-53/-/client-route-53-3.1002.0.tgz", + "integrity": "sha512-JQNcDu4xYOEZNEAo4WcobkYEtOuHeIEcx0HuzXuDNXGVsxq31GCJazuaYXBOO4Y5XPMlw6VxtpAncy4sNagdjQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", "@aws-sdk/middleware-sdk-route53": "^3.972.8", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1535,32 +1535,32 @@ } }, "node_modules/@aws-sdk/client-s3": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1001.0.tgz", - "integrity": "sha512-uKgFjQuBjMcd0iigLQwnqIp9gOy/5TGBxa42rcb6l5byDt1mrwOe6fyWTEUEJaNHG2LKYSPUibteGvM1zfm0Rw==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1002.0.tgz", + "integrity": "sha512-tc+vZgvjcm+1Ot+YhQjXZxVELKGGGO3D5cuR4p5xaeitXYX2+RRiz4/WdSak9slumIClnlXsdqhJ0OHognUT+w==", "license": "Apache-2.0", "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.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-bucket-endpoint": "^3.972.6", "@aws-sdk/middleware-expect-continue": "^3.972.6", - "@aws-sdk/middleware-flexible-checksums": "^3.973.2", + "@aws-sdk/middleware-flexible-checksums": "^3.973.3", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-location-constraint": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-sdk-s3": "^3.972.16", + "@aws-sdk/middleware-sdk-s3": "^3.972.17", "@aws-sdk/middleware-ssec": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", - "@aws-sdk/signature-v4-multi-region": "^3.996.4", + "@aws-sdk/signature-v4-multi-region": "^3.996.5", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/eventstream-serde-browser": "^4.2.10", @@ -1601,24 +1601,24 @@ } }, "node_modules/@aws-sdk/client-secrets-manager": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.1001.0.tgz", - "integrity": "sha512-XKx1ScMO5mE6VZei7E+deDpLfKrlhHflZrQIsP1JJZBm5k+9/fwUcBRwMatI3a+vUPLI57NIKddeYFqyLNFpkQ==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.1002.0.tgz", + "integrity": "sha512-7UjWXrGpUxcVfLa/avPosc8KBGCjqixLeqCqXxZMoo/AZLNYDxYGW8wk/eoxkaoW+yZbVPqPSLeJ5/6dPztZrQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1651,24 +1651,24 @@ } }, "node_modules/@aws-sdk/client-sfn": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sfn/-/client-sfn-3.1001.0.tgz", - "integrity": "sha512-83M5YDJ6ud/56dWfHaLdoiiv/Y55bYYfUGkvuj18S3f5diw60VunbNclw3amJRuxpYM8qXoSM2YybsNlLvFlhg==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sfn/-/client-sfn-3.1002.0.tgz", + "integrity": "sha512-jWGUhIcgfSUXeDwDCmpsbcPmr7tS0Y3XlmtCD5nh5usPOyaYWEECL1ftw4kYicDH1ThvIQpnl4JLosIAccrXMQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1701,24 +1701,24 @@ } }, "node_modules/@aws-sdk/client-ssm": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.1001.0.tgz", - "integrity": "sha512-WnEFtzczBF1f+hNvnmucbccYeGfHXnQOaARnI4c2WYGzcCN0SF/R7B4Xl2V1DpsLxtldx5dkX2hwIc40rYk1Rg==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.1002.0.tgz", + "integrity": "sha512-eu60crX7/4EUtWEWTlbm8AT0+R+9kSTv5iB3mwrK2w0uExBuS0r5YRNqO+F2itLhRR3s3ghl9vQ65V7ccRfGuA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1752,24 +1752,24 @@ } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.1001.0.tgz", - "integrity": "sha512-1HVxJcad+BTMVQ4lN2jw4SzyVqnIRZ7mb8YjwqMQ6p1MjuklSriVUXKtYFyxLVJnqaw61nFv9F8oHMOK69p6BQ==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.1002.0.tgz", + "integrity": "sha512-KoWtMWq0o95k/8hMl2gzrxFehP3FxIH3j7k8gsOWW9qP/OyfU/Dp7KyopjuXSPQSE0HqjFibefExEdFbMr15Cw==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-node": "^3.972.15", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-node": "^3.972.16", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -1802,9 +1802,9 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.973.16", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.16.tgz", - "integrity": "sha512-Nasoyb5K4jfvncTKQyA13q55xHoz9as01NVYP05B0Kzux/X5UhMn3qXsZDyWOSXkfSCAIrMBKmVVWbI0vUapdQ==", + "version": "3.973.17", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.17.tgz", + "integrity": "sha512-VtgGP0TjbCeyp6DQpiBqJKbemTSIaN2bZc3UbeTDCani3lBCyxn75ouJYD6koSSp0bh7rKLEbUpiFsNCI7tr0w==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.4", @@ -1839,12 +1839,12 @@ } }, "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.972.7", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.972.7.tgz", - "integrity": "sha512-0mn0mnu7UiA+7s0weXVlAGmXyC0vb9sqnWpBbuuSNDHK3v7IXBaq2WdNKRwmVPqqBFSuy+R7nOIq9LerdpyNJA==", + "version": "3.972.8", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.972.8.tgz", + "integrity": "sha512-ATo3JAoPiGFM+m6cW42ntpOAgHY817NnRZOoe3jNRsMDibHKfjkCPFz1azgIjKRwFp3ioY7QNkOZNp4t8XNI2Q==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/nested-clients": "^3.996.4", + "@aws-sdk/nested-clients": "^3.996.5", "@aws-sdk/types": "^3.973.4", "@smithy/property-provider": "^4.2.10", "@smithy/types": "^4.13.0", @@ -1855,12 +1855,12 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.14", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.14.tgz", - "integrity": "sha512-PvnBY9rwBuLh9MEsAng28DG+WKl+txerKgf4BU9IPAqYI7FBIo1x6q/utLf4KLyQYgSy1TLQnbQuXx5xfBGASg==", + "version": "3.972.15", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.15.tgz", + "integrity": "sha512-RhHQG1lhkWHL4tK1C/KDjaOeis+9U0tAMnWDiwiSVQZMC7CsST9Xin+sK89XywJ5g/tyABtb7TvFePJ4Te5XSQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.16", + "@aws-sdk/core": "^3.973.17", "@aws-sdk/types": "^3.973.4", "@smithy/property-provider": "^4.2.10", "@smithy/types": "^4.13.0", @@ -1871,12 +1871,12 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.16", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.16.tgz", - "integrity": "sha512-m/QAcvw5OahqGPjeAnKtgfWgjLxeWOYj7JSmxKK6PLyKp2S/t2TAHI6EELEzXnIz28RMgbQLukJkVAqPASVAGQ==", + "version": "3.972.17", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.17.tgz", + "integrity": "sha512-b/bDL76p51+yQ+0O9ZDH5nw/ioE0sRYkjwjOwFWAWZXo6it2kQZUOXhVpjohx3ldKyUxt/SwAivjUu1Nr/PWlQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.16", + "@aws-sdk/core": "^3.973.17", "@aws-sdk/types": "^3.973.4", "@smithy/fetch-http-handler": "^5.3.12", "@smithy/node-http-handler": "^4.4.13", @@ -1892,19 +1892,19 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.972.14", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.14.tgz", - "integrity": "sha512-EGA7ufqNpZKZcD0RwM6gRDEQgwAf19wQ99R1ptdWYDJAnpcMcWiFyT0RIrgiZFLD28CwJmYjnra75hChnEveWA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-env": "^3.972.14", - "@aws-sdk/credential-provider-http": "^3.972.16", - "@aws-sdk/credential-provider-login": "^3.972.14", - "@aws-sdk/credential-provider-process": "^3.972.14", - "@aws-sdk/credential-provider-sso": "^3.972.14", - "@aws-sdk/credential-provider-web-identity": "^3.972.14", - "@aws-sdk/nested-clients": "^3.996.4", + "version": "3.972.15", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.15.tgz", + "integrity": "sha512-qWnM+wB8MmU2kKY7f4KowKjOjkwRosaFxrtseEEIefwoXn1SjN+CbHzXBVdTAQxxkbBiqhPgJ/WHiPtES4grRQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-env": "^3.972.15", + "@aws-sdk/credential-provider-http": "^3.972.17", + "@aws-sdk/credential-provider-login": "^3.972.15", + "@aws-sdk/credential-provider-process": "^3.972.15", + "@aws-sdk/credential-provider-sso": "^3.972.15", + "@aws-sdk/credential-provider-web-identity": "^3.972.15", + "@aws-sdk/nested-clients": "^3.996.5", "@aws-sdk/types": "^3.973.4", "@smithy/credential-provider-imds": "^4.2.10", "@smithy/property-provider": "^4.2.10", @@ -1917,13 +1917,13 @@ } }, "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.14", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.14.tgz", - "integrity": "sha512-P2kujQHAoV7irCTv6EGyReKFofkHCjIK+F0ZYf5UxeLeecrCwtrDkHoO2Vjsv/eRUumaKblD8czuk3CLlzwGDw==", + "version": "3.972.15", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.15.tgz", + "integrity": "sha512-x92FJy34/95wgu+qOGD8SHcgh1hZ9Qx2uFtQEGn4m9Ljou8ICIv3Ybq5yxdB7A60S8ZGCQB0mIopmjJwiLbh5g==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/nested-clients": "^3.996.4", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/nested-clients": "^3.996.5", "@aws-sdk/types": "^3.973.4", "@smithy/property-provider": "^4.2.10", "@smithy/protocol-http": "^5.3.10", @@ -1936,17 +1936,17 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.15", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.15.tgz", - "integrity": "sha512-59NBJgTcQ2FC94T+SWkN5UQgViFtrLnkswSKhG5xbjPAotOXnkEF2Bf0bfUV1F3VaXzqAPZJoZ3bpg4rr8XD5Q==", + "version": "3.972.16", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.16.tgz", + "integrity": "sha512-7mlt14Ee4rPFAFUVgpWE7+0CBhetJJyzVFqfIsMp7sgyOSm9Y/+qHZOWAuK5I4JNc+Y5PltvJ9kssTzRo92iXQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.14", - "@aws-sdk/credential-provider-http": "^3.972.16", - "@aws-sdk/credential-provider-ini": "^3.972.14", - "@aws-sdk/credential-provider-process": "^3.972.14", - "@aws-sdk/credential-provider-sso": "^3.972.14", - "@aws-sdk/credential-provider-web-identity": "^3.972.14", + "@aws-sdk/credential-provider-env": "^3.972.15", + "@aws-sdk/credential-provider-http": "^3.972.17", + "@aws-sdk/credential-provider-ini": "^3.972.15", + "@aws-sdk/credential-provider-process": "^3.972.15", + "@aws-sdk/credential-provider-sso": "^3.972.15", + "@aws-sdk/credential-provider-web-identity": "^3.972.15", "@aws-sdk/types": "^3.973.4", "@smithy/credential-provider-imds": "^4.2.10", "@smithy/property-provider": "^4.2.10", @@ -1959,12 +1959,12 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.14", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.14.tgz", - "integrity": "sha512-KAF5LBkJInUPaR9dJDw8LqmbPDRTLyXyRoWVGcJQ+DcN9rxVKBRzAK+O4dTIvQtQ7xaIDZ2kY7zUmDlz6CCXdw==", + "version": "3.972.15", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.15.tgz", + "integrity": "sha512-PrH3iTeD18y/8uJvQD2s/T87BTGhsdS/1KZU7ReWHXsplBwvCqi7AbnnNbML1pFlQwRWCE2RdSZFWDVId3CvkA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.16", + "@aws-sdk/core": "^3.973.17", "@aws-sdk/types": "^3.973.4", "@smithy/property-provider": "^4.2.10", "@smithy/shared-ini-file-loader": "^4.4.5", @@ -1976,14 +1976,14 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.972.14", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.14.tgz", - "integrity": "sha512-LQzIYrNABnZzkyuIguFa3VVOox9UxPpRW6PL+QYtRHaGl1Ux/+Zi54tAVK31VdeBKPKU3cxqeu8dbOgNqy+naw==", + "version": "3.972.15", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.15.tgz", + "integrity": "sha512-M/+LBHTPKZxxXckM6m4dnJeR+jlm9NynH9b2YDswN4Zj2St05SK/crdL3Wy3WfJTZootnnhm3oTh87Usl7PS7w==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/nested-clients": "^3.996.4", - "@aws-sdk/token-providers": "3.1001.0", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/nested-clients": "^3.996.5", + "@aws-sdk/token-providers": "3.1002.0", "@aws-sdk/types": "^3.973.4", "@smithy/property-provider": "^4.2.10", "@smithy/shared-ini-file-loader": "^4.4.5", @@ -1995,13 +1995,13 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.14", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.14.tgz", - "integrity": "sha512-rOwB3vXHHHnGvAOjTgQETxVAsWjgF61XlbGd/ulvYo7EpdXs8cbIHE3PGih9tTj/65ZOegSqZGFqLaKntaI9Kw==", + "version": "3.972.15", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.15.tgz", + "integrity": "sha512-QTH6k93v+UOfFam/ado8zc71tH+enTVyuvLy9uEWXX1x894dN5ovtf/MdBDgFwq3g6c9mbtgVJ4B+yBqDtXvdA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/nested-clients": "^3.996.4", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/nested-clients": "^3.996.5", "@aws-sdk/types": "^3.973.4", "@smithy/property-provider": "^4.2.10", "@smithy/shared-ini-file-loader": "^4.4.5", @@ -2013,23 +2013,23 @@ } }, "node_modules/@aws-sdk/credential-providers": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.1001.0.tgz", - "integrity": "sha512-l83IOlkbPBiBl9zXV4A9z/EtUNgEzb4lMusRIe1L2N5xEic83mhP8lFzQzVoq4TGbCObFdr/C62VzNbrOM0QaA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/client-cognito-identity": "3.1001.0", - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/credential-provider-cognito-identity": "^3.972.7", - "@aws-sdk/credential-provider-env": "^3.972.14", - "@aws-sdk/credential-provider-http": "^3.972.16", - "@aws-sdk/credential-provider-ini": "^3.972.14", - "@aws-sdk/credential-provider-login": "^3.972.14", - "@aws-sdk/credential-provider-node": "^3.972.15", - "@aws-sdk/credential-provider-process": "^3.972.14", - "@aws-sdk/credential-provider-sso": "^3.972.14", - "@aws-sdk/credential-provider-web-identity": "^3.972.14", - "@aws-sdk/nested-clients": "^3.996.4", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.1002.0.tgz", + "integrity": "sha512-D9E3iBWt7kQ3WZ6R6mOy4GDiC/fV+z5lVMVuHNdicryga0fWkuoZBK/dTEdFBEiQBQ3WdDORzEzD+PytYstFBg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-cognito-identity": "3.1002.0", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/credential-provider-cognito-identity": "^3.972.8", + "@aws-sdk/credential-provider-env": "^3.972.15", + "@aws-sdk/credential-provider-http": "^3.972.17", + "@aws-sdk/credential-provider-ini": "^3.972.15", + "@aws-sdk/credential-provider-login": "^3.972.15", + "@aws-sdk/credential-provider-node": "^3.972.16", + "@aws-sdk/credential-provider-process": "^3.972.15", + "@aws-sdk/credential-provider-sso": "^3.972.15", + "@aws-sdk/credential-provider-web-identity": "^3.972.15", + "@aws-sdk/nested-clients": "^3.996.5", "@aws-sdk/types": "^3.973.4", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", @@ -2044,9 +2044,9 @@ } }, "node_modules/@aws-sdk/ec2-metadata-service": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/ec2-metadata-service/-/ec2-metadata-service-3.1001.0.tgz", - "integrity": "sha512-j1c8dJYvVfkO9fdGXDp4c4Z/GeuxhN8Hr0q7wOJZZhln5ltI4JDGzEdGI4DUvNXT2zolkb6f6OgNo0j+7c34Jg==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/ec2-metadata-service/-/ec2-metadata-service-3.1002.0.tgz", + "integrity": "sha512-ePC+WKeQpR9NvkfE48TFb1f9/JX7E66e5qi6hvSbAOpST7NVJhDTeAx/H3+q+xOdFYZA6wttcebN8jViz1Ad7A==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/types": "^3.973.4", @@ -2077,9 +2077,9 @@ } }, "node_modules/@aws-sdk/lib-storage": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.1001.0.tgz", - "integrity": "sha512-h1EO4CKayPb7KqdC8M8aSr/7g8LueCN048WvasFMKxH5wuN5UBa+slE1OHfi/tR+fHILa6K7YUJ6L0Ibg3OdBA==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.1002.0.tgz", + "integrity": "sha512-vOzNq63BLXUTawI4/D2kU/92wZcHsng6yuIAZuW1FofCvsWORdwdRxJYame506lKZTPCNw49LIAoBT2YJ2+pGw==", "license": "Apache-2.0", "dependencies": { "@smithy/abort-controller": "^4.2.10", @@ -2094,7 +2094,7 @@ "node": ">=20.0.0" }, "peerDependencies": { - "@aws-sdk/client-s3": "^3.1001.0" + "@aws-sdk/client-s3": "^3.1002.0" } }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { @@ -2146,15 +2146,15 @@ } }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.973.2", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.973.2.tgz", - "integrity": "sha512-KM6QujWdasNjRLG+f7YEqEY5D36vR6Govm7nPIwxjILpb5rJ0pPJZpYY1nrzgtlxwJIYAznfBK5YXoLOHKHyfQ==", + "version": "3.973.3", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.973.3.tgz", + "integrity": "sha512-C9Mu9pXMpQh7jBydx0MrfQxNIKwJvKbVbJJ0GZthM+cQ+KTChXA01MwttRsMq0ZRb4pBJZQtIKDUxXusDr5OKg==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", "@aws-crypto/crc32c": "5.2.0", "@aws-crypto/util": "5.2.0", - "@aws-sdk/core": "^3.973.16", + "@aws-sdk/core": "^3.973.17", "@aws-sdk/crc64-nvme": "^3.972.3", "@aws-sdk/types": "^3.973.4", "@smithy/is-array-buffer": "^4.2.1", @@ -2263,12 +2263,12 @@ } }, "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.972.16", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.16.tgz", - "integrity": "sha512-U4K1rqyJYvT/zgTI3+rN+MToa51dFnnq1VSsVJuJWPNEKcEnuZVqf7yTpkJJMkYixVW5TTi1dgupd+nmJ0JyWw==", + "version": "3.972.17", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.17.tgz", + "integrity": "sha512-uSyOGoVFMP44pTt29MIMfsOjegqE/7lT0K3HG0GWPiH2lD4rqZC/TRi/kH4zrGiOQdsaLc+dkfd7Sb2q8vh+gA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.16", + "@aws-sdk/core": "^3.973.17", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-arn-parser": "^3.972.2", "@smithy/core": "^3.23.7", @@ -2302,12 +2302,12 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.972.16", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.16.tgz", - "integrity": "sha512-AmVxtxn8ZkNJbuPu3KKfW9IkJgTgcEtgSwbo0NVcAb31iGvLgHXj2nbbyrUDfh2fx8otXmqL+qw1lRaTi+V3vA==", + "version": "3.972.17", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.17.tgz", + "integrity": "sha512-HHArkgWzomuwufXwheQqkddu763PWCpoNTq1dGjqXzJT/lojX3VlOqjNSR2Xvb6/T9ISfwYcMOcbFgUp4EWxXA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.16", + "@aws-sdk/core": "^3.973.17", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@smithy/core": "^3.23.7", @@ -2343,23 +2343,23 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.996.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.4.tgz", - "integrity": "sha512-NowB1HfOnWC4kwZOnTg8E8rSL0U+RSjSa++UtEV4ipoH6JOjMLnHyGilqwl+Pe1f0Al6v9yMkSJ/8Ot0f578CQ==", + "version": "3.996.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.996.5.tgz", + "integrity": "sha512-zn0WApcULn7Rtl6T+KP2CQTZo/7wOa2YV1yHQnbijTQoi4YXQHM8s21JcJzt33/mqPh8AdvWX1f+83KvKuxlZw==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "^3.973.16", + "@aws-sdk/core": "^3.973.17", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", - "@aws-sdk/util-user-agent-node": "^3.973.1", + "@aws-sdk/util-user-agent-node": "^3.973.2", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.7", "@smithy/fetch-http-handler": "^5.3.12", @@ -2408,12 +2408,12 @@ } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.996.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.4.tgz", - "integrity": "sha512-MGa8ro0onekYIiesHX60LwKdkxK3Kd61p7TTbLwZemBqlnD9OLrk9sXZdFOIxXanJ+3AaJnV/jiX866eD/4PDg==", + "version": "3.996.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.5.tgz", + "integrity": "sha512-AVIhf74wRMzU1WBPVzcGPjlADF5VxZ8m8Ctm1v7eO4/reWMhZnEBn4tlR4vM4pOYFkdrYp3MTzYVZIikCO+53Q==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-sdk-s3": "^3.972.16", + "@aws-sdk/middleware-sdk-s3": "^3.972.17", "@aws-sdk/types": "^3.973.4", "@smithy/protocol-http": "^5.3.10", "@smithy/signature-v4": "^5.3.10", @@ -2425,13 +2425,13 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.1001.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1001.0.tgz", - "integrity": "sha512-09XAq/uIYgeZhohuGRrR/R+ek3+ljFNdzWCXdqb9rlIERDjSfNiLjTtpHgSK1xTPmC5G4yWoEAyMfTXiggS6wA==", + "version": "3.1002.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1002.0.tgz", + "integrity": "sha512-x972uKOydFn4Rb0PZJzLdNW59rH0KWC78Q2JbQzZpGlGt0DxjYdDRwBG6F42B1MyaEwHGqO/tkGc4r3/PRFfMw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.973.16", - "@aws-sdk/nested-clients": "^3.996.4", + "@aws-sdk/core": "^3.973.17", + "@aws-sdk/nested-clients": "^3.996.5", "@aws-sdk/types": "^3.973.4", "@smithy/property-provider": "^4.2.10", "@smithy/shared-ini-file-loader": "^4.4.5", @@ -2523,12 +2523,12 @@ } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.973.1", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.1.tgz", - "integrity": "sha512-kmgbDqT7aCBEVrqESM2JUjbf0zhDUQ7wnt3q1RuVS+3mglrcfVb2bwkbmf38npOyyPGtQPV5dWN3m+sSFAVAgQ==", + "version": "3.973.2", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.973.2.tgz", + "integrity": "sha512-lpaIuekdkpw7VRiik0IZmd6TyvEUcuLgKZ5fKRGpCA3I4PjrD/XH15sSwW+OptxQjNU4DEzSxag70spC9SluvA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "^3.972.16", + "@aws-sdk/middleware-user-agent": "^3.972.17", "@aws-sdk/types": "^3.973.4", "@smithy/node-config-provider": "^4.3.10", "@smithy/types": "^4.13.0", @@ -7043,9 +7043,9 @@ "license": "CC-BY-4.0" }, "node_modules/cdk-from-cfn": { - "version": "0.283.0", - "resolved": "https://registry.npmjs.org/cdk-from-cfn/-/cdk-from-cfn-0.283.0.tgz", - "integrity": "sha512-qqXpt8leAMC4hlws9ulDhpyWyaNk5LWdkzCRFInpLEJm+UfqK5AII7rB31Vg/yBd1fw0zm/r6ntER8XTUB5Elw==", + "version": "0.286.0", + "resolved": "https://registry.npmjs.org/cdk-from-cfn/-/cdk-from-cfn-0.286.0.tgz", + "integrity": "sha512-MT4NG5c9FkJZiXuSNW0H3YtvmMwwVlfiyXrBXr6nTnb8gP/ougQ+SlP3kdafkut+BWEZnjmDuOEEhtjGMqEGXA==", "license": "MIT OR Apache-2.0" }, "node_modules/chai": { @@ -7694,9 +7694,9 @@ } }, "node_modules/es-toolkit": { - "version": "1.45.0", - "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.45.0.tgz", - "integrity": "sha512-RArCX+Zea16+R1jg4mH223Z8p/ivbJjIkU3oC6ld2bdUfmDxiCkFYSi9zLOR2anucWJUeH4Djnzgd0im0nD3dw==", + "version": "1.45.1", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.45.1.tgz", + "integrity": "sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==", "license": "MIT", "workspaces": [ "docs", @@ -10535,9 +10535,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", "dev": true, "license": "MIT" }, @@ -13098,6 +13098,22 @@ } } }, + "node_modules/vitest/node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "extraneous": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/src/cli/commands/logs/__tests__/action.test.ts b/src/cli/commands/logs/__tests__/action.test.ts index 174fe325..81e1f39f 100644 --- a/src/cli/commands/logs/__tests__/action.test.ts +++ b/src/cli/commands/logs/__tests__/action.test.ts @@ -1,5 +1,5 @@ import { detectMode, formatLogLine, resolveAgentContext } from '../action'; -import type { LogsContext } from '../action'; +import type { DeployedProjectConfig } from '../action'; import { describe, expect, it } from 'vitest'; describe('detectMode', () => { @@ -39,7 +39,7 @@ describe('formatLogLine', () => { describe('resolveAgentContext', () => { // Use 'as any' to avoid branded type issues with FilePath/DirectoryPath - const makeContext = (overrides?: Partial): LogsContext => ({ + const makeContext = (overrides?: Partial): DeployedProjectConfig => ({ project: { name: 'TestProject', version: 1, diff --git a/src/cli/commands/logs/__tests__/time-parser.test.ts b/src/cli/commands/logs/__tests__/time-parser.test.ts index 82bd8aca..0180109c 100644 --- a/src/cli/commands/logs/__tests__/time-parser.test.ts +++ b/src/cli/commands/logs/__tests__/time-parser.test.ts @@ -1,4 +1,4 @@ -import { parseTimeString } from '../time-parser'; +import { parseTimeString } from '../../../../lib/utils/time-parser'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; describe('parseTimeString', () => { diff --git a/src/cli/commands/logs/action.ts b/src/cli/commands/logs/action.ts index 61eee30f..f64b81e8 100644 --- a/src/cli/commands/logs/action.ts +++ b/src/cli/commands/logs/action.ts @@ -1,15 +1,11 @@ -import { ConfigIO } from '../../../lib'; -import type { AgentCoreProjectSpec, AwsDeploymentTargets, DeployedState } from '../../../schema'; +import { parseTimeString } from '../../../lib/utils'; import { searchLogs, streamLogs } from '../../aws/cloudwatch'; +import type { DeployedProjectConfig } from '../../operations/resolve-agent'; +import { loadDeployedProjectConfig, resolveAgent } from '../../operations/resolve-agent'; import { VALID_LEVELS, buildFilterPattern } from './filter-pattern'; -import { parseTimeString } from './time-parser'; import type { LogsOptions } from './types'; -export interface LogsContext { - project: AgentCoreProjectSpec; - deployedState: DeployedState; - awsTargets: AwsDeploymentTargets; -} +export type { DeployedProjectConfig }; export interface AgentContext { agentId: string; @@ -25,17 +21,6 @@ export interface LogsResult { error?: string; } -/** - * Loads configuration required for logs - */ -export async function loadLogsConfig(configIO: ConfigIO = new ConfigIO()): Promise { - return { - project: await configIO.readProjectSpec(), - deployedState: await configIO.readDeployedState(), - awsTargets: await configIO.readAWSDeploymentTargets(), - }; -} - /** * Detect whether to stream or search based on options */ @@ -61,73 +46,23 @@ export function formatLogLine(event: { timestamp: number; message: string }, jso * Resolve agent context from config + options */ export function resolveAgentContext( - context: LogsContext, + context: DeployedProjectConfig, options: LogsOptions ): { success: true; agentContext: AgentContext } | { success: false; error: string } { - const { project, deployedState, awsTargets } = context; - - if (project.agents.length === 0) { - return { success: false, error: 'No agents defined in agentcore.json' }; - } - - // Resolve agent - const agentNames = project.agents.map(a => a.name); - - if (!options.agent && project.agents.length > 1) { - return { - success: false, - error: `Multiple agents found. Use --agent to specify one: ${agentNames.join(', ')}`, - }; + const result = resolveAgent(context, options); + if (!result.success) { + return { success: false, error: result.error }; } - - const agentSpec = options.agent ? project.agents.find(a => a.name === options.agent) : project.agents[0]; - - if (options.agent && !agentSpec) { - return { - success: false, - error: `Agent '${options.agent}' not found. Available: ${agentNames.join(', ')}`, - }; - } - - if (!agentSpec) { - return { success: false, error: 'No agents defined in agentcore.json' }; - } - - // Resolve target - const targetNames = Object.keys(deployedState.targets); - if (targetNames.length === 0) { - return { success: false, error: 'No deployed targets found. Run `agentcore deploy` first.' }; - } - const selectedTargetName = targetNames[0]!; - - const targetState = deployedState.targets[selectedTargetName]; - const targetConfig = awsTargets.find(t => t.name === selectedTargetName); - - if (!targetConfig) { - return { success: false, error: `Target config '${selectedTargetName}' not found in aws-targets` }; - } - - // Get the deployed state for this specific agent - const agentState = targetState?.resources?.agents?.[agentSpec.name]; - - if (!agentState) { - return { - success: false, - error: `Agent '${agentSpec.name}' is not deployed to target '${selectedTargetName}'. Run 'agentcore deploy' first.`, - }; - } - - const agentId = agentState.runtimeId; + const { agent } = result; const endpointName = 'DEFAULT'; - const logGroupName = `/aws/bedrock-agentcore/runtimes/${agentId}-${endpointName}`; - + const logGroupName = `/aws/bedrock-agentcore/runtimes/${agent.runtimeId}-${endpointName}`; return { success: true, agentContext: { - agentId, - agentName: agentSpec.name, - accountId: targetConfig.account, - region: targetConfig.region, + agentId: agent.runtimeId, + agentName: agent.agentName, + accountId: agent.accountId, + region: agent.region, endpointName, logGroupName, }, @@ -146,7 +81,7 @@ export async function handleLogs(options: LogsOptions): Promise { }; } - const context = await loadLogsConfig(); + const context = await loadDeployedProjectConfig(); const resolution = resolveAgentContext(context, options); if (!resolution.success) { diff --git a/src/cli/commands/traces/action.ts b/src/cli/commands/traces/action.ts index 66333fb8..817159d9 100644 --- a/src/cli/commands/traces/action.ts +++ b/src/cli/commands/traces/action.ts @@ -1,81 +1,9 @@ -import { ConfigIO } from '../../../lib'; -import type { AgentCoreProjectSpec, AwsDeploymentTargets, DeployedState } from '../../../schema'; -import { buildTraceConsoleUrl, getTrace, listTraces, parseRuntimeArn } from '../../operations/traces'; +import { parseTimeString } from '../../../lib/utils'; +import type { DeployedProjectConfig } from '../../operations/resolve-agent'; +import { resolveAgent } from '../../operations/resolve-agent'; +import { buildTraceConsoleUrl, getTrace, listTraces } from '../../operations/traces'; import type { TracesGetOptions, TracesListOptions } from './types'; -export interface TracesContext { - project: AgentCoreProjectSpec; - deployedState: DeployedState; - awsTargets: AwsDeploymentTargets; -} - -export async function loadTracesConfig(configIO: ConfigIO = new ConfigIO()): Promise { - return { - project: await configIO.readProjectSpec(), - deployedState: await configIO.readDeployedState(), - awsTargets: await configIO.readAWSDeploymentTargets(), - }; -} - -interface ResolvedAgent { - agentName: string; - region: string; - accountId: string; - runtimeId: string; - targetName: string; -} - -function resolveAgent(context: TracesContext, options: { agent?: string }): ResolvedAgent | { error: string } { - const { project, deployedState, awsTargets } = context; - - const targetNames = Object.keys(deployedState.targets); - if (targetNames.length === 0) { - return { error: 'No deployed targets found. Run `agentcore deploy` first.' }; - } - - const selectedTargetName = targetNames[0]!; - const targetState = deployedState.targets[selectedTargetName]; - const targetConfig = awsTargets.find(t => t.name === selectedTargetName); - if (!targetConfig) { - return { error: `Target config '${selectedTargetName}' not found in aws-targets` }; - } - - if (project.agents.length === 0) { - return { error: 'No agents defined in configuration' }; - } - - const agentNames = project.agents.map(a => a.name); - if (!options.agent && project.agents.length > 1) { - return { error: `Multiple agents found. Use --agent to specify one: ${agentNames.join(', ')}` }; - } - - const agentSpec = options.agent ? project.agents.find(a => a.name === options.agent) : project.agents[0]; - if (options.agent && !agentSpec) { - return { error: `Agent '${options.agent}' not found. Available: ${agentNames.join(', ')}` }; - } - if (!agentSpec) { - return { error: 'No agents defined in configuration' }; - } - - const agentState = targetState?.resources?.agents?.[agentSpec.name]; - if (!agentState) { - return { error: `Agent '${agentSpec.name}' is not deployed to target '${selectedTargetName}'` }; - } - - const parsed = parseRuntimeArn(agentState.runtimeArn); - if (!parsed) { - return { error: `Could not parse runtime ARN: ${agentState.runtimeArn}` }; - } - - return { - agentName: agentSpec.name, - region: targetConfig.region, - accountId: parsed.accountId, - runtimeId: parsed.runtimeId, - targetName: selectedTargetName, - }; -} - export interface TracesListResult { success: boolean; agentName?: string; @@ -85,25 +13,43 @@ export interface TracesListResult { error?: string; } -export async function handleTracesList(context: TracesContext, options: TracesListOptions): Promise { +export async function handleTracesList( + context: DeployedProjectConfig, + options: TracesListOptions +): Promise { const resolved = resolveAgent(context, options); - if ('error' in resolved) { + if (!resolved.success) { return { success: false, error: resolved.error }; } + const { agent } = resolved; + const consoleUrl = buildTraceConsoleUrl({ - region: resolved.region, - accountId: resolved.accountId, - runtimeId: resolved.runtimeId, - agentName: resolved.agentName, + region: agent.region, + accountId: agent.accountId, + runtimeId: agent.runtimeId, + agentName: agent.agentName, }); const limit = options.limit ? parseInt(options.limit, 10) : 20; + + // Parse time options + let startTime: number | undefined; + let endTime: number | undefined; + if (options.since) { + startTime = parseTimeString(options.since); + } + if (options.until) { + endTime = parseTimeString(options.until); + } + const result = await listTraces({ - region: resolved.region, - runtimeId: resolved.runtimeId, - agentName: resolved.agentName, + region: agent.region, + runtimeId: agent.runtimeId, + agentName: agent.agentName, limit, + startTime, + endTime, }); if (!result.success) { @@ -112,8 +58,8 @@ export async function handleTracesList(context: TracesContext, options: TracesLi return { success: true, - agentName: resolved.agentName, - targetName: resolved.targetName, + agentName: agent.agentName, + targetName: agent.targetName, consoleUrl, traces: result.traces, }; @@ -129,28 +75,42 @@ export interface TracesGetResult { } export async function handleTracesGet( - context: TracesContext, + context: DeployedProjectConfig, traceId: string, options: TracesGetOptions ): Promise { const resolved = resolveAgent(context, options); - if ('error' in resolved) { + if (!resolved.success) { return { success: false, error: resolved.error }; } + const { agent } = resolved; + const consoleUrl = buildTraceConsoleUrl({ - region: resolved.region, - accountId: resolved.accountId, - runtimeId: resolved.runtimeId, - agentName: resolved.agentName, + region: agent.region, + accountId: agent.accountId, + runtimeId: agent.runtimeId, + agentName: agent.agentName, }); + // Parse time options + let startTime: number | undefined; + let endTime: number | undefined; + if (options.since) { + startTime = parseTimeString(options.since); + } + if (options.until) { + endTime = parseTimeString(options.until); + } + const result = await getTrace({ - region: resolved.region, - runtimeId: resolved.runtimeId, - agentName: resolved.agentName, + region: agent.region, + runtimeId: agent.runtimeId, + agentName: agent.agentName, traceId, outputPath: options.output, + startTime, + endTime, }); if (!result.success) { @@ -159,8 +119,8 @@ export async function handleTracesGet( return { success: true, - agentName: resolved.agentName, - targetName: resolved.targetName, + agentName: agent.agentName, + targetName: agent.targetName, consoleUrl, filePath: result.filePath, }; diff --git a/src/cli/commands/traces/command.tsx b/src/cli/commands/traces/command.tsx index 796cb013..b34d61e8 100644 --- a/src/cli/commands/traces/command.tsx +++ b/src/cli/commands/traces/command.tsx @@ -1,7 +1,8 @@ import { getErrorMessage } from '../../errors'; +import { loadDeployedProjectConfig } from '../../operations/resolve-agent'; import { COMMAND_DESCRIPTIONS } from '../../tui/copy'; import { requireProject } from '../../tui/guards'; -import { handleTracesGet, handleTracesList, loadTracesConfig } from './action'; +import { handleTracesGet, handleTracesList } from './action'; import type { TracesGetOptions, TracesListOptions } from './types'; import type { Command } from '@commander-js/extra-typings'; import { Box, Text, render } from 'ink'; @@ -24,11 +25,13 @@ export const registerTraces = (program: Command) => { .description('List recent traces for a deployed agent') .option('--agent ', 'Select specific agent') .option('--limit ', 'Maximum number of traces to display', '20') + .option('--since