diff --git a/CHANGELOG.md b/CHANGELOG.md index 997b4b48..726c15ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -268,6 +268,23 @@ Entries before v0.5.0 were written retroactively as summaries. button, the agent's calls to the MCP runtime and external MCP clients keep working; a caller that ran commands in a runtime session through `InvokeAgentRuntimeCommand` now gets 403. +- **Narrow the agent's execution role to what it uses.** The agent role no longer has access to + the decks table or the PPTX bucket (deck storage is the MCP server's), and the agent runtime no + longer gets the `DECKS_TABLE` / `PPTX_BUCKET` variables. AgentCore access is limited to the + Memory events the session manager writes and reads, on the agent's own Memory; ECR pulls to the + image repository; and the role explicitly denies user-id delegation + (`InvokeAgentRuntimeForUser`, `GetWorkloadAccessTokenForUserId`) and any call made through an + AWS-managed MCP server. The trust policies of the agent and MCP runtime roles accept AgentCore + only for resources of the deploying account and Region (`aws:SourceAccount` / + `aws:SourceArn`). The MCP runtime role drops its unused AWS Marketplace permissions and its + ECR pull on `*`, and the API Lambda's `ListEvents` is limited to the agent's Memory. +- **Limit the AWS knowledge tools to documentation tools.** The agent connects to the public AWS + Knowledge MCP Server endpoint (`knowledge-mcp.global.api.aws`) and offers its model only + `aws___search_documentation`, `aws___read_documentation`, `aws___retrieve_skill`, + `aws___list_regions` and `aws___get_regional_availability`. The `mcp-proxy-for-aws` + dependency is removed. +- **The agent accepts `prompt` as text only.** An invocation whose `prompt` is not a string is + answered with a `bad_input` error. - **The agent no longer sees the user's id in Cloud attachments.** The upload handle the API returns and the Web UI puts in the `[Attached:…]` marker is now `uploads/{uuid}/{name}` instead of the S3 key `uploads/{userId}/{uuid}/{name}`. The MCP server builds the S3 key from diff --git a/agent/README.md b/agent/README.md index 9e605d8e..e73ef090 100644 --- a/agent/README.md +++ b/agent/README.md @@ -141,8 +141,6 @@ In addition to MCP tools, the agent includes built-in tools defined locally: | `MEMORY_ID` | Bedrock AgentCore Memory ID | `""` | | `MODEL_ID` | Bedrock model ID | `global.anthropic.claude-sonnet-4-6` | | `AWS_REGION` / `AWS_DEFAULT_REGION` | AWS region | `us-east-1` | -| `DECKS_TABLE` | DynamoDB table name | (required) | -| `PPTX_BUCKET` | S3 bucket name | (required) | --- diff --git a/agent/basic_agent.py b/agent/basic_agent.py index 426782e7..6c250157 100644 --- a/agent/basic_agent.py +++ b/agent/basic_agent.py @@ -45,6 +45,12 @@ async def agent_stream(payload, context): user_query = payload.get("prompt") session_id = payload.get("runtimeSessionId") + # Text only: the agent framework also accepts content-block lists, which + # this entrypoint does not take from callers. + if user_query is not None and not isinstance(user_query, str): + yield error_event("Invalid field: prompt must be a string", code=BAD_INPUT) + return + if not all([user_query, session_id]): yield error_event("Missing required fields: prompt or runtimeSessionId", code=BAD_INPUT) return diff --git a/agent/mcp_clients.py b/agent/mcp_clients.py index 2224c1f3..4299e720 100644 --- a/agent/mcp_clients.py +++ b/agent/mcp_clients.py @@ -2,15 +2,12 @@ # SPDX-License-Identifier: MIT-0 """MCP client factories and server instruction collection.""" -import logging import os import urllib.parse from mcp.client.streamable_http import streamablehttp_client from strands.tools.mcp import MCPClient -logger = logging.getLogger("sdpm.agent") - # MCP server definitions: (display_name, required) MCP_DEFS: list[tuple[str, bool]] = [ ("Presentation Maker", True), @@ -70,26 +67,29 @@ def mcp_agentcore_runtime( ) +AWS_KNOWLEDGE_URL = "https://knowledge-mcp.global.api.aws" + +# The AWS documentation tools the agent offers its model. The allowlist pins the +# set even if the endpoint adds tools later. +AWS_KNOWLEDGE_TOOLS: list[str] = [ + "aws___search_documentation", + "aws___read_documentation", + "aws___retrieve_skill", + "aws___list_regions", + "aws___get_regional_availability", +] + + def mcp_aws_knowledge() -> MCPClient: - """Pattern 2: IAM-authenticated AWS Knowledge MCP with public fallback. + """Pattern 2: AWS Knowledge MCP Server (public endpoint, no authentication). - Note: AWS MCP Server is currently only available in us-east-1. - We hard-code the endpoint region regardless of the agent's region. + The agent uses the AWS documentation tools only. The public endpoint serves + exactly those and is called without the execution role's credentials. """ - try: - from mcp_proxy_for_aws.client import aws_iam_streamablehttp_client - return MCPClient( - lambda: aws_iam_streamablehttp_client( - endpoint="https://aws-mcp.us-east-1.api.aws/mcp", - aws_service="aws-mcp", - aws_region="us-east-1", - ), - ) - except Exception: - logger.warning("IAM auth unavailable for AWS Knowledge MCP, using public endpoint") - return MCPClient( - lambda: streamablehttp_client(url="https://knowledge-mcp.global.api.aws"), - ) + return MCPClient( + lambda: streamablehttp_client(url=AWS_KNOWLEDGE_URL), + tool_filters={"allowed": list(AWS_KNOWLEDGE_TOOLS)}, + ) def mcp_aws_pricing() -> MCPClient: diff --git a/agent/pyproject.toml b/agent/pyproject.toml index 546f7a53..81fec16c 100644 --- a/agent/pyproject.toml +++ b/agent/pyproject.toml @@ -12,7 +12,6 @@ dependencies = [ "bedrock-agentcore[strands-agents]>=1.0.6", "aws-opentelemetry-distro>=0.10.0", "awslabs.aws-pricing-mcp-server", - "mcp-proxy-for-aws>=1.1.0", "requests", "html2text", "pymupdf", diff --git a/infra/bin/infra.ts b/infra/bin/infra.ts index 70079e1b..83e4d2ad 100644 --- a/infra/bin/infra.ts +++ b/infra/bin/infra.ts @@ -236,8 +236,6 @@ if (config.stacks?.agent) { const agent = new AgentStack(app, "SdpmAgent", { env, description: "Spec-Driven Presentation Maker - Agent (uksb-ynuz0lkrea)(tag:agent)", - table: data.table, - pptxBucket: data.pptxBucket, mcpRuntimeArn: runtime.runtimeArn, oidcDiscoveryUrl: authStack ? undefined : oidcDiscoveryUrl, allowedClients, diff --git a/infra/lib/agent-stack.ts b/infra/lib/agent-stack.ts index 36d1ee18..9a274c9e 100644 --- a/infra/lib/agent-stack.ts +++ b/infra/lib/agent-stack.ts @@ -11,21 +11,16 @@ import * as cdk from "aws-cdk-lib"; import * as bedrockagentcore from "aws-cdk-lib/aws-bedrockagentcore"; -import * as dynamodb from "aws-cdk-lib/aws-dynamodb"; import * as ecr_assets from "aws-cdk-lib/aws-ecr-assets"; import * as iam from "aws-cdk-lib/aws-iam"; -import * as s3 from "aws-cdk-lib/aws-s3"; import * as ssm from "aws-cdk-lib/aws-ssm"; import { Construct } from "constructs"; import * as path from "path"; import { AUTH_SSM_PARAMS } from "./auth-stack"; import { RuntimeResourcePolicy } from "./construct/runtime-resource-policy"; +import { agentCoreServicePrincipal } from "./construct/agentcore-principal"; interface AgentStackProps extends cdk.StackProps { - /** Amazon DynamoDB table from DataStack. */ - table: dynamodb.TableV2; - /** S3 bucket for PPTX output. */ - pptxBucket: s3.Bucket; /** MCP Server Runtime ARN. */ mcpRuntimeArn: string; /** @@ -73,12 +68,17 @@ export class AgentStack extends cdk.Stack { }); // --- IAM Role --- + // Execution role: only what the agent code uses. Deck storage (DynamoDB / S3) + // belongs to the MCP Runtime, which the agent calls with the user's JWT, so + // the agent role needs no storage or runtime-invoke permissions. + // Trust: only AgentCore resources of this account (confused-deputy guard). const role = new iam.Role(this, "AgentRole", { - assumedBy: new iam.ServicePrincipal("bedrock-agentcore.amazonaws.com"), + assumedBy: agentCoreServicePrincipal(this), description: "Execution role for spec-driven-presentation-maker Agent Runtime", }); - // IAM: Least-privilege — Agent role only gets Bedrock InvokeModel and MCP Runtime invoke. + // Bedrock Converse / ConverseStream. Resource stays "*": the model can be + // switched per user among allowedModelIds (cross-region inference profiles). role.addToPolicy( new iam.PolicyStatement({ actions: ["bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream"], @@ -86,9 +86,6 @@ export class AgentStack extends cdk.Stack { }) ); - props.table.grantReadWriteData(role); - props.pptxBucket.grantReadWrite(role); - // CloudWatch Logs (AgentCore writes stdout/stderr directly via execution role) role.addToPolicy(new iam.PolicyStatement({ actions: ["logs:CreateLogGroup", "logs:DescribeLogStreams"], @@ -111,51 +108,47 @@ export class AgentStack extends cdk.Stack { }) ); - // Amazon Bedrock AgentCore Memory + // Explicit denies (security best practices for AgentCore Runtime): + // - user-id delegation: the agent identifies users by the verified JWT only. + // - calls made through AWS-managed MCP servers: the agent uses the public + // AWS Knowledge endpoint, which carries no AWS credentials. role.addToPolicy( new iam.PolicyStatement({ - actions: ["bedrock-agentcore:*"], + sid: "DenyUserIdDelegation", + effect: iam.Effect.DENY, + actions: [ + "bedrock-agentcore:InvokeAgentRuntimeForUser", + "bedrock-agentcore:GetWorkloadAccessTokenForUserId", + ], resources: ["*"], }) ); - - // AWS MCP service (IAM-authenticated Knowledge MCP endpoint) role.addToPolicy( new iam.PolicyStatement({ - actions: ["aws-mcp:*"], + sid: "DenyViaAwsManagedMcp", + effect: iam.Effect.DENY, + actions: ["*"], resources: ["*"], + conditions: { Bool: { "aws:ViaAWSMCPService": "true" } }, }) ); - // ECR pull + // ECR pull: the image repository only (GetAuthorizationToken has no resource scope) role.addToPolicy( new iam.PolicyStatement({ - actions: [ - "ecr:GetDownloadUrlForLayer", - "ecr:BatchGetImage", - "ecr:GetAuthorizationToken", - ], - resources: ["*"], + actions: ["ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage"], + resources: [image.repository.repositoryArn], }) ); - - // CloudWatch Logs / X-Ray / Metrics — required for AgentCore Runtime observability - // https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-permissions.html role.addToPolicy( new iam.PolicyStatement({ - actions: [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents", - "logs:DescribeLogGroups", - "logs:DescribeLogStreams", - ], - resources: [ - `arn:aws:logs:${this.region}:${this.account}:log-group:/aws/bedrock-agentcore/runtimes/*`, - `arn:aws:logs:${this.region}:${this.account}:log-group:/aws/bedrock-agentcore/runtimes/*:log-stream:*`, - ], + actions: ["ecr:GetAuthorizationToken"], + resources: ["*"], }) ); + + // X-Ray / Metrics — required for AgentCore Runtime observability + // https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-permissions.html role.addToPolicy( new iam.PolicyStatement({ actions: [ @@ -191,6 +184,20 @@ export class AgentStack extends cdk.Stack { }); const memoryId = memory.attrMemoryId; + // Memory: the short-term event calls of the Strands session manager + // (AgentCoreMemorySessionManager; no long-term retrieval is configured). + role.addToPolicy( + new iam.PolicyStatement({ + actions: [ + "bedrock-agentcore:CreateEvent", + "bedrock-agentcore:ListEvents", + "bedrock-agentcore:GetEvent", + "bedrock-agentcore:DeleteEvent", + ], + resources: [memory.attrMemoryArn], + }) + ); + // --- Amazon Bedrock AgentCore Runtime --- const defaultPolicy = role.node.findChild("DefaultPolicy") as iam.Policy; @@ -231,8 +238,6 @@ export class AgentStack extends cdk.Stack { CREATE_MODEL_ID: this.node.tryGetContext("createModelId") || props.createModelId || props.chatModelId || "global.anthropic.claude-sonnet-4-6", ALLOWED_MODEL_IDS: JSON.stringify(props.allowedModelIds ?? []), MEMORY_ID: memoryId, - DECKS_TABLE: props.table.tableName, - PPTX_BUCKET: props.pptxBucket.bucketName, AWS_DEFAULT_REGION: this.region, COMPOSER_MAX_CONCURRENCY: "10", DEPLOY_TIMESTAMP: new Date().toISOString(), diff --git a/infra/lib/construct/agentcore-principal.ts b/infra/lib/construct/agentcore-principal.ts new file mode 100644 index 00000000..20bdae59 --- /dev/null +++ b/infra/lib/construct/agentcore-principal.ts @@ -0,0 +1,18 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: MIT-0 +import * as cdk from "aws-cdk-lib"; +import * as iam from "aws-cdk-lib/aws-iam"; + +/** + * The AgentCore service principal for a runtime execution role's trust policy, + * limited to AgentCore resources of this account and Region + * (confused-deputy prevention, AgentCore Runtime security best practices). + */ +export function agentCoreServicePrincipal(stack: cdk.Stack): iam.ServicePrincipal { + return new iam.ServicePrincipal("bedrock-agentcore.amazonaws.com", { + conditions: { + StringEquals: { "aws:SourceAccount": stack.account }, + ArnLike: { "aws:SourceArn": `arn:aws:bedrock-agentcore:${stack.region}:${stack.account}:*` }, + }, + }); +} diff --git a/infra/lib/runtime-stack.ts b/infra/lib/runtime-stack.ts index 457f9d1a..75269443 100644 --- a/infra/lib/runtime-stack.ts +++ b/infra/lib/runtime-stack.ts @@ -23,6 +23,7 @@ import { Construct } from "constructs"; import * as path from "path"; import { AUTH_SSM_PARAMS } from "./auth-stack"; import { RuntimeResourcePolicy } from "./construct/runtime-resource-policy"; +import { agentCoreServicePrincipal } from "./construct/agentcore-principal"; interface RuntimeStackProps extends cdk.StackProps { /** Amazon DynamoDB table from DataStack. */ @@ -71,8 +72,9 @@ export class RuntimeStack extends cdk.Stack { }); // --- IAM Role for Runtime --- + // Trust: only AgentCore resources of this account (confused-deputy guard). const runtimeRole = new iam.Role(this, "RuntimeRole", { - assumedBy: new iam.ServicePrincipal("bedrock-agentcore.amazonaws.com"), + assumedBy: agentCoreServicePrincipal(this), description: "Execution role for spec-driven-presentation-maker AgentCore Runtime", }); @@ -99,34 +101,17 @@ export class RuntimeStack extends cdk.Stack { actions: ["logs:CreateLogStream", "logs:PutLogEvents"], resources: [`arn:aws:logs:${this.region}:${this.account}:log-group:/aws/bedrock-agentcore/runtimes/*:log-stream:*`], })); + // ECR pull: the image repository is granted below (image.repository.grant); + // GetAuthorizationToken has no resource scope. runtimeRole.addToPolicy( new iam.PolicyStatement({ - actions: [ - "ecr:GetDownloadUrlForLayer", - "ecr:BatchGetImage", - "ecr:GetAuthorizationToken", - ], + actions: ["ecr:GetAuthorizationToken"], resources: ["*"], }) ); - // CloudWatch Logs / X-Ray / Metrics — required for AgentCore Runtime observability + // X-Ray / Metrics — required for AgentCore Runtime observability // https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-permissions.html - runtimeRole.addToPolicy( - new iam.PolicyStatement({ - actions: [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents", - "logs:DescribeLogGroups", - "logs:DescribeLogStreams", - ], - resources: [ - `arn:aws:logs:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:log-group:/aws/bedrock-agentcore/runtimes/*`, - `arn:aws:logs:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:log-group:/aws/bedrock-agentcore/runtimes/*:log-stream:*`, - ], - }) - ); runtimeRole.addToPolicy( new iam.PolicyStatement({ actions: [ @@ -182,17 +167,6 @@ export class RuntimeStack extends cdk.Stack { }) ); - // --- AWS Marketplace permissions (required for Bedrock model subscriptions) --- - runtimeRole.addToPolicy( - new iam.PolicyStatement({ - actions: [ - "aws-marketplace:ViewSubscriptions", - "aws-marketplace:Subscribe", - ], - resources: ["*"], - }) - ); - // --- KB permissions (Amazon Titan Embed + S3 Vectors + Amazon Bedrock Retrieve) --- if (props.vectorBucketName) { runtimeRole.addToPolicy( diff --git a/infra/lib/web-ui-stack.ts b/infra/lib/web-ui-stack.ts index a801a958..f9a45539 100644 --- a/infra/lib/web-ui-stack.ts +++ b/infra/lib/web-ui-stack.ts @@ -293,7 +293,7 @@ function handler(event) { apiLambda.addEnvironment("MEMORY_ID", props.memoryId); apiLambda.addToRolePolicy(new iam.PolicyStatement({ actions: ["bedrock-agentcore:ListEvents"], - resources: ["*"], + resources: [`arn:aws:bedrock-agentcore:${this.region}:${this.account}:memory/${props.memoryId}`], })); } diff --git a/infra/package.json b/infra/package.json index c75b8337..61de2bdc 100644 --- a/infra/package.json +++ b/infra/package.json @@ -6,8 +6,8 @@ }, "scripts": { "build": "tsc", - "cdk": "cdk", - "test": "node --require ts-node/register --test test/*.test.ts" + "test": "TS_NODE_TRANSPILE_ONLY=1 node --require ts-node/register --test test/*.test.ts", + "cdk": "cdk" }, "devDependencies": { "@types/node": "^26.6.5", diff --git a/infra/test/execution-roles.test.ts b/infra/test/execution-roles.test.ts new file mode 100644 index 00000000..f5cc4427 --- /dev/null +++ b/infra/test/execution-roles.test.ts @@ -0,0 +1,209 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: MIT-0 +/** + * Execution roles of the agent runtime, the MCP runtime and the API Lambda grant + * what their code uses. Synthesizes the stacks the way bin/infra.ts wires them + * (AuthStack mode), with asset bundling skipped. + */ + +import { test } from "node:test"; +import * as assert from "node:assert/strict"; +import * as cdk from "aws-cdk-lib"; +import { Template } from "aws-cdk-lib/assertions"; +import { DataStack } from "../lib/data-stack"; +import { RuntimeStack } from "../lib/runtime-stack"; +import { AgentStack } from "../lib/agent-stack"; +import { WebUiStack } from "../lib/web-ui-stack"; + +const ACCOUNT = "111122223333"; +const REGION = "ap-northeast-1"; +const MODEL = "global.anthropic.claude-sonnet-4-6"; + +function synth() { + const app = new cdk.App({ context: { "aws:cdk:bundling-stacks": [] } }); + const env = { account: ACCOUNT, region: REGION }; + const data = new DataStack(app, "SdpmData", { env, enableInvocationLogging: false, enableTransactionSearch: false }); + const runtime = new RuntimeStack(app, "SdpmRuntime", { + env, + table: data.table, + pptxBucket: data.pptxBucket, + resourceBucket: data.resourceBucket, + allowedClients: [], + kbSsmParamName: data.kbSsmParamName || undefined, + vectorBucketName: data.vectorBucketName || undefined, + vectorIndexName: data.vectorIndexName || undefined, + useAuthStack: true, + }); + const agent = new AgentStack(app, "SdpmAgent", { + env, + mcpRuntimeArn: runtime.runtimeArn, + allowedClients: [], + useAuthStack: true, + chatModelId: MODEL, + createModelId: MODEL, + allowedModelIds: [MODEL], + }); + const webUi = new WebUiStack(app, "SdpmWebUi", { + env, + table: data.table, + pptxBucket: data.pptxBucket, + resourceBucket: data.resourceBucket, + agentRuntimeArn: agent.agentRuntimeArn, + memoryId: agent.memoryId, + kbId: data.kbSsmParamName, + vectorBucketName: data.vectorBucketName || undefined, + vectorIndexName: data.vectorIndexName || undefined, + defaultChatModelId: MODEL, + defaultCreateModelId: MODEL, + allowedModels: [], + }); + return { + runtime: Template.fromStack(runtime), + agent: Template.fromStack(agent), + webUi: Template.fromStack(webUi), + }; +} + +const templates = synth(); + +type Statement = { + Effect: string; + Action: string | string[]; + Resource: unknown; + Condition?: Record>; + Sid?: string; +}; + +const asList = (v: T | T[]): T[] => (Array.isArray(v) ? v : [v]); + +/** Logical id of the only role whose logical id starts with `prefix`. */ +function roleId(template: Template, prefix: string): string { + const ids = Object.keys(template.findResources("AWS::IAM::Role")).filter((id) => id.startsWith(prefix)); + assert.equal(ids.length, 1, `expected one role starting with ${prefix}, got ${ids}`); + return ids[0]; +} + +/** Every statement of the inline policies attached to the role. */ +function statements(template: Template, role: string): Statement[] { + const policies = Object.values(template.findResources("AWS::IAM::Policy")); + return policies + .filter((p) => asList(p.Properties.Roles).some((r: unknown) => JSON.stringify(r) === JSON.stringify({ Ref: role }))) + .flatMap((p) => p.Properties.PolicyDocument.Statement as Statement[]); +} + +const allows = (s: Statement[]) => s.filter((x) => x.Effect === "Allow"); +const actionsOf = (s: Statement[]) => s.flatMap((x) => asList(x.Action)); + +function assertTrustLimitedToAccount(template: Template, role: string) { + const doc = template.findResources("AWS::IAM::Role")[role].Properties.AssumeRolePolicyDocument; + assert.deepEqual(doc.Statement, [ + { + Action: "sts:AssumeRole", + Effect: "Allow", + Principal: { Service: "bedrock-agentcore.amazonaws.com" }, + Condition: { + StringEquals: { "aws:SourceAccount": ACCOUNT }, + ArnLike: { "aws:SourceArn": `arn:aws:bedrock-agentcore:${REGION}:${ACCOUNT}:*` }, + }, + }, + ]); +} + +// --- Agent runtime --- + +const agentRole = roleId(templates.agent, "AgentRole"); +const agentStatements = statements(templates.agent, agentRole); + +test("agent role has no deck storage, AWS MCP or wildcard AgentCore access", () => { + const actions = actionsOf(allows(agentStatements)); + for (const action of actions) { + assert.doesNotMatch(action, /^(dynamodb|s3|aws-mcp|kms):/, action); + assert.notEqual(action, "bedrock-agentcore:*"); + } +}); + +test("agent role uses Memory events on its own Memory only", () => { + const agentcore = allows(agentStatements).filter((s) => actionsOf([s]).some((a) => a.startsWith("bedrock-agentcore:"))); + assert.deepEqual(agentcore, [ + { + Effect: "Allow", + Action: [ + "bedrock-agentcore:CreateEvent", + "bedrock-agentcore:ListEvents", + "bedrock-agentcore:GetEvent", + "bedrock-agentcore:DeleteEvent", + ], + Resource: { "Fn::GetAtt": ["AgentMemory", "MemoryArn"] }, + }, + ]); +}); + +test("agent role denies user-id delegation and calls through AWS-managed MCP servers", () => { + const denies = agentStatements.filter((s) => s.Effect === "Deny"); + assert.deepEqual( + denies.find((s) => s.Sid === "DenyUserIdDelegation")?.Action, + ["bedrock-agentcore:InvokeAgentRuntimeForUser", "bedrock-agentcore:GetWorkloadAccessTokenForUserId"], + ); + const viaMcp = denies.find((s) => s.Sid === "DenyViaAwsManagedMcp"); + assert.equal(viaMcp?.Action, "*"); + assert.equal(viaMcp?.Resource, "*"); + assert.deepEqual(viaMcp?.Condition, { Bool: { "aws:ViaAWSMCPService": "true" } }); +}); + +test("agent role pulls images from the asset repository only", () => { + for (const s of allows(agentStatements)) { + const ecr = actionsOf([s]).filter((a) => a.startsWith("ecr:")); + if (ecr.length === 0) continue; + if (ecr.includes("ecr:GetAuthorizationToken")) { + assert.deepEqual(ecr, ["ecr:GetAuthorizationToken"]); + continue; + } + assert.notEqual(s.Resource, "*"); + assert.match(JSON.stringify(s.Resource), /:repository\//); + } +}); + +test("agent trust policy is limited to AgentCore in this account", () => { + assertTrustLimitedToAccount(templates.agent, agentRole); +}); + +test("agent runtime gets no deck storage names", () => { + const runtimes = Object.values(templates.agent.findResources("AWS::BedrockAgentCore::Runtime")); + assert.equal(runtimes.length, 1); + const env = runtimes[0].Properties.EnvironmentVariables; + assert.ok(env.MEMORY_ID); + assert.equal(env.DECKS_TABLE, undefined); + assert.equal(env.PPTX_BUCKET, undefined); +}); + +// --- MCP runtime --- + +const mcpRole = roleId(templates.runtime, "RuntimeRole"); +const mcpStatements = statements(templates.runtime, mcpRole); + +test("MCP role has no AWS Marketplace permissions", () => { + for (const action of actionsOf(mcpStatements)) assert.doesNotMatch(action, /^aws-marketplace:/); +}); + +test("MCP role grants ECR image pull on a repository, not on *", () => { + for (const s of allows(mcpStatements)) { + const ecr = actionsOf([s]).filter((a) => a.startsWith("ecr:") && a !== "ecr:GetAuthorizationToken"); + if (ecr.length > 0) assert.notEqual(s.Resource, "*"); + } +}); + +test("MCP trust policy is limited to AgentCore in this account", () => { + assertTrustLimitedToAccount(templates.runtime, mcpRole); +}); + +// --- API Lambda --- + +test("API Lambda lists events of the agent's Memory only", () => { + const role = roleId(templates.webUi, "ApiLambdaServiceRole"); + const listEvents = statements(templates.webUi, role).filter((s) => actionsOf([s]).includes("bedrock-agentcore:ListEvents")); + assert.equal(listEvents.length, 1); + assert.equal(listEvents[0].Action, "bedrock-agentcore:ListEvents"); + const resource = JSON.stringify(listEvents[0].Resource); + assert.match(resource, new RegExp(`arn:aws:bedrock-agentcore:${REGION}:${ACCOUNT}:memory/`)); + assert.match(resource, /AgentMemory/); +}); diff --git a/infra/test/runtime-resource-policy.test.ts b/infra/test/runtime-resource-policy.test.ts index c2020842..b3d564cd 100644 --- a/infra/test/runtime-resource-policy.test.ts +++ b/infra/test/runtime-resource-policy.test.ts @@ -37,8 +37,6 @@ function synth(): { runtime: Template; agent: Template } { }); const agent = new AgentStack(app, "Agent", { env, - table, - pptxBucket, mcpRuntimeArn: runtime.runtimeArn, allowedClients: [], useAuthStack: true, diff --git a/tests/test_agent_tool_exposure.py b/tests/test_agent_tool_exposure.py new file mode 100644 index 00000000..3f8716ae --- /dev/null +++ b/tests/test_agent_tool_exposure.py @@ -0,0 +1,182 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: MIT-0 +"""The agent offers its model only the AWS documentation tools, and takes the prompt as text. + +The AWS Knowledge client connects to the public, unauthenticated endpoint and keeps an +allowlist of the documentation tools. The test serves it the full tool set of the +IAM-authenticated AWS MCP Server (tools/list on 2026-11-02) in memory, so the filter is +the one Strands applies when the agent loads its tools. +""" + +import asyncio +import base64 +import json +import sys +from contextlib import asynccontextmanager +from pathlib import Path + +import anyio +import pytest +from mcp.server.fastmcp import FastMCP +from mcp.shared.memory import create_client_server_memory_streams + +AGENT_DIR = Path(__file__).resolve().parents[1] / "agent" + + +def _factory(): + # Imported lazily: test_mcp_parallel_connect puts agent/ on sys.path when it is + # imported, and agent/tools would then shadow servers/remote's tools package + # for the test modules collected after this one. + from test_mcp_parallel_connect import _factory as load + + return load() + +# tools/list of https://aws-mcp.us-east-1.api.aws/mcp (IAM-authenticated), 2026-11-02. +AWS_MCP_SERVER_TOOLS = [ + "aws___get_presigned_url", + "aws___get_regional_availability", + "aws___get_tasks", + "aws___list_regions", + "aws___read_documentation", + "aws___retrieve_skill", + "aws___run_script", + "aws___search_documentation", +] +API_TOOLS = {"aws___run_script", "aws___get_presigned_url", "aws___get_tasks"} + + +def _server_with(names: list[str]) -> FastMCP: + server = FastMCP("fake-aws-mcp") + for name in names: + server.add_tool(lambda: "", name=name, description=name) + return server + + +def _in_memory_transport(server: FastMCP): + """A streamablehttp_client stand-in connected to *server* in memory.""" + + @asynccontextmanager + async def transport(): + low = server._mcp_server + async with create_client_server_memory_streams() as (client_streams, server_streams): + async with anyio.create_task_group() as tg: + tg.start_soon(lambda: low.run(*server_streams, low.create_initialization_options())) + yield client_streams[0], client_streams[1], lambda: None + tg.cancel_scope.cancel() + + return transport() + + +def _knowledge_tool_names(monkeypatch, server_tools: list[str]) -> tuple[list[str], dict]: + """Tool names of the AWS Knowledge client the agent factory builds.""" + factory = _factory() + import mcp_clients + + seen: dict = {} + + def fake_streamablehttp_client(**kwargs): + seen.update(kwargs) + return _in_memory_transport(_server_with(server_tools)) + + monkeypatch.setattr(mcp_clients, "streamablehttp_client", fake_streamablehttp_client) + index = [name for name, _ in factory.MCP_DEFS].index("AWS Knowledge") + client = factory._MCP_FACTORIES[index]("jwt", session_id="s1") + try: + # load_tools() is what _prewarm_mcp_clients calls; Strands' own call reuses it. + tools = asyncio.run(client.load_tools()) + return sorted(t.tool_name for t in tools), seen + finally: + client.stop(None, None, None) + + +def test_knowledge_client_offers_only_documentation_tools(monkeypatch): + names, _ = _knowledge_tool_names(monkeypatch, AWS_MCP_SERVER_TOOLS) + + assert not API_TOOLS & set(names) + assert names == sorted([ + "aws___search_documentation", + "aws___read_documentation", + "aws___retrieve_skill", + "aws___list_regions", + "aws___get_regional_availability", + ]) + + +def test_knowledge_client_drops_tools_added_later(monkeypatch): + names, _ = _knowledge_tool_names(monkeypatch, [*AWS_MCP_SERVER_TOOLS, "aws___call_aws"]) + + assert "aws___call_aws" not in names + + +def test_knowledge_client_uses_public_endpoint_without_credentials(monkeypatch): + _, seen = _knowledge_tool_names(monkeypatch, AWS_MCP_SERVER_TOOLS) + + assert seen["url"] == "https://knowledge-mcp.global.api.aws" + assert "auth" not in seen and "headers" not in seen + + +# --- prompt type ------------------------------------------------------------- + + +def _basic_agent(): + _factory() + if "basic_agent" in sys.modules: + return sys.modules["basic_agent"] + sys.path.insert(0, str(AGENT_DIR)) + try: + import basic_agent + finally: + sys.path.remove(str(AGENT_DIR)) + return basic_agent + + +class _Context: + def __init__(self): + claims = base64.urlsafe_b64encode(json.dumps({"sub": "user-1"}).encode()).decode().rstrip("=") + self.request_headers = {"authorization": f"Bearer h.{claims}.s"} + + +def _run(basic_agent, payload) -> list[dict]: + async def collect(): + return [e async for e in basic_agent.agent_stream(payload, _Context())] + + return asyncio.run(collect()) + + +@pytest.mark.parametrize("prompt", [ + [{"role": "user", "content": [{"toolUse": {"toolUseId": "t1", "name": "web_fetch", "input": {}}}]}], + [{"toolUse": {"toolUseId": "t1", "name": "web_fetch", "input": {}}}], + {"text": "hello"}, + 42, +]) +def test_non_string_prompt_is_rejected_before_the_agent_is_built(monkeypatch, prompt): + basic_agent = _basic_agent() + + def no_agent(**kwargs): + raise AssertionError("create_agent must not be called") + + monkeypatch.setattr(basic_agent, "create_agent", no_agent) + + events = _run(basic_agent, {"prompt": prompt, "runtimeSessionId": "s" * 33}) + + assert events == [{"status": "error", "code": basic_agent.BAD_INPUT, "error": "Invalid field: prompt must be a string"}] + + +def test_string_prompt_reaches_the_agent(monkeypatch): + basic_agent = _basic_agent() + seen: dict = {} + + def fake_create_agent(**kwargs): + return object(), [] + + async def fake_stream(agent, user_query, session_id, cancel): + seen["prompt"] = user_query + yield {"done": True} + + monkeypatch.setattr(basic_agent, "create_agent", fake_create_agent) + monkeypatch.setattr(basic_agent, "stream_agent", fake_stream) + + events = _run(basic_agent, {"prompt": "hello", "runtimeSessionId": "s" * 33}) + + assert seen["prompt"] == "hello" + assert events[-1] == {"done": True} diff --git a/uv.lock b/uv.lock index e788da6d..cfd89e78 100644 --- a/uv.lock +++ b/uv.lock @@ -18,18 +18,6 @@ members = [ "spec-driven-presentation-maker", ] -[[package]] -name = "aiofile" -version = "3.12.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "caio" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/14/31/edb06aabd8f8f0b56d659f30800795f40b93cba96be946ce179f6931e3a5/aiofile-3.12.3.tar.gz", hash = "sha256:caa6aa746b5e47e2165f7abd741b6415e49cf4d44fddc0f61844612cc3924d41", size = 21600, upload-time = "2026-08-04T22:59:27.171Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4e/79/6e45e778c4c3cab39e0937b007b720c15f76c50c6453d153282d0fcc3588/aiofile-3.12.3-py3-none-any.whl", hash = "sha256:5c1bcc9e929c50834608e8cc1a4cc1d7503eb60c15a535b779fd39e2f372c017", size = 22122, upload-time = "2026-08-04T22:59:25.838Z" }, -] - [[package]] name = "annotated-doc" version = "0.0.5" @@ -79,19 +67,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, ] -[[package]] -name = "authlib" -version = "1.9.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cryptography" }, - { name = "joserfc" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c9/dc/087c08741a98d234c9b98beef8a28d3c309f814d14b6156422c5815bf6d6/authlib-1.9.1.tar.gz", hash = "sha256:5c7d9848f47cac340f060f76ae0bc09b59f5c8e89cc1bb032d4370a0c55b5974", size = 182700, upload-time = "2026-10-14T14:17:52.307Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/39/44/a46089266de32a0d809023b6bf31b80a1f26a46954446a7ce695a565cbea/authlib-1.9.1-py2.py3-none-any.whl", hash = "sha256:8b9be8b1e5174dcbf5520e984f1a22dc2edae5b6e40a61d4cedbf86b97e9e69b", size = 266042, upload-time = "2026-10-14T14:17:50.695Z" }, -] - [[package]] name = "aws-encryption-sdk" version = "4.0.7" @@ -221,38 +196,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4c/36/62d2509b223d86aab5cc67a653b56633e5b8c37bd5343a4b26cbff2a3be6/aws_xray_sdk-2.16.0-py2.py3-none-any.whl", hash = "sha256:d2ae9400654369cbce65f6402276b211afd8fd0931e208e6199a20dc1e01a5da", size = 105229, upload-time = "2026-10-30T21:25:23.018Z" }, ] -[[package]] -name = "awscrt" -version = "0.38.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/0c/c4/1f7c4161aa665b06ddb9c34acbe6b5ea8fc8bf72b78de474d65e6f494ca4/awscrt-0.38.0.tar.gz", hash = "sha256:4a8423c4a76390c6e5c4f386e3e367dccdcf67d6d1a0bc1c59776bb14cdc2ad9", size = 37915957, upload-time = "2026-10-16T19:14:10.674Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/38/1bcbc5240d952b74a857ef4498714bb9107bdeb2786b3569caee6e11d03c/awscrt-0.38.0-cp311-abi3-macosx_10_15_universal2.whl", hash = "sha256:fa7b3bae4518c199ca35a442784237fce562121aa83f838fe23994ffddccb17b", size = 5225304, upload-time = "2026-10-16T19:13:14.688Z" }, - { url = "https://files.pythonhosted.org/packages/b2/32/1403fa8c73c723c8299b8162f46ce3d42940b8fcb10f0eccc87ae5d6aa8a/awscrt-0.38.0-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f54a804f321912f3d5e856721d5fbfb8129eda8120eec3e9cae8eb26bb9349af", size = 4108660, upload-time = "2026-10-16T19:13:16.466Z" }, - { url = "https://files.pythonhosted.org/packages/a9/ce/c1b84969cc9b830a96b0c42bbf0fec765ac338945dae5994d5d9124983c0/awscrt-0.38.0-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b91feaa8bafd264cd06484dc4efa5d95fbd25a9a46204eb71bf12a9dc8640a93", size = 4383864, upload-time = "2026-10-16T19:13:17.825Z" }, - { url = "https://files.pythonhosted.org/packages/8b/e2/1e36aaee1262231dca41dda6c25f1d718c976446e5ef6826bcc60f4da8fa/awscrt-0.38.0-cp311-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2a7c9aeaa9c64f33d5373b4d9e5d5a343a663b231e9c036269c3c9d5c8dd003c", size = 4009518, upload-time = "2026-10-16T19:13:18.984Z" }, - { url = "https://files.pythonhosted.org/packages/24/fa/1787950aae6429f23ae3216e83dbc78051888887da802268ba0fb1f34fa5/awscrt-0.38.0-cp311-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:d40b7a038ee37a378b320704cd76e59124f5009e98eeb19ca6daf9a5915220a9", size = 4239170, upload-time = "2026-10-16T19:13:20.567Z" }, - { url = "https://files.pythonhosted.org/packages/9f/6c/872f7cfbf629d1e0bc5471b616cf837a7a9183f5b76d33289fc318ceb2dc/awscrt-0.38.0-cp311-abi3-win32.whl", hash = "sha256:7012194d886576dc71eca7b2720a95c895bdde0cc875cce0646cab69009ca182", size = 4260927, upload-time = "2026-10-16T19:13:21.892Z" }, - { url = "https://files.pythonhosted.org/packages/42/b6/37bb001ebdfbcf1032eacd0db57fbfb25411bb34026b6f212bec47b45c2b/awscrt-0.38.0-cp311-abi3-win_amd64.whl", hash = "sha256:91ff2ff3af31428c5b835e91197b3b7d6a1526b78b8fcaf9ef31ed75e3d07e58", size = 4400851, upload-time = "2026-10-16T19:13:23.071Z" }, - { url = "https://files.pythonhosted.org/packages/97/bb/d54a0ae302a741ee0776184c93bb37b5dd221cab82681759c1ac36a17a30/awscrt-0.38.0-cp313-abi3-macosx_10_15_universal2.whl", hash = "sha256:a2b60b393d7eeb733604b8bd01709969a1833811e82cff574ccac5fc10de1f0e", size = 5223704, upload-time = "2026-10-16T19:13:24.635Z" }, - { url = "https://files.pythonhosted.org/packages/07/db/ba87b1e3a58c429866f5d472584746f3aee44b37932cb3cbc7ec33d5b84d/awscrt-0.38.0-cp313-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ef306404d069a8735bebc9415ba63b11251e7ad02b3e9a4dcc43dac685ebc838", size = 4098896, upload-time = "2026-10-16T19:13:26.013Z" }, - { url = "https://files.pythonhosted.org/packages/ff/84/d551f708df4ee610072c966dc8f72a79e47295c3e91c083c3e9ea7b6281e/awscrt-0.38.0-cp313-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:45bc3d46f6ee42fb106757dffd8536791dcace5c17e6b72639709282ac18b93f", size = 4377461, upload-time = "2026-10-16T19:13:27.603Z" }, - { url = "https://files.pythonhosted.org/packages/52/57/85e1aa6bee2eeede6c8a2c410f383a56e6fce34ff41f4e84e15cfa3119ce/awscrt-0.38.0-cp313-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:03a7ae10f93dbe54fe7af76507932538508dc3156e74576de826cfa80f40b862", size = 4001917, upload-time = "2026-10-16T19:13:28.795Z" }, - { url = "https://files.pythonhosted.org/packages/64/4c/4119fdcb47c4a441dbf0afc4a11910c37be61dae285c396d27bf608707e9/awscrt-0.38.0-cp313-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:30f15cc0bf4e7a9c6542ca11ba636e94b80571f332fc56c28652369aaece9627", size = 4233907, upload-time = "2026-10-16T19:13:30.308Z" }, - { url = "https://files.pythonhosted.org/packages/34/cf/2f77e2646628cd96d6cbb0d2c3f5e8663675a77e2b60f75adb1d595659c0/awscrt-0.38.0-cp313-abi3-win32.whl", hash = "sha256:b90229ac169bac976abf0029b5313504a53da87d393fd04b06888db444aebb12", size = 4258325, upload-time = "2026-10-16T19:13:31.533Z" }, - { url = "https://files.pythonhosted.org/packages/6c/ff/8792bb4288f5a034838074f592b00c6b2c10e137eb7811a5b386fc3fb10c/awscrt-0.38.0-cp313-abi3-win_amd64.whl", hash = "sha256:65d404ed5e22146154fc62626b1b8a8d8539cabd1b589337df6737361335ec0a", size = 4396443, upload-time = "2026-10-16T19:13:32.85Z" }, - { url = "https://files.pythonhosted.org/packages/85/fa/c096d6a4364c2da455cb6ad5eba07e9f8d7f754908a9e2acf7813ef7c36d/awscrt-0.38.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:f04d0710dde83bfa19dcfcb55524d632680b2edb2151afa7b9c986f364766b5d", size = 5235148, upload-time = "2026-10-16T19:13:34.121Z" }, - { url = "https://files.pythonhosted.org/packages/fa/50/1effa079885c4f36496477ece5434122e9c3fce48396236f250190d6807f/awscrt-0.38.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:2049d0480481f5ba1bd7dae290f2bfc2e2b757e95ec53b5247976f29673c0e60", size = 4143903, upload-time = "2026-10-16T19:13:35.272Z" }, - { url = "https://files.pythonhosted.org/packages/e4/3c/4f1ecb8db6cc413f3d9f16adb88b382baa1afd067a61eaf5f0d8f9f8f9ce/awscrt-0.38.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:e887bad4d11e1e30b6f3aef2b617f62825c9b591b3bc82effa3ffe2ac2ddf00d", size = 4368910, upload-time = "2026-10-16T19:13:36.576Z" }, - { url = "https://files.pythonhosted.org/packages/39/0c/01827948ed1cc0105fd96495ae83c08a22c582802becfec0068f9c8e5221/awscrt-0.38.0-cp313-cp313t-win32.whl", hash = "sha256:ab0a263c467f908496df52f4b6fec8f20b0576bfcc3360f3ebe4ea29d00c35ed", size = 4307287, upload-time = "2026-10-16T19:13:37.735Z" }, - { url = "https://files.pythonhosted.org/packages/7e/85/8b8e817167e10cf631e571209cf6c90d2299d10417a7d345b3cd4c4fe888/awscrt-0.38.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5a679e83a0d4eb69bc06677fa96117409f5707cdd2df8c7592673c5070b16bcf", size = 4448771, upload-time = "2026-10-16T19:13:38.889Z" }, - { url = "https://files.pythonhosted.org/packages/5e/1a/a826c05fae855deb3cb634e2f72125885eecbff7a6d0d0633af3a82ebedb/awscrt-0.38.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:d6ca05bacb737e273feb1916a022da71d1aa84213a73b79b5a98ecd8eddc4905", size = 5235147, upload-time = "2026-10-16T19:13:40.139Z" }, - { url = "https://files.pythonhosted.org/packages/93/d8/ddeba7cc2d40c5d1ecc5349da113df73ab2c4bb87375bd1d29ebb6412be8/awscrt-0.38.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8757c70b0862f4195371ed69636c7a40f2f4519b02aa2c0ab07618a7b71d545c", size = 4229995, upload-time = "2026-10-16T19:13:41.815Z" }, - { url = "https://files.pythonhosted.org/packages/54/5e/69d6863ae78251ba75834f6f14ffde92e54e1ea0eda8d299d41150e3bf81/awscrt-0.38.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:522eea71c67192f9e3a6707d59b7165599f9b8292ae0513c41ac4cb3b53b0074", size = 4502995, upload-time = "2026-10-16T19:13:43.118Z" }, - { url = "https://files.pythonhosted.org/packages/dc/65/7ec3e696edc1963bf3e117277cfc5537509e696588def528414cf8730218/awscrt-0.38.0-cp314-cp314t-win32.whl", hash = "sha256:86163dbf8ff3e615bcae82d140c89a693b907e583c67141437676eb5042b8d45", size = 4392495, upload-time = "2026-10-16T19:13:44.814Z" }, - { url = "https://files.pythonhosted.org/packages/05/64/bcb865c82011255e15d66438157812b79fd50886b4a473851004540cac95/awscrt-0.38.0-cp314-cp314t-win_amd64.whl", hash = "sha256:cc70517731a6742706870d6c853bdec8eb29f3f085093b086792ed701270c24a", size = 4550440, upload-time = "2026-10-16T19:13:46.127Z" }, -] - [[package]] name = "awslabs-aws-pricing-mcp-server" version = "1.0.34" @@ -271,24 +214,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/02/6e/b12a417a187d1573355be6c4bd877a7553ce46c6ffad8c196e430f9cd2aa/awslabs_aws_pricing_mcp_server-1.0.34-py3-none-any.whl", hash = "sha256:cc23199a83798ef4caa8fb8d80f3114b888bcf1dd4f13ac7ae6bfad1f7576e09", size = 66447, upload-time = "2026-08-10T23:26:57.365Z" }, ] -[[package]] -name = "backports-tarfile" -version = "1.2.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/86/72/cd9b395f25e290e633655a100af28cb253e4393396264a98bd5f5951d50f/backports_tarfile-1.2.0.tar.gz", hash = "sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991", size = 86406, upload-time = "2024-05-28T17:01:54.731Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b9/fa/123043af240e49752f1c4bd24da5053b6bd00cad78c2be53c0d1e8b975bc/backports.tarfile-1.2.0-py3-none-any.whl", hash = "sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34", size = 30181, upload-time = "2024-05-28T17:01:53.112Z" }, -] - -[[package]] -name = "beartype" -version = "0.23.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/79/34/c0cfdaee9c796c8381439fed0fcab62810753b8b0adb1ec88fa7f41eaa5d/beartype-0.23.1.tar.gz", hash = "sha256:8b805f246b32931c74f2b321ea0939fe5bb2ff43c12a3eff19cc4c854b832e1d", size = 1993714, upload-time = "2026-10-11T05:36:55.251Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1c/cb/2f6aa982e2860c1156830db3da7f823b71784ed7d533ca289ea9b6c6347a/beartype-0.23.1-py3-none-any.whl", hash = "sha256:4461b4dc57e3fdd6c8a8464b22cf118002eea107c33e9fef651c69068ab3cce3", size = 1582101, upload-time = "2026-10-11T05:36:52.431Z" }, -] - [[package]] name = "bedrock-agentcore" version = "1.25.2" @@ -342,11 +267,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/db/96/4f2dffd304425c07160ab2c12cb13322d852fd956fe9d4386228c93f02ea/botocore-1.43.123-py3-none-any.whl", hash = "sha256:e30580f9c1282c321529238ff8ff75066096a2adbd0a293c8ae592c21d1733a3", size = 16185987, upload-time = "2026-10-30T19:18:39.794Z" }, ] -[package.optional-dependencies] -crt = [ - { name = "awscrt" }, -] - [[package]] name = "bytecode" version = "0.19.1" @@ -365,51 +285,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/fc/1d7b80d0eb7b714984ce40efc78859c022cd930e402f599d8ca9e39c78a4/cachetools-6.2.4-py3-none-any.whl", hash = "sha256:69a7a52634fed8b8bf6e24a050fb60bff1c9bd8f6d24572b99c32d4e71e62a51", size = 11551, upload-time = "2025-12-15T18:24:52.332Z" }, ] -[[package]] -name = "caio" -version = "0.12.10" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/66/66/a36d1367bd5ef70b6b97b2fb502f682106555e9e49e229f35c0a49d154d5/caio-0.12.10.tar.gz", hash = "sha256:5cecc44c04d5c6291d98b61bdba999f49a7e58dff2d782b4bb0642dc6f7ecf58", size = 84118, upload-time = "2026-10-22T21:35:06.294Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/45/ba/f545a34076181400dd0ad2b9883c4a5eeae85d142daf0f5ac2e3b718604f/caio-0.12.10-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f09366a7eaaa23f7dbf19c14802a3ba57b72e9efec463b89a8ff77bcbe3c8c09", size = 48895, upload-time = "2026-10-22T21:34:20.962Z" }, - { url = "https://files.pythonhosted.org/packages/28/e3/fc6c49b78d4168510f183ca502d9f0529b9b26db185e871d5331f3c57d40/caio-0.12.10-cp311-cp311-manylinux_2_34_aarch64.whl", hash = "sha256:9f5add2fea913a7dfc0e196b76c8d16c059b04a6c1651ae0118e86be11ecd9ad", size = 162811, upload-time = "2026-10-22T21:34:22.023Z" }, - { url = "https://files.pythonhosted.org/packages/5e/fa/29d14e56ab9aa18cbacce84cfa2d29c61befce876d24bb818412524c2c64/caio-0.12.10-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:2d7f65d34a27a0969db7fb810a6beeebea13327a37f7dae3a39da64fd2534b6e", size = 159023, upload-time = "2026-10-22T21:34:23.296Z" }, - { url = "https://files.pythonhosted.org/packages/43/58/5f87b9a03218bdd8abe84f32e815712569ae765f4c635975c563eb0d2eb2/caio-0.12.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ca2fd82729aba943e190aefffd9dc96d49a1a401d466ea9743e6f54fa20f0e2f", size = 160341, upload-time = "2026-10-22T21:34:24.512Z" }, - { url = "https://files.pythonhosted.org/packages/27/fb/96bd3812166292f395a1e8fc217f75aac01eca476b95e13c0b1ed46480e3/caio-0.12.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2786535292cbd7cf1f13fb13d94f7173e71cd353bec4cb2e3de13d94b7615a79", size = 158710, upload-time = "2026-10-22T21:34:25.755Z" }, - { url = "https://files.pythonhosted.org/packages/c5/ba/689a44c2f0d8ea68dfe2d721699fa81601dcc83f238102df22feb31697a0/caio-0.12.10-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c396c9a850681bf51dcc9943468260f6fa7861498f84b5f3b9413e9d3283cbec", size = 49062, upload-time = "2026-10-22T21:34:27.004Z" }, - { url = "https://files.pythonhosted.org/packages/db/20/21fd0dbf1b2b0211f3a451587b6d63d3ad99385487323f2b9062d6e42ff8/caio-0.12.10-cp312-cp312-manylinux_2_34_aarch64.whl", hash = "sha256:93bb3a3f0bd684ac6b559c33a84817395c4d2c75d98dae2b7c40c57acce83737", size = 164716, upload-time = "2026-10-22T21:34:28.119Z" }, - { url = "https://files.pythonhosted.org/packages/95/00/8900d474b5e3285635865c9d5bdc71ad822f7932a7f90cd800fc837c1e67/caio-0.12.10-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:70d5032f3e0b2dbeceb12d418951415e936cff7f33132ac9f7759937ff1916f3", size = 162411, upload-time = "2026-10-22T21:34:29.402Z" }, - { url = "https://files.pythonhosted.org/packages/6e/2c/0704c708eb255f2995fc9830a969e883338c3de204e1eac726ec337a7e9c/caio-0.12.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:347ff5321a23675ed3b2396bbc6b7220ec5531303395c6b0135ed6cda04277cd", size = 162211, upload-time = "2026-10-22T21:34:30.617Z" }, - { url = "https://files.pythonhosted.org/packages/67/52/5b9ccb8205c3d3d870540f0ffea07977b68a9b018c91c43fae0bdb780954/caio-0.12.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:bd3cb22b0c5ca195b35c2b7d57892c23cc13d969f24c44fea876af2cfee02e7a", size = 161998, upload-time = "2026-10-22T21:34:31.934Z" }, - { url = "https://files.pythonhosted.org/packages/84/3e/98ddc781ae6d76407b74f33136f838e444df41a1a43d80373da01da47bbb/caio-0.12.10-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6b8e0724415ae86889df59af2d44fd6a531851ebc62c9cfdb1cc8235c929524d", size = 49054, upload-time = "2026-10-22T21:34:33.252Z" }, - { url = "https://files.pythonhosted.org/packages/8b/d6/9851c6b24674ef72054c7b05569bd444f1358955c19ba5b5f7e15fa64be6/caio-0.12.10-cp313-cp313-manylinux_2_34_aarch64.whl", hash = "sha256:4e72602d4c348d105c9e46dd300b85df3fd3e857e2068370847f5e29879181b5", size = 164861, upload-time = "2026-10-22T21:34:34.472Z" }, - { url = "https://files.pythonhosted.org/packages/85/9a/1f6eac05eb23284c834c08c17cc5f39fafe3754f1d2df94bcf5a2cb93179/caio-0.12.10-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:1d8b6e9275d8f9608b8ecb4b97189e7f1d0b8ed948fb552eb06518d6342a1e53", size = 162592, upload-time = "2026-10-22T21:34:35.566Z" }, - { url = "https://files.pythonhosted.org/packages/1a/be/4bb0538aa4c953c4681c7b309a9cb452eb91640e6b62f250b464f91dfad4/caio-0.12.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cff7a239334b36c4dc82a0ab69aa3244188e5c9e2c30a242d81e4502520f2b1b", size = 162324, upload-time = "2026-10-22T21:34:36.977Z" }, - { url = "https://files.pythonhosted.org/packages/0a/9a/290190821dbc29fccb0ad96e51a7f573394df621da547cb13701de685805/caio-0.12.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a9645aeed1cdeeff34ca78442e6b274c0f801876a6bf0991724d92b7d639655", size = 162171, upload-time = "2026-10-22T21:34:38.173Z" }, - { url = "https://files.pythonhosted.org/packages/39/9d/2a2177a43901f69ef120fb0dfe4a7dc6938e57a086da3ecdeacc12a05635/caio-0.12.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:edda39ac24b4cec74486a06afe7499fc9ddb2c3d5cb98494b2c9fdf95ed7aecd", size = 42798, upload-time = "2026-10-22T21:34:39.444Z" }, - { url = "https://files.pythonhosted.org/packages/b9/0a/5e404a09363c71dfb5f7c20234ee31dc9ad75c7072dc868b6cc5be6f9af3/caio-0.12.10-cp314-cp314-macosx_26_0_arm64.whl", hash = "sha256:3b9c6e6355267f2eccd23e1a17ec2f78dce02ab00b10276999ff7a4615512952", size = 42033, upload-time = "2026-10-22T21:34:40.448Z" }, - { url = "https://files.pythonhosted.org/packages/06/94/41549be5a09a0441f1c1313d5eeb8b60b08034c89cd2c0b5cfeb6a9b9111/caio-0.12.10-cp314-cp314-manylinux_2_34_aarch64.whl", hash = "sha256:a2b897245d5e6593a39ea9a52c7b372efc41e5a746c46a2985bdf94622f273fe", size = 165369, upload-time = "2026-10-22T21:34:41.513Z" }, - { url = "https://files.pythonhosted.org/packages/28/47/f272ce0eed9700749934823086434a94d9bea51555724188d8ee660a7fd4/caio-0.12.10-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:40e84b8679f44bee5c2b7cc7093719e15616b6752560809896dc15a8667cd69f", size = 162620, upload-time = "2026-10-22T21:34:42.671Z" }, - { url = "https://files.pythonhosted.org/packages/65/ae/644e7e72a81c4d8ce31dac9865b2a6b38fdc4c56a1418cc2d4d55591be20/caio-0.12.10-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccd4efddafd48018d30cd560f7c393d177fe01365ee0dcf0bc88528f220732ed", size = 162986, upload-time = "2026-10-22T21:34:43.801Z" }, - { url = "https://files.pythonhosted.org/packages/63/2a/557a90ae71f8411a2cfa0238ad70bddb60178133b7eb41e3fe8e8c854235/caio-0.12.10-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2138670dd6cab64bd29cfcbd6a7259c0c21646c4dc86a4ec12de907210a2aba9", size = 162258, upload-time = "2026-10-22T21:34:45.271Z" }, - { url = "https://files.pythonhosted.org/packages/78/1a/1ffea8df50383d5bc468e94d2b45d1c458f965b80bb12ad28891d0a55266/caio-0.12.10-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:79a4e0000dd92b1e4e7842fca99fdaa5fd0259dd33a9892741e7126e74656c49", size = 42801, upload-time = "2026-10-22T21:34:46.485Z" }, - { url = "https://files.pythonhosted.org/packages/f0/59/43da115afd82281312166711ceff5b7ca08d53f79a8955d2e22ac9968eca/caio-0.12.10-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:6fff1f609e54a2e007b6c5c0933f4782ecbf8b6f9144e0930e2dcd2e7440c637", size = 186884, upload-time = "2026-10-22T21:34:47.611Z" }, - { url = "https://files.pythonhosted.org/packages/fa/5d/708aed113a2ae829a265b5ce030bab52ff0e41339cc6047f29bb0b15dfdf/caio-0.12.10-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:925b938bcdf09d1c3df2b6ddd534004b616451ef1810e47f6a63257365376b25", size = 182799, upload-time = "2026-10-22T21:34:48.86Z" }, - { url = "https://files.pythonhosted.org/packages/a1/c3/8de2c1c89548902a389406560e67930333984194217d5bcef6129ff7f18a/caio-0.12.10-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1ebcac2a14e045aa0a4f63824264a4a845c6b1ac9074d5d673c52ef564a1ada6", size = 185097, upload-time = "2026-10-22T21:34:50.035Z" }, - { url = "https://files.pythonhosted.org/packages/94/43/98997e24fa52f1e6a2a808e446693702773830a863a036a5e727024e7aa0/caio-0.12.10-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:39e91aab7d0a5f0cac5930562d751e9938ceef1c7ae18477a5689a4e437eada1", size = 182593, upload-time = "2026-10-22T21:34:51.256Z" }, - { url = "https://files.pythonhosted.org/packages/c3/17/78046176bc3572430d03bab1b9e82966bc5b9a28d27c41e6764a20144044/caio-0.12.10-cp315-cp315-macosx_26_0_arm64.whl", hash = "sha256:c0b52bd6fd006d2d07713025f0e1cad61ebd12342f86bfa47e2eff239fbdd01f", size = 42039, upload-time = "2026-10-22T21:34:52.646Z" }, - { url = "https://files.pythonhosted.org/packages/ea/ed/14a90cfe02f14813674a1cc91ff2fad9b0d1bb98260be09b987f579baa28/caio-0.12.10-cp315-cp315-manylinux_2_34_aarch64.whl", hash = "sha256:b7a42ef7379e36e99cc6990aa62465919a3be3fb1f049a40e5aef29fbbd859e1", size = 166510, upload-time = "2026-10-22T21:34:53.703Z" }, - { url = "https://files.pythonhosted.org/packages/c2/b1/9fbeafd6aae00cc0dae96d190cc4fe6e23d20ecd4f26e970878611761fdb/caio-0.12.10-cp315-cp315-manylinux_2_34_x86_64.whl", hash = "sha256:89fe0e3c849a07aba1f76012a50eaf4fb2eaed0398c01bd43912a1bd0f4ab5eb", size = 163501, upload-time = "2026-10-22T21:34:54.988Z" }, - { url = "https://files.pythonhosted.org/packages/34/81/2342f17ab96a7b5d3666cc7dccea59728c4d421e7c954e2937cd817c3be5/caio-0.12.10-cp315-cp315-musllinux_1_2_aarch64.whl", hash = "sha256:21b04f6722884e5fb19690743772875b34306e5ba68d9ecabf7454193bb5caab", size = 164139, upload-time = "2026-10-22T21:34:56.201Z" }, - { url = "https://files.pythonhosted.org/packages/17/b3/e15cfdc902a13d885fa16481c7d01ad04de7b50e0195b9dd5e219ce07614/caio-0.12.10-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:a04ac9769fd8eddc1c0ca6308f0f6e668a86cf8d577770c11d85d0aeb584fcf4", size = 163137, upload-time = "2026-10-22T21:34:57.402Z" }, - { url = "https://files.pythonhosted.org/packages/49/ad/7fda5be8557afa8833ea65ebb29feaeeb96cb2b3373fe3220fe1e6899260/caio-0.12.10-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:c8fc80a37f08bba4c2f108277b6eabba564f74963a1a6cab01e50f9ae4434681", size = 42800, upload-time = "2026-10-22T21:34:58.494Z" }, - { url = "https://files.pythonhosted.org/packages/0d/e0/e2692eeb6841614f60ec099eac3c9b10a00dac74adf7321f442a2291ef8d/caio-0.12.10-cp315-cp315t-manylinux_2_34_aarch64.whl", hash = "sha256:3e3799d09b08401e83c30c671f6fa1e1227f6346a3b1336f24cb94c5a8a82b64", size = 187471, upload-time = "2026-10-22T21:34:59.585Z" }, - { url = "https://files.pythonhosted.org/packages/cc/a8/2c3a0cd781732057ab6a8023ef0fe14017b29ef75259295df8f585e3dfba/caio-0.12.10-cp315-cp315t-manylinux_2_34_x86_64.whl", hash = "sha256:ea2e0ea832d36c1e50ab730ba304153f34eb7dc2300b1285fc7cdfae1f1f4075", size = 183526, upload-time = "2026-10-22T21:35:00.764Z" }, - { url = "https://files.pythonhosted.org/packages/62/e2/9f32db16441875afaa2a8a27d9734c2c8421f259163d7d814528160fa6c8/caio-0.12.10-cp315-cp315t-musllinux_1_2_aarch64.whl", hash = "sha256:8d1071f8cb5d23c8aeccffe36c50a17d32257cddbf913b7e9b6fb524ba42d7a8", size = 185740, upload-time = "2026-10-22T21:35:02.059Z" }, - { url = "https://files.pythonhosted.org/packages/0d/7d/17836b477a1e57a648b90f16a27ebd367d686a02e5b2a4e72b53ae5ad7fe/caio-0.12.10-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:2a54ddadb7db4eab50bfc8b34f36fcf6763e9007f86b92f7cd03f07b542e891e", size = 183396, upload-time = "2026-10-22T21:35:03.492Z" }, - { url = "https://files.pythonhosted.org/packages/5c/c3/1c44005ec4d4c3f7c51b707308efe7836ee16c466f4ff2e2a6f2089eceee/caio-0.12.10-py3-none-any.whl", hash = "sha256:b34a5483b987d207348ebbf86921bc42f08abcde833b91e0caa8760c7daa2f03", size = 26166, upload-time = "2026-10-22T21:35:04.842Z" }, -] - [[package]] name = "certifi" version = "2026.10.23" @@ -877,21 +752,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ca/1d/1271f287ff7170ddafc2aad36260c4eec20ccd2fea70f38455e9d56d427b/cryptography-50.0.2-pp311-pypy311_pp80-win_amd64.whl", hash = "sha256:7b75de3c8b3be1cdb1052747c929440c3eea46c1bc2cb8a6e3a48388e9b7b452", size = 3805376, upload-time = "2026-09-30T15:29:58.729Z" }, ] -[[package]] -name = "cyclopts" -version = "5.3.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "attrs" }, - { name = "docstring-parser" }, - { name = "rich" }, - { name = "rich-rst" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fe/43/65f29e6cd5356f4a7910a80fce5df317b3edf1a6594525ec4c3a388c22cd/cyclopts-5.3.2.tar.gz", hash = "sha256:0b5c0975361c5eb8a65a98de358b10349a88fab74f8bd9f0c966ae6cf41a8c82", size = 254163, upload-time = "2026-10-27T14:28:41.694Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a2/82/fbb7d04cfd2afaf3e8eb9715f71b2899313cea9a205e5099959e8296ba43/cyclopts-5.3.2-py3-none-any.whl", hash = "sha256:0e1a1615b42da7af1c9cebd285578fa003f4d6bef8b65de9e77c2faf645c2df7", size = 297090, upload-time = "2026-10-27T14:28:39.858Z" }, -] - [[package]] name = "defusedxml" version = "0.7.1" @@ -901,15 +761,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" }, ] -[[package]] -name = "dnspython" -version = "2.9.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/91/21/7fcd6780f61e9756aafaea760560509bb4111375daa2e23c1be7a89f33f1/dnspython-2.9.1.tar.gz", hash = "sha256:9a6d30e55f8dc63e6052597666112bff0586b95a2474a9deda03afbbf820d37a", size = 455302, upload-time = "2026-10-29T18:05:12.156Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/61/55/f90405bbbbd3dd8f788e92cec2d39964f5c09783f0570fc35f3bb3381485/dnspython-2.9.1-py3-none-any.whl", hash = "sha256:7c81caf8de1ed57b8cfc7e0ad4f528a0b8ceace473c7eb946df195dc9def751f", size = 360364, upload-time = "2026-10-29T18:05:10.206Z" }, -] - [[package]] name = "docstring-parser" version = "0.18.0" @@ -919,19 +770,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" }, ] -[[package]] -name = "email-validator" -version = "2.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "dnspython" }, - { name = "idna" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4", size = 35604, upload-time = "2025-08-26T13:09:05.858Z" }, -] - [[package]] name = "et-xmlfile" version = "2.0.0" @@ -941,18 +779,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c1/8b/5fe2cc11fee489817272089c4203e679c63b570a5aaeb18d852ae3cbba6a/et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", size = 18059, upload-time = "2024-10-25T17:25:39.051Z" }, ] -[[package]] -name = "exceptiongroup" -version = "1.3.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" }, -] - [[package]] name = "fastjsonschema" version = "2.22.2" @@ -962,71 +788,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/49/82/2755c7c982086f00d4dab85bc120ec35045a9fc2191893a6ce79afe94443/fastjsonschema-2.22.2-py3-none-any.whl", hash = "sha256:0fb3915616adac85ccfdd737d26be1089845d2019819505b42d39888458f74d4", size = 27413, upload-time = "2026-08-15T19:47:04.406Z" }, ] -[[package]] -name = "fastmcp" -version = "3.4.11" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "fastmcp-slim", extra = ["client", "server"] }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f7/77/b5ef8688b0dd3e403b7671106533d62e93252d7d8f3c75f547e4686bba1e/fastmcp-3.4.11.tar.gz", hash = "sha256:36273b04eff98021da4601d4f86c64dfa10e61119e9ddd17ad80650465c65355", size = 28868316, upload-time = "2026-10-20T22:44:36.64Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/fb/e6b04a2f4dbce64994f3239267b6899411e8fd9693238c39ee99fe6f2b35/fastmcp-3.4.11-py3-none-any.whl", hash = "sha256:f50a7aa4cc2a5954d02fcc9672ff1d69daff73a02387f959c2647523cd6d5606", size = 8028, upload-time = "2026-10-20T22:44:33.334Z" }, -] - -[[package]] -name = "fastmcp-slim" -version = "3.4.11" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "platformdirs" }, - { name = "pydantic", extra = ["email"] }, - { name = "pydantic-settings" }, - { name = "python-dotenv" }, - { name = "rich" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9d/35/5f61dc70141df213eddff40bb2b8ccf68b02ecd666da6a1efab7c55b5694/fastmcp_slim-3.4.11.tar.gz", hash = "sha256:50e29b0830fb216aba437f35cfc7dd4bce7451f2f85f8786d6fff3da78d79386", size = 610380, upload-time = "2026-10-20T22:44:12.833Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ff/71/614669d0a0d8dea87dc0dc684650bb36793027fc409197526532f587fcab/fastmcp_slim-3.4.11-py3-none-any.whl", hash = "sha256:24535dd843b3dcb3272b86c88fdf6ada5026c39ec5b56e2426557223c4d2c8bf", size = 785938, upload-time = "2026-10-20T22:44:10.921Z" }, -] - -[package.optional-dependencies] -client = [ - { name = "authlib" }, - { name = "certifi" }, - { name = "exceptiongroup" }, - { name = "httpx" }, - { name = "mcp" }, - { name = "opentelemetry-api" }, - { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] }, - { name = "starlette" }, -] -server = [ - { name = "authlib" }, - { name = "certifi" }, - { name = "cyclopts" }, - { name = "exceptiongroup" }, - { name = "griffelib" }, - { name = "httpx" }, - { name = "joserfc" }, - { name = "jsonref" }, - { name = "jsonschema-path" }, - { name = "mcp" }, - { name = "openapi-pydantic" }, - { name = "opentelemetry-api" }, - { name = "packaging" }, - { name = "py-key-value-aio", extra = ["filetree", "keyring", "memory"] }, - { name = "pyperclip" }, - { name = "python-multipart" }, - { name = "pyyaml" }, - { name = "starlette" }, - { name = "uncalled-for" }, - { name = "uvicorn" }, - { name = "watchfiles" }, - { name = "websockets" }, -] - [[package]] name = "flatbuffers" version = "25.12.19" @@ -1047,15 +808,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/05/6d/78dc67a9e779e594b49bf62604034d3a6aa428a55afc729cafda4b7333e1/googleapis_common_protos-1.76.0-py3-none-any.whl", hash = "sha256:59e13344a9f3651aa201a03e2bee815a3bf43a4baf1f9ff8a9b62a840ce25fac", size = 307707, upload-time = "2026-10-22T23:43:10.445Z" }, ] -[[package]] -name = "griffelib" -version = "2.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/36/e2/0f5d8ed08766bc6dcd3eebf5a6623d83cbca33a6e4c90aef57156ce745ad/griffelib-2.4.1.tar.gz", hash = "sha256:40c028dd2e623f464423f0e11e3c553158f1cf4f1368239a370534d73e1407ff", size = 245153, upload-time = "2026-10-22T11:20:03.705Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/de/02/1156d5f5307f573b901b14373848b84e69ca6cab09169b8cc97d16a181f9/griffelib-2.4.1-py3-none-any.whl", hash = "sha256:76bc562f936ad1ce198d2cf6d0731bd5c92a7d934b69ef828ef22ee0ffdb62ce", size = 172983, upload-time = "2026-10-22T11:19:59.843Z" }, -] - [[package]] name = "grpcio" version = "1.85.1" @@ -1181,18 +933,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/58/a2/bb081bab032533a855d44de1d56f8e8426114ff1ba5d1f07a438a0a654f8/idna-3.20-py3-none-any.whl", hash = "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c", size = 69583, upload-time = "2026-09-17T14:11:03.168Z" }, ] -[[package]] -name = "importlib-metadata" -version = "10.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "zipp", marker = "python_full_version < '3.12'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/98/f6/4eda8458eb00ec03e715c376c6b23b3def69687924c68d36d1c4003d3bc4/importlib_metadata-10.1.0.tar.gz", hash = "sha256:82b04047fa09792c1a8cfeddfe08bec79e4b13c29c8469b0d3949860f61017e8", size = 67761, upload-time = "2026-10-24T00:01:44.856Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/65/b6/495438ad95e0102aff8f6786b5474202f38cd5d4700d03a72b77977dec10/importlib_metadata-10.1.0-py3-none-any.whl", hash = "sha256:cf45ce66a929c64e994185a809c04840d0501db17e663810d993d0f4829265c7", size = 32221, upload-time = "2026-10-24T00:01:43.507Z" }, -] - [[package]] name = "iniconfig" version = "2.3.1" @@ -1202,51 +942,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/56/43/4ca9e49d27a1fcf6bece6f6aec0ea46bb9112489b93d4b688fb415457bdb/iniconfig-2.3.1-py3-none-any.whl", hash = "sha256:9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7", size = 7552, upload-time = "2026-10-06T22:48:36.959Z" }, ] -[[package]] -name = "jaraco-classes" -version = "3.4.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "more-itertools" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/06/c0/ed4a27bc5571b99e3cff68f8a9fa5b56ff7df1c2251cc715a652ddd26402/jaraco.classes-3.4.0.tar.gz", hash = "sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd", size = 11780, upload-time = "2024-03-31T07:27:36.643Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7f/66/b15ce62552d84bbfcec9a4873ab79d993a1dd4edb922cbfccae192bd5b5f/jaraco.classes-3.4.0-py3-none-any.whl", hash = "sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790", size = 6777, upload-time = "2024-03-31T07:27:34.792Z" }, -] - -[[package]] -name = "jaraco-context" -version = "6.1.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "backports-tarfile", marker = "python_full_version < '3.12'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/af/50/4763cd07e722bb6285316d390a164bc7e479db9d90daa769f22578f698b4/jaraco_context-6.1.2.tar.gz", hash = "sha256:f1a6c9d391e661cc5b8d39861ff077a7dc24dc23833ccee564b234b81c82dfe3", size = 16801, upload-time = "2026-03-20T22:13:33.922Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/58/bc8954bda5fcda97bd7c19be11b85f91973d67a706ed4a3aec33e7de22db/jaraco_context-6.1.2-py3-none-any.whl", hash = "sha256:bf8150b79a2d5d91ae48629d8b427a8f7ba0e1097dd6202a9059f29a36379535", size = 7871, upload-time = "2026-03-20T22:13:32.808Z" }, -] - -[[package]] -name = "jaraco-functools" -version = "4.6.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "more-itertools" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/6c/1f/c23395957d41ccf27c4e535c3d334c4051e5395b3752057ba4cbaec35c56/jaraco_functools-4.6.0.tar.gz", hash = "sha256:880c577ec9720b3a052d5bc611fb9f2269b3d87902ef42440df443b88e443280", size = 20837, upload-time = "2026-07-14T01:28:02.544Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/02/36/ecc85bc96c273dc8a11273ed4782272975e6338d4a3e9228621175edf0e3/jaraco_functools-4.6.0-py3-none-any.whl", hash = "sha256:99e3dc0060c5cbe8fcd1cdb36258e2a65ca40f1566b2033b12abb1bb44dd3c30", size = 11677, upload-time = "2026-07-14T01:28:01.59Z" }, -] - -[[package]] -name = "jeepney" -version = "0.9.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7b/6f/357efd7602486741aa73ffc0617fb310a29b588ed0fd69c2399acbb85b0c/jeepney-0.9.0.tar.gz", hash = "sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732", size = 106758, upload-time = "2025-02-27T18:51:01.684Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b2/a3/e137168c9c44d18eff0376253da9f1e9234d0239e0ee230d2fee6cea8e55/jeepney-0.9.0-py3-none-any.whl", hash = "sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683", size = 49010, upload-time = "2025-02-27T18:51:00.104Z" }, -] - [[package]] name = "jmespath" version = "1.1.0" @@ -1256,18 +951,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64", size = 20419, upload-time = "2026-01-22T16:35:24.919Z" }, ] -[[package]] -name = "joserfc" -version = "1.7.7" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cryptography" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/bd/15/48ff246732232d35ee234228def22b52455fcc55577f06146602399a29b0/joserfc-1.7.7.tar.gz", hash = "sha256:471d0fd12a5a0d1c0942de280f39efe6f597878315033270b504d4d006d25510", size = 237446, upload-time = "2026-10-19T00:30:29.974Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/df/9f/934db284aa22f37af59708e382903860d4b81329c137b1b0ed2745daeb65/joserfc-1.7.7-py3-none-any.whl", hash = "sha256:06979cfbab78bc802f14c0358f32969826cc26720e13cb38926ffdc86bc0cb2c", size = 71758, upload-time = "2026-10-19T00:30:28.498Z" }, -] - [[package]] name = "jsonpath-ng" version = "1.15.0" @@ -1277,15 +960,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4b/a1/ec64128a063e501bd84b73cfbd2f204f9756c20d9be7eceeea8d997bd6f2/jsonpath_ng-1.15.0-py3-none-any.whl", hash = "sha256:a079a4d1d3e9ecb452437f26c18ec6854bd1beab36f5d5bafc121ea7330ad1b7", size = 84764, upload-time = "2026-10-29T14:18:09.724Z" }, ] -[[package]] -name = "jsonref" -version = "1.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/aa/0d/c1f3277e90ccdb50d33ed5ba1ec5b3f0a242ed8c1b1a85d3afeb68464dca/jsonref-1.1.0.tar.gz", hash = "sha256:32fe8e1d85af0fdefbebce950af85590b22b60f9e95443176adbde4e1ecea552", size = 8814, upload-time = "2023-01-16T16:10:04.455Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0c/ec/e1db9922bceb168197a558a2b8c03a7963f1afe93517ddd3cf99f202f996/jsonref-1.1.0-py3-none-any.whl", hash = "sha256:590dc7773df6c21cbf948b5dac07a72a251db28b0238ceecce0a2abfa8ec30a9", size = 9425, upload-time = "2023-01-16T16:10:02.255Z" }, -] - [[package]] name = "jsonschema" version = "4.26.0" @@ -1301,21 +975,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/69/90/f63fb5873511e014207a475e2bb4e8b2e570d655b00ac19a9a0ca0a385ee/jsonschema-4.26.0-py3-none-any.whl", hash = "sha256:d489f15263b8d200f8387e64b4c3a75f06629559fb73deb8fdfb525f2dab50ce", size = 90630, upload-time = "2026-01-07T13:41:05.306Z" }, ] -[[package]] -name = "jsonschema-path" -version = "0.5.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "attrs" }, - { name = "pathable" }, - { name = "pyyaml" }, - { name = "referencing" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/39/79/cd02a4df6d9270efdc7d3feefe6edd730b0820c39eeaa107a2faee8322d5/jsonschema_path-0.5.0.tar.gz", hash = "sha256:493b156ba895c97602655b620a8456caa2ce08c1aa389f5a7addec065e6e855c", size = 19597, upload-time = "2026-05-19T20:45:00.971Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/2c/9e69d73c4297508be9e3b64a970ea3971b3eb8db64ffc5802d40bd25981f/jsonschema_path-0.5.0-py3-none-any.whl", hash = "sha256:2790a070bc7abb08ea3dbe4d340ece4efadf639223001f020c7503229ba068e2", size = 24077, upload-time = "2026-05-19T20:44:59.225Z" }, -] - [[package]] name = "jsonschema-specifications" version = "2025.9.1" @@ -1328,24 +987,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/41/45/1a4ed80516f02155c51f51e8cedb3c1902296743db0bbc66608a0db2814f/jsonschema_specifications-2025.9.1-py3-none-any.whl", hash = "sha256:98802fee3a11ee76ecaca44429fda8a41bff98b00a0f2838151b113f210cc6fe", size = 18437, upload-time = "2025-09-08T01:34:57.871Z" }, ] -[[package]] -name = "keyring" -version = "25.7.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "importlib-metadata", marker = "python_full_version < '3.12'" }, - { name = "jaraco-classes" }, - { name = "jaraco-context" }, - { name = "jaraco-functools" }, - { name = "jeepney", marker = "sys_platform == 'linux'" }, - { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, - { name = "secretstorage", marker = "sys_platform == 'linux'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/43/4b/674af6ef2f97d56f0ab5153bf0bfa28ccb6c3ed4d1babf4305449668807b/keyring-25.7.0.tar.gz", hash = "sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b", size = 63516, upload-time = "2025-11-16T16:26:09.482Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/81/db/e655086b7f3a705df045bf0933bdd9c2f79bb3c97bfef1384598bb79a217/keyring-25.7.0-py3-none-any.whl", hash = "sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f", size = 39160, upload-time = "2025-11-16T16:26:08.402Z" }, -] - [[package]] name = "loguru" version = "0.7.3" @@ -1534,21 +1175,6 @@ cli = [ { name = "typer" }, ] -[[package]] -name = "mcp-proxy-for-aws" -version = "1.7.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "boto3" }, - { name = "botocore", extra = ["crt"] }, - { name = "fastmcp" }, - { name = "httpx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/d0/05/aac4db583a4e261381f82f593f7bacbf64841e7e33c327eb2c45f1c831d5/mcp_proxy_for_aws-1.7.0.tar.gz", hash = "sha256:f981ab4adb8862cdc3870decc39294c37bc37dd0f392bd98a93b3d73f7ea31dc", size = 461251, upload-time = "2026-09-15T11:20:49.803Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/73/df/04a7dba8d3ed744daff2783b220e9239969f0e0714266c52f0ced8d4ebf2/mcp_proxy_for_aws-1.7.0-py3-none-any.whl", hash = "sha256:d7e6c8f45ef89303cb48822e25f91c0234bb28ee987ebb56615cd16a5d044a1b", size = 45971, upload-time = "2026-09-15T11:20:48.726Z" }, -] - [[package]] name = "mdurl" version = "0.1.2" @@ -1558,15 +1184,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] -[[package]] -name = "more-itertools" -version = "11.2.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/52/b8/c63995bebbb9ac9c059350e0fb8c82c2420c85aeca7d34e40aecf3df9281/more_itertools-11.2.1.tar.gz", hash = "sha256:cbf08fd0af284dc69718b9b76a8e6203df624d70209ea511e4219d350c856f63", size = 154133, upload-time = "2026-10-14T18:50:30.407Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5d/57/3c4b1c6f2e0cc29ba023802458ea3d2a996f87085559e4a5f2192d549532/more_itertools-11.2.1-py3-none-any.whl", hash = "sha256:35a7377edd1dd6608dcb2cdf534ded55ea32d49448875ad042cd3f879fb1ded0", size = 74405, upload-time = "2026-10-14T18:50:29.116Z" }, -] - [[package]] name = "networkx" version = "3.6.1" @@ -1791,18 +1408,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c6/3d/a5b15c4ab9d67a384da5a2c10fb569e643076c28179fe1a265af7d8f1b87/onnxruntime-1.31.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:4d5f5fcc01f0c334d282a8991eab44e7752ad01c47b336d848ba43eb38084958", size = 23772582, upload-time = "2026-10-26T19:27:12.025Z" }, ] -[[package]] -name = "openapi-pydantic" -version = "0.6.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pydantic" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/2b/32/0c9bd3e4e847cd6117b64dbef4cf810faa9cdbd6689323b811569cc8a1b8/openapi_pydantic-0.6.0.tar.gz", hash = "sha256:11f3ac6ad41521fc156381ec587246b0c0ecea523bd9565ed74d3e7fac9d91cd", size = 1667049, upload-time = "2026-10-02T12:20:00.508Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/31/57/9d3eb823a03c33e9d4c810e6a3276e3a6dc820a7fdc0961db2c04e613817/openapi_pydantic-0.6.0-py3-none-any.whl", hash = "sha256:8bd6d548a250da37db96f461bcd52b3468e8834ad7d6db14b00a6b2ebbd163a3", size = 96931, upload-time = "2026-10-02T12:19:58.917Z" }, -] - [[package]] name = "openpyxl" version = "3.1.5" @@ -2724,15 +2329,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/42/32/658973117bf0fd82a24abbfb94fe73a5e86216e49342985e10acce54775a/partial_json_parser-0.2.1.1.post7-py3-none-any.whl", hash = "sha256:145119e5eabcf80cbb13844a6b50a85c68bf99d376f8ed771e2a3c3b03e653ae", size = 10877, upload-time = "2025-11-17T07:27:40.457Z" }, ] -[[package]] -name = "pathable" -version = "0.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/66/f3/5a20387de9bcd0607871bfc2198ee0e15836da7baa4592ccd7f24c27c986/pathable-0.6.0.tar.gz", hash = "sha256:6404b8b82aef5ff0fd478934137128b99b12212ba35afdde5525ca4f8388ea58", size = 18970, upload-time = "2026-05-19T18:15:11.911Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a2/e8/6d75ffd9784bce2e93d1ae4415649427e39a53bb172d4672b2b59c6f0a7b/pathable-0.6.0-py3-none-any.whl", hash = "sha256:82c4ca6c98c502ad12e0d4e9779b6210afee93c38990988c8c5d1b49bdcdf566", size = 18983, upload-time = "2026-05-19T18:15:10.728Z" }, -] - [[package]] name = "pdfminer-six" version = "20260107" @@ -2850,15 +2446,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c0/37/66b12dc476041fe523bca29c9d58fbf1ea92a4eaf73acfb9e993948f1191/pillow-13.0.0-pp312-pypy312_pp80-win_amd64.whl", hash = "sha256:567f20f1c75897d7663830da6ea8af719e03d712b1d9ee7f813319f9ece42e5a", size = 7366030, upload-time = "2026-10-16T22:18:06.638Z" }, ] -[[package]] -name = "platformdirs" -version = "4.14.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6e/4e/2684728d9f2c8c4110738dcadca7e0bed4b60c8dc68c40c2a9e0cf017900/platformdirs-4.14.2.tar.gz", hash = "sha256:6d13b4c1d66b7548dcec9e3db13c1ba9d9adb65041b5d07869313afc07e6e41b", size = 70792, upload-time = "2026-10-31T15:10:34.029Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/2d/98af31fdcd7c95c7114e2eb7c2eb0fa55d2a012c37ba4eb3722b7272abcb/platformdirs-4.14.2-py3-none-any.whl", hash = "sha256:dc1f93390f2a9265e44e5afc8667ec7faf737739604e39bc538fec889720c36b", size = 35291, upload-time = "2026-10-31T15:10:32.615Z" }, -] - [[package]] name = "pluggy" version = "1.7.0" @@ -2911,31 +2498,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" }, ] -[[package]] -name = "py-key-value-aio" -version = "0.4.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "beartype" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ca/99/c346e3474853801ec5ecf4c3ee60cfc6060327ebc31424df4e346620dde4/py_key_value_aio-0.4.6.tar.gz", hash = "sha256:267c03c3e24cb99d3097612f8a5cfd8e11785c6a2975e272db0e303ea1850bfd", size = 112876, upload-time = "2026-09-18T15:29:52.002Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9a/46/12871550fb0613d149144bb9d41f22680d5f46717bc45a76eb5798c20c3f/py_key_value_aio-0.4.6-py3-none-any.whl", hash = "sha256:820b30c7959fc738ea3d00160cdb10cd258f51e38737b2add530defeea1ded77", size = 171289, upload-time = "2026-09-18T15:29:50.665Z" }, -] - -[package.optional-dependencies] -filetree = [ - { name = "aiofile" }, - { name = "anyio" }, -] -keyring = [ - { name = "keyring" }, -] -memory = [ - { name = "cachetools" }, -] - [[package]] name = "pycparser" version = "3.12" @@ -2960,11 +2522,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/97/01/c71a71258b58659c72504e5fd65b451f6e36e34dc931d0b237ded213c814/pydantic-2.14.2-py3-none-any.whl", hash = "sha256:7efbf7507b937931cd32a5755acb00ea1cf5ccb1d4e8067a5850d5069e382118", size = 490403, upload-time = "2026-10-29T16:37:10.181Z" }, ] -[package.optional-dependencies] -email = [ - { name = "email-validator" }, -] - [[package]] name = "pydantic-core" version = "2.50.2" @@ -3219,15 +2776,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/46/ab/35f2276deeeebb781925e2647dd88a39f8ea1a910104a0dbb28218473502/pypdfium2-5.14.0-py3-none-win_arm64.whl", hash = "sha256:eb8aeca157808f323e39ea298cc6d6c8e080c192ea2efb1ca81daa0f0ff4d095", size = 3745021, upload-time = "2026-10-04T15:19:18.276Z" }, ] -[[package]] -name = "pyperclip" -version = "1.11.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/52/d87eba7cb129b81563019d1679026e7a112ef76855d6159d24754dbd2a51/pyperclip-1.11.0.tar.gz", hash = "sha256:244035963e4428530d9e3a6101a1ef97209c6825edab1567beac148ccc1db1b6", size = 12185, upload-time = "2025-09-26T14:40:37.245Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/df/80/fc9d01d5ed37ba4c42ca2b55b4339ae6e200b456be3a1aaddf4a9fa99b8c/pyperclip-1.11.0-py3-none-any.whl", hash = "sha256:299403e9ff44581cb9ba2ffeed69c7aa96a008622ad0c46cb575ca75b5b84273", size = 11063, upload-time = "2025-09-26T14:40:36.069Z" }, -] - [[package]] name = "pytest" version = "9.2.0" @@ -3351,15 +2899,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/23/ed/4532e9388e65fa16b46776ef47ad631a64eda1631884488af707666350ed/pywin32-312-cp315-cp315-win_arm64.whl", hash = "sha256:a8597d28f267b39074aef51fa593530082b39cbe5a074226096857b1fed2dfb9", size = 6840337, upload-time = "2026-06-04T07:49:57.531Z" }, ] -[[package]] -name = "pywin32-ctypes" -version = "0.2.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" }, -] - [[package]] name = "pyyaml" version = "6.0.3" @@ -3469,19 +3008,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, ] -[[package]] -name = "rich-rst" -version = "2.2.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pygments" }, - { name = "rich" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/cf/0e/faf7c7e36630561e3e9611730c47510cd972dd5fde8f95941ff78f76accd/rich_rst-2.2.0.tar.gz", hash = "sha256:b1e6a67f8f694a6f36035624bf73e2b1a0a4be13edaf3ba5e654d9758b61073a", size = 326270, upload-time = "2026-09-27T19:12:42.163Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/4e/716b42bf066e180c1235783b46f095a5d871d05dca7006d2295aac29c491/rich_rst-2.2.0-py3-none-any.whl", hash = "sha256:1ea1c43813dc4a8d86475fce27ffb74e0ada3d4656c9f8130ba2a59868055fe9", size = 279274, upload-time = "2026-09-27T19:12:40.548Z" }, -] - [[package]] name = "rpds-py" version = "2026.9.1" @@ -3664,7 +3190,6 @@ dependencies = [ { name = "bedrock-agentcore", extra = ["strands-agents"] }, { name = "html2text" }, { name = "mcp" }, - { name = "mcp-proxy-for-aws" }, { name = "partial-json-parser" }, { name = "pymupdf" }, { name = "requests" }, @@ -3678,7 +3203,6 @@ requires-dist = [ { name = "bedrock-agentcore", extras = ["strands-agents"], specifier = ">=1.0.6" }, { name = "html2text" }, { name = "mcp", specifier = ">=1.30.0,<2" }, - { name = "mcp-proxy-for-aws", specifier = ">=1.1.0" }, { name = "partial-json-parser" }, { name = "pymupdf" }, { name = "requests" }, @@ -3786,19 +3310,6 @@ requires-dist = [ { name = "websockets", specifier = ">=13" }, ] -[[package]] -name = "secretstorage" -version = "3.5.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cryptography" }, - { name = "jeepney" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/1c/03/e834bcd866f2f8a49a85eaff47340affa3bfa391ee9912a952a1faa68c7b/secretstorage-3.5.0.tar.gz", hash = "sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be", size = 19884, upload-time = "2025-11-23T19:02:53.191Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/46/f5af3402b579fd5e11573ce652019a67074317e18c1935cc0b4ba9b35552/secretstorage-3.5.0-py3-none-any.whl", hash = "sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137", size = 15554, upload-time = "2025-11-23T19:02:51.545Z" }, -] - [[package]] name = "shellingham" version = "1.5.4" @@ -3949,15 +3460,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/67/81/4add07e5172b7ac40d8ed5ff580409a7801a4fe26d529bdd915401dabfbe/typing_inspection-0.4.4-py3-none-any.whl", hash = "sha256:65b8397ba37ccbce054456aaccddfc91e6e3083c92824df348d96ca832f3f147", size = 14750, upload-time = "2026-08-12T12:37:24.648Z" }, ] -[[package]] -name = "uncalled-for" -version = "0.4.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6c/54/4651e4c5fe84300f8e03c0390aaad41bcb9c7b81d7783542a3ee690b40ee/uncalled_for-0.4.1.tar.gz", hash = "sha256:6412b19d1b1e7d431981fee01f8b47be7802f48328a48cbe9603acee757ec553", size = 56971, upload-time = "2026-10-09T12:54:34.941Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/a6/ba763e3812e572de7291676c3a41adfac1ef1209a6acda6bae055970f127/uncalled_for-0.4.1-py3-none-any.whl", hash = "sha256:b611b38879d9fe5088297e7bb28f2ddd12d2d73dad933d93da107fb63eb4058e", size = 14889, upload-time = "2026-10-09T12:54:33.596Z" }, -] - [[package]] name = "urllib3" version = "2.8.0" @@ -4007,49 +3509,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/33/e8/e40370e6d74ddba47f002a32919d91310d6074130fe4e17dabcafc15cbf1/watchdog-6.0.0-py3-none-win_ia64.whl", hash = "sha256:a1914259fa9e1454315171103c6a30961236f508b9b623eae470268bbcc6a22f", size = 79067, upload-time = "2024-11-01T14:07:11.845Z" }, ] -[[package]] -name = "watchfiles" -version = "1.3.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b3/68/e6aa0b77d217b31f8f486ec0cdfe5e00e6e38dc0be657e7d85819b9faf0a/watchfiles-1.3.0.tar.gz", hash = "sha256:99aee4a07847c06820765fd7b1b49ceac4f3f711ccb7d104655a33231de1c207", size = 108119, upload-time = "2026-09-21T09:08:55.664Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/68/fa/c0b840d5d8bafe640925408ce11095948c8945bb61be1e67d0ab629b872a/watchfiles-1.3.0-cp310-abi3-macosx_10_12_x86_64.whl", hash = "sha256:000b9688fc8133037a8b075c8ebf98f32844ff8964dda61e85c1db547dafc441", size = 399703, upload-time = "2026-09-21T09:08:13.518Z" }, - { url = "https://files.pythonhosted.org/packages/c7/8a/894799b485fe9473ad10422a0d9668e53fb78e3a2b5cc6061159572844ad/watchfiles-1.3.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:bbc1198edfdc90fda0600f825aa94150f428dfcbf8138746f55998e0e660d64c", size = 397647, upload-time = "2026-09-21T09:08:15.16Z" }, - { url = "https://files.pythonhosted.org/packages/5a/61/f277cd5ead05f5d37b98b41fbdd0c943ee0c04d49738f62e902cb291cf43/watchfiles-1.3.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4af9c464d410e8c44b58ddf1cbec7c3a02c1cb2c6c80df9c74659ba2fbda0ab5", size = 454994, upload-time = "2026-09-21T09:08:16.587Z" }, - { url = "https://files.pythonhosted.org/packages/46/66/ea4c01382975e53b1ac1b0a0ea1b353416b8127fb6e04f5c1c313119aab6/watchfiles-1.3.0-cp310-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb94e40b9a0db19636b5e3fed0a9803452ecc7381df13b385272abb779ee83ca", size = 460105, upload-time = "2026-09-21T09:08:17.961Z" }, - { url = "https://files.pythonhosted.org/packages/31/c3/1a501b597817096c9831c255f6270c124ce0e2faeb74124be24dcc93b86d/watchfiles-1.3.0-cp310-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7398930a2b76b9dc67a4e6b8bfc7baf30946892a86f417a3920c07bdd6febc30", size = 493761, upload-time = "2026-09-21T09:08:19.327Z" }, - { url = "https://files.pythonhosted.org/packages/5a/16/77352d05e152c7786a016e9f1decdb4507e8aa5bcf3343c72142a0413d14/watchfiles-1.3.0-cp310-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:025b108f2d5cc2799cb941f79380df3e8b22bfb589c218e801767fe78d598c95", size = 577500, upload-time = "2026-09-21T09:08:20.723Z" }, - { url = "https://files.pythonhosted.org/packages/95/fe/81001c55b24466fe9911135e50269fd3a29f43e446627a92adfab54553b6/watchfiles-1.3.0-cp310-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:be9ef3cd403d756a304a0a08a112163c63da7ec72c8c9d083c98818291ff8f29", size = 469209, upload-time = "2026-09-21T09:08:22.346Z" }, - { url = "https://files.pythonhosted.org/packages/8a/cf/e3ad894ed5909a7c44b0707e89bc25d19a3d78b3a7aec846119443b6ae56/watchfiles-1.3.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b5768b49e426fd5b550b012c866db347cdf15c398ef98dc557b6e6b72fa74cd1", size = 458353, upload-time = "2026-09-21T09:08:23.7Z" }, - { url = "https://files.pythonhosted.org/packages/7f/f5/2f106829e6e2bc91ad74614730f6df484202b9a4d20d927dbf2f08d37d44/watchfiles-1.3.0-cp310-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:d36c72fcdc08f143d87316a4c4c3b064e340da2c7383d39803950740ed418935", size = 468707, upload-time = "2026-09-21T09:08:25.167Z" }, - { url = "https://files.pythonhosted.org/packages/15/37/2741ab776b978669c1f3bba1e573f1a184f727ab8b4d3a6d9c61090800ed/watchfiles-1.3.0-cp310-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:f0c9865240e065a2247f4b5248528ae3d01e0e8ae071462c250c884dc16e3ee3", size = 632510, upload-time = "2026-09-21T09:08:26.532Z" }, - { url = "https://files.pythonhosted.org/packages/48/64/db4a4684275fe9b696ee5118c194705c1423b3d42181c3f8ee70194d5c73/watchfiles-1.3.0-cp310-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:380f513d26cc2e598266b88d66456e07d67ef4be8f0f435a1154d9c44b43d509", size = 661723, upload-time = "2026-09-21T09:08:28.004Z" }, - { url = "https://files.pythonhosted.org/packages/52/80/95ddb24f6a2f595c031c24432ab7b8aa7d6d1ada0c6d63a552166e06e8d1/watchfiles-1.3.0-cp310-abi3-win32.whl", hash = "sha256:509d9f74d2bec5c1f4cd868ddcfe0c9601f7ea53066dfcb19d8ede742c4de661", size = 277761, upload-time = "2026-09-21T09:08:29.335Z" }, - { url = "https://files.pythonhosted.org/packages/48/a1/1c4a1b3c8030cd03206232612be8a6e8799093490c220b0fcb935d02b75a/watchfiles-1.3.0-cp310-abi3-win_amd64.whl", hash = "sha256:1acabde19b67e673274e89a04d613b7fb1f122e2c4b8ec9a581e59c149264b61", size = 290643, upload-time = "2026-09-21T09:08:30.45Z" }, - { url = "https://files.pythonhosted.org/packages/82/e0/d2db577c632d26d08078c4390dd870b8555c4e558df25d22270f0166c71f/watchfiles-1.3.0-cp310-abi3-win_arm64.whl", hash = "sha256:d978cc1dd7ba44f5590d7de74f7a9c8be7262d9e469c2c0efb8bbfc2574321dc", size = 285510, upload-time = "2026-09-21T09:08:31.561Z" }, - { url = "https://files.pythonhosted.org/packages/4f/55/a122743607939429ab6a7272672f49303aa02bbd34c3f06676765a3861de/watchfiles-1.3.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:e0204f90677b7fb8d3a824279a71a01166bea9f6e53923b8056592d87b33b0b6", size = 395978, upload-time = "2026-09-21T09:08:32.747Z" }, - { url = "https://files.pythonhosted.org/packages/3e/9d/0ee1b0ea42acfe72afa2484f0222e2386dd09992e9034a81e63cc3cdab0a/watchfiles-1.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7c1125e99f84934a92996ae343501285617373acd66f16b59fd5654b27ad8d80", size = 387997, upload-time = "2026-09-21T09:08:33.953Z" }, - { url = "https://files.pythonhosted.org/packages/b7/f2/4319c6b683e8bd28465dfc53c750617a2a07f072eb2e3ab0182ccf812229/watchfiles-1.3.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a85e243c87109d9f48a2e0d10d6abdee8768cc114848b32281ec83d7f81d86ef", size = 448067, upload-time = "2026-09-21T09:08:35.104Z" }, - { url = "https://files.pythonhosted.org/packages/b7/71/9f37ac192a51a24de3a2d7fe9aac1e99b2b2668300674ff7a9f85d95beb1/watchfiles-1.3.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dd538c71766c59c732e2c5cedc39323c99c11897b99f93eac773438e54af206a", size = 452881, upload-time = "2026-09-21T09:08:36.238Z" }, - { url = "https://files.pythonhosted.org/packages/34/07/1224667c32a4a96876ddd642da69733cbfe6a15897db0865aec5a882cebc/watchfiles-1.3.0-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da213822ec9082b62cadf3008e07a8c690ec7a3c89f6dc5e55a8cf07b56a1b26", size = 484802, upload-time = "2026-09-21T09:08:37.717Z" }, - { url = "https://files.pythonhosted.org/packages/bd/4d/7f29cd87e1f826df86fc0418d0b8f370ca0311c29c618406dc492aad9951/watchfiles-1.3.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4593392e87669836670f87d62fc754059eaeb0e6157af44060a46558cebe5a3", size = 567522, upload-time = "2026-09-21T09:08:38.94Z" }, - { url = "https://files.pythonhosted.org/packages/e3/ac/3aa1f84abd4dbbfbae99a817dd931f77b439261c911189cad4c30fdfd470/watchfiles-1.3.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26b81bc515a0f03f66a69a6fea86eea54c8eca4173c46dd7222569f79dd2f977", size = 461997, upload-time = "2026-09-21T09:08:40.142Z" }, - { url = "https://files.pythonhosted.org/packages/82/1c/27c66764d5b0dbb70a36770a32eca217eba739c28b24e8583a035087a3d7/watchfiles-1.3.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca39661934749df580d89f3dde266f2af7c6968f4c21c72ce2dc387d299e6aa7", size = 451856, upload-time = "2026-09-21T09:08:41.305Z" }, - { url = "https://files.pythonhosted.org/packages/1e/b3/a45827084d953c1d0dd3d75abf85dcac26a0f5d115ad2fe0b7e9e931573b/watchfiles-1.3.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:04c5500faa725d69a99b0f63750e80795e455bb951849e9c98a811b4324997c4", size = 459889, upload-time = "2026-09-21T09:08:42.58Z" }, - { url = "https://files.pythonhosted.org/packages/7a/3d/07740d23ce2bb23419bb24055c435a9abe5fe03efdaea1ba0720b831aab6/watchfiles-1.3.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:ec3cd4bb181a7b6329134204c2277c7144ab5f62cce9c5335d6f901ee7ce8d6a", size = 624482, upload-time = "2026-09-21T09:08:44.064Z" }, - { url = "https://files.pythonhosted.org/packages/91/46/9540f8123eaec86df989f26d7704cad0448d9fb7271763a4f8f9fe23617d/watchfiles-1.3.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:e5871d4a7f788a9f64fb06f5793389d29d171e5c32d37c3ebfd520b017cc7694", size = 653724, upload-time = "2026-09-21T09:08:45.257Z" }, - { url = "https://files.pythonhosted.org/packages/25/9d/b9deb52f1e4528ffe44338c5ebab95c32ed79203082da661de50288e130a/watchfiles-1.3.0-cp314-cp314t-win32.whl", hash = "sha256:81c989d7267bfb7b676cd32c83bec97914e396870983cbf493e29415037bff5e", size = 270863, upload-time = "2026-09-21T09:08:46.518Z" }, - { url = "https://files.pythonhosted.org/packages/59/59/8b1881afccbafda06248be4185e28034dd73c80c85e4da24f2cb0c1321eb/watchfiles-1.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d754e049006e81a9be49dc78ba7802081cee426e968cbc63ee19e164fa2d0e39", size = 286879, upload-time = "2026-09-21T09:08:47.874Z" }, - { url = "https://files.pythonhosted.org/packages/46/dd/41c12ae9745d5d72f709333287679d71cbba68ad7678fed872207bba94f4/watchfiles-1.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:a5b631db08fd3032db57ec6a92d1777cd60f88803287e4e941a4858c53aab1e0", size = 276924, upload-time = "2026-09-21T09:08:48.976Z" }, - { url = "https://files.pythonhosted.org/packages/cd/eb/289fec71eba51d6c3ef3a28c81f7213f4e860084ffae5abc866933c564f0/watchfiles-1.3.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:45726c6b5a8d67c8087eb2933c4398948546d04206ef40f629dc4881d65d23d1", size = 396932, upload-time = "2026-09-21T09:08:50.217Z" }, - { url = "https://files.pythonhosted.org/packages/92/cc/a3c3f557992a20a5bb24607f0da44d39cf6d6ba3f8f6ed7cb31f6c73371a/watchfiles-1.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:6398d250994baff581147ccba846223076fe6492ca93c0d1b3588fcf5355eb5c", size = 394852, upload-time = "2026-09-21T09:08:51.412Z" }, - { url = "https://files.pythonhosted.org/packages/55/65/d45763a5e1108a65af85a217af2930ebf1081c73fd8169d3f75e586992bb/watchfiles-1.3.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:591de392458bca26f6130fea4e667c06b657e873ad334ea06fad5a79f5086cef", size = 451789, upload-time = "2026-09-21T09:08:53.144Z" }, - { url = "https://files.pythonhosted.org/packages/02/96/165c6e540bf765ca1115062017adf861d0816525f02464ba71313fe7cf92/watchfiles-1.3.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ec46a1ff4c1d81405a5fc645abdbff5e4e9388f7c9a6cdb392316a7c29b884f", size = 456919, upload-time = "2026-09-21T09:08:54.372Z" }, -] - [[package]] name = "websockets" version = "17.4" @@ -4314,12 +3773,3 @@ sdist = { url = "https://files.pythonhosted.org/packages/9c/fb/31bdbf3737222d92e wheels = [ { url = "https://files.pythonhosted.org/packages/88/eb/1e6af9959a567901a7e7c7cef2e75883e487df223ed67f9a8977ff863bd8/xlsxwriter-3.3.1-py3-none-any.whl", hash = "sha256:8e2c89e59d733fe59e112317218c64fbbc276d90a8c144ebd6f7fa15e7ab184a", size = 180583, upload-time = "2026-10-28T22:52:45.048Z" }, ] - -[[package]] -name = "zipp" -version = "4.1.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/05/ba1458dee0ac485b2a01071c1b88f5199fe878a485df482e10e1ef2205cc/zipp-4.1.2.tar.gz", hash = "sha256:cf474b90b07ea932637e17c6b9479de2b2882900b0d311bdaf4f5c000a15a97f", size = 27864, upload-time = "2026-10-21T18:57:04.743Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b8/44/7bd2007260da11cccca29ba2d4c345f1287aa663db38ee7cefeabf6386a5/zipp-4.1.2-py3-none-any.whl", hash = "sha256:b30cb6cd253122169c47de245ca24a86bac2a5d3802ba15bf7ba6414eb9e144d", size = 10581, upload-time = "2026-10-21T18:57:03.79Z" }, -]