@aws/nx-plugin 1.0.0-rc.71 → 1.0.0-rc.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-THIRD-PARTY +210 -730
- package/migrations.json +34 -19
- package/package.json +4 -4
- package/src/agentcore-gateway/__snapshots__/generator.spec.ts.snap +1 -1
- package/src/agentcore-harness/generator.d.ts +1 -1
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +3 -3
- package/src/infra/app/generator.d.ts +1 -1
- package/src/init/generator.d.ts +1 -1
- package/src/license/config.d.ts +9 -0
- package/src/license/config.js +28 -0
- package/src/license/config.js.map +1 -1
- package/src/license/dependency-check/collectors/collector.js.map +1 -1
- package/src/license/dependency-check/evaluator.js +55 -10
- package/src/license/dependency-check/evaluator.js.map +1 -1
- package/src/license/generator.js +3 -17
- package/src/license/generator.js.map +1 -1
- package/src/license/known-exceptions.d.ts +0 -1
- package/src/license/known-exceptions.js +1 -23
- package/src/license/known-exceptions.js.map +1 -1
- package/src/migrations/latest/apt-security-updates-in-container-images/__snapshots__/migration.spec.ts.snap +90 -0
- package/src/migrations/latest/apt-security-updates-in-container-images/metadata.json +3 -0
- package/src/migrations/latest/apt-security-updates-in-container-images/migration.js +90 -0
- package/src/migrations/latest/apt-security-updates-in-container-images/migration.js.map +1 -0
- package/src/migrations/latest/remove-mcp-inspector-license-exceptions/metadata.json +3 -0
- package/src/migrations/latest/remove-mcp-inspector-license-exceptions/migration.d.ts +6 -0
- package/src/migrations/latest/remove-mcp-inspector-license-exceptions/migration.js +38 -0
- package/src/migrations/latest/remove-mcp-inspector-license-exceptions/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.67/0001-smithy-server-package-rename/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.68/0001-translate-script-whole-file-writes/migration.js.map +1 -0
- package/src/migrations/{latest/py-agent-a2a-lifespan-construction → v1.0.0-rc.70/0001-py-agent-a2a-lifespan-construction}/migration.js +14 -2
- package/src/migrations/v1.0.0-rc.70/0001-py-agent-a2a-lifespan-construction/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.71/0001-py-agent-a2a-httpx-client-per-call/migration.d.ts +6 -0
- package/src/migrations/v1.0.0-rc.71/0001-py-agent-a2a-httpx-client-per-call/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.72/0001-py-agent-session-management-support/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.72/0001-py-agent-session-management-support/migration.d.ts +2 -0
- package/src/migrations/v1.0.0-rc.72/0001-py-agent-session-management-support/migration.js +308 -0
- package/src/migrations/v1.0.0-rc.72/0001-py-agent-session-management-support/migration.js.map +1 -0
- package/src/preset/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/preset/generator.d.ts +1 -1
- package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +626 -10
- package/src/py/agent/__snapshots__/generator.core.spec.ts.snap +186 -0
- package/src/py/agent/__snapshots__/generator.frameworks.spec.ts.snap +55 -11
- package/src/py/agent/__snapshots__/generator.protocols.spec.ts.snap +669 -4
- package/src/py/agent/a2a-connection/generator.js +5 -11
- package/src/py/agent/a2a-connection/generator.js.map +1 -1
- package/src/py/agent/files/deploy/Dockerfile.template +7 -0
- package/src/py/agent/files/langchain/common/__init__.py.template +0 -0
- package/src/py/agent/files/langchain/common/agent.py.template +3 -3
- package/src/py/agent/files/langchain/common/session.py.template +61 -0
- package/src/py/agent/files/strands/ag-ui/main.py.template +5 -1
- package/src/py/agent/files/strands/common/agent.py.template +9 -2
- package/src/py/agent/files/strands/common/session.py.template +36 -0
- package/src/py/agent/generator.d.ts +11 -1
- package/src/py/agent/generator.js +78 -28
- package/src/py/agent/generator.js.map +1 -1
- package/src/py/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +2 -0
- package/src/py/agent/react-connection/generator.d.ts +1 -1
- package/src/py/agent/schema.d.js.map +1 -1
- package/src/py/agent/schema.d.ts +1 -1
- package/src/py/agent/schema.json +3 -3
- package/src/py/fast-api/react/generator.d.ts +1 -1
- package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +5 -5
- package/src/py/mcp-server/files/deploy/Dockerfile.template +7 -0
- package/src/py/mcp-server/generator.js +8 -3
- package/src/py/mcp-server/generator.js.map +1 -1
- package/src/py/rdb/__snapshots__/generator.spec.ts.snap +7 -5
- package/src/py/rdb/generator.js +36 -2
- package/src/py/rdb/generator.js.map +1 -1
- package/src/smithy/project/__snapshots__/generator.spec.ts.snap +14 -14
- package/src/smithy/project/generator.d.ts +1 -1
- package/src/smithy/react-connection/generator.d.ts +1 -1
- package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +1 -1
- package/src/terraform/project/generator.d.ts +1 -1
- package/src/trpc/react/generator.d.ts +1 -1
- package/src/ts/agent/__snapshots__/generator.spec.ts.snap +36 -8
- package/src/ts/agent/a2a-connection/generator.d.ts +1 -1
- package/src/ts/agent/a2a-connection/generator.js +4 -2
- package/src/ts/agent/a2a-connection/generator.js.map +1 -1
- package/src/ts/agent/files/deploy/Dockerfile.template +7 -0
- package/src/ts/agent/gateway-connection/generator.d.ts +1 -1
- package/src/ts/agent/mcp-connection/generator.d.ts +1 -1
- package/src/ts/agent/react-connection/generator.d.ts +1 -1
- package/src/ts/astro-docs/generator.d.ts +1 -1
- package/src/ts/dcr-proxy/generator.d.ts +1 -1
- package/src/ts/dynamodb/generator.d.ts +1 -1
- package/src/ts/lambda-function/generator.d.ts +1 -1
- package/src/ts/lib/generator.d.ts +1 -1
- package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/ts/mcp-server/files/Dockerfile.template +7 -0
- package/src/ts/mcp-server/generator.js +8 -3
- package/src/ts/mcp-server/generator.js.map +1 -1
- package/src/ts/nx-generator/generator.d.ts +1 -1
- package/src/ts/nx-migration/generator.d.ts +1 -1
- package/src/ts/nx-plugin/generator.d.ts +1 -1
- package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +8 -6
- package/src/ts/rdb/generator.d.ts +1 -1
- package/src/ts/rdb/generator.js +29 -2
- package/src/ts/rdb/generator.js.map +1 -1
- package/src/ts/react-website/agui/generator.d.ts +1 -1
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +15 -15
- package/src/ts/react-website/app/generator.js +4 -2
- package/src/ts/react-website/app/generator.js.map +1 -1
- package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +1 -1
- package/src/utils/agent-connection/agent-connection.d.ts +10 -0
- package/src/utils/agent-connection/agent-connection.js +20 -9
- package/src/utils/agent-connection/agent-connection.js.map +1 -1
- package/src/utils/agent-connection/files/core-runtime-config/runtime-config.ts.template +5 -3
- package/src/utils/agent-connection/files/py-core-langchain/s3/s3_checkpoint_saver_langchain.py.template +360 -0
- package/src/utils/agent-connection/files/py-core-runtime-config/runtime_config.py.template +2 -4
- package/src/utils/agent-connection/files/py-core-strands/base/tool_errors_strands.py.template +24 -0
- package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +1 -1
- package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
- package/src/utils/agent-core-constructs/files/cdk/app/agent-core/__nameKebabCase__/__nameKebabCase__.ts.template +113 -13
- package/src/utils/agent-core-constructs/files/terraform/app/agent-core/__nameKebabCase__/__nameKebabCase__.tf.template +76 -7
- package/src/utils/ast.d.ts +29 -0
- package/src/utils/ast.js +31 -0
- package/src/utils/ast.js.map +1 -1
- package/src/utils/metrics.js +2 -2
- package/src/utils/metrics.js.map +1 -1
- package/src/utils/versions.d.ts +75 -72
- package/src/utils/versions.js +72 -69
- package/src/utils/versions.js.map +1 -1
- package/src/migrations/latest/py-agent-a2a-httpx-client-per-call/migration.js.map +0 -1
- package/src/migrations/latest/py-agent-a2a-lifespan-construction/migration.js.map +0 -1
- package/src/migrations/latest/smithy-server-package-rename/migration.js.map +0 -1
- package/src/migrations/latest/translate-script-whole-file-writes/migration.js.map +0 -1
- package/src/py/rdb/files/__name__/__init__.py.template +0 -3
- package/src/py/rdb/files/config.json.template +0 -14
- package/src/ts/rdb/files/config.json.template +0 -14
- package/src/ts/rdb/files/src/index.ts.template +0 -1
- /package/src/migrations/latest/{py-agent-a2a-httpx-client-per-call → apt-security-updates-in-container-images}/migration.d.ts +0 -0
- /package/src/migrations/{latest/smithy-server-package-rename → v1.0.0-rc.67/0001-smithy-server-package-rename}/metadata.json +0 -0
- /package/src/migrations/{latest/py-agent-a2a-lifespan-construction → v1.0.0-rc.67/0001-smithy-server-package-rename}/migration.d.ts +0 -0
- /package/src/migrations/{latest/smithy-server-package-rename → v1.0.0-rc.67/0001-smithy-server-package-rename}/migration.js +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/files/build-system-prompt.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/files/build-user-prompt.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/files/config-path.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/files/file-to-translate.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/files/get-files-to-translate.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/files/header.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/files/log.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/files/main-call.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/files/main.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/files/project-root.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/files/run-with-concurrency.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/files/scripts-dir.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/files/translate-file-for-language.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/grit/already-migrated.grit +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/grit/build-system-prompt.grit +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/grit/build-user-prompt.grit +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/grit/config-path.grit +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/grit/file-to-translate.grit +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/grit/get-files-to-translate.grit +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/grit/log.grit +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/grit/main-call.grit +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/grit/main.grit +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/grit/project-root.grit +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/grit/run-with-concurrency.grit +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/grit/translate-file-for-language.grit +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/metadata.json +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/migration.d.ts +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/migration.js +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/test-fixtures/released-script-first.ts.fixture +0 -0
- /package/src/migrations/{latest/translate-script-whole-file-writes → v1.0.0-rc.68/0001-translate-script-whole-file-writes}/test-fixtures/released-script.ts.fixture +0 -0
- /package/src/migrations/{latest/py-agent-a2a-lifespan-construction → v1.0.0-rc.70/0001-py-agent-a2a-lifespan-construction}/metadata.json +0 -0
- /package/src/migrations/{latest/smithy-server-package-rename → v1.0.0-rc.70/0001-py-agent-a2a-lifespan-construction}/migration.d.ts +0 -0
- /package/src/migrations/{latest/py-agent-a2a-httpx-client-per-call → v1.0.0-rc.71/0001-py-agent-a2a-httpx-client-per-call}/metadata.json +0 -0
- /package/src/migrations/{latest/py-agent-a2a-httpx-client-per-call → v1.0.0-rc.71/0001-py-agent-a2a-httpx-client-per-call}/migration.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../packages/nx-plugin/src/license/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { getProjects, readNxJson, type Tree, updateNxJson } from '@nx/devkit';\nimport { PY_AGENT_GENERATOR_INFO } from '../py/agent/generator';\nimport { PY_MCP_SERVER_GENERATOR_INFO } from '../py/mcp-server/generator';\nimport { TS_MCP_SERVER_GENERATOR_INFO } from '../ts/mcp-server/generator';\nimport { ensureAwsNxPluginConfig } from '../utils/config/utils';\nimport { formatFilesInSubtree } from '../utils/format';\nimport { addGeneratorMetricsIfApplicable } from '../utils/metrics';\nimport {\n getGeneratorInfo,\n mergeTargetDefault,\n type NxGeneratorInfo,\n} from '../utils/nx';\nimport {\n addLicenseCheckToAllLintTargets,\n defaultLicenseConfig,\n ensureDependencyCheckBlock,\n ensureLicenseExceptions,\n ensurePythonLicenseCollector,\n updateLicenseCheckTargetInputs,\n writeLicenseConfig,\n} from './config';\nimport {\n AG_UI_LANGGRAPH_EXCEPTIONS,\n MCP_INSPECTOR_EXCEPTIONS,\n} from './known-exceptions';\nimport type { LicenseGeneratorSchema } from './schema';\nimport { SYNC_GENERATOR_NAME } from './sync/generator';\n\nexport const LICENSE_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport async function licenseGenerator(\n tree: Tree,\n options: LicenseGeneratorSchema,\n) {\n const { license, copyrightHolder } = options;\n const dependencyCheckEnabled = options.dependencyCheck !== false;\n\n await ensureAwsNxPluginConfig(tree);\n await writeLicenseConfig(\n tree,\n defaultLicenseConfig(license, copyrightHolder),\n );\n\n if (dependencyCheckEnabled) {\n const hasPython = hasPythonProjects(tree);\n await ensureDependencyCheckBlock(tree, {\n includeCollectors: hasPython ? 'npm+python' : 'npm',\n });\n // When the dependencyCheck block already existed (e.g. on a re-run after\n // python projects were added), the block above is a no-op — so explicitly\n // ensure the python collector is present. This is idempotent.\n if (hasPython) {\n await ensurePythonLicenseCollector(tree);\n }\n await addExceptionsForExistingProjects(tree);\n await writeLicenseCheckTarget(tree);\n // Make every existing project's lint target depend on the root\n // license-check target, so the check runs as part of lint/build regardless\n // of whether projects were created before or after the license generator.\n addLicenseCheckToAllLintTargets(tree);\n }\n\n const nxJson = readNxJson(tree);\n const updatedNxJson = {\n ...nxJson,\n targetDefaults: {\n ...nxJson.targetDefaults,\n lint: mergeTargetDefault(nxJson.targetDefaults?.lint, (base) => ({\n ...base,\n syncGenerators: [\n ...(base.syncGenerators ?? []).filter(\n (g) => g !== SYNC_GENERATOR_NAME,\n ),\n SYNC_GENERATOR_NAME,\n ],\n })),\n },\n };\n\n updateNxJson(tree, updatedNxJson);\n\n await addGeneratorMetricsIfApplicable(tree, [LICENSE_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n}\n\n/**\n * Write/update root project.json with the license-check target.\n */\nconst writeLicenseCheckTarget = async (tree: Tree): Promise<void> => {\n const rootProjectJsonPath = 'project.json';\n let rootProject: any = {};\n if (tree.exists(rootProjectJsonPath)) {\n rootProject = JSON.parse(tree.read(rootProjectJsonPath, 'utf-8')!);\n }\n rootProject.targets = rootProject.targets ?? {};\n rootProject.targets['license-check'] = {\n executor: '@aws/nx-plugin:license-check',\n cache: true,\n inputs: [],\n options: {},\n };\n tree.write(rootProjectJsonPath, JSON.stringify(rootProject, null, 2));\n\n // Populate `inputs` from the lockfiles actually present (+ uv.lock if a\n // Python collector is configured) and the config file.\n await updateLicenseCheckTargetInputs(tree);\n\n // Adding a root project.json registers the workspace root as an Nx project.\n // Suppress target inference from the root package.json scripts (build, lint,\n // test, etc. are `nx run-many` wrappers) so they don't become targets — an\n // inferred `build` target would recurse when running `nx run-many --target build`.\n if (tree.exists('package.json')) {\n const packageJson = JSON.parse(tree.read('package.json', 'utf-8')!);\n if (\n !packageJson.nx?.includedScripts ||\n packageJson.nx.includedScripts.length !== 0\n ) {\n packageJson.nx = { ...packageJson.nx, includedScripts: [] };\n tree.write('package.json', JSON.stringify(packageJson, null, 2));\n }\n }\n};\n\nconst addExceptionsForExistingProjects = async (tree: Tree): Promise<void> => {\n const projects = getProjects(tree);\n let needsMcp = false;\n // A LangChain AG-UI agent pulls jsonpatch/jsonpointer (BSD-3-Clause but with\n // only free-text metadata) via langchain-core. The py#agent generator adds\n // these exceptions itself, but if the license generator runs afterwards (or\n // the agent predates the dependency-check block) they may be missing, so\n // re-assert them here when such an agent exists.\n let needsLangchain = false;\n\n const mcpIds = [\n TS_MCP_SERVER_GENERATOR_INFO.id,\n PY_MCP_SERVER_GENERATOR_INFO.id,\n ];\n\n for (const [, config] of projects) {\n const components =\n (config as any).metadata?.components ??\n (config as any).metadata?.generators ??\n [];\n for (const comp of components) {\n const gen = comp.generator ?? comp;\n if (typeof gen === 'string' && mcpIds.includes(gen)) {\n needsMcp = true;\n }\n if (\n gen === PY_AGENT_GENERATOR_INFO.id &&\n comp.framework === 'langchain'\n ) {\n needsLangchain = true;\n }\n }\n }\n\n const exceptions = [\n ...(needsMcp ? MCP_INSPECTOR_EXCEPTIONS : []),\n ...(needsLangchain ? AG_UI_LANGGRAPH_EXCEPTIONS : []),\n ];\n\n if (exceptions.length > 0) {\n await ensureLicenseExceptions(tree, exceptions);\n }\n};\n\nconst hasPythonProjects = (tree: Tree): boolean => {\n const projects = getProjects(tree);\n for (const [, config] of projects) {\n if (tree.exists(`${config.root}/pyproject.toml`)) return true;\n }\n return tree.exists('pyproject.toml');\n};\n\nexport default licenseGenerator;\n"],"names":["getProjects","readNxJson","updateNxJson","PY_AGENT_GENERATOR_INFO","PY_MCP_SERVER_GENERATOR_INFO","TS_MCP_SERVER_GENERATOR_INFO","ensureAwsNxPluginConfig","formatFilesInSubtree","addGeneratorMetricsIfApplicable","getGeneratorInfo","mergeTargetDefault","addLicenseCheckToAllLintTargets","defaultLicenseConfig","ensureDependencyCheckBlock","ensureLicenseExceptions","ensurePythonLicenseCollector","updateLicenseCheckTargetInputs","writeLicenseConfig","AG_UI_LANGGRAPH_EXCEPTIONS","MCP_INSPECTOR_EXCEPTIONS","SYNC_GENERATOR_NAME","LICENSE_GENERATOR_INFO","filename","licenseGenerator","tree","options","license","copyrightHolder","dependencyCheckEnabled","dependencyCheck","hasPython","hasPythonProjects","includeCollectors","addExceptionsForExistingProjects","writeLicenseCheckTarget","nxJson","updatedNxJson","targetDefaults","lint","base","syncGenerators","filter","g","rootProjectJsonPath","rootProject","exists","JSON","parse","read","targets","executor","cache","inputs","write","stringify","packageJson","nx","includedScripts","length","projects","needsMcp","needsLangchain","mcpIds","id","config","components","metadata","generators","comp","gen","generator","includes","framework","exceptions","root"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx-plugin/src/license/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { getProjects, readNxJson, type Tree, updateNxJson } from '@nx/devkit';\nimport { PY_AGENT_GENERATOR_INFO } from '../py/agent/generator';\nimport { ensureAwsNxPluginConfig } from '../utils/config/utils';\nimport { formatFilesInSubtree } from '../utils/format';\nimport { addGeneratorMetricsIfApplicable } from '../utils/metrics';\nimport {\n getGeneratorInfo,\n mergeTargetDefault,\n type NxGeneratorInfo,\n} from '../utils/nx';\nimport {\n addLicenseCheckToAllLintTargets,\n defaultLicenseConfig,\n ensureDependencyCheckBlock,\n ensureLicenseExceptions,\n ensurePythonLicenseCollector,\n updateLicenseCheckTargetInputs,\n writeLicenseConfig,\n} from './config';\nimport { AG_UI_LANGGRAPH_EXCEPTIONS } from './known-exceptions';\nimport type { LicenseGeneratorSchema } from './schema';\nimport { SYNC_GENERATOR_NAME } from './sync/generator';\n\nexport const LICENSE_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport async function licenseGenerator(\n tree: Tree,\n options: LicenseGeneratorSchema,\n) {\n const { license, copyrightHolder } = options;\n const dependencyCheckEnabled = options.dependencyCheck !== false;\n\n await ensureAwsNxPluginConfig(tree);\n await writeLicenseConfig(\n tree,\n defaultLicenseConfig(license, copyrightHolder),\n );\n\n if (dependencyCheckEnabled) {\n const hasPython = hasPythonProjects(tree);\n await ensureDependencyCheckBlock(tree, {\n includeCollectors: hasPython ? 'npm+python' : 'npm',\n });\n // When the dependencyCheck block already existed (e.g. on a re-run after\n // python projects were added), the block above is a no-op — so explicitly\n // ensure the python collector is present. This is idempotent.\n if (hasPython) {\n await ensurePythonLicenseCollector(tree);\n }\n await addExceptionsForExistingProjects(tree);\n await writeLicenseCheckTarget(tree);\n // Make every existing project's lint target depend on the root\n // license-check target, so the check runs as part of lint/build regardless\n // of whether projects were created before or after the license generator.\n addLicenseCheckToAllLintTargets(tree);\n }\n\n const nxJson = readNxJson(tree);\n const updatedNxJson = {\n ...nxJson,\n targetDefaults: {\n ...nxJson.targetDefaults,\n lint: mergeTargetDefault(nxJson.targetDefaults?.lint, (base) => ({\n ...base,\n syncGenerators: [\n ...(base.syncGenerators ?? []).filter(\n (g) => g !== SYNC_GENERATOR_NAME,\n ),\n SYNC_GENERATOR_NAME,\n ],\n })),\n },\n };\n\n updateNxJson(tree, updatedNxJson);\n\n await addGeneratorMetricsIfApplicable(tree, [LICENSE_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n}\n\n/**\n * Write/update root project.json with the license-check target.\n */\nconst writeLicenseCheckTarget = async (tree: Tree): Promise<void> => {\n const rootProjectJsonPath = 'project.json';\n let rootProject: any = {};\n if (tree.exists(rootProjectJsonPath)) {\n rootProject = JSON.parse(tree.read(rootProjectJsonPath, 'utf-8')!);\n }\n rootProject.targets = rootProject.targets ?? {};\n rootProject.targets['license-check'] = {\n executor: '@aws/nx-plugin:license-check',\n cache: true,\n inputs: [],\n options: {},\n };\n tree.write(rootProjectJsonPath, JSON.stringify(rootProject, null, 2));\n\n // Populate `inputs` from the lockfiles actually present (+ uv.lock if a\n // Python collector is configured) and the config file.\n await updateLicenseCheckTargetInputs(tree);\n\n // Adding a root project.json registers the workspace root as an Nx project.\n // Suppress target inference from the root package.json scripts (build, lint,\n // test, etc. are `nx run-many` wrappers) so they don't become targets — an\n // inferred `build` target would recurse when running `nx run-many --target build`.\n if (tree.exists('package.json')) {\n const packageJson = JSON.parse(tree.read('package.json', 'utf-8')!);\n if (\n !packageJson.nx?.includedScripts ||\n packageJson.nx.includedScripts.length !== 0\n ) {\n packageJson.nx = { ...packageJson.nx, includedScripts: [] };\n tree.write('package.json', JSON.stringify(packageJson, null, 2));\n }\n }\n};\n\nconst addExceptionsForExistingProjects = async (tree: Tree): Promise<void> => {\n const projects = getProjects(tree);\n // A LangChain AG-UI agent pulls jsonpatch/jsonpointer (BSD-3-Clause but with\n // only free-text metadata) via langchain-core. The py#agent generator adds\n // these exceptions itself, but if the license generator runs afterwards (or\n // the agent predates the dependency-check block) they may be missing, so\n // re-assert them here when such an agent exists.\n let needsLangchain = false;\n\n for (const [, config] of projects) {\n const components =\n (config as any).metadata?.components ??\n (config as any).metadata?.generators ??\n [];\n for (const comp of components) {\n const gen = comp.generator ?? comp;\n if (\n gen === PY_AGENT_GENERATOR_INFO.id &&\n comp.framework === 'langchain'\n ) {\n needsLangchain = true;\n }\n }\n }\n\n if (needsLangchain) {\n await ensureLicenseExceptions(tree, AG_UI_LANGGRAPH_EXCEPTIONS);\n }\n};\n\nconst hasPythonProjects = (tree: Tree): boolean => {\n const projects = getProjects(tree);\n for (const [, config] of projects) {\n if (tree.exists(`${config.root}/pyproject.toml`)) return true;\n }\n return tree.exists('pyproject.toml');\n};\n\nexport default licenseGenerator;\n"],"names":["getProjects","readNxJson","updateNxJson","PY_AGENT_GENERATOR_INFO","ensureAwsNxPluginConfig","formatFilesInSubtree","addGeneratorMetricsIfApplicable","getGeneratorInfo","mergeTargetDefault","addLicenseCheckToAllLintTargets","defaultLicenseConfig","ensureDependencyCheckBlock","ensureLicenseExceptions","ensurePythonLicenseCollector","updateLicenseCheckTargetInputs","writeLicenseConfig","AG_UI_LANGGRAPH_EXCEPTIONS","SYNC_GENERATOR_NAME","LICENSE_GENERATOR_INFO","filename","licenseGenerator","tree","options","license","copyrightHolder","dependencyCheckEnabled","dependencyCheck","hasPython","hasPythonProjects","includeCollectors","addExceptionsForExistingProjects","writeLicenseCheckTarget","nxJson","updatedNxJson","targetDefaults","lint","base","syncGenerators","filter","g","rootProjectJsonPath","rootProject","exists","JSON","parse","read","targets","executor","cache","inputs","write","stringify","packageJson","nx","includedScripts","length","projects","needsLangchain","config","components","metadata","generators","comp","gen","generator","id","framework","root"],"mappings":"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"}
|
|
@@ -3,5 +3,4 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
import type { DependencyCheckException } from './dependency-check/types';
|
|
6
|
-
export declare const MCP_INSPECTOR_EXCEPTIONS: DependencyCheckException[];
|
|
7
6
|
export declare const AG_UI_LANGGRAPH_EXCEPTIONS: DependencyCheckException[];
|
|
@@ -1,29 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/ export const
|
|
5
|
-
{
|
|
6
|
-
package: '@modelcontextprotocol/inspector',
|
|
7
|
-
reason: 'MCP project is licensed Apache-2.0 / MIT. Tarball omits the LICENSE file.',
|
|
8
|
-
spdx: 'Apache-2.0'
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
package: '@modelcontextprotocol/inspector-cli',
|
|
12
|
-
reason: 'MCP project is licensed Apache-2.0 / MIT. Tarball omits the LICENSE file.',
|
|
13
|
-
spdx: 'Apache-2.0'
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
package: '@modelcontextprotocol/inspector-server',
|
|
17
|
-
reason: 'MCP project is licensed Apache-2.0 / MIT. Tarball omits the LICENSE file.',
|
|
18
|
-
spdx: 'Apache-2.0'
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
package: '@modelcontextprotocol/inspector-client',
|
|
22
|
-
reason: 'MCP project is licensed Apache-2.0 / MIT. Tarball omits the LICENSE file.',
|
|
23
|
-
spdx: 'Apache-2.0'
|
|
24
|
-
}
|
|
25
|
-
];
|
|
26
|
-
export const AG_UI_LANGGRAPH_EXCEPTIONS = [
|
|
4
|
+
*/ export const AG_UI_LANGGRAPH_EXCEPTIONS = [
|
|
27
5
|
{
|
|
28
6
|
package: 'jsonpatch',
|
|
29
7
|
reason: 'Unconditional dependency of langchain-core. Genuinely BSD-3-Clause (LICENSE matches the SPDX BSD-3-Clause template), but the wheel only carries the free-text "Modified BSD License" metadata, not an SPDX expression.',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../packages/nx-plugin/src/license/known-exceptions.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { DependencyCheckException } from './dependency-check/types';\n\nexport const
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx-plugin/src/license/known-exceptions.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { DependencyCheckException } from './dependency-check/types';\n\nexport const AG_UI_LANGGRAPH_EXCEPTIONS: DependencyCheckException[] = [\n {\n package: 'jsonpatch',\n reason:\n 'Unconditional dependency of langchain-core. Genuinely BSD-3-Clause (LICENSE matches the SPDX BSD-3-Clause template), but the wheel only carries the free-text \"Modified BSD License\" metadata, not an SPDX expression.',\n spdx: 'BSD-3-Clause',\n },\n {\n package: 'jsonpointer',\n reason:\n 'Transitive dependency of jsonpatch (via langchain-core). Genuinely BSD-3-Clause (LICENSE matches the SPDX BSD-3-Clause template), but the wheel only carries the free-text \"Modified BSD License\" metadata, not an SPDX expression.',\n spdx: 'BSD-3-Clause',\n },\n];\n"],"names":["AG_UI_LANGGRAPH_EXCEPTIONS","package","reason","spdx"],"mappings":"AAAA;;;CAGC,GAGD,OAAO,MAAMA,6BAAyD;IACpE;QACEC,SAAS;QACTC,QACE;QACFC,MAAM;IACR;IACA;QACEF,SAAS;QACTC,QACE;QACFC,MAAM;IACR;CACD,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`apt-security-updates-in-container-images migration > adds the security updates to a py#agent Dockerfile 1`] = `
|
|
4
|
+
"FROM public.ecr.aws/docker/library/python:3.14-slim
|
|
5
|
+
|
|
6
|
+
# Apply the distribution's security updates: base image tags lag behind the
|
|
7
|
+
# security suite, so its OS packages carry fixed HIGH/CRITICAL vulnerabilities
|
|
8
|
+
# flagged by the image scan.
|
|
9
|
+
RUN apt-get update && \\
|
|
10
|
+
apt-get upgrade -y --no-install-recommends && \\
|
|
11
|
+
rm -rf /var/lib/apt/lists/*
|
|
12
|
+
|
|
13
|
+
# Remove the base image's pip: the agent runs from the bundled environment and
|
|
14
|
+
# never needs it at runtime, and pip's vendored packages carry known
|
|
15
|
+
# HIGH/CRITICAL vulnerabilities flagged by the image scan.
|
|
16
|
+
RUN python -m pip uninstall -y pip && \\
|
|
17
|
+
rm -rf /usr/local/lib/python*/site-packages/pip \\
|
|
18
|
+
/usr/local/lib/python*/site-packages/pip-*.dist-info
|
|
19
|
+
|
|
20
|
+
WORKDIR /app
|
|
21
|
+
|
|
22
|
+
# Copy bundled package
|
|
23
|
+
COPY . /app
|
|
24
|
+
|
|
25
|
+
EXPOSE 8080
|
|
26
|
+
|
|
27
|
+
ENV PYTHONPATH=/app
|
|
28
|
+
ENV PATH="/app/bin:\${PATH}"
|
|
29
|
+
|
|
30
|
+
CMD ["python", "bin/opentelemetry-instrument", "python", "-m", "proj_py_project.my_agent.main"]
|
|
31
|
+
"
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
exports[`apt-security-updates-in-container-images migration > adds the security updates to a py#mcp-server Dockerfile 1`] = `
|
|
35
|
+
"FROM public.ecr.aws/docker/library/python:3.14-slim
|
|
36
|
+
|
|
37
|
+
# Apply the distribution's security updates: base image tags lag behind the
|
|
38
|
+
# security suite, so its OS packages carry fixed HIGH/CRITICAL vulnerabilities
|
|
39
|
+
# flagged by the image scan.
|
|
40
|
+
RUN apt-get update && \\
|
|
41
|
+
apt-get upgrade -y --no-install-recommends && \\
|
|
42
|
+
rm -rf /var/lib/apt/lists/*
|
|
43
|
+
|
|
44
|
+
# Remove the base image's pip: the server runs from the bundled environment and
|
|
45
|
+
# never needs it at runtime, and pip's vendored packages carry known
|
|
46
|
+
# HIGH/CRITICAL vulnerabilities flagged by the image scan.
|
|
47
|
+
RUN python -m pip uninstall -y pip && \\
|
|
48
|
+
rm -rf /usr/local/lib/python*/site-packages/pip \\
|
|
49
|
+
/usr/local/lib/python*/site-packages/pip-*.dist-info
|
|
50
|
+
|
|
51
|
+
WORKDIR /app
|
|
52
|
+
|
|
53
|
+
# Copy bundled package
|
|
54
|
+
COPY . /app
|
|
55
|
+
|
|
56
|
+
EXPOSE 8000
|
|
57
|
+
|
|
58
|
+
ENV PYTHONPATH=/app
|
|
59
|
+
|
|
60
|
+
CMD ["python", "bin/opentelemetry-instrument", "python", "-m", "uvicorn", "proj_py_project.my_mcp.http:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
61
|
+
"
|
|
62
|
+
`;
|
|
63
|
+
|
|
64
|
+
exports[`apt-security-updates-in-container-images migration > adds the security updates to a ts#agent Dockerfile 1`] = `
|
|
65
|
+
"FROM public.ecr.aws/docker/library/node:lts-slim
|
|
66
|
+
|
|
67
|
+
# Apply the distribution's security updates: base image tags lag behind the
|
|
68
|
+
# security suite, so its OS packages carry fixed HIGH/CRITICAL vulnerabilities
|
|
69
|
+
# flagged by the image scan.
|
|
70
|
+
RUN apt-get update && \\
|
|
71
|
+
apt-get upgrade -y --no-install-recommends && \\
|
|
72
|
+
rm -rf /var/lib/apt/lists/*
|
|
73
|
+
|
|
74
|
+
# Upgrade npm to a version free of known HIGH/CRITICAL vulnerabilities
|
|
75
|
+
RUN npm install -g npm@11.0.0
|
|
76
|
+
|
|
77
|
+
WORKDIR /app
|
|
78
|
+
|
|
79
|
+
RUN npm init -y \\
|
|
80
|
+
&& npm install @aws/aws-distro-opentelemetry-node-autoinstrumentation@0.12.0 \\
|
|
81
|
+
&& npm uninstall -g npm
|
|
82
|
+
|
|
83
|
+
# Copy bundled agent
|
|
84
|
+
COPY index.js /app
|
|
85
|
+
|
|
86
|
+
EXPOSE 8080
|
|
87
|
+
|
|
88
|
+
CMD [ "node", "--require", "@aws/aws-distro-opentelemetry-node-autoinstrumentation/register", "index.js" ]
|
|
89
|
+
"
|
|
90
|
+
`;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { getProjects, joinPathFragments } from "@nx/devkit";
|
|
5
|
+
import { formatFilesInSubtree } from "../../../utils/format.js";
|
|
6
|
+
/**
|
|
7
|
+
* Apply the distribution's security updates in the vended agent / MCP server
|
|
8
|
+
* images.
|
|
9
|
+
*
|
|
10
|
+
* A base image tag lags behind its distribution's security suite, so the OS
|
|
11
|
+
* packages it ships carry vulnerabilities that already have a fixed version
|
|
12
|
+
* published — which the image scan flags as HIGH/CRITICAL. Upgrading them in the
|
|
13
|
+
* image build clears those findings whenever the scan runs, rather than waiting
|
|
14
|
+
* for the base image to be rebuilt. New workspaces get this from the generator
|
|
15
|
+
* templates; this brings existing ones up to date.
|
|
16
|
+
*
|
|
17
|
+
* Only the Dockerfiles of the components whose images the generators vend are
|
|
18
|
+
* touched, located from their project metadata. The Dockerfile is generated
|
|
19
|
+
* `KeepExisting`, so it is edited in place: the upgrade is inserted right after
|
|
20
|
+
* the `FROM` line, ahead of every other instruction, so later layers install
|
|
21
|
+
* against the upgraded packages. One that already runs `apt-get upgrade`, or
|
|
22
|
+
* which has been re-based onto an image `apt-get` can't upgrade, is left alone.
|
|
23
|
+
*/ /**
|
|
24
|
+
* The generators whose runtime images the vended Dockerfiles build. Hardcoded
|
|
25
|
+
* rather than imported from the generators: a migration matches the ids
|
|
26
|
+
* workspaces recorded at generation time, which must stay fixed even if the
|
|
27
|
+
* generators' current ids change later.
|
|
28
|
+
*/ const RUNTIME_IMAGE_GENERATOR_IDS = [
|
|
29
|
+
'py#agent',
|
|
30
|
+
'py#mcp-server',
|
|
31
|
+
'ts#agent',
|
|
32
|
+
'ts#mcp-server'
|
|
33
|
+
];
|
|
34
|
+
const APT_UPGRADE = `# Apply the distribution's security updates: base image tags lag behind the
|
|
35
|
+
# security suite, so its OS packages carry fixed HIGH/CRITICAL vulnerabilities
|
|
36
|
+
# flagged by the image scan.
|
|
37
|
+
RUN apt-get update && \\
|
|
38
|
+
apt-get upgrade -y --no-install-recommends && \\
|
|
39
|
+
rm -rf /var/lib/apt/lists/*`;
|
|
40
|
+
/** The apt command this migration adds; used to detect an applied fix. */ const APT_UPGRADE_COMMAND = 'apt-get upgrade';
|
|
41
|
+
/**
|
|
42
|
+
* The Debian-derived base images the generators vend, whose packages `apt-get`
|
|
43
|
+
* upgrades. A user who has re-based onto another image (Alpine, distroless,
|
|
44
|
+
* Amazon Linux) needs a different command, so theirs is left as they wrote it.
|
|
45
|
+
*/ const DEBIAN_BASE_IMAGE = /^FROM\s+\S*(?:node|python):\S*\n/m;
|
|
46
|
+
/**
|
|
47
|
+
* The Dockerfiles of every runtime image component, located from each project's
|
|
48
|
+
* recorded component metadata (`path` is the component directory relative to
|
|
49
|
+
* the project root).
|
|
50
|
+
*/ const runtimeImageDockerfiles = (tree)=>{
|
|
51
|
+
const paths = [];
|
|
52
|
+
for (const project of getProjects(tree).values()){
|
|
53
|
+
const components = project.metadata?.components ?? [];
|
|
54
|
+
for (const component of components){
|
|
55
|
+
if (!RUNTIME_IMAGE_GENERATOR_IDS.includes(component.generator) || !component.path) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const dockerfile = joinPathFragments(projectRoot(project), component.path, 'Dockerfile');
|
|
59
|
+
if (tree.exists(dockerfile)) {
|
|
60
|
+
paths.push(dockerfile);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return paths;
|
|
65
|
+
};
|
|
66
|
+
/** A project's root, falling back to sourceRoot for the TS-solution layout. */ const projectRoot = (project)=>project.root ?? project.sourceRoot ?? '';
|
|
67
|
+
export default async function migration(tree) {
|
|
68
|
+
for (const filePath of runtimeImageDockerfiles(tree)){
|
|
69
|
+
const content = tree.read(filePath, 'utf-8');
|
|
70
|
+
if (!content) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (content.includes(APT_UPGRADE_COMMAND)) {
|
|
74
|
+
continue; // Already upgrading (migrated or user-added).
|
|
75
|
+
}
|
|
76
|
+
const from = content.match(DEBIAN_BASE_IMAGE);
|
|
77
|
+
if (from?.index === undefined) {
|
|
78
|
+
continue; // The user has re-based the image; theirs to patch, not ours.
|
|
79
|
+
}
|
|
80
|
+
// Insert the upgrade after the FROM line, ahead of every other instruction
|
|
81
|
+
// so later layers install against the upgraded packages, with the spacing a
|
|
82
|
+
// freshly generated Dockerfile has.
|
|
83
|
+
const insertAt = from.index + from[0].length;
|
|
84
|
+
tree.write(filePath, `${content.slice(0, insertAt)}\n${APT_UPGRADE}\n${content.slice(insertAt)}`);
|
|
85
|
+
}
|
|
86
|
+
await formatFilesInSubtree(tree);
|
|
87
|
+
return {};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/apt-security-updates-in-container-images/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n joinPathFragments,\n type MigrationReturnObject,\n type ProjectConfiguration,\n type Tree,\n} from '@nx/devkit';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport type { ComponentMetadata } from '../../../utils/nx';\n\n/**\n * Apply the distribution's security updates in the vended agent / MCP server\n * images.\n *\n * A base image tag lags behind its distribution's security suite, so the OS\n * packages it ships carry vulnerabilities that already have a fixed version\n * published — which the image scan flags as HIGH/CRITICAL. Upgrading them in the\n * image build clears those findings whenever the scan runs, rather than waiting\n * for the base image to be rebuilt. New workspaces get this from the generator\n * templates; this brings existing ones up to date.\n *\n * Only the Dockerfiles of the components whose images the generators vend are\n * touched, located from their project metadata. The Dockerfile is generated\n * `KeepExisting`, so it is edited in place: the upgrade is inserted right after\n * the `FROM` line, ahead of every other instruction, so later layers install\n * against the upgraded packages. One that already runs `apt-get upgrade`, or\n * which has been re-based onto an image `apt-get` can't upgrade, is left alone.\n */\n\n/**\n * The generators whose runtime images the vended Dockerfiles build. Hardcoded\n * rather than imported from the generators: a migration matches the ids\n * workspaces recorded at generation time, which must stay fixed even if the\n * generators' current ids change later.\n */\nconst RUNTIME_IMAGE_GENERATOR_IDS = [\n 'py#agent',\n 'py#mcp-server',\n 'ts#agent',\n 'ts#mcp-server',\n];\n\nconst APT_UPGRADE = `# Apply the distribution's security updates: base image tags lag behind the\n# security suite, so its OS packages carry fixed HIGH/CRITICAL vulnerabilities\n# flagged by the image scan.\nRUN apt-get update && \\\\\n apt-get upgrade -y --no-install-recommends && \\\\\n rm -rf /var/lib/apt/lists/*`;\n\n/** The apt command this migration adds; used to detect an applied fix. */\nconst APT_UPGRADE_COMMAND = 'apt-get upgrade';\n\n/**\n * The Debian-derived base images the generators vend, whose packages `apt-get`\n * upgrades. A user who has re-based onto another image (Alpine, distroless,\n * Amazon Linux) needs a different command, so theirs is left as they wrote it.\n */\nconst DEBIAN_BASE_IMAGE = /^FROM\\s+\\S*(?:node|python):\\S*\\n/m;\n\n/**\n * The Dockerfiles of every runtime image component, located from each project's\n * recorded component metadata (`path` is the component directory relative to\n * the project root).\n */\nconst runtimeImageDockerfiles = (tree: Tree): string[] => {\n const paths: string[] = [];\n for (const project of getProjects(tree).values()) {\n const components = ((\n project.metadata as { components?: ComponentMetadata[] }\n )?.components ?? []) as ComponentMetadata[];\n for (const component of components) {\n if (\n !RUNTIME_IMAGE_GENERATOR_IDS.includes(component.generator) ||\n !component.path\n ) {\n continue;\n }\n const dockerfile = joinPathFragments(\n projectRoot(project),\n component.path,\n 'Dockerfile',\n );\n if (tree.exists(dockerfile)) {\n paths.push(dockerfile);\n }\n }\n }\n return paths;\n};\n\n/** A project's root, falling back to sourceRoot for the TS-solution layout. */\nconst projectRoot = (project: ProjectConfiguration): string =>\n project.root ?? project.sourceRoot ?? '';\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n for (const filePath of runtimeImageDockerfiles(tree)) {\n const content = tree.read(filePath, 'utf-8');\n if (!content) {\n continue;\n }\n if (content.includes(APT_UPGRADE_COMMAND)) {\n continue; // Already upgrading (migrated or user-added).\n }\n\n const from = content.match(DEBIAN_BASE_IMAGE);\n if (from?.index === undefined) {\n continue; // The user has re-based the image; theirs to patch, not ours.\n }\n\n // Insert the upgrade after the FROM line, ahead of every other instruction\n // so later layers install against the upgraded packages, with the spacing a\n // freshly generated Dockerfile has.\n const insertAt = from.index + from[0].length;\n tree.write(\n filePath,\n `${content.slice(0, insertAt)}\\n${APT_UPGRADE}\\n${content.slice(insertAt)}`,\n );\n }\n\n await formatFilesInSubtree(tree);\n\n return {};\n}\n"],"names":["getProjects","joinPathFragments","formatFilesInSubtree","RUNTIME_IMAGE_GENERATOR_IDS","APT_UPGRADE","APT_UPGRADE_COMMAND","DEBIAN_BASE_IMAGE","runtimeImageDockerfiles","tree","paths","project","values","components","metadata","component","includes","generator","path","dockerfile","projectRoot","exists","push","root","sourceRoot","migration","filePath","content","read","from","match","index","undefined","insertAt","length","write","slice"],"mappings":"AAAA;;;CAGC,GACD,SACEA,WAAW,EACXC,iBAAiB,QAIZ,aAAa;AACpB,SAASC,oBAAoB,QAAQ,2BAAwB;AAG7D;;;;;;;;;;;;;;;;;CAiBC,GAED;;;;;CAKC,GACD,MAAMC,8BAA8B;IAClC;IACA;IACA;IACA;CACD;AAED,MAAMC,cAAc,CAAC;;;;;+BAKU,CAAC;AAEhC,wEAAwE,GACxE,MAAMC,sBAAsB;AAE5B;;;;CAIC,GACD,MAAMC,oBAAoB;AAE1B;;;;CAIC,GACD,MAAMC,0BAA0B,CAACC;IAC/B,MAAMC,QAAkB,EAAE;IAC1B,KAAK,MAAMC,WAAWV,YAAYQ,MAAMG,MAAM,GAAI;QAChD,MAAMC,aAAc,AAClBF,QAAQG,QAAQ,EACfD,cAAc,EAAE;QACnB,KAAK,MAAME,aAAaF,WAAY;YAClC,IACE,CAACT,4BAA4BY,QAAQ,CAACD,UAAUE,SAAS,KACzD,CAACF,UAAUG,IAAI,EACf;gBACA;YACF;YACA,MAAMC,aAAajB,kBACjBkB,YAAYT,UACZI,UAAUG,IAAI,EACd;YAEF,IAAIT,KAAKY,MAAM,CAACF,aAAa;gBAC3BT,MAAMY,IAAI,CAACH;YACb;QACF;IACF;IACA,OAAOT;AACT;AAEA,6EAA6E,GAC7E,MAAMU,cAAc,CAACT,UACnBA,QAAQY,IAAI,IAAIZ,QAAQa,UAAU,IAAI;AAExC,eAAe,eAAeC,UAC5BhB,IAAU;IAEV,KAAK,MAAMiB,YAAYlB,wBAAwBC,MAAO;QACpD,MAAMkB,UAAUlB,KAAKmB,IAAI,CAACF,UAAU;QACpC,IAAI,CAACC,SAAS;YACZ;QACF;QACA,IAAIA,QAAQX,QAAQ,CAACV,sBAAsB;YACzC,UAAU,8CAA8C;QAC1D;QAEA,MAAMuB,OAAOF,QAAQG,KAAK,CAACvB;QAC3B,IAAIsB,MAAME,UAAUC,WAAW;YAC7B,UAAU,8DAA8D;QAC1E;QAEA,2EAA2E;QAC3E,4EAA4E;QAC5E,oCAAoC;QACpC,MAAMC,WAAWJ,KAAKE,KAAK,GAAGF,IAAI,CAAC,EAAE,CAACK,MAAM;QAC5CzB,KAAK0B,KAAK,CACRT,UACA,GAAGC,QAAQS,KAAK,CAAC,GAAGH,UAAU,EAAE,EAAE5B,YAAY,EAAE,EAAEsB,QAAQS,KAAK,CAACH,WAAW;IAE/E;IAEA,MAAM9B,qBAAqBM;IAE3B,OAAO,CAAC;AACV"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { readJson } from "@nx/devkit";
|
|
5
|
+
import { removeLicenseExceptions } from "../../../license/config.js";
|
|
6
|
+
import { registerPnpmBuiltDependencies } from "../../../utils/pnpm-workspace.js";
|
|
7
|
+
const INSPECTOR = '@modelcontextprotocol/inspector';
|
|
8
|
+
/**
|
|
9
|
+
* MCP Inspector v1 declared `SEE LICENSE IN LICENSE`, which resolves to no SPDX
|
|
10
|
+
* identifier, so the license check needed an exception per published package.
|
|
11
|
+
* v2 ships as a single package declaring `MIT`, which the allowlist already
|
|
12
|
+
* covers, and the stale exceptions would override that with `Apache-2.0`.
|
|
13
|
+
*/ const OBSOLETE_EXCEPTIONS = [
|
|
14
|
+
INSPECTOR,
|
|
15
|
+
`${INSPECTOR}-cli`,
|
|
16
|
+
`${INSPECTOR}-server`,
|
|
17
|
+
`${INSPECTOR}-client`
|
|
18
|
+
];
|
|
19
|
+
/** Whether the workspace root declares the inspector as a devDependency. */ const hasInspector = (tree)=>{
|
|
20
|
+
if (!tree.exists('package.json')) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
const packageJson = readJson(tree, 'package.json');
|
|
24
|
+
return Boolean(packageJson.devDependencies?.[INSPECTOR] ?? packageJson.dependencies?.[INSPECTOR]);
|
|
25
|
+
};
|
|
26
|
+
export default async function migration(tree) {
|
|
27
|
+
await removeLicenseExceptions(tree, OBSOLETE_EXCEPTIONS);
|
|
28
|
+
// The version sync bumps the inspector to v2, which added a postinstall
|
|
29
|
+
// script. Register it as an explicitly-rejected build so the upgrade's
|
|
30
|
+
// install isn't failed by pnpm 11's default `strictDepBuilds=true`.
|
|
31
|
+
if (hasInspector(tree)) {
|
|
32
|
+
registerPnpmBuiltDependencies(tree, {
|
|
33
|
+
[INSPECTOR]: false
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/latest/remove-mcp-inspector-license-exceptions/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { readJson, type Tree } from '@nx/devkit';\nimport { removeLicenseExceptions } from '../../../license/config';\nimport { registerPnpmBuiltDependencies } from '../../../utils/pnpm-workspace';\n\nconst INSPECTOR = '@modelcontextprotocol/inspector';\n\n/**\n * MCP Inspector v1 declared `SEE LICENSE IN LICENSE`, which resolves to no SPDX\n * identifier, so the license check needed an exception per published package.\n * v2 ships as a single package declaring `MIT`, which the allowlist already\n * covers, and the stale exceptions would override that with `Apache-2.0`.\n */\nconst OBSOLETE_EXCEPTIONS = [\n INSPECTOR,\n `${INSPECTOR}-cli`,\n `${INSPECTOR}-server`,\n `${INSPECTOR}-client`,\n];\n\n/** Whether the workspace root declares the inspector as a devDependency. */\nconst hasInspector = (tree: Tree): boolean => {\n if (!tree.exists('package.json')) {\n return false;\n }\n const packageJson = readJson(tree, 'package.json');\n return Boolean(\n packageJson.devDependencies?.[INSPECTOR] ??\n packageJson.dependencies?.[INSPECTOR],\n );\n};\n\nexport default async function migration(tree: Tree): Promise<void> {\n await removeLicenseExceptions(tree, OBSOLETE_EXCEPTIONS);\n\n // The version sync bumps the inspector to v2, which added a postinstall\n // script. Register it as an explicitly-rejected build so the upgrade's\n // install isn't failed by pnpm 11's default `strictDepBuilds=true`.\n if (hasInspector(tree)) {\n registerPnpmBuiltDependencies(tree, { [INSPECTOR]: false });\n }\n}\n"],"names":["readJson","removeLicenseExceptions","registerPnpmBuiltDependencies","INSPECTOR","OBSOLETE_EXCEPTIONS","hasInspector","tree","exists","packageJson","Boolean","devDependencies","dependencies","migration"],"mappings":"AAAA;;;CAGC,GACD,SAASA,QAAQ,QAAmB,aAAa;AACjD,SAASC,uBAAuB,QAAQ,6BAA0B;AAClE,SAASC,6BAA6B,QAAQ,mCAAgC;AAE9E,MAAMC,YAAY;AAElB;;;;;CAKC,GACD,MAAMC,sBAAsB;IAC1BD;IACA,GAAGA,UAAU,IAAI,CAAC;IAClB,GAAGA,UAAU,OAAO,CAAC;IACrB,GAAGA,UAAU,OAAO,CAAC;CACtB;AAED,0EAA0E,GAC1E,MAAME,eAAe,CAACC;IACpB,IAAI,CAACA,KAAKC,MAAM,CAAC,iBAAiB;QAChC,OAAO;IACT;IACA,MAAMC,cAAcR,SAASM,MAAM;IACnC,OAAOG,QACLD,YAAYE,eAAe,EAAE,CAACP,UAAU,IACtCK,YAAYG,YAAY,EAAE,CAACR,UAAU;AAE3C;AAEA,eAAe,eAAeS,UAAUN,IAAU;IAChD,MAAML,wBAAwBK,MAAMF;IAEpC,wEAAwE;IACxE,uEAAuE;IACvE,oEAAoE;IACpE,IAAIC,aAAaC,OAAO;QACtBJ,8BAA8BI,MAAM;YAAE,CAACH,UAAU,EAAE;QAAM;IAC3D;AACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/v1.0.0-rc.67/0001-smithy-server-package-rename/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n joinPathFragments,\n type MigrationReturnObject,\n readJson,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { applyGritQL, matchGritQL } from '../../../utils/ast';\nimport { formatFilesInSubtree } from '../../../utils/format';\n\n/**\n * Move a Smithy API onto the renamed `@smithy/server-*` packages.\n *\n * The Smithy server runtime was published as `@aws-smithy/server-*`, stopped at\n * `1.0.0-alpha.10`, and was renamed to `@smithy/server-*`. The Server SDK codegen\n * this release vends generates against the renamed packages, importing\n * `AuthScheme` and `ServerInterceptor` — types the deprecated packages never\n * exported — so a workspace left on them fails to bundle its SSDK.\n *\n * Both the imports and the declarations move: the renamed packages are no longer\n * the same names, so the version sync cannot recognise the old ones and would\n * leave them installed alongside the new.\n *\n * Guardrails:\n * - Scoped to a Smithy API project this plugin generated, found through the\n * metadata the generator records. A file of the user's own that happens to\n * import these packages is left alone.\n * - Imports are rewritten by module specifier, preserving whatever the file\n * imports from it, so a project that imports more than the generated shape\n * keeps its own bindings. Only the two packages the generators vend are\n * matched: `@aws-smithy/server-common` is a transitive dependency of those and\n * is never declared or imported directly.\n * - A manifest is only rewritten where it declares the old package, and the new\n * name takes the field the old one occupied. A workspace that already moved\n * itself is left alone.\n * - Idempotent: nothing matches the old names once they are gone.\n *\n * Every value here is hardcoded rather than read from the generators: this runs\n * once, for the release that renamed the packages, so it has to keep applying\n * that exact change however far the vended versions and generators move\n * afterwards.\n */\n\n/** The id the `ts#smithy-api` generator records on the projects it creates. */\nconst SMITHY_API_GENERATOR_ID = 'ts#smithy-api';\n\n/** The renamed packages, old name to new, with the version this release vends. */\nconst RENAMES = [\n {\n old: '@aws-smithy/server-apigateway',\n renamed: '@smithy/server-apigateway',\n version: '0.2.0',\n },\n {\n old: '@aws-smithy/server-node',\n renamed: '@smithy/server-node',\n version: '0.2.0',\n },\n] as const;\n\n/** The source files the generators give these imports. */\nconst SOURCE_FILES = ['src/handler.ts', 'src/local-server.ts'];\n\n/**\n * Rewrite an import's module specifier, keeping its bindings — `$bindings` holds\n * whatever the file imports, so a binding the project added survives the move.\n */\nconst importPattern = (from: string, to: string): string =>\n `\\`import { $bindings } from '${from}'\\` => \\`import { $bindings } from '${to}'\\``;\n\n/** Whether the file still imports the old package under any other form. */\nconst hasRemainingImport = (from: string): string =>\n `\\`import $_ from '${from}'\\``;\n\n/** Rename the packages a manifest declares, reporting whether anything changed. */\nconst renameInManifest = (tree: Tree, path: string): boolean => {\n if (!tree.exists(path)) {\n return false;\n }\n const json = readJson(tree, path);\n const fields = (['dependencies', 'devDependencies'] as const).filter(\n (field) => RENAMES.some(({ old }) => json[field]?.[old]),\n );\n if (fields.length === 0) {\n return false;\n }\n updateJson(tree, path, (manifest) => {\n for (const field of fields) {\n const declared = manifest[field] as Record<string, string>;\n for (const { old, renamed, version } of RENAMES) {\n if (!declared[old]) {\n continue;\n }\n delete declared[old];\n // The vended pin rather than the old specifier: the renamed line\n // restarted at 0.x, so carrying `1.0.0-alpha.10` across resolves nothing.\n declared[renamed] = version;\n }\n }\n return manifest;\n });\n return true;\n};\n\nconst divergedNextStep = (path: string): string =>\n `${path}: still imports a deprecated '@aws-smithy/server-*' package in a form this migration does not rewrite - update the import to the matching '@smithy/server-*' package by hand.`;\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n // Only a Smithy API project this plugin generated carries these packages.\n const projects = [...getProjects(tree).values()].filter(\n (project) =>\n (project.metadata as { generator?: string } | undefined)?.generator ===\n SMITHY_API_GENERATOR_ID,\n );\n\n for (const project of projects) {\n for (const sourceFile of SOURCE_FILES) {\n const sourcePath = joinPathFragments(project.root, sourceFile);\n if (!tree.exists(sourcePath)) {\n continue;\n }\n for (const { old, renamed } of RENAMES) {\n await applyGritQL(tree, sourcePath, importPattern(old, renamed));\n // A namespace or default import of the same package is left as it is —\n // reported rather than rewritten, so a diverged file is never clobbered.\n if (await matchGritQL(tree, sourcePath, hasRemainingImport(old))) {\n nextSteps.push(divergedNextStep(sourcePath));\n }\n }\n }\n\n renameInManifest(tree, joinPathFragments(project.root, 'package.json'));\n }\n\n // A workspace may hoist these to the root manifest, which is not an nx project.\n if (projects.length > 0) {\n renameInManifest(tree, 'package.json');\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["getProjects","joinPathFragments","readJson","updateJson","applyGritQL","matchGritQL","formatFilesInSubtree","SMITHY_API_GENERATOR_ID","RENAMES","old","renamed","version","SOURCE_FILES","importPattern","from","to","hasRemainingImport","renameInManifest","tree","path","exists","json","fields","filter","field","some","length","manifest","declared","divergedNextStep","migration","nextSteps","projects","values","project","metadata","generator","sourceFile","sourcePath","root","push"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/v1.0.0-rc.68/0001-translate-script-whole-file-writes/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport {\n getProjects,\n joinPathFragments,\n type MigrationReturnObject,\n type Tree,\n} from '@nx/devkit';\nimport { TS_ASTRO_DOCS_GENERATOR_INFO } from '../../../ts/astro-docs/generator';\nimport { insertViaGritQL, matchGritQL } from '../../../utils/ast';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { isEsmWorkspace } from '../../../utils/module-format';\nimport { getPackageManagerDisplayCommands } from '../../../utils/pkg-manager';\n\n/**\n * Rewrite the docs translate script so it writes whole translated files.\n *\n * The script used to tell the agent to update an existing translation with\n * `str_replace` edits. A replacement that did not match cleanly duplicated or\n * spliced sections, and nothing checked the result, so the damage was committed.\n * The rewrite also fixes incremental runs, which never matched a changed file in\n * a generated workspace, and raises the Bedrock socket timeout that made every\n * large file fail.\n *\n * Most of the script changed, so it is rewritten a declaration at a time. Each\n * pattern in `grit/` matches one declaration as a previous release wrote it and\n * rewrites it to a placeholder, which `insertViaGritQL` swaps for today's version\n * from `files/`. Routing the replacement through a placeholder keeps it out of the\n * pattern: the script is full of template literals, and a GritQL snippet\n * containing a backtick cannot be parsed.\n *\n * Each pattern recognises its declaration by name *and* by statements the released\n * body contained, so a declaration the user has edited no longer matches. The\n * rewrite is all or nothing — every pattern must match before anything is written\n * — so an edited script keeps its whole file and is reported through `nextSteps`\n * rather than being half-rewritten from two different versions.\n */\n\n/**\n * The declarations that changed, in the order they appear in the script. Each name\n * pairs a `grit/<name>.grit` pattern matching its previous form with a\n * `files/<name>.ts.fixture` holding its replacement, which carries any new\n * declarations that follow it.\n *\n * `grit/already-migrated.grit` stands apart: it recognises today's script rather\n * than rewriting anything.\n */\nconst REWRITES = [\n 'project-root',\n 'config-path',\n 'file-to-translate',\n 'log',\n 'get-files-to-translate',\n 'build-system-prompt',\n 'build-user-prompt',\n 'translate-file-for-language',\n 'run-with-concurrency',\n 'main',\n 'main-call',\n] as const;\n\n/** A leading block comment, which GritQL does not match. */\nconst HEADER_COMMENT = /^\\/\\*\\*[\\s\\S]*?\\*\\/\\n/;\n\nconst readGritPattern = (name: string): string =>\n `language js\\n${readFileSync(join(import.meta.dirname, 'grit', `${name}.grit`), 'utf-8').trim()}`;\n\nconst readReplacement = (name: string): string =>\n readFileSync(\n join(import.meta.dirname, 'files', `${name}.ts.fixture`),\n 'utf-8',\n );\n\n/** Fills in the values the generator interpolates when it vends the script. */\nconst render = (\n tree: Tree,\n source: string,\n fullyQualifiedName: string,\n): string =>\n source\n .replace(\n /<% if \\(esm\\) \\{ %>(.*?)<% \\} else \\{ %>(.*?)<% \\} %>/g,\n isEsmWorkspace(tree) ? '$1' : '$2',\n )\n .replace(/<%= pkgMgrCmd %>/g, getPackageManagerDisplayCommands().exec)\n .replace(/<%= fullyQualifiedName %>/g, fullyQualifiedName);\n\nconst editedNextStep = (projectName: string): string =>\n `${projectName}: its scripts/translate.ts has been customised, so it was left as it is. The script now writes each translation as a whole file rather than editing it in place — see https://awslabs.github.io/nx-plugin-for-aws/guides/astro-docs/ for the version it expects.`;\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n for (const [name, project] of getProjects(tree)) {\n const metadata = project.metadata as { generator?: string } | undefined;\n if (metadata?.generator !== TS_ASTRO_DOCS_GENERATOR_INFO.id) {\n continue;\n }\n\n // Absent when the docs site was generated with --noTranslation.\n const scriptPath = joinPathFragments(\n project.root,\n 'scripts',\n 'translate.ts',\n );\n if (!tree.exists(scriptPath)) {\n continue;\n }\n\n // Already migrated: matched by a declaration only today's script has, so a\n // second run is a no-op rather than a rewrite.\n if (\n await matchGritQL(tree, scriptPath, readGritPattern('already-migrated'))\n ) {\n continue;\n }\n\n // All or nothing: every declaration must still be the one a release vended,\n // so a partly edited script is never left half-rewritten.\n const matches = await Promise.all(\n REWRITES.map((rewrite) =>\n matchGritQL(tree, scriptPath, readGritPattern(rewrite)),\n ),\n );\n if (!matches.every(Boolean)) {\n nextSteps.push(editedNextStep(name));\n continue;\n }\n\n // The header is a leading comment, which GritQL does not reach. Anchored to\n // the start of the file so the replacement cannot match anything else.\n tree.write(\n scriptPath,\n (tree.read(scriptPath, 'utf-8') ?? '').replace(\n HEADER_COMMENT,\n render(tree, readReplacement('header'), name),\n ),\n );\n\n // The first release resolved paths from `__dirname` directly, with no\n // `SCRIPTS_DIR` for the rewrites below to build on.\n const script = tree.read(scriptPath, 'utf-8') ?? '';\n if (!/^const SCRIPTS_DIR /m.test(script)) {\n tree.write(\n scriptPath,\n script.replace(\n /^const PROJECT_ROOT /m,\n `${render(tree, readReplacement('scripts-dir'), name).trimEnd()}\\nconst PROJECT_ROOT `,\n ),\n );\n }\n\n for (const rewrite of REWRITES) {\n await insertViaGritQL(\n tree,\n scriptPath,\n readGritPattern(rewrite),\n render(tree, readReplacement(rewrite), name).trimEnd(),\n );\n }\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["readFileSync","join","getProjects","joinPathFragments","TS_ASTRO_DOCS_GENERATOR_INFO","insertViaGritQL","matchGritQL","formatFilesInSubtree","isEsmWorkspace","getPackageManagerDisplayCommands","REWRITES","HEADER_COMMENT","readGritPattern","name","dirname","trim","readReplacement","render","tree","source","fullyQualifiedName","replace","exec","editedNextStep","projectName","migration","nextSteps","project","metadata","generator","id","scriptPath","root","exists","matches","Promise","all","map","rewrite","every","Boolean","push","write","read","script","test","trimEnd"],"mappings":"AAAA;;;CAGC,GACD,SAASA,YAAY,QAAQ,UAAU;AACvC,SAASC,IAAI,QAAQ,YAAY;AACjC,SACEC,WAAW,EACXC,iBAAiB,QAGZ,aAAa;AACpB,SAASC,4BAA4B,QAAQ,sCAAmC;AAChF,SAASC,eAAe,EAAEC,WAAW,QAAQ,wBAAqB;AAClE,SAASC,oBAAoB,QAAQ,2BAAwB;AAC7D,SAASC,cAAc,QAAQ,kCAA+B;AAC9D,SAASC,gCAAgC,QAAQ,gCAA6B;AAE9E;;;;;;;;;;;;;;;;;;;;;;CAsBC,GAED;;;;;;;;CAQC,GACD,MAAMC,WAAW;IACf;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD;AAED,0DAA0D,GAC1D,MAAMC,iBAAiB;AAEvB,MAAMC,kBAAkB,CAACC,OACvB,CAAC,aAAa,EAAEb,aAAaC,KAAK,YAAYa,OAAO,EAAE,QAAQ,GAAGD,KAAK,KAAK,CAAC,GAAG,SAASE,IAAI,IAAI;AAEnG,MAAMC,kBAAkB,CAACH,OACvBb,aACEC,KAAK,YAAYa,OAAO,EAAE,SAAS,GAAGD,KAAK,WAAW,CAAC,GACvD;AAGJ,6EAA6E,GAC7E,MAAMI,SAAS,CACbC,MACAC,QACAC,qBAEAD,OACGE,OAAO,CACN,0DACAb,eAAeU,QAAQ,OAAO,MAE/BG,OAAO,CAAC,qBAAqBZ,mCAAmCa,IAAI,EACpED,OAAO,CAAC,8BAA8BD;AAE3C,MAAMG,iBAAiB,CAACC,cACtB,GAAGA,YAAY,gQAAgQ,CAAC;AAElR,eAAe,eAAeC,UAC5BP,IAAU;IAEV,MAAMQ,YAAsB,EAAE;IAE9B,KAAK,MAAM,CAACb,MAAMc,QAAQ,IAAIzB,YAAYgB,MAAO;QAC/C,MAAMU,WAAWD,QAAQC,QAAQ;QACjC,IAAIA,UAAUC,cAAczB,6BAA6B0B,EAAE,EAAE;YAC3D;QACF;QAEA,gEAAgE;QAChE,MAAMC,aAAa5B,kBACjBwB,QAAQK,IAAI,EACZ,WACA;QAEF,IAAI,CAACd,KAAKe,MAAM,CAACF,aAAa;YAC5B;QACF;QAEA,2EAA2E;QAC3E,+CAA+C;QAC/C,IACE,MAAMzB,YAAYY,MAAMa,YAAYnB,gBAAgB,sBACpD;YACA;QACF;QAEA,4EAA4E;QAC5E,0DAA0D;QAC1D,MAAMsB,UAAU,MAAMC,QAAQC,GAAG,CAC/B1B,SAAS2B,GAAG,CAAC,CAACC,UACZhC,YAAYY,MAAMa,YAAYnB,gBAAgB0B;QAGlD,IAAI,CAACJ,QAAQK,KAAK,CAACC,UAAU;YAC3Bd,UAAUe,IAAI,CAAClB,eAAeV;YAC9B;QACF;QAEA,4EAA4E;QAC5E,uEAAuE;QACvEK,KAAKwB,KAAK,CACRX,YACA,AAACb,CAAAA,KAAKyB,IAAI,CAACZ,YAAY,YAAY,EAAC,EAAGV,OAAO,CAC5CV,gBACAM,OAAOC,MAAMF,gBAAgB,WAAWH;QAI5C,sEAAsE;QACtE,oDAAoD;QACpD,MAAM+B,SAAS1B,KAAKyB,IAAI,CAACZ,YAAY,YAAY;QACjD,IAAI,CAAC,uBAAuBc,IAAI,CAACD,SAAS;YACxC1B,KAAKwB,KAAK,CACRX,YACAa,OAAOvB,OAAO,CACZ,yBACA,GAAGJ,OAAOC,MAAMF,gBAAgB,gBAAgBH,MAAMiC,OAAO,GAAG,qBAAqB,CAAC;QAG5F;QAEA,KAAK,MAAMR,WAAW5B,SAAU;YAC9B,MAAML,gBACJa,MACAa,YACAnB,gBAAgB0B,UAChBrB,OAAOC,MAAMF,gBAAgBsB,UAAUzB,MAAMiC,OAAO;QAExD;IACF;IAEA,MAAMvC,qBAAqBW;IAE3B,OAAO;QAAEQ;IAAU;AACrB"}
|
|
@@ -168,13 +168,25 @@ const migrateLangchainA2AAgent = async (tree, mainPath, nextSteps)=>{
|
|
|
168
168
|
// --- Iterator -> Generator (with_session_id_strands.py / session_context.py) ---
|
|
169
169
|
const WITH_SESSION_ID_IMPORT_OLD = 'from collections.abc import Callable, Iterator';
|
|
170
170
|
const WITH_SESSION_ID_IMPORT_NEW = 'from collections.abc import Callable, Generator';
|
|
171
|
+
/**
|
|
172
|
+
* Whether every `Iterator` reference in the file is one this migration is about
|
|
173
|
+
* to convert, so dropping the import cannot leave an undefined name behind. A
|
|
174
|
+
* user's own `Iterator[...]` annotation elsewhere in the file is not rewritten
|
|
175
|
+
* (the rewrite targets one exact annotation), so removing the import would leave
|
|
176
|
+
* the module raising `NameError` on import.
|
|
177
|
+
*/ const onlyIteratorUseIs = (contents, annotation)=>{
|
|
178
|
+
const withoutImport = contents.replace(/^from collections\.abc import .*$/m, '');
|
|
179
|
+
const uses = withoutImport.match(/\bIterator\b/g) ?? [];
|
|
180
|
+
const converted = withoutImport.match(new RegExp(annotation.replace(/[[\]]/g, '\\$&'), 'g'));
|
|
181
|
+
return uses.length === (converted?.length ?? 0);
|
|
182
|
+
};
|
|
171
183
|
const migrateWithSessionId = async (tree, filePath, nextSteps)=>{
|
|
172
184
|
const contents = tree.read(filePath, 'utf-8') ?? '';
|
|
173
185
|
if (!contents.includes('Iterator[Any]')) return;
|
|
174
186
|
const ready = await allMatch(tree, filePath, [
|
|
175
187
|
pyMatch(WITH_SESSION_ID_IMPORT_OLD),
|
|
176
188
|
pyMatch('Iterator[Any]')
|
|
177
|
-
]);
|
|
189
|
+
]) && onlyIteratorUseIs(contents, 'Iterator[Any]');
|
|
178
190
|
if (!ready) {
|
|
179
191
|
nextSteps.push(`${filePath}: diverged from the generated shape - left untouched. Manually change the \`Iterator\` import and \`Iterator[Any]\` return annotation on \`with_session_id\` to \`Generator\`/\`Generator[Any]\` (see the agent-connection generator's with_session_id_strands.py template).`);
|
|
180
192
|
return;
|
|
@@ -190,7 +202,7 @@ const migrateSessionContext = async (tree, filePath, nextSteps)=>{
|
|
|
190
202
|
const ready = await allMatch(tree, filePath, [
|
|
191
203
|
pyMatch(SESSION_CONTEXT_IMPORT_OLD),
|
|
192
204
|
pyMatch('Iterator[None]')
|
|
193
|
-
]);
|
|
205
|
+
]) && onlyIteratorUseIs(contents, 'Iterator[None]');
|
|
194
206
|
if (!ready) {
|
|
195
207
|
nextSteps.push(`${filePath}: diverged from the generated shape - left untouched. Manually change the \`Iterator\` import and \`Iterator[None]\` return annotation on \`session_id_context\` to \`Generator\`/\`Generator[None]\` (see the agent-connection generator's session_context.py template).`);
|
|
196
208
|
return;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/v1.0.0-rc.70/0001-py-agent-a2a-lifespan-construction/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n getProjects,\n joinPathFragments,\n type MigrationReturnObject,\n type Tree,\n visitNotIgnoredFiles,\n} from '@nx/devkit';\nimport { PY_AGENT_GENERATOR_INFO } from '../../../py/agent/generator';\nimport {\n addPythonDestructuredImport,\n applyGritQL,\n captureGritQLVariable,\n matchGritQL,\n} from '../../../utils/ast';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport type { ComponentMetadata } from '../../../utils/nx';\n\n/**\n * Move py#agent A2A agent construction (Strands and LangChain) out of module\n * import time and into a FastAPI `lifespan` handler, stored on `app.state`.\n *\n * The `v1.0.0-rc.61/0001-py-agent-lifespan-construction` migration (HTTP/AG-UI)\n * deliberately left A2A alone, reasoning that `with_session_id` only touches\n * its agent factory lazily on first use, so the eager `_agent_ctx.__enter__()`\n * was never actually eager in practice. That held for `with_session_id`'s own\n * laziness, but missed a separate trigger: `strands.multiagent.a2a.executor\n * .StrandsA2AExecutor.__init__`, in its deprecated single-`agent=` mode, does\n * `getattr(agent, \"_session_manager\", None)` - which the session-routing\n * proxy's `__getattr__` happily serves by building the real underlying Agent\n * right then, under a bogus \"default\" session, since no request has bound a\n * real session id yet. That call happens inside `A2AServer.__init__`, which\n * the old template constructed at plain module import time - so the \"lazy\"\n * proxy was forced eager anyway, just one layer further down than the\n * previous migration checked.\n *\n * Strands: `agent_factory=` mode sidesteps this - `StrandsA2AExecutor` takes\n * an entirely different branch when given a factory (no `_session_manager`\n * probe at all), and the one placeholder call `A2AServer.__init__` makes\n * before `lifespan` has run returns a bare `SimpleNamespace` with just\n * `name`/`description` - no `__getattr__`, nothing to force construction.\n *\n * LangChain: the compiled graph from `get_agent()` has no such trap, but was\n * still built eagerly at import time (`_graph = get_agent()`). Moved into\n * `lifespan` for the same reason HTTP/AG-UI were: it can require env vars\n * (model id, region) or do network setup that isn't guaranteed available at\n * import - e.g. under test collection or OpenAPI spec generation tooling.\n *\n * Also folds in an unrelated but adjacent fix: Pylance (Pyright) deprecates\n * annotating a `@contextmanager`-decorated function's return type as\n * `Iterator[T]`, in favor of the single-argument `Generator[T]` form enabled\n * by PEP 696 default type parameters (Python 3.13+ - generated projects\n * target >=3.14). `with_session_id_strands.py` and `session_context.py` both\n * use this pattern. Both files are shared, protocol-agnostic files copied\n * once per workspace (not per py#agent component), so that part scans the\n * whole tree by basename rather than going through component metadata.\n */\nconst pyMatch = (snippet: string) => `language python\\n\\`${snippet}\\``;\n\nconst pyDelete = (snippet: string) => `${pyMatch(snippet)} => .`;\n\nconst pyRewrite = (from: string, to: string): string => {\n const replacement = to.includes('\\n') ? `raw\\`${to}\\`` : `\\`${to}\\``;\n return `${pyMatch(from)} => ${replacement}`;\n};\n\nconst AGENT_ENTER = '_agent = _agent_ctx.__enter__()';\n\nconst OLD_AGENT_CONTEXT = `_agent_ctx = with_session_id(\n get_agent,\n name=\"$name\",\n description=\"A Strands Agent exposed via the Agent-to-Agent (A2A) protocol.\",\n)`;\n\nconst NEW_CONSTANTS_AND_LIFESPAN = `AGENT_NAME = \"$name\"\nAGENT_DESCRIPTION = \"A Strands Agent exposed via the Agent-to-Agent (A2A) protocol.\"\n\n# A2AServer.__init__ calls agent_factory once, synchronously, before the lifespan\n# below has run - this is what it reads name/description from at that point.\n# The cast is a lie about runtime shape, not behavior: only .name/.description\n# are ever read off this value.\n_card_placeholder = cast(\n Agent, SimpleNamespace(name=AGENT_NAME, description=AGENT_DESCRIPTION)\n)\n\n\n@asynccontextmanager\nasync def lifespan(app: FastAPI):\n with with_session_id(\n get_agent,\n name=AGENT_NAME,\n description=AGENT_DESCRIPTION,\n ) as agent:\n app.state.agent = agent\n yield`;\n\nconst A2A_SERVER_STATEMENT = 'a2a_server = A2AServer($args)';\n\nconst OLD_MOUNT_STATEMENT = 'app.mount(\"/\", a2a_server.to_fastapi_app())';\n\nconst OLD_FASTAPI_APP = 'app = FastAPI()';\n\nconst NEW_FASTAPI_APP = 'app = FastAPI(lifespan=lifespan)';\n\nconst SERVER_MATCH =\n 'language python\\n`A2AServer($args)` where { $args <: contains `agent=_agent` }';\n\nconst allMatch = async (\n tree: Tree,\n filePath: string,\n patterns: string[],\n): Promise<boolean> => {\n for (const pattern of patterns) {\n if (!(await matchGritQL(tree, filePath, pattern))) return false;\n }\n return true;\n};\n\nconst migrateStrandsA2AAgent = async (\n tree: Tree,\n mainPath: string,\n nextSteps: string[],\n): Promise<void> => {\n if (!tree.exists(mainPath)) return;\n\n const contents = tree.read(mainPath, 'utf-8') ?? '';\n if (!contents.includes('_agent_ctx = with_session_id(')) return;\n\n const ready = await allMatch(tree, mainPath, [\n pyMatch('import logging'),\n pyMatch('from $mod import session_id_context, with_session_id'),\n pyMatch(OLD_AGENT_CONTEXT),\n pyMatch(AGENT_ENTER),\n pyMatch(OLD_FASTAPI_APP),\n pyMatch(OLD_MOUNT_STATEMENT),\n SERVER_MATCH,\n ]);\n\n const diverged = () => {\n nextSteps.push(\n `${mainPath}: diverged from the generated Strands A2A shape - left untouched. Manually rebuild the agent inside the FastAPI \\`lifespan\\` and have \\`agent_factory\\` read it off \\`app.state\\` (see the py#agent generator's strands/a2a template).`,\n );\n };\n\n if (!ready) {\n diverged();\n return;\n }\n\n await addPythonDestructuredImport(\n tree,\n mainPath,\n ['asynccontextmanager'],\n 'contextlib',\n );\n await addPythonDestructuredImport(\n tree,\n mainPath,\n ['SimpleNamespace'],\n 'types',\n );\n await addPythonDestructuredImport(tree, mainPath, ['cast'], 'typing');\n await addPythonDestructuredImport(tree, mainPath, ['Agent'], 'strands');\n await applyGritQL(\n tree,\n mainPath,\n pyRewrite(OLD_AGENT_CONTEXT, NEW_CONSTANTS_AND_LIFESPAN),\n );\n await applyGritQL(tree, mainPath, pyDelete(AGENT_ENTER));\n\n // Swap the kwarg while the call is still in its original spot (any extra\n // kwargs a user added are left alone), then capture the whole arg list so\n // it can be reinserted at the call's new home below.\n await applyGritQL(\n tree,\n mainPath,\n pyRewrite(\n 'agent=_agent',\n 'agent_factory=lambda _context_id: getattr(app.state, \"agent\", _card_placeholder)',\n ),\n );\n const capturedArgs = await captureGritQLVariable(\n tree,\n mainPath,\n `language python\\n\\`${A2A_SERVER_STATEMENT}\\``,\n 'args',\n );\n if (capturedArgs === undefined) {\n diverged();\n return;\n }\n\n await applyGritQL(tree, mainPath, pyDelete(A2A_SERVER_STATEMENT));\n await applyGritQL(\n tree,\n mainPath,\n pyRewrite(OLD_FASTAPI_APP, NEW_FASTAPI_APP),\n );\n await applyGritQL(\n tree,\n mainPath,\n pyRewrite(\n OLD_MOUNT_STATEMENT,\n `a2a_server = A2AServer(${capturedArgs})\\n\\n${OLD_MOUNT_STATEMENT}`,\n ),\n );\n};\n\n// --- LangChain A2A -----------------------------------------------------------\n\nconst LANGCHAIN_GRAPH_OLD = '_graph = get_agent()';\n\nconst LANGCHAIN_LIFESPAN_NEW = `@asynccontextmanager\nasync def lifespan(app: FastAPI):\n app.state.agent = get_agent()\n yield`;\n\nconst LANGCHAIN_GRAPH_INVOKE_OLD = '_graph.ainvoke($args)';\n\nconst LANGCHAIN_GRAPH_INVOKE_NEW = 'app.state.agent.ainvoke($args)';\n\nconst LANGCHAIN_APP_OLD = 'app = FastAPI(title=\"$name\")';\n\nconst LANGCHAIN_APP_NEW = 'app = FastAPI(title=\"$name\", lifespan=lifespan)';\n\nconst migrateLangchainA2AAgent = async (\n tree: Tree,\n mainPath: string,\n nextSteps: string[],\n): Promise<void> => {\n if (!tree.exists(mainPath)) return;\n\n const contents = tree.read(mainPath, 'utf-8') ?? '';\n if (!contents.includes(LANGCHAIN_GRAPH_OLD)) return;\n\n const ready = await allMatch(tree, mainPath, [\n pyMatch(LANGCHAIN_GRAPH_OLD),\n pyMatch('from .agent import get_agent'),\n pyMatch(LANGCHAIN_GRAPH_INVOKE_OLD),\n pyMatch(LANGCHAIN_APP_OLD),\n ]);\n\n if (!ready) {\n nextSteps.push(\n `${mainPath}: diverged from the generated LangChain A2A shape - left untouched. Manually wrap \\`get_agent()\\` in a \\`lifespan\\` handler storing the graph on \\`app.state.agent\\` (see the py#agent generator's langchain/a2a template).`,\n );\n return;\n }\n\n await addPythonDestructuredImport(\n tree,\n mainPath,\n ['asynccontextmanager'],\n 'contextlib',\n );\n await applyGritQL(\n tree,\n mainPath,\n pyRewrite(LANGCHAIN_GRAPH_OLD, LANGCHAIN_LIFESPAN_NEW),\n );\n await applyGritQL(\n tree,\n mainPath,\n pyRewrite(LANGCHAIN_GRAPH_INVOKE_OLD, LANGCHAIN_GRAPH_INVOKE_NEW),\n );\n await applyGritQL(\n tree,\n mainPath,\n pyRewrite(LANGCHAIN_APP_OLD, LANGCHAIN_APP_NEW),\n );\n};\n\n// --- Iterator -> Generator (with_session_id_strands.py / session_context.py) ---\n\nconst WITH_SESSION_ID_IMPORT_OLD =\n 'from collections.abc import Callable, Iterator';\nconst WITH_SESSION_ID_IMPORT_NEW =\n 'from collections.abc import Callable, Generator';\n\n/**\n * Whether every `Iterator` reference in the file is one this migration is about\n * to convert, so dropping the import cannot leave an undefined name behind. A\n * user's own `Iterator[...]` annotation elsewhere in the file is not rewritten\n * (the rewrite targets one exact annotation), so removing the import would leave\n * the module raising `NameError` on import.\n */\nconst onlyIteratorUseIs = (contents: string, annotation: string): boolean => {\n const withoutImport = contents.replace(\n /^from collections\\.abc import .*$/m,\n '',\n );\n const uses = withoutImport.match(/\\bIterator\\b/g) ?? [];\n const converted = withoutImport.match(\n new RegExp(annotation.replace(/[[\\]]/g, '\\\\$&'), 'g'),\n );\n return uses.length === (converted?.length ?? 0);\n};\n\nconst migrateWithSessionId = async (\n tree: Tree,\n filePath: string,\n nextSteps: string[],\n): Promise<void> => {\n const contents = tree.read(filePath, 'utf-8') ?? '';\n if (!contents.includes('Iterator[Any]')) return;\n\n const ready =\n (await allMatch(tree, filePath, [\n pyMatch(WITH_SESSION_ID_IMPORT_OLD),\n pyMatch('Iterator[Any]'),\n ])) && onlyIteratorUseIs(contents, 'Iterator[Any]');\n\n if (!ready) {\n nextSteps.push(\n `${filePath}: diverged from the generated shape - left untouched. Manually change the \\`Iterator\\` import and \\`Iterator[Any]\\` return annotation on \\`with_session_id\\` to \\`Generator\\`/\\`Generator[Any]\\` (see the agent-connection generator's with_session_id_strands.py template).`,\n );\n return;\n }\n\n await applyGritQL(\n tree,\n filePath,\n pyRewrite(WITH_SESSION_ID_IMPORT_OLD, WITH_SESSION_ID_IMPORT_NEW),\n );\n await applyGritQL(\n tree,\n filePath,\n pyRewrite('Iterator[Any]', 'Generator[Any]'),\n );\n};\n\nconst SESSION_CONTEXT_IMPORT_OLD = 'from collections.abc import Iterator';\nconst SESSION_CONTEXT_IMPORT_NEW = 'from collections.abc import Generator';\n\nconst migrateSessionContext = async (\n tree: Tree,\n filePath: string,\n nextSteps: string[],\n): Promise<void> => {\n const contents = tree.read(filePath, 'utf-8') ?? '';\n if (!contents.includes('Iterator[None]')) return;\n\n const ready =\n (await allMatch(tree, filePath, [\n pyMatch(SESSION_CONTEXT_IMPORT_OLD),\n pyMatch('Iterator[None]'),\n ])) && onlyIteratorUseIs(contents, 'Iterator[None]');\n\n if (!ready) {\n nextSteps.push(\n `${filePath}: diverged from the generated shape - left untouched. Manually change the \\`Iterator\\` import and \\`Iterator[None]\\` return annotation on \\`session_id_context\\` to \\`Generator\\`/\\`Generator[None]\\` (see the agent-connection generator's session_context.py template).`,\n );\n return;\n }\n\n await applyGritQL(\n tree,\n filePath,\n pyRewrite(SESSION_CONTEXT_IMPORT_OLD, SESSION_CONTEXT_IMPORT_NEW),\n );\n await applyGritQL(\n tree,\n filePath,\n pyRewrite('Iterator[None]', 'Generator[None]'),\n );\n};\n\nconst findAgentComponents = (\n components: ComponentMetadata[] | undefined,\n): ComponentMetadata[] =>\n (components ?? []).filter(\n (component) => component.generator === PY_AGENT_GENERATOR_INFO.id,\n );\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n for (const project of getProjects(tree).values()) {\n const components = findAgentComponents(\n (project.metadata as { components?: ComponentMetadata[] })?.components,\n );\n\n for (const component of components) {\n if (!component.path || component.protocol !== 'a2a') {\n continue;\n }\n\n const componentDir = component.path.endsWith('/agent.py')\n ? component.path.slice(0, -'/agent.py'.length)\n : component.path;\n const mainPath = joinPathFragments(project.root, componentDir, 'main.py');\n\n if ((component.framework ?? 'strands') === 'langchain') {\n await migrateLangchainA2AAgent(tree, mainPath, nextSteps);\n } else {\n await migrateStrandsA2AAgent(tree, mainPath, nextSteps);\n }\n }\n }\n\n const filePaths: string[] = [];\n visitNotIgnoredFiles(tree, '', (filePath) => filePaths.push(filePath));\n\n for (const filePath of filePaths) {\n if (filePath.endsWith('/with_session_id_strands.py')) {\n await migrateWithSessionId(tree, filePath, nextSteps);\n } else if (filePath.endsWith('/session_context.py')) {\n await migrateSessionContext(tree, filePath, nextSteps);\n }\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["getProjects","joinPathFragments","visitNotIgnoredFiles","PY_AGENT_GENERATOR_INFO","addPythonDestructuredImport","applyGritQL","captureGritQLVariable","matchGritQL","formatFilesInSubtree","pyMatch","snippet","pyDelete","pyRewrite","from","to","replacement","includes","AGENT_ENTER","OLD_AGENT_CONTEXT","NEW_CONSTANTS_AND_LIFESPAN","A2A_SERVER_STATEMENT","OLD_MOUNT_STATEMENT","OLD_FASTAPI_APP","NEW_FASTAPI_APP","SERVER_MATCH","allMatch","tree","filePath","patterns","pattern","migrateStrandsA2AAgent","mainPath","nextSteps","exists","contents","read","ready","diverged","push","capturedArgs","undefined","LANGCHAIN_GRAPH_OLD","LANGCHAIN_LIFESPAN_NEW","LANGCHAIN_GRAPH_INVOKE_OLD","LANGCHAIN_GRAPH_INVOKE_NEW","LANGCHAIN_APP_OLD","LANGCHAIN_APP_NEW","migrateLangchainA2AAgent","WITH_SESSION_ID_IMPORT_OLD","WITH_SESSION_ID_IMPORT_NEW","onlyIteratorUseIs","annotation","withoutImport","replace","uses","match","converted","RegExp","length","migrateWithSessionId","SESSION_CONTEXT_IMPORT_OLD","SESSION_CONTEXT_IMPORT_NEW","migrateSessionContext","findAgentComponents","components","filter","component","generator","id","migration","project","values","metadata","path","protocol","componentDir","endsWith","slice","root","framework","filePaths"],"mappings":"AAAA;;;CAGC,GACD,SACEA,WAAW,EACXC,iBAAiB,EAGjBC,oBAAoB,QACf,aAAa;AACpB,SAASC,uBAAuB,QAAQ,iCAA8B;AACtE,SACEC,2BAA2B,EAC3BC,WAAW,EACXC,qBAAqB,EACrBC,WAAW,QACN,wBAAqB;AAC5B,SAASC,oBAAoB,QAAQ,2BAAwB;AAG7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCC,GACD,MAAMC,UAAU,CAACC,UAAoB,CAAC,mBAAmB,EAAEA,QAAQ,EAAE,CAAC;AAEtE,MAAMC,WAAW,CAACD,UAAoB,GAAGD,QAAQC,SAAS,KAAK,CAAC;AAEhE,MAAME,YAAY,CAACC,MAAcC;IAC/B,MAAMC,cAAcD,GAAGE,QAAQ,CAAC,QAAQ,CAAC,KAAK,EAAEF,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,EAAEA,GAAG,EAAE,CAAC;IACpE,OAAO,GAAGL,QAAQI,MAAM,IAAI,EAAEE,aAAa;AAC7C;AAEA,MAAME,cAAc;AAEpB,MAAMC,oBAAoB,CAAC;;;;CAI1B,CAAC;AAEF,MAAMC,6BAA6B,CAAC;;;;;;;;;;;;;;;;;;;;aAoBvB,CAAC;AAEd,MAAMC,uBAAuB;AAE7B,MAAMC,sBAAsB;AAE5B,MAAMC,kBAAkB;AAExB,MAAMC,kBAAkB;AAExB,MAAMC,eACJ;AAEF,MAAMC,WAAW,OACfC,MACAC,UACAC;IAEA,KAAK,MAAMC,WAAWD,SAAU;QAC9B,IAAI,CAAE,MAAMrB,YAAYmB,MAAMC,UAAUE,UAAW,OAAO;IAC5D;IACA,OAAO;AACT;AAEA,MAAMC,yBAAyB,OAC7BJ,MACAK,UACAC;IAEA,IAAI,CAACN,KAAKO,MAAM,CAACF,WAAW;IAE5B,MAAMG,WAAWR,KAAKS,IAAI,CAACJ,UAAU,YAAY;IACjD,IAAI,CAACG,SAASlB,QAAQ,CAAC,kCAAkC;IAEzD,MAAMoB,QAAQ,MAAMX,SAASC,MAAMK,UAAU;QAC3CtB,QAAQ;QACRA,QAAQ;QACRA,QAAQS;QACRT,QAAQQ;QACRR,QAAQa;QACRb,QAAQY;QACRG;KACD;IAED,MAAMa,WAAW;QACfL,UAAUM,IAAI,CACZ,GAAGP,SAAS,sOAAsO,CAAC;IAEvP;IAEA,IAAI,CAACK,OAAO;QACVC;QACA;IACF;IAEA,MAAMjC,4BACJsB,MACAK,UACA;QAAC;KAAsB,EACvB;IAEF,MAAM3B,4BACJsB,MACAK,UACA;QAAC;KAAkB,EACnB;IAEF,MAAM3B,4BAA4BsB,MAAMK,UAAU;QAAC;KAAO,EAAE;IAC5D,MAAM3B,4BAA4BsB,MAAMK,UAAU;QAAC;KAAQ,EAAE;IAC7D,MAAM1B,YACJqB,MACAK,UACAnB,UAAUM,mBAAmBC;IAE/B,MAAMd,YAAYqB,MAAMK,UAAUpB,SAASM;IAE3C,yEAAyE;IACzE,0EAA0E;IAC1E,qDAAqD;IACrD,MAAMZ,YACJqB,MACAK,UACAnB,UACE,gBACA;IAGJ,MAAM2B,eAAe,MAAMjC,sBACzBoB,MACAK,UACA,CAAC,mBAAmB,EAAEX,qBAAqB,EAAE,CAAC,EAC9C;IAEF,IAAImB,iBAAiBC,WAAW;QAC9BH;QACA;IACF;IAEA,MAAMhC,YAAYqB,MAAMK,UAAUpB,SAASS;IAC3C,MAAMf,YACJqB,MACAK,UACAnB,UAAUU,iBAAiBC;IAE7B,MAAMlB,YACJqB,MACAK,UACAnB,UACES,qBACA,CAAC,uBAAuB,EAAEkB,aAAa,KAAK,EAAElB,qBAAqB;AAGzE;AAEA,gFAAgF;AAEhF,MAAMoB,sBAAsB;AAE5B,MAAMC,yBAAyB,CAAC;;;SAGvB,CAAC;AAEV,MAAMC,6BAA6B;AAEnC,MAAMC,6BAA6B;AAEnC,MAAMC,oBAAoB;AAE1B,MAAMC,oBAAoB;AAE1B,MAAMC,2BAA2B,OAC/BrB,MACAK,UACAC;IAEA,IAAI,CAACN,KAAKO,MAAM,CAACF,WAAW;IAE5B,MAAMG,WAAWR,KAAKS,IAAI,CAACJ,UAAU,YAAY;IACjD,IAAI,CAACG,SAASlB,QAAQ,CAACyB,sBAAsB;IAE7C,MAAML,QAAQ,MAAMX,SAASC,MAAMK,UAAU;QAC3CtB,QAAQgC;QACRhC,QAAQ;QACRA,QAAQkC;QACRlC,QAAQoC;KACT;IAED,IAAI,CAACT,OAAO;QACVJ,UAAUM,IAAI,CACZ,GAAGP,SAAS,2NAA2N,CAAC;QAE1O;IACF;IAEA,MAAM3B,4BACJsB,MACAK,UACA;QAAC;KAAsB,EACvB;IAEF,MAAM1B,YACJqB,MACAK,UACAnB,UAAU6B,qBAAqBC;IAEjC,MAAMrC,YACJqB,MACAK,UACAnB,UAAU+B,4BAA4BC;IAExC,MAAMvC,YACJqB,MACAK,UACAnB,UAAUiC,mBAAmBC;AAEjC;AAEA,kFAAkF;AAElF,MAAME,6BACJ;AACF,MAAMC,6BACJ;AAEF;;;;;;CAMC,GACD,MAAMC,oBAAoB,CAAChB,UAAkBiB;IAC3C,MAAMC,gBAAgBlB,SAASmB,OAAO,CACpC,sCACA;IAEF,MAAMC,OAAOF,cAAcG,KAAK,CAAC,oBAAoB,EAAE;IACvD,MAAMC,YAAYJ,cAAcG,KAAK,CACnC,IAAIE,OAAON,WAAWE,OAAO,CAAC,UAAU,SAAS;IAEnD,OAAOC,KAAKI,MAAM,KAAMF,CAAAA,WAAWE,UAAU,CAAA;AAC/C;AAEA,MAAMC,uBAAuB,OAC3BjC,MACAC,UACAK;IAEA,MAAME,WAAWR,KAAKS,IAAI,CAACR,UAAU,YAAY;IACjD,IAAI,CAACO,SAASlB,QAAQ,CAAC,kBAAkB;IAEzC,MAAMoB,QACJ,AAAC,MAAMX,SAASC,MAAMC,UAAU;QAC9BlB,QAAQuC;QACRvC,QAAQ;KACT,KAAMyC,kBAAkBhB,UAAU;IAErC,IAAI,CAACE,OAAO;QACVJ,UAAUM,IAAI,CACZ,GAAGX,SAAS,4QAA4Q,CAAC;QAE3R;IACF;IAEA,MAAMtB,YACJqB,MACAC,UACAf,UAAUoC,4BAA4BC;IAExC,MAAM5C,YACJqB,MACAC,UACAf,UAAU,iBAAiB;AAE/B;AAEA,MAAMgD,6BAA6B;AACnC,MAAMC,6BAA6B;AAEnC,MAAMC,wBAAwB,OAC5BpC,MACAC,UACAK;IAEA,MAAME,WAAWR,KAAKS,IAAI,CAACR,UAAU,YAAY;IACjD,IAAI,CAACO,SAASlB,QAAQ,CAAC,mBAAmB;IAE1C,MAAMoB,QACJ,AAAC,MAAMX,SAASC,MAAMC,UAAU;QAC9BlB,QAAQmD;QACRnD,QAAQ;KACT,KAAMyC,kBAAkBhB,UAAU;IAErC,IAAI,CAACE,OAAO;QACVJ,UAAUM,IAAI,CACZ,GAAGX,SAAS,yQAAyQ,CAAC;QAExR;IACF;IAEA,MAAMtB,YACJqB,MACAC,UACAf,UAAUgD,4BAA4BC;IAExC,MAAMxD,YACJqB,MACAC,UACAf,UAAU,kBAAkB;AAEhC;AAEA,MAAMmD,sBAAsB,CAC1BC,aAEA,AAACA,CAAAA,cAAc,EAAE,AAAD,EAAGC,MAAM,CACvB,CAACC,YAAcA,UAAUC,SAAS,KAAKhE,wBAAwBiE,EAAE;AAGrE,eAAe,eAAeC,UAC5B3C,IAAU;IAEV,MAAMM,YAAsB,EAAE;IAE9B,KAAK,MAAMsC,WAAWtE,YAAY0B,MAAM6C,MAAM,GAAI;QAChD,MAAMP,aAAaD,oBAChBO,QAAQE,QAAQ,EAA2CR;QAG9D,KAAK,MAAME,aAAaF,WAAY;YAClC,IAAI,CAACE,UAAUO,IAAI,IAAIP,UAAUQ,QAAQ,KAAK,OAAO;gBACnD;YACF;YAEA,MAAMC,eAAeT,UAAUO,IAAI,CAACG,QAAQ,CAAC,eACzCV,UAAUO,IAAI,CAACI,KAAK,CAAC,GAAG,CAAC,YAAYnB,MAAM,IAC3CQ,UAAUO,IAAI;YAClB,MAAM1C,WAAW9B,kBAAkBqE,QAAQQ,IAAI,EAAEH,cAAc;YAE/D,IAAI,AAACT,CAAAA,UAAUa,SAAS,IAAI,SAAQ,MAAO,aAAa;gBACtD,MAAMhC,yBAAyBrB,MAAMK,UAAUC;YACjD,OAAO;gBACL,MAAMF,uBAAuBJ,MAAMK,UAAUC;YAC/C;QACF;IACF;IAEA,MAAMgD,YAAsB,EAAE;IAC9B9E,qBAAqBwB,MAAM,IAAI,CAACC,WAAaqD,UAAU1C,IAAI,CAACX;IAE5D,KAAK,MAAMA,YAAYqD,UAAW;QAChC,IAAIrD,SAASiD,QAAQ,CAAC,gCAAgC;YACpD,MAAMjB,qBAAqBjC,MAAMC,UAAUK;QAC7C,OAAO,IAAIL,SAASiD,QAAQ,CAAC,wBAAwB;YACnD,MAAMd,sBAAsBpC,MAAMC,UAAUK;QAC9C;IACF;IAEA,MAAMxB,qBAAqBkB;IAE3B,OAAO;QAAEM;IAAU;AACrB"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { type MigrationReturnObject, type Tree } from '@nx/devkit';
|
|
6
|
+
export default function migration(tree: Tree): Promise<MigrationReturnObject>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/migrations/v1.0.0-rc.71/0001-py-agent-a2a-httpx-client-per-call/migration.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n type MigrationReturnObject,\n type Tree,\n visitNotIgnoredFiles,\n} from '@nx/devkit';\nimport { applyGritQL, matchGritQL } from '../../../utils/ast';\nimport { formatFilesInSubtree } from '../../../utils/format';\n\n/**\n * Rebuild the `httpx.AsyncClient` (and, for Strands, the `A2AAgent`) fresh on\n * every A2A delegate call, instead of reusing the one built once at factory\n * time - fixes a reproducible `RuntimeError: Event loop is closed` on the\n * second call through a shared client.\n *\n * Both frameworks' A2A clients call out through a synchronous wrapper\n * (`_run_sync`) that runs the async call via `asyncio.run(...)` - a brand new\n * event loop per call, closed when the call returns. `AgentCoreA2aClientConfig`\n * builds one `httpx.AsyncClient` a single time, at factory call time, and that\n * client's connection pool binds to whichever event loop first touches it. So\n * call #1 creates a loop, uses the shared client, closes the loop; call #2\n * creates a *new* loop, but the shared client's pool is still bound to the\n * old, now-closed one.\n *\n * Strands hits the same failure one layer down: `A2AAgent.__call__` is itself\n * synchronous and does its own `asyncio.run(...)` per call internally, while\n * reusing the same factory-built `httpx.AsyncClient` via `client_config`.\n *\n * The fix in both `AgentCoreA2aClientLangChain`/`AgentCoreA2aClientStrands` is\n * to stop handing out a client wired to one long-lived `httpx.AsyncClient`.\n * Instead each call opens a fresh `httpx.AsyncClient` (reusing only the\n * `auth`/`timeout` off the once-built shared config) scoped to that call via\n * `async with`, so its connection pool lives and dies with the same loop that\n * created it. For Strands this also means `AgentCoreA2aClientStrands`'s\n * factories no longer return a raw `A2AAgent` (dropped in favour of a private\n * `_A2AClient` built per call), so the per-target `<Agent>ClientStrands.create`\n * wrapper's `-> A2AAgent` return annotation and its now-unused `A2AAgent`\n * import go stale too.\n */\nconst pyMatch = (snippet: string) => `language python\\n\\`${snippet}\\``;\n\nconst pyRewrite = (from: string, to: string): string => {\n const replacement = to.includes('\\n') ? `raw\\`${to}\\`` : `\\`${to}\\``;\n return `${pyMatch(from)} => ${replacement}`;\n};\n\nconst allMatch = async (\n tree: Tree,\n filePath: string,\n patterns: string[],\n): Promise<boolean> => {\n for (const pattern of patterns) {\n if (!(await matchGritQL(tree, filePath, pattern))) return false;\n }\n return true;\n};\n\n// --- agentcore_a2a_client_langchain.py (framework-agnostic core, shared) ---\n\nconst LANGCHAIN_IMPORT_OLD =\n 'from a2a.client import A2ACardResolver, ClientConfig, ClientFactory';\nconst LANGCHAIN_IMPORT_NEW = `import httpx\nfrom a2a.client import A2ACardResolver, ClientConfig, ClientFactory`;\n\nconst LANGCHAIN_INVOKE_OLD = ` async def _invoke(self, prompt: str) -> str:\n # AgentCoreA2aClientConfig always sets the signed httpx client.\n httpx_client = self._config.httpx_client\n if httpx_client is None:\n raise RuntimeError(\"A2A client config is missing an httpx client\")\n card = await A2ACardResolver(\n httpx_client=httpx_client, base_url=self._url\n ).get_agent_card()\n client = ClientFactory(self._config).create(card)\n message = Message(\n kind=\"message\",\n role=Role.user,\n message_id=uuid4().hex,\n parts=[Part(TextPart(kind=\"text\", text=prompt))],\n )\n # The client config uses streaming=False, so the last event carries the\n # complete response.\n reply = \"\"\n async for event in client.send_message(message):\n text = _text(event)\n if text:\n reply = text\n return reply`;\n\nconst LANGCHAIN_INVOKE_NEW = `async def _invoke(self, prompt: str) -> str:\n # AgentCoreA2aClientConfig always sets the signed httpx client.\n shared_client = self._config.httpx_client\n if shared_client is None:\n raise RuntimeError(\"A2A client config is missing an httpx client\")\n async with httpx.AsyncClient(\n auth=shared_client.auth, timeout=shared_client.timeout\n ) as httpx_client:\n card = await A2ACardResolver(\n httpx_client=httpx_client, base_url=self._url\n ).get_agent_card()\n client = ClientFactory(\n ClientConfig(httpx_client=httpx_client, streaming=False)\n ).create(card)\n message = Message(\n kind=\"message\",\n role=Role.user,\n message_id=uuid4().hex,\n parts=[Part(TextPart(kind=\"text\", text=prompt))],\n )\n # The client config uses streaming=False, so the last event carries\n # the complete response.\n reply = \"\"\n async for event in client.send_message(message):\n text = _text(event)\n if text:\n reply = text\n return reply`;\n\nconst migrateLangchainCoreClient = async (\n tree: Tree,\n filePath: string,\n nextSteps: string[],\n): Promise<void> => {\n const contents = tree.read(filePath, 'utf-8') ?? '';\n if (!contents.includes('client = ClientFactory(self._config).create(card)'))\n return;\n\n const ready = await allMatch(tree, filePath, [\n pyMatch(LANGCHAIN_IMPORT_OLD),\n pyMatch(LANGCHAIN_INVOKE_OLD),\n ]);\n\n if (!ready) {\n nextSteps.push(\n `${filePath}: diverged from the generated shape - left untouched. Manually rebuild a fresh httpx.AsyncClient per call in _invoke instead of reusing the one built at factory time (see the agent-connection generator's agentcore_a2a_client_langchain.py template).`,\n );\n return;\n }\n\n await applyGritQL(\n tree,\n filePath,\n pyRewrite(LANGCHAIN_IMPORT_OLD, LANGCHAIN_IMPORT_NEW),\n );\n await applyGritQL(\n tree,\n filePath,\n pyRewrite(LANGCHAIN_INVOKE_OLD, LANGCHAIN_INVOKE_NEW),\n );\n};\n\n// --- agentcore_a2a_client_strands.py (Strands core client) ------------------\n\nconst STRANDS_IMPORT1_OLD = 'from collections.abc import Callable';\nconst STRANDS_IMPORT1_NEW = `import asyncio\nfrom collections.abc import Callable\nfrom concurrent.futures import ThreadPoolExecutor`;\n\nconst STRANDS_IMPORT2_OLD = 'from strands.agent.a2a_agent import A2AAgent';\nconst STRANDS_IMPORT2_NEW = `import httpx\nfrom a2a.client import ClientConfig\nfrom strands.agent.a2a_agent import A2AAgent\nfrom strands.agent.agent_result import AgentResult`;\n\nconst STRANDS_BUILD_OLD = `def _build(\n config: tuple, *, name: str | None, description: str | None\n) -> A2AAgent:\n url, client_config = config\n kwargs: dict = {\"endpoint\": url, \"client_config\": client_config}\n if name:\n kwargs[\"name\"] = name\n if description:\n kwargs[\"description\"] = description\n return A2AAgent(**kwargs)`;\n\nconst STRANDS_BUILD_NEW = `def _run_sync(coro):\n # The tool is invoked from sync agent code, which under uvicorn runs inside a\n # live event loop where asyncio.run() would raise — fall back to a worker.\n try:\n asyncio.get_running_loop()\n except RuntimeError:\n return asyncio.run(coro)\n with ThreadPoolExecutor(max_workers=1) as pool:\n return pool.submit(asyncio.run, coro).result()\n\n\nclass _A2AClient:\n def __init__(\n self,\n url: str,\n client_config: ClientConfig,\n *,\n name: str | None,\n description: str | None,\n ):\n shared_client = client_config.httpx_client\n if shared_client is None:\n raise RuntimeError(\"A2A client config is missing an httpx client\")\n self._url = url\n self._auth = shared_client.auth\n self._timeout = shared_client.timeout\n self._name = name\n self._description = description\n\n def __call__(self, prompt: str) -> AgentResult:\n return _run_sync(self._invoke(prompt))\n\n async def _invoke(self, prompt: str) -> AgentResult:\n async with httpx.AsyncClient(\n auth=self._auth, timeout=self._timeout\n ) as httpx_client:\n agent = A2AAgent(\n endpoint=self._url,\n name=self._name,\n description=self._description,\n client_config=ClientConfig(httpx_client=httpx_client, streaming=False),\n )\n return await agent.invoke_async(prompt)\n\n\ndef _build(\n config: tuple, *, name: str | None, description: str | None\n) -> _A2AClient:\n url, client_config = config\n return _A2AClient(url, client_config, name=name, description=description)`;\n\nconst STRANDS_IAM_OLD = ` @staticmethod\n def with_iam_auth(\n agent_runtime_arn: str,\n *,\n name: str | None = None,\n description: str | None = None,\n ) -> A2AAgent:\n \"\"\"SigV4-authenticated client for a Bedrock AgentCore runtime.\"\"\"\n return _build(\n AgentCoreA2aClientConfig.with_iam_auth(agent_runtime_arn),\n name=name,\n description=description,\n )`;\n\nconst STRANDS_IAM_NEW = `@staticmethod\ndef with_iam_auth(\n agent_runtime_arn: str,\n *,\n name: str | None = None,\n description: str | None = None,\n) -> _A2AClient:\n \"\"\"SigV4-authenticated client for a Bedrock AgentCore runtime.\"\"\"\n return _build(\n AgentCoreA2aClientConfig.with_iam_auth(agent_runtime_arn),\n name=name,\n description=description,\n )`;\n\nconst STRANDS_JWT_OLD = ` @staticmethod\n def with_jwt_auth(\n agent_runtime_arn: str,\n access_token_provider: Callable[[], str],\n *,\n name: str | None = None,\n description: str | None = None,\n ) -> A2AAgent:\n \"\"\"Bearer-authenticated client for a Bedrock AgentCore runtime.\"\"\"\n return _build(\n AgentCoreA2aClientConfig.with_jwt_auth(\n agent_runtime_arn, access_token_provider\n ),\n name=name,\n description=description,\n )`;\n\nconst STRANDS_JWT_NEW = `@staticmethod\ndef with_jwt_auth(\n agent_runtime_arn: str,\n access_token_provider: Callable[[], str],\n *,\n name: str | None = None,\n description: str | None = None,\n) -> _A2AClient:\n \"\"\"Bearer-authenticated client for a Bedrock AgentCore runtime.\"\"\"\n return _build(\n AgentCoreA2aClientConfig.with_jwt_auth(\n agent_runtime_arn, access_token_provider\n ),\n name=name,\n description=description,\n )`;\n\nconst STRANDS_NOAUTH_OLD = ` @staticmethod\n def without_auth(\n url: str,\n *,\n name: str | None = None,\n description: str | None = None,\n ) -> A2AAgent:\n \"\"\"Plain-HTTP client — for local dev.\"\"\"\n return _build(\n AgentCoreA2aClientConfig.without_auth(url),\n name=name,\n description=description,\n )`;\n\nconst STRANDS_NOAUTH_NEW = `@staticmethod\ndef without_auth(\n url: str,\n *,\n name: str | None = None,\n description: str | None = None,\n) -> _A2AClient:\n \"\"\"Plain-HTTP client — for local dev.\"\"\"\n return _build(\n AgentCoreA2aClientConfig.without_auth(url),\n name=name,\n description=description,\n )`;\n\nconst migrateStrandsCoreClient = async (\n tree: Tree,\n filePath: string,\n nextSteps: string[],\n): Promise<void> => {\n const contents = tree.read(filePath, 'utf-8') ?? '';\n if (!contents.includes('return A2AAgent(**kwargs)')) return;\n\n const ready = await allMatch(tree, filePath, [\n pyMatch(STRANDS_IMPORT1_OLD),\n pyMatch(STRANDS_IMPORT2_OLD),\n pyMatch(STRANDS_BUILD_OLD),\n pyMatch(STRANDS_IAM_OLD),\n pyMatch(STRANDS_JWT_OLD),\n pyMatch(STRANDS_NOAUTH_OLD),\n ]);\n\n if (!ready) {\n nextSteps.push(\n `${filePath}: diverged from the generated shape - left untouched. Manually rebuild a fresh httpx.AsyncClient (and A2AAgent) per call instead of reusing the ones built at factory time (see the agent-connection generator's agentcore_a2a_client_strands.py template).`,\n );\n return;\n }\n\n await applyGritQL(\n tree,\n filePath,\n pyRewrite(STRANDS_IMPORT1_OLD, STRANDS_IMPORT1_NEW),\n );\n await applyGritQL(\n tree,\n filePath,\n pyRewrite(STRANDS_IMPORT2_OLD, STRANDS_IMPORT2_NEW),\n );\n await applyGritQL(\n tree,\n filePath,\n pyRewrite(STRANDS_BUILD_OLD, STRANDS_BUILD_NEW),\n );\n await applyGritQL(\n tree,\n filePath,\n pyRewrite(STRANDS_IAM_OLD, STRANDS_IAM_NEW),\n );\n await applyGritQL(\n tree,\n filePath,\n pyRewrite(STRANDS_JWT_OLD, STRANDS_JWT_NEW),\n );\n await applyGritQL(\n tree,\n filePath,\n pyRewrite(STRANDS_NOAUTH_OLD, STRANDS_NOAUTH_NEW),\n );\n};\n\n// --- <target>_client_strands.py (per-target wrapper, one per connection) ---\n\nconst WRAPPER_IMPORT_OLD = 'from strands.agent.a2a_agent import A2AAgent';\n\nconst WRAPPER_CREATE_OLD = 'def create() -> A2AAgent:\\n $body';\nconst WRAPPER_CREATE_NEW = 'def create():\\n $body';\n\nconst migrateStrandsWrapperClient = async (\n tree: Tree,\n filePath: string,\n nextSteps: string[],\n): Promise<void> => {\n const contents = tree.read(filePath, 'utf-8') ?? '';\n if (!contents.includes('def create() -> A2AAgent:')) return;\n\n const ready = await allMatch(tree, filePath, [\n pyMatch(WRAPPER_IMPORT_OLD),\n pyMatch(WRAPPER_CREATE_OLD),\n ]);\n\n if (!ready) {\n nextSteps.push(\n `${filePath}: diverged from the generated shape - left untouched. Manually drop the A2AAgent import and its -> A2AAgent return annotation on create() (see the py#agent#a2a-connection generator's per-target client_strands.py template).`,\n );\n return;\n }\n\n await applyGritQL(tree, filePath, `${pyMatch(WRAPPER_IMPORT_OLD)} => .`);\n await applyGritQL(\n tree,\n filePath,\n pyRewrite(WRAPPER_CREATE_OLD, WRAPPER_CREATE_NEW),\n );\n};\n\nexport default async function migration(\n tree: Tree,\n): Promise<MigrationReturnObject> {\n const nextSteps: string[] = [];\n\n const filePaths: string[] = [];\n visitNotIgnoredFiles(tree, '', (filePath) => filePaths.push(filePath));\n\n for (const filePath of filePaths) {\n if (filePath.endsWith('/agentcore_a2a_client_langchain.py')) {\n await migrateLangchainCoreClient(tree, filePath, nextSteps);\n } else if (filePath.endsWith('/agentcore_a2a_client_strands.py')) {\n await migrateStrandsCoreClient(tree, filePath, nextSteps);\n } else if (filePath.endsWith('_client_strands.py')) {\n await migrateStrandsWrapperClient(tree, filePath, nextSteps);\n }\n }\n\n await formatFilesInSubtree(tree);\n\n return { nextSteps };\n}\n"],"names":["visitNotIgnoredFiles","applyGritQL","matchGritQL","formatFilesInSubtree","pyMatch","snippet","pyRewrite","from","to","replacement","includes","allMatch","tree","filePath","patterns","pattern","LANGCHAIN_IMPORT_OLD","LANGCHAIN_IMPORT_NEW","LANGCHAIN_INVOKE_OLD","LANGCHAIN_INVOKE_NEW","migrateLangchainCoreClient","nextSteps","contents","read","ready","push","STRANDS_IMPORT1_OLD","STRANDS_IMPORT1_NEW","STRANDS_IMPORT2_OLD","STRANDS_IMPORT2_NEW","STRANDS_BUILD_OLD","STRANDS_BUILD_NEW","STRANDS_IAM_OLD","STRANDS_IAM_NEW","STRANDS_JWT_OLD","STRANDS_JWT_NEW","STRANDS_NOAUTH_OLD","STRANDS_NOAUTH_NEW","migrateStrandsCoreClient","WRAPPER_IMPORT_OLD","WRAPPER_CREATE_OLD","WRAPPER_CREATE_NEW","migrateStrandsWrapperClient","migration","filePaths","endsWith"],"mappings":"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"}
|