@aws/nx-plugin 1.0.0 → 1.0.2

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.
Files changed (124) hide show
  1. package/LICENSE-THIRD-PARTY +11686 -23398
  2. package/README.md +18 -0
  3. package/generators.json +7 -0
  4. package/migrations.json +39 -1
  5. package/package.json +6 -6
  6. package/src/agentcore-gateway/agent-connection/generator.js +6 -0
  7. package/src/agentcore-gateway/agent-connection/generator.js.map +1 -1
  8. package/src/agentcore-gateway/schema.json +1 -0
  9. package/src/agentcore-harness/generator.d.ts +1 -1
  10. package/src/connection/scaffold-catalog.d.ts +21 -0
  11. package/src/connection/scaffold-catalog.js +14 -6
  12. package/src/connection/scaffold-catalog.js.map +1 -1
  13. package/src/infra/app/generator.d.ts +1 -1
  14. package/src/init/generator.d.ts +1 -1
  15. package/src/mcp-server/guide-pipeline.d.ts +2 -1
  16. package/src/mcp-server/guide-pipeline.js +6 -0
  17. package/src/mcp-server/guide-pipeline.js.map +1 -1
  18. package/src/mcp-server/mdx-ast.d.ts +7 -0
  19. package/src/mcp-server/mdx-ast.js +15 -0
  20. package/src/mcp-server/mdx-ast.js.map +1 -1
  21. package/src/mcp-server/schema-registry.d.ts +2 -2
  22. package/src/mcp-server/schema-registry.js +2 -2
  23. package/src/mcp-server/schema-registry.js.map +1 -1
  24. package/src/migrations/latest/terraform-harness-environment-variables/metadata.json +3 -0
  25. package/src/migrations/latest/terraform-harness-environment-variables/migration.d.ts +6 -0
  26. package/src/migrations/latest/terraform-harness-environment-variables/migration.js +54 -0
  27. package/src/migrations/latest/terraform-harness-environment-variables/migration.js.map +1 -0
  28. package/src/open-api/py-client/__snapshots__/generator.additional-properties.spec.ts.snap +34 -0
  29. package/src/open-api/py-client/__snapshots__/generator.arrays.spec.ts.snap +1750 -0
  30. package/src/open-api/py-client/__snapshots__/generator.complex-types.spec.ts.snap +82 -0
  31. package/src/open-api/py-client/__snapshots__/generator.composite-types.spec.ts.snap +447 -0
  32. package/src/open-api/py-client/__snapshots__/generator.duplicate-types.spec.ts.snap +404 -0
  33. package/src/open-api/py-client/__snapshots__/generator.errors.spec.ts.snap +430 -0
  34. package/src/open-api/py-client/__snapshots__/generator.fast-api.spec.ts.snap +447 -0
  35. package/src/open-api/py-client/__snapshots__/generator.petstore.spec.ts.snap +3488 -0
  36. package/src/open-api/py-client/__snapshots__/generator.primitive-types.spec.ts.snap +1444 -0
  37. package/src/open-api/py-client/__snapshots__/generator.request.spec.ts.snap +390 -0
  38. package/src/open-api/py-client/__snapshots__/generator.reserved-keywords.spec.ts.snap +364 -0
  39. package/src/open-api/py-client/__snapshots__/generator.response.spec.ts.snap +739 -0
  40. package/src/open-api/py-client/__snapshots__/generator.streaming.spec.ts.snap +384 -0
  41. package/src/open-api/py-client/__snapshots__/generator.tags.spec.ts.snap +414 -0
  42. package/src/open-api/py-client/files/client/__clientModuleName__.py.template +1076 -0
  43. package/src/open-api/py-client/files/shared/__init__.py.template +28 -0
  44. package/src/open-api/py-client/files/shared/errors.py.template +37 -0
  45. package/src/open-api/py-client/files/shared/types.py.template +319 -0
  46. package/src/open-api/py-client/generator.d.ts +53 -0
  47. package/src/open-api/py-client/generator.js +119 -0
  48. package/src/open-api/py-client/generator.js.map +1 -0
  49. package/src/open-api/py-client/schema.d.js +6 -0
  50. package/src/open-api/py-client/schema.d.js.map +1 -0
  51. package/src/open-api/py-client/schema.d.ts +12 -0
  52. package/src/open-api/py-client/schema.json +28 -0
  53. package/src/open-api/py-client/vessel-registry-spec.json +2716 -0
  54. package/src/open-api/ts-client/__snapshots__/generator.edge-cases.spec.ts.snap +274 -0
  55. package/src/open-api/ts-client/petstore-spec.d.ts +6 -0
  56. package/src/open-api/ts-client/petstore-spec.js +1275 -0
  57. package/src/open-api/ts-client/petstore-spec.js.map +1 -0
  58. package/src/open-api/ts-hooks/generator.spec.tsx +1 -1
  59. package/src/open-api/utils/codegen-data/languages.d.ts +68 -2
  60. package/src/open-api/utils/codegen-data/languages.js +433 -21
  61. package/src/open-api/utils/codegen-data/languages.js.map +1 -1
  62. package/src/open-api/utils/codegen-data/types.d.ts +187 -0
  63. package/src/open-api/utils/codegen-data/types.js +10 -1
  64. package/src/open-api/utils/codegen-data/types.js.map +1 -1
  65. package/src/open-api/utils/codegen-data.d.ts +40 -1
  66. package/src/open-api/utils/codegen-data.js +622 -17
  67. package/src/open-api/utils/codegen-data.js.map +1 -1
  68. package/src/open-api/utils/normalise.js +175 -41
  69. package/src/open-api/utils/normalise.js.map +1 -1
  70. package/src/open-api/utils/parser.js +1 -1
  71. package/src/open-api/utils/parser.js.map +1 -1
  72. package/src/preset/__snapshots__/generator.spec.ts.snap +3 -3
  73. package/src/preset/generator.d.ts +1 -1
  74. package/src/py/agent/gateway-connection/generator.js +0 -3
  75. package/src/py/agent/gateway-connection/generator.js.map +1 -1
  76. package/src/py/agent/react-connection/generator.d.ts +1 -1
  77. package/src/py/agent/schema.json +2 -0
  78. package/src/py/fast-api/react/generator.d.ts +1 -1
  79. package/src/py/mcp-server/schema.json +1 -0
  80. package/src/sdk/open-api.d.ts +2 -0
  81. package/src/sdk/open-api.js +1 -0
  82. package/src/sdk/open-api.js.map +1 -1
  83. package/src/smithy/project/generator.d.ts +1 -1
  84. package/src/smithy/react-connection/generator.d.ts +1 -1
  85. package/src/terraform/project/generator.d.ts +1 -1
  86. package/src/trpc/react/generator.d.ts +1 -1
  87. package/src/ts/agent/a2a-connection/generator.d.ts +1 -1
  88. package/src/ts/agent/gateway-connection/generator.d.ts +1 -1
  89. package/src/ts/agent/gateway-connection/generator.js +0 -3
  90. package/src/ts/agent/gateway-connection/generator.js.map +1 -1
  91. package/src/ts/agent/mcp-connection/generator.d.ts +1 -1
  92. package/src/ts/agent/react-connection/generator.d.ts +1 -1
  93. package/src/ts/agent/schema.json +1 -0
  94. package/src/ts/api/schema.json +2 -0
  95. package/src/ts/astro-docs/generator.d.ts +1 -1
  96. package/src/ts/dcr-proxy/generator.d.ts +1 -1
  97. package/src/ts/dynamodb/generator.d.ts +1 -1
  98. package/src/ts/lambda-function/generator.d.ts +1 -1
  99. package/src/ts/lib/generator.d.ts +1 -1
  100. package/src/ts/mcp-server/schema.json +1 -0
  101. package/src/ts/nx-generator/__snapshots__/generator.spec.ts.snap +1 -1
  102. package/src/ts/nx-generator/files/nx-plugin-for-aws/generator/generator.spec.ts.template +1 -1
  103. package/src/ts/nx-generator/generator.d.ts +1 -1
  104. package/src/ts/nx-migration/generator.d.ts +1 -1
  105. package/src/ts/nx-plugin/generator.d.ts +1 -1
  106. package/src/ts/rdb/generator.d.ts +1 -1
  107. package/src/ts/react-website/agui/generator.d.ts +1 -1
  108. package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +10 -10
  109. package/src/ts/react-website/app/schema.json +1 -0
  110. package/src/ts/website/app/schema.json +1 -0
  111. package/src/utils/agent-core-constructs/files/terraform/app/agentcore-harness/__nameKebabCase__/__nameKebabCase__.tf.template +1 -1
  112. package/src/utils/metrics-assertions.d.ts +18 -0
  113. package/src/utils/metrics-assertions.js +42 -0
  114. package/src/utils/metrics-assertions.js.map +1 -0
  115. package/src/utils/test/python-dependencies.d.ts +8 -0
  116. package/src/utils/test/python-dependencies.js +14 -0
  117. package/src/utils/test/python-dependencies.js.map +1 -0
  118. package/src/utils/test/python-worker/worker.py +703 -0
  119. package/src/utils/test/warm-python-cache.d.ts +18 -0
  120. package/src/utils/test/warm-python-cache.js +46 -0
  121. package/src/utils/test/warm-python-cache.js.map +1 -0
  122. package/src/utils/versions.d.ts +10 -9
  123. package/src/utils/versions.js +9 -8
  124. package/src/utils/versions.js.map +1 -1
package/README.md CHANGED
@@ -22,12 +22,23 @@
22
22
  alt="Commit activity"
23
23
  />
24
24
  </a>
25
+ <p>
26
+ <a href="https://awslabs.github.io/nx-plugin-for-aws/"><b>Documentation Site</b></a>
27
+ </p>
25
28
  </div>
26
29
 
27
30
  ---
28
31
 
29
32
  **@aws/nx-plugin** is a collection of code generators that scaffold full-stack AWS applications inside an [Nx](https://nx.dev) monorepo. Every generator produces best-practice application code **and** the infrastructure to deploy it — type-safe, locally runnable, and deployable from the start, getting you closer to production.
30
33
 
34
+ <div align="center">
35
+ <img
36
+ src="https://raw.githubusercontent.com/awslabs/nx-plugin-for-aws/main/docs/src/content/docs/assets/nx-plugin-showcase-desktop-dark.gif"
37
+ alt="Scaffolding, running and deploying a full-stack AWS application with the Nx Plugin for AWS"
38
+ width="900"
39
+ />
40
+ </div>
41
+
31
42
  ## Quick Start
32
43
 
33
44
  ### Build with AI
@@ -79,22 +90,29 @@ pnpm nx g @aws/nx-plugin:ts#infra
79
90
 
80
91
  | Generator | Description |
81
92
  | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
93
+ | `init` | Configure an existing Nx workspace to use the plugin |
82
94
  | `ts#project` | TypeScript library |
83
95
  | `ts#api` | TypeScript API (tRPC or Smithy) with API Gateway + Lambda + [Powertools](https://github.com/aws-powertools/powertools-lambda-typescript) |
84
96
  | `ts#rdb` | Relational databases with Aurora RDS |
97
+ | `ts#dynamodb` | Type-safe DynamoDB single-table design (TypeScript, ElectroDB) |
85
98
  | `ts#website` | React app (Vite) |
86
99
  | `ts#website#auth` | Add Cognito auth to a website |
87
100
  | `ts#infra` | AWS CDK infrastructure project |
88
101
  | `ts#lambda-function` | TypeScript Lambda with type-safe event sources |
89
102
  | `ts#mcp-server` | MCP server (TypeScript) |
103
+ | `ts#dcr-proxy` | OAuth DCR proxy construct for Cognito-authenticated MCP servers |
90
104
  | `ts#agent` | [Strands Agent](https://strandsagents.com/) (TypeScript) |
91
105
  | `ts#nx-generator` | Nx generator scaffold |
106
+ | `ts#docs` | Documentation site (Astro + Starlight) |
92
107
  | `smithy#project` | Smithy model project — a service model, or a shape library shared between Smithy projects |
93
108
  | `py#project` | Python project (uv) |
94
109
  | `py#api` | Python API (FastAPI) with API Gateway + Lambda + [Powertools](https://github.com/aws-powertools/powertools-lambda-python) |
110
+ | `py#rdb` | Relational databases with Aurora RDS (Python) |
111
+ | `py#dynamodb` | Python DynamoDB project |
95
112
  | `py#lambda-function` | Python Lambda with type-safe event sources |
96
113
  | `py#mcp-server` | MCP server (Python) |
97
114
  | `py#agent` | [Strands Agent](https://strandsagents.com/) (Python) |
115
+ | `agentcore-gateway` | [AgentCore Gateway](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway.html) project |
98
116
  | `agentcore-harness` | [AgentCore Harness](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/harness.html) agent loop (experimental) |
99
117
  | `connection` | Connect projects together (e.g. frontend to API) |
100
118
  | `terraform#project` | Terraform project |
package/generators.json CHANGED
@@ -104,6 +104,13 @@
104
104
  "metric": "g15",
105
105
  "hidden": true
106
106
  },
107
+ "open-api#py-client": {
108
+ "factory": "./src/open-api/py-client/generator",
109
+ "schema": "./src/open-api/py-client/schema.json",
110
+ "description": "Generate a Python httpx client from an OpenAPI specification",
111
+ "metric": "g73",
112
+ "hidden": true
113
+ },
107
114
  "open-api#ts-client": {
108
115
  "factory": "./src/open-api/ts-client/generator",
109
116
  "schema": "./src/open-api/ts-client/schema.json",
package/migrations.json CHANGED
@@ -12,6 +12,11 @@
12
12
  "description": "Move the shared shadcn package's components onto the cn package the shadcn registry now depends on",
13
13
  "implementation": "./src/migrations/latest/shadcn-cn-package/migration"
14
14
  },
15
+ "latest-terraform-harness-environment-variables": {
16
+ "version": "1.0.2",
17
+ "description": "Send an empty map rather than null for a vended Terraform AgentCore Harness module's environment_variables, so the first apply does not fail after creating the Harness",
18
+ "implementation": "./src/migrations/latest/terraform-harness-environment-variables/migration"
19
+ },
15
20
  "v1.0.0-rc.50-0001-modernize-function-props-cast": {
16
21
  "version": "1.0.0-rc.50",
17
22
  "description": "Replace the legacy angle-bracket FunctionProps type assertion with the modern as syntax in generated API constructs",
@@ -368,7 +373,7 @@
368
373
  "implementation": "./src/migrations/v1.0.0-rc.97/0006-script-project-quality-gates/migration"
369
374
  },
370
375
  "sync-vended-versions": {
371
- "version": "1.0.0",
376
+ "version": "1.0.2",
372
377
  "description": "Sync vended dependency versions and the tracked plugin version to those vended by this release",
373
378
  "implementation": "./src/utils/version-upgrade-migration/migration"
374
379
  }
@@ -472,6 +477,39 @@
472
477
  "alwaysAddToPackageJson": false
473
478
  }
474
479
  }
480
+ },
481
+ "nx-23.2.1-nx-packages": {
482
+ "version": "1.0.2",
483
+ "packages": {
484
+ "nx": {
485
+ "version": "23.2.1",
486
+ "alwaysAddToPackageJson": false
487
+ },
488
+ "@nx/devkit": {
489
+ "version": "23.2.1",
490
+ "alwaysAddToPackageJson": false
491
+ },
492
+ "@nx/js": {
493
+ "version": "23.2.1",
494
+ "alwaysAddToPackageJson": false
495
+ },
496
+ "@nx/react": {
497
+ "version": "23.2.1",
498
+ "alwaysAddToPackageJson": false
499
+ },
500
+ "@nx/vite": {
501
+ "version": "23.2.1",
502
+ "alwaysAddToPackageJson": false
503
+ },
504
+ "@nx/vitest": {
505
+ "version": "23.2.1",
506
+ "alwaysAddToPackageJson": false
507
+ },
508
+ "@nx/workspace": {
509
+ "version": "23.2.1",
510
+ "alwaysAddToPackageJson": false
511
+ }
512
+ }
475
513
  }
476
514
  }
477
515
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws/nx-plugin",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/awslabs/nx-plugin-for-aws.git",
@@ -36,7 +36,7 @@
36
36
  "node": ">=20.19.0"
37
37
  },
38
38
  "peerDependencies": {
39
- "nx": "23.2.0"
39
+ "nx": "23.2.1"
40
40
  },
41
41
  "dependencies": {
42
42
  "@apidevtools/swagger-parser": "12.1.0",
@@ -46,10 +46,10 @@
46
46
  "@getgrit/gritql": "0.0.3",
47
47
  "@iarna/toml": "2.2.5",
48
48
  "@modelcontextprotocol/sdk": "1.30.0",
49
- "@nx/devkit": "23.2.0",
50
- "@nx/js": "23.2.0",
51
- "@nx/react": "23.2.0",
52
- "@nx/vite": "23.2.0",
49
+ "@nx/devkit": "23.2.1",
50
+ "@nx/js": "23.2.1",
51
+ "@nx/react": "23.2.1",
52
+ "@nx/vite": "23.2.1",
53
53
  "@nxlv/python": "23.0.0",
54
54
  "@phenomnomnominal/tsquery": "6.2.0",
55
55
  "@types/estree": "1.0.9",
@@ -63,6 +63,12 @@ export const AGENTCORE_GATEWAY_AGENT_CONNECTION_GENERATOR_INFO = getGeneratorInf
63
63
  if (agentAuth !== 'iam' && agentAuth !== 'cognito') {
64
64
  throw new Error(`Agent '${agentComponent.name}' uses auth='${agentAuth}', which a gateway cannot front. Supported: iam, cognito.`);
65
65
  }
66
+ // JWT passthrough forwards the token the gateway validated on the way in, so
67
+ // a Cognito agent needs a Cognito gateway in front of it. An IAM gateway
68
+ // authenticates its callers with SigV4 and has no bearer token to forward.
69
+ if (agentAuth === 'cognito' && gateway.auth !== 'cognito') {
70
+ throw new Error(`Agent '${agentComponent.name}' uses auth='cognito', but gateway '${gateway.name}' uses auth='${gateway.auth}'. A Cognito agent authorizes on the caller's forwarded JWT, which only a Cognito gateway receives — generate the gateway with --auth=cognito against the same user pool, or front an IAM agent instead.`);
71
+ }
66
72
  // The target name must match what the deployed Gateway uses (`agentName` on
67
73
  // the agent construct, derived from the project's class name) so the
68
74
  // `/<target>/invocations` path resolves identically locally and deployed.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../packages/nx-plugin/src/agentcore-gateway/agent-connection/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { GeneratorCallback, Tree } from '@nx/devkit';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { kebabCase, toClassName } from '../../utils/names.js';\nimport {\n addComponentGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx.js';\nimport { attachAgentToLocalGateway } from '../attach-upstream.js';\nimport { readAgentCoreGatewayMetadata } from '../generator.js';\nimport type { AgentcoreGatewayAgentConnectionGeneratorSchema } from './schema';\n\nexport const AGENTCORE_GATEWAY_AGENT_CONNECTION_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\n/**\n * The agent protocols an http gateway can front, by agent language. The\n * gateway proxies plain HTTP request/response and SSE streams:\n *\n * - `ag-ui` (ts + py) and `http` (py) serve POST /invocations with streamed\n * responses, which proxy cleanly.\n * - `a2a` (ts + py) is JSON-RPC over POST, which AgentCore applies a default\n * schema for.\n * - `http` (ts) is tRPC over WebSocket, and the gateway does not support\n * WebSocket / bidirectional streaming, so it cannot sit behind one.\n */\nconst SUPPORTED_AGENT_PROTOCOLS: Record<string, string[]> = {\n 'ts#agent': ['ag-ui', 'a2a'],\n 'py#agent': ['ag-ui', 'http', 'a2a'],\n};\n\n/**\n * Connect an AgentCore Gateway to an agent, so the agent is added as a\n * gateway target and served under `<gatewayUrl>/<targetName>/invocations`.\n *\n * Chains the gateway's dev target to the agent's dev target, and registers\n * the agent in the gateway's local-dev.ts so the local gateway proxies to it.\n * Users must still call `gateway.addAgent(...)` in their application stack to\n * create the actual CDK/Terraform resource.\n */\nexport const agentcoreGatewayAgentConnectionGenerator = async (\n tree: Tree,\n options: AgentcoreGatewayAgentConnectionGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const sourceProject = readProjectConfigurationUnqualified(\n tree,\n options.sourceProject,\n );\n const targetProject = readProjectConfigurationUnqualified(\n tree,\n options.targetProject,\n );\n\n const gateway = readAgentCoreGatewayMetadata(sourceProject);\n const agentComponent = options.targetComponent;\n\n if (!agentComponent) {\n throw new Error(\n `Target project '${options.targetProject}' has no agent component metadata. Did you run the 'ts#agent' or 'py#agent' generator?`,\n );\n }\n\n if (gateway.protocol !== 'http') {\n throw new Error(\n `Gateway '${gateway.name}' has protocol='${gateway.protocol}'. Agent targets can only be attached to http-protocol gateways — generate one with the 'agentcore-gateway' generator and --protocol=http.`,\n );\n }\n\n const agentGenerator = agentComponent.generator ?? 'ts#agent';\n const agentProtocol = (\n (agentComponent.protocol as string | undefined) ?? 'http'\n ).toLowerCase();\n const supportedProtocols = SUPPORTED_AGENT_PROTOCOLS[agentGenerator] ?? [];\n if (!supportedProtocols.includes(agentProtocol)) {\n throw new Error(\n `Agent '${agentComponent.name}' uses protocol='${agentProtocol}', which cannot be fronted by a gateway` +\n (agentGenerator === 'ts#agent' && agentProtocol === 'http'\n ? ` — a TypeScript HTTP agent serves tRPC over WebSocket, and AgentCore Gateway does not support WebSocket streaming. Consider the ag-ui protocol instead.`\n : `. Supported protocols: ${supportedProtocols.join(', ')}.`),\n );\n }\n // Both IAM and Cognito agents can be fronted. An IAM agent is invoked with\n // the gateway's own role (GATEWAY_IAM_ROLE); a Cognito agent has the caller's\n // JWT forwarded to it (JWT_PASSTHROUGH) so it authorizes on the token. The\n // vended `addAgent` picks the credential from the agent's `auth`.\n const agentAuth = (agentComponent.auth as string | undefined) ?? 'iam';\n if (agentAuth !== 'iam' && agentAuth !== 'cognito') {\n throw new Error(\n `Agent '${agentComponent.name}' uses auth='${agentAuth}', which a gateway cannot front. Supported: iam, cognito.`,\n );\n }\n\n // The target name must match what the deployed Gateway uses (`agentName` on\n // the agent construct, derived from the project's class name) so the\n // `/<target>/invocations` path resolves identically locally and deployed.\n const agentComponentName = agentComponent.name ?? 'agent';\n const agentTargetName = kebabCase(\n (agentComponent.rc as string | undefined) ??\n toClassName(agentComponentName),\n );\n\n await attachAgentToLocalGateway(tree, sourceProject, 'dev', {\n targetName: agentTargetName,\n port: (agentComponent.port as number | undefined) ?? 8081,\n upstreamProjectName: targetProject.name,\n upstreamDevTargetName: `${agentComponentName}-dev`,\n // The deployed gateway maps an A2A target's `/invocations/...` paths onto\n // the agent container's root; HTTP and AG-UI agents serve /invocations\n // themselves.\n stripInvocations: agentProtocol === 'a2a',\n });\n\n // Recorded so the version sync can identify this connection.\n addComponentGeneratorMetadata(\n tree,\n sourceProject.name,\n AGENTCORE_GATEWAY_AGENT_CONNECTION_GENERATOR_INFO,\n targetProject.root,\n agentTargetName,\n );\n\n await addGeneratorMetricsIfApplicable(tree, [\n AGENTCORE_GATEWAY_AGENT_CONNECTION_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\n\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nexport default agentcoreGatewayAgentConnectionGenerator;\n"],"names":["formatFilesInSubtree","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","addComponentGeneratorMetadata","getGeneratorInfo","readProjectConfigurationUnqualified","attachAgentToLocalGateway","readAgentCoreGatewayMetadata","AGENTCORE_GATEWAY_AGENT_CONNECTION_GENERATOR_INFO","filename","SUPPORTED_AGENT_PROTOCOLS","agentcoreGatewayAgentConnectionGenerator","tree","options","sourceProject","targetProject","gateway","agentComponent","targetComponent","Error","protocol","name","agentGenerator","generator","agentProtocol","toLowerCase","supportedProtocols","includes","join","agentAuth","auth","agentComponentName","agentTargetName","rc","targetName","port","upstreamProjectName","upstreamDevTargetName","stripInvocations","root","preferInstallDependencies","languages"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../packages/nx-plugin/src/agentcore-gateway/agent-connection/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { GeneratorCallback, Tree } from '@nx/devkit';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { kebabCase, toClassName } from '../../utils/names.js';\nimport {\n addComponentGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx.js';\nimport { attachAgentToLocalGateway } from '../attach-upstream.js';\nimport { readAgentCoreGatewayMetadata } from '../generator.js';\nimport type { AgentcoreGatewayAgentConnectionGeneratorSchema } from './schema';\n\nexport const AGENTCORE_GATEWAY_AGENT_CONNECTION_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\n/**\n * The agent protocols an http gateway can front, by agent language. The\n * gateway proxies plain HTTP request/response and SSE streams:\n *\n * - `ag-ui` (ts + py) and `http` (py) serve POST /invocations with streamed\n * responses, which proxy cleanly.\n * - `a2a` (ts + py) is JSON-RPC over POST, which AgentCore applies a default\n * schema for.\n * - `http` (ts) is tRPC over WebSocket, and the gateway does not support\n * WebSocket / bidirectional streaming, so it cannot sit behind one.\n */\nconst SUPPORTED_AGENT_PROTOCOLS: Record<string, string[]> = {\n 'ts#agent': ['ag-ui', 'a2a'],\n 'py#agent': ['ag-ui', 'http', 'a2a'],\n};\n\n/**\n * Connect an AgentCore Gateway to an agent, so the agent is added as a\n * gateway target and served under `<gatewayUrl>/<targetName>/invocations`.\n *\n * Chains the gateway's dev target to the agent's dev target, and registers\n * the agent in the gateway's local-dev.ts so the local gateway proxies to it.\n * Users must still call `gateway.addAgent(...)` in their application stack to\n * create the actual CDK/Terraform resource.\n */\nexport const agentcoreGatewayAgentConnectionGenerator = async (\n tree: Tree,\n options: AgentcoreGatewayAgentConnectionGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const sourceProject = readProjectConfigurationUnqualified(\n tree,\n options.sourceProject,\n );\n const targetProject = readProjectConfigurationUnqualified(\n tree,\n options.targetProject,\n );\n\n const gateway = readAgentCoreGatewayMetadata(sourceProject);\n const agentComponent = options.targetComponent;\n\n if (!agentComponent) {\n throw new Error(\n `Target project '${options.targetProject}' has no agent component metadata. Did you run the 'ts#agent' or 'py#agent' generator?`,\n );\n }\n\n if (gateway.protocol !== 'http') {\n throw new Error(\n `Gateway '${gateway.name}' has protocol='${gateway.protocol}'. Agent targets can only be attached to http-protocol gateways — generate one with the 'agentcore-gateway' generator and --protocol=http.`,\n );\n }\n\n const agentGenerator = agentComponent.generator ?? 'ts#agent';\n const agentProtocol = (\n (agentComponent.protocol as string | undefined) ?? 'http'\n ).toLowerCase();\n const supportedProtocols = SUPPORTED_AGENT_PROTOCOLS[agentGenerator] ?? [];\n if (!supportedProtocols.includes(agentProtocol)) {\n throw new Error(\n `Agent '${agentComponent.name}' uses protocol='${agentProtocol}', which cannot be fronted by a gateway` +\n (agentGenerator === 'ts#agent' && agentProtocol === 'http'\n ? ` — a TypeScript HTTP agent serves tRPC over WebSocket, and AgentCore Gateway does not support WebSocket streaming. Consider the ag-ui protocol instead.`\n : `. Supported protocols: ${supportedProtocols.join(', ')}.`),\n );\n }\n // Both IAM and Cognito agents can be fronted. An IAM agent is invoked with\n // the gateway's own role (GATEWAY_IAM_ROLE); a Cognito agent has the caller's\n // JWT forwarded to it (JWT_PASSTHROUGH) so it authorizes on the token. The\n // vended `addAgent` picks the credential from the agent's `auth`.\n const agentAuth = (agentComponent.auth as string | undefined) ?? 'iam';\n if (agentAuth !== 'iam' && agentAuth !== 'cognito') {\n throw new Error(\n `Agent '${agentComponent.name}' uses auth='${agentAuth}', which a gateway cannot front. Supported: iam, cognito.`,\n );\n }\n // JWT passthrough forwards the token the gateway validated on the way in, so\n // a Cognito agent needs a Cognito gateway in front of it. An IAM gateway\n // authenticates its callers with SigV4 and has no bearer token to forward.\n if (agentAuth === 'cognito' && gateway.auth !== 'cognito') {\n throw new Error(\n `Agent '${agentComponent.name}' uses auth='cognito', but gateway '${gateway.name}' uses auth='${gateway.auth}'. A Cognito agent authorizes on the caller's forwarded JWT, which only a Cognito gateway receives — generate the gateway with --auth=cognito against the same user pool, or front an IAM agent instead.`,\n );\n }\n\n // The target name must match what the deployed Gateway uses (`agentName` on\n // the agent construct, derived from the project's class name) so the\n // `/<target>/invocations` path resolves identically locally and deployed.\n const agentComponentName = agentComponent.name ?? 'agent';\n const agentTargetName = kebabCase(\n (agentComponent.rc as string | undefined) ??\n toClassName(agentComponentName),\n );\n\n await attachAgentToLocalGateway(tree, sourceProject, 'dev', {\n targetName: agentTargetName,\n port: (agentComponent.port as number | undefined) ?? 8081,\n upstreamProjectName: targetProject.name,\n upstreamDevTargetName: `${agentComponentName}-dev`,\n // The deployed gateway maps an A2A target's `/invocations/...` paths onto\n // the agent container's root; HTTP and AG-UI agents serve /invocations\n // themselves.\n stripInvocations: agentProtocol === 'a2a',\n });\n\n // Recorded so the version sync can identify this connection.\n addComponentGeneratorMetadata(\n tree,\n sourceProject.name,\n AGENTCORE_GATEWAY_AGENT_CONNECTION_GENERATOR_INFO,\n targetProject.root,\n agentTargetName,\n );\n\n await addGeneratorMetricsIfApplicable(tree, [\n AGENTCORE_GATEWAY_AGENT_CONNECTION_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\n\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\nexport default agentcoreGatewayAgentConnectionGenerator;\n"],"names":["formatFilesInSubtree","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","addComponentGeneratorMetadata","getGeneratorInfo","readProjectConfigurationUnqualified","attachAgentToLocalGateway","readAgentCoreGatewayMetadata","AGENTCORE_GATEWAY_AGENT_CONNECTION_GENERATOR_INFO","filename","SUPPORTED_AGENT_PROTOCOLS","agentcoreGatewayAgentConnectionGenerator","tree","options","sourceProject","targetProject","gateway","agentComponent","targetComponent","Error","protocol","name","agentGenerator","generator","agentProtocol","toLowerCase","supportedProtocols","includes","join","agentAuth","auth","agentComponentName","agentTargetName","rc","targetName","port","upstreamProjectName","upstreamDevTargetName","stripInvocations","root","preferInstallDependencies","languages"],"mappings":"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"}
@@ -35,6 +35,7 @@
35
35
  "auth": {
36
36
  "type": "string",
37
37
  "description": "The method used to authenticate inbound requests to your gateway. Only applicable when infra is set (ignored when infra is none).",
38
+ "x-when": { "infra": "agentcore" },
38
39
  "enum": ["iam", "cognito"],
39
40
  "default": "iam",
40
41
  "x-prompt": "How would you like to authenticate inbound requests to your gateway?",
@@ -40,7 +40,7 @@ export declare const DEPENDENCIES: import("../utils/declared-dependencies.js").D
40
40
  readonly name: "@types/node";
41
41
  } & {
42
42
  versionOnly: true;
43
- }], readonly import("../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", AgentCoreHarnessMetadata>[]>;
43
+ }], readonly import("../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", AgentCoreHarnessMetadata>[]>;
44
44
  export declare const AGENTCORE_HARNESS_GENERATOR_INFO: NxGeneratorInfo;
45
45
  export declare const agentcoreHarnessGenerator: (tree: Tree, options: AgentcoreHarnessGeneratorSchema) => Promise<GeneratorCallback>;
46
46
  /**
@@ -75,6 +75,10 @@ export type GeneratorSchema = {
75
75
  enum?: string[];
76
76
  default?: unknown;
77
77
  'x-priority'?: string;
78
+ /** The option values this option applies under. */
79
+ 'x-when'?: Record<string, string | string[]>;
80
+ /** The same, per value, where one of an option's values applies sometimes. */
81
+ 'x-value-when'?: Record<string, Record<string, string | string[]>>;
78
82
  }>;
79
83
  required?: string[];
80
84
  };
@@ -103,6 +107,18 @@ export declare const CONNECTION_ENDPOINT_TYPES: readonly string[];
103
107
  * edit to this file.
104
108
  */
105
109
  export declare const buildScaffoldRecipes: (schemaOf: SchemaResolver) => Readonly<Record<string, ScaffoldRecipe>>;
110
+ /**
111
+ * An option value one end of a connection must hold for a constraint to apply,
112
+ * narrowing a rule that only binds some of a connection's configurations.
113
+ */
114
+ export interface ConnectionConstraintCondition {
115
+ /** Which end of the connection the conditioning option belongs to. */
116
+ readonly side: 'source' | 'target';
117
+ /** The generator option whose value decides whether the constraint applies. */
118
+ readonly option: string;
119
+ /** The value that brings the constraint into effect. */
120
+ readonly equals: string;
121
+ }
106
122
  /**
107
123
  * A requirement one end of a connection places on the other's options, mirroring
108
124
  * the guard the corresponding connection generator enforces.
@@ -121,6 +137,11 @@ export interface ConnectionConstraint {
121
137
  readonly equals?: string;
122
138
  /** A value rejected, for options accepting all but one. */
123
139
  readonly notEquals?: string;
140
+ /**
141
+ * Limits the rule to connections whose endpoints read this way. Absent for a
142
+ * rule binding every connection of its kind.
143
+ */
144
+ readonly when?: ConnectionConstraintCondition;
124
145
  /** Why the constraint exists, phrased for the user choosing the option. */
125
146
  readonly reason: string;
126
147
  }
@@ -146,13 +146,10 @@ const AGENT_TO_MCP = [
146
146
  reason: 'An agent reaches an MCP server with IAM authentication.'
147
147
  }
148
148
  ];
149
+ // The agent's own `auth` governs inbound requests to it, so it places no
150
+ // requirement here — the agent signs its outbound call to the gateway with
151
+ // SigV4 from its execution role either way.
149
152
  const AGENT_TO_GATEWAY = [
150
- {
151
- side: 'source',
152
- option: 'auth',
153
- equals: 'iam',
154
- reason: 'Only an IAM-authenticated agent can reach an IAM gateway.'
155
- },
156
153
  {
157
154
  side: 'target',
158
155
  option: 'auth',
@@ -186,6 +183,17 @@ const GATEWAY_TO_AGENT = [
186
183
  option: 'protocol',
187
184
  equals: 'http',
188
185
  reason: 'Agent runtime targets can only be attached to an http-protocol gateway.'
186
+ },
187
+ {
188
+ side: 'source',
189
+ option: 'auth',
190
+ equals: 'cognito',
191
+ when: {
192
+ side: 'target',
193
+ option: 'auth',
194
+ equals: 'cognito'
195
+ },
196
+ reason: "A Cognito agent authorizes on the caller's forwarded JWT, which only a Cognito gateway receives. An IAM gateway can front an IAM agent, which it invokes with its own role."
189
197
  }
190
198
  ];
191
199
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../packages/nx-plugin/src/connection/scaffold-catalog.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport GeneratorsJson from '../../generators.json' with { type: 'json' };\nimport {\n type ConnectionKey,\n SUPPORTED_CONNECTIONS,\n type SUPPORTED_PROJECT_TYPES,\n} from './supported-connections.js';\n\n/**\n * How to scaffold each end of a connection, derived from the plugin's own\n * metadata rather than hand-listed.\n *\n * Every connection endpoint type is also a generator id, which is what makes the\n * derivation possible:\n *\n * - **kind** — a generator whose schema `required`s a `project` adds a component\n * to an existing project; anything else creates a project of its own.\n * - **host** — a component lands in a project made by its language's base\n * generator (`ts#project` / `py#project`).\n * - **generator + options** — a type whose own generator is `hidden` is reached\n * through the public wrapper that selects it, found by matching the wrapper's\n * enum values against the type's name (`ts#trpc-api` ← `ts#api\n * --framework=trpc`). A visible generator is run directly.\n *\n * - **label** — the generator schema's own `x-label`.\n *\n * The result is that adding a generator and a connection for it needs no edit\n * here at all. The one thing still declared below is the option constraints,\n * which live as imperative guards inside each connection generator and so cannot\n * be read from metadata.\n */\n\n/**\n * Every type that can sit at either end of a connection: the project-level\n * types resolved by introspection, plus the component generator ids recorded in\n * component metadata.\n */\nexport type ConnectionEndpointType =\n | (typeof SUPPORTED_PROJECT_TYPES)[number]\n | (typeof SUPPORTED_CONNECTIONS)[number]['source']\n | (typeof SUPPORTED_CONNECTIONS)[number]['target'];\n\n/**\n * Whether scaffolding an endpoint creates a project of its own, or adds a\n * component to a project that must already exist.\n */\nexport type ScaffoldKind = 'project' | 'component';\n\n/** How to scaffold one end of a connection from the CLI. */\nexport interface ScaffoldRecipe {\n /** Human-readable name for this endpoint type. */\n readonly label: string;\n /** The generator id in `generators.json` that produces this endpoint. */\n readonly generator: string;\n /**\n * Options that select this endpoint type from its generator, for generators\n * producing more than one type (e.g. `framework`).\n */\n readonly options?: Readonly<Record<string, string>>;\n /** Whether the generator creates a project or adds a component to one. */\n readonly kind: ScaffoldKind;\n /**\n * The generator producing a project able to host this component, for\n * `component` recipes. Components are added to an existing project, so one\n * must be scaffolded first.\n */\n readonly host?: {\n readonly generator: string;\n readonly options?: Readonly<Record<string, string>>;\n /**\n * Whether the host project's name is referenced in snake_case. Python\n * project names are snake_cased when qualified, TypeScript ones are not.\n */\n readonly snakeCaseName?: boolean;\n };\n}\n\ntype GeneratorEntry = { schema: string; hidden?: boolean };\n/** The subset of JSON Schema the catalogue and the docs builder read. */\nexport type GeneratorSchema = {\n /**\n * Short display name for the thing this generator produces, used by the docs\n * graph builder's palette. Set it on any generator that can take part in a\n * connection.\n */\n 'x-label'?: string;\n properties?: Record<\n string,\n {\n type?: string;\n description?: string;\n enum?: string[];\n default?: unknown;\n 'x-priority'?: string;\n }\n >;\n required?: string[];\n};\n\ntype Schema = GeneratorSchema;\n\nconst GENERATORS = GeneratorsJson.generators as Record<string, GeneratorEntry>;\n\n/**\n * Resolves a generator's JSON schema by generator id.\n *\n * Injected rather than fixed because the two callers load files differently: the\n * plugin reads from disk (see `./schema-resolver`), while the docs site bundles\n * the schemas for the browser, where `node:fs` does not exist. Keeping this\n * module free of `node:fs` is what lets the browser import it at all.\n */\nexport type SchemaResolver = (generatorId: string) => Schema;\n\n/** The path `generators.json` records for a generator, relative to the plugin root. */\nexport const schemaPathOf = (generatorId: string): string => {\n const entry = GENERATORS[generatorId];\n if (!entry) {\n throw new Error(\n `Scaffold catalog: '${generatorId}' is not in generators.json`,\n );\n }\n return entry.schema;\n};\n\n/** The language prefix of a generator id: `ts` for `ts#agent`, `` for `license`. */\nconst languageOf = (id: string): string =>\n id.includes('#') ? id.slice(0, id.indexOf('#')) : '';\n\n/** Compare ids ignoring the separators that differ between wrapper and variant. */\nconst alike = (a: string, b: string): boolean =>\n a.replace(/[^a-z0-9]/gi, '').toLowerCase() ===\n b.replace(/[^a-z0-9]/gi, '').toLowerCase();\n\n/**\n * The public generator and option value that select a hidden endpoint type.\n *\n * A wrapper like `ts#api` produces several endpoint types, choosing between them\n * with an enum option: `--framework=trpc` yields `ts#trpc-api`. The pairing is\n * found by looking for a same-language public generator with an enum value that\n * reconstructs the endpoint's own name.\n */\nconst findWrapper = (\n endpointType: string,\n schemaOf: SchemaResolver,\n): { generator: string; options: Record<string, string> } | undefined => {\n const language = languageOf(endpointType);\n const name = endpointType.slice(endpointType.indexOf('#') + 1);\n\n for (const [generatorId, entry] of Object.entries(GENERATORS)) {\n if (entry.hidden) continue;\n if (languageOf(generatorId) !== language) continue;\n const wrapperName = generatorId.slice(generatorId.indexOf('#') + 1);\n\n for (const [option, property] of Object.entries(\n schemaOf(generatorId).properties ?? {},\n )) {\n for (const value of property.enum ?? []) {\n // Either the value names the variant outright (`react` for\n // `react-website`), or it qualifies the wrapper's own name\n // (`trpc` + `api` for `trpc-api`).\n if (alike(value, name) || alike(`${value}${wrapperName}`, name)) {\n return { generator: generatorId, options: { [option]: value } };\n }\n }\n }\n }\n return undefined;\n};\n\n/**\n * Derive the recipe for one endpoint type. Exported so a test can assert the\n * derivation against every type the plugin supports.\n */\nexport const deriveScaffoldRecipe = (\n endpointType: string,\n schemaOf: SchemaResolver,\n): ScaffoldRecipe => {\n const own = GENERATORS[endpointType];\n if (!own) {\n throw new Error(\n `Scaffold catalog: connection endpoint '${endpointType}' is not a generator id`,\n );\n }\n\n // A hidden generator is an implementation detail reached through its public\n // wrapper, which is what a user would actually run.\n const wrapper = own.hidden ? findWrapper(endpointType, schemaOf) : undefined;\n if (own.hidden && !wrapper) {\n throw new Error(\n `Scaffold catalog: '${endpointType}' is hidden and no public generator selects it`,\n );\n }\n\n // A generator requiring a `project` adds a component to one; anything else\n // creates its own project.\n const kind: ScaffoldKind = (schemaOf(endpointType).required ?? []).includes(\n 'project',\n )\n ? 'component'\n : 'project';\n\n const language = languageOf(endpointType);\n const hostGenerator = `${language}#project`;\n if (kind === 'component' && !GENERATORS[hostGenerator]) {\n throw new Error(\n `Scaffold catalog: '${endpointType}' is a component but '${hostGenerator}' does not exist to host it`,\n );\n }\n\n return {\n // `x-label` is the short noun a palette entry needs; `title` and\n // `description` are prose aimed at CLI prompts (\"Create a relational database\n // project\"). A generator without one falls back to its id, so a new endpoint\n // type still appears rather than being dropped.\n label: schemaOf(endpointType)['x-label'] ?? endpointType,\n generator: wrapper?.generator ?? endpointType,\n ...(wrapper ? { options: wrapper.options } : {}),\n kind,\n ...(kind === 'component'\n ? {\n host: {\n generator: hostGenerator,\n // Only options the host's schema actually requires, so a base\n // project generator gaining a required option is handled here.\n options: Object.fromEntries(\n (schemaOf(hostGenerator).required ?? [])\n .filter((option) => option !== 'name')\n .map((option) => {\n const property = schemaOf(hostGenerator).properties?.[option];\n const value = property?.default ?? property?.enum?.[0];\n if (value === undefined) {\n throw new Error(\n `Scaffold catalog: '${hostGenerator}' requires '${option}' but its schema offers no value to use`,\n );\n }\n return [option, String(value)];\n }),\n ),\n // Python project names are snake_cased when Nx qualifies them.\n snakeCaseName: language === 'py',\n },\n }\n : {}),\n };\n};\n\n/** Every endpoint type appearing at either end of a supported connection. */\nexport const CONNECTION_ENDPOINT_TYPES: readonly string[] = [\n ...new Set(\n SUPPORTED_CONNECTIONS.flatMap(({ source, target }) => [source, target]),\n ),\n].sort();\n\n/**\n * How to scaffold each connection endpoint type, derived from the generator\n * metadata. A connection added to `SUPPORTED_CONNECTIONS` appears here with no\n * edit to this file.\n */\nexport const buildScaffoldRecipes = (\n schemaOf: SchemaResolver,\n): Readonly<Record<string, ScaffoldRecipe>> =>\n Object.fromEntries(\n CONNECTION_ENDPOINT_TYPES.map((type) => [\n type,\n deriveScaffoldRecipe(type, schemaOf),\n ]),\n );\n\n/**\n * A requirement one end of a connection places on the other's options, mirroring\n * the guard the corresponding connection generator enforces.\n *\n * Declared rather than derived: each guard is an imperative `throw` inside its\n * connection generator, reachable only by running it. Recording them here lets a\n * caller choosing options up front check them first, and the paired test asserts\n * every entry names a real option with a value its enum allows.\n */\nexport interface ConnectionConstraint {\n /** Which end of the connection the constrained option belongs to. */\n readonly side: 'source' | 'target';\n /** The generator option carrying the constrained value. */\n readonly option: string;\n /** The only value accepted, if the option is pinned to one. */\n readonly equals?: string;\n /** A value rejected, for options accepting all but one. */\n readonly notEquals?: string;\n /** Why the constraint exists, phrased for the user choosing the option. */\n readonly reason: string;\n}\n\n/** Reusable constraint shapes, so the map below states each rule once. */\nconst AGENT_TO_AGENT: readonly ConnectionConstraint[] = [\n {\n side: 'target',\n option: 'protocol',\n equals: 'a2a',\n reason: 'Only an A2A agent can be connected to another agent as a tool.',\n },\n {\n side: 'target',\n option: 'auth',\n equals: 'iam',\n reason: 'A2A agent connections authenticate with IAM.',\n },\n];\n\nconst WEBSITE_TO_AGENT: readonly ConnectionConstraint[] = [\n {\n side: 'target',\n option: 'protocol',\n notEquals: 'a2a',\n reason:\n 'A2A agents are reached by other agents, not by a website. Use the http or ag-ui protocol.',\n },\n];\n\nconst AGENT_TO_MCP: readonly ConnectionConstraint[] = [\n {\n side: 'target',\n option: 'auth',\n equals: 'iam',\n reason: 'An agent reaches an MCP server with IAM authentication.',\n },\n];\n\nconst AGENT_TO_GATEWAY: readonly ConnectionConstraint[] = [\n {\n side: 'source',\n option: 'auth',\n equals: 'iam',\n reason: 'Only an IAM-authenticated agent can reach an IAM gateway.',\n },\n {\n side: 'target',\n option: 'auth',\n equals: 'iam',\n reason: 'Agent connections require the gateway to authenticate with IAM.',\n },\n {\n side: 'target',\n option: 'protocol',\n equals: 'mcp',\n reason:\n 'An agent reaches a gateway as an MCP client, so the gateway must serve the mcp protocol. Note a single gateway cannot both front an agent and be called by one, since fronting requires the http protocol.',\n },\n];\n\nconst GATEWAY_TO_MCP: readonly ConnectionConstraint[] = [\n {\n side: 'source',\n option: 'protocol',\n equals: 'mcp',\n reason:\n 'MCP server targets can only be attached to an mcp-protocol gateway.',\n },\n {\n side: 'target',\n option: 'auth',\n equals: 'iam',\n reason: 'A gateway reaches an MCP server target with IAM authentication.',\n },\n];\n\nconst GATEWAY_TO_AGENT: readonly ConnectionConstraint[] = [\n {\n side: 'source',\n option: 'protocol',\n equals: 'http',\n reason:\n 'Agent runtime targets can only be attached to an http-protocol gateway.',\n },\n];\n\n/**\n * The option-level requirements each connection places on its endpoints.\n *\n * Only connections carrying a requirement appear. Keyed by `ConnectionKey`, so a\n * key that no longer names a supported connection is a compile error.\n */\nexport const CONNECTION_CONSTRAINTS = {\n 'ts#react-website -> ts#agent': WEBSITE_TO_AGENT,\n 'ts#react-website -> py#agent': WEBSITE_TO_AGENT,\n 'ts#agent -> ts#agent': AGENT_TO_AGENT,\n 'ts#agent -> py#agent': AGENT_TO_AGENT,\n 'py#agent -> ts#agent': AGENT_TO_AGENT,\n 'py#agent -> py#agent': AGENT_TO_AGENT,\n 'ts#agent -> ts#mcp-server': AGENT_TO_MCP,\n 'ts#agent -> py#mcp-server': AGENT_TO_MCP,\n 'py#agent -> ts#mcp-server': AGENT_TO_MCP,\n 'py#agent -> py#mcp-server': AGENT_TO_MCP,\n 'ts#agent -> agentcore-gateway': AGENT_TO_GATEWAY,\n 'py#agent -> agentcore-gateway': AGENT_TO_GATEWAY,\n 'ts#react-website -> agentcore-gateway': [\n {\n side: 'target',\n option: 'protocol',\n equals: 'http',\n reason:\n 'A website connects to an http-protocol gateway, which proxies requests to its agent targets.',\n },\n ],\n 'agentcore-gateway -> ts#agent': [\n ...GATEWAY_TO_AGENT,\n {\n side: 'target',\n option: 'protocol',\n notEquals: 'http',\n reason:\n 'A TypeScript http agent serves tRPC over WebSocket, which AgentCore Gateway does not support. Use the ag-ui or a2a protocol.',\n },\n ],\n 'agentcore-gateway -> py#agent': GATEWAY_TO_AGENT,\n 'agentcore-gateway -> ts#mcp-server': GATEWAY_TO_MCP,\n 'agentcore-gateway -> py#mcp-server': GATEWAY_TO_MCP,\n 'agentcore-gateway -> agentcore-gateway': [\n {\n side: 'source',\n option: 'protocol',\n equals: 'mcp',\n reason:\n 'A gateway is aggregated into another as an MCP target, so both must be mcp-protocol gateways.',\n },\n {\n side: 'target',\n option: 'protocol',\n equals: 'mcp',\n reason:\n 'A gateway is aggregated into another as an MCP target, so both must be mcp-protocol gateways.',\n },\n {\n side: 'target',\n option: 'auth',\n equals: 'iam',\n reason:\n 'The source gateway signs its request with IAM, so the target gateway must accept IAM.',\n },\n ],\n} as const satisfies Partial<\n Record<ConnectionKey, readonly ConnectionConstraint[]>\n>;\n\n/**\n * A generator run automatically after an endpoint is scaffolded, adding something\n * that endpoint should always have.\n *\n * A website is only useful with authentication in front of it, and `ts#website`\n * does not add it — `ts#website#auth` is a separate follow-up generator. Declared\n * here so the docs graph builder emits it without hardcoding the pairing.\n */\nexport interface FollowUpGenerator {\n /** The generator id to run after the endpoint's own. */\n readonly generator: string;\n /** Options to pass, beyond the `--project` naming the endpoint. */\n readonly options?: Readonly<Record<string, string>>;\n /** What it adds, for the emitted command's comment. */\n readonly adds: string;\n}\n\n/**\n * Generators run automatically after an endpoint type is scaffolded, keyed by\n * endpoint type.\n */\nexport const ENDPOINT_FOLLOW_UPS: Readonly<\n Record<string, readonly FollowUpGenerator[]>\n> = {\n 'ts#react-website': [\n {\n generator: 'ts#website#auth',\n // `cognitoDomain` is derived from the npm scope and project name when\n // omitted, so the command stays short.\n adds: 'Cognito authentication',\n },\n ],\n};\n\n/**\n * An option value a connection works best against, without requiring it.\n *\n * Distinct from `CONNECTION_CONSTRAINTS`: a constraint is a rule the connection\n * generator enforces, whereas a preference is the setting most users want. A\n * React website can call an `http` agent perfectly well, but AG-UI is the\n * protocol built for driving a frontend, so that is what a new connection picks.\n *\n * A caller applies these only where the user has not chosen the option, so a\n * preference never overrides a deliberate decision.\n */\nexport interface ConnectionPreference {\n readonly side: 'source' | 'target';\n readonly option: string;\n readonly value: string;\n /** Why this is the better default, phrased for the user. */\n readonly reason: string;\n}\n\n/** An agent target only attaches to an http gateway, an MCP server only to an mcp one. */\nconst GATEWAY_PREFERS_HTTP: ConnectionPreference = {\n side: 'source',\n option: 'protocol',\n value: 'http',\n reason:\n 'Agent runtime targets are proxied by an http gateway, so attaching an agent selects that protocol.',\n};\n\nconst GATEWAY_PREFERS_MCP: ConnectionPreference = {\n side: 'source',\n option: 'protocol',\n value: 'mcp',\n reason:\n 'MCP server targets are aggregated by an mcp gateway, so attaching an MCP server selects that protocol.',\n};\n\n/**\n * Preferred option values per connection. Keyed by `ConnectionKey`, so a key that\n * no longer names a supported connection is a compile error.\n */\nexport const CONNECTION_PREFERENCES = {\n 'ts#react-website -> ts#agent': [\n {\n side: 'target',\n option: 'protocol',\n value: 'ag-ui',\n reason:\n 'AG-UI is the protocol built for driving a frontend, so a website connection selects it.',\n },\n ],\n 'ts#react-website -> py#agent': [\n {\n side: 'target',\n option: 'protocol',\n value: 'ag-ui',\n reason:\n 'AG-UI is the protocol built for driving a frontend, so a website connection selects it.',\n },\n ],\n // A gateway's protocol is decided by what it fronts, and the two are mutually\n // exclusive: agent runtime targets need an http gateway, MCP server targets an\n // mcp one. The gateway schema defaults to mcp, so only the agent side needs a\n // preference — but both are stated, so whichever target the user attaches\n // first settles the protocol.\n 'agentcore-gateway -> ts#agent': [GATEWAY_PREFERS_HTTP],\n 'agentcore-gateway -> py#agent': [GATEWAY_PREFERS_HTTP],\n 'agentcore-gateway -> ts#mcp-server': [GATEWAY_PREFERS_MCP],\n 'agentcore-gateway -> py#mcp-server': [GATEWAY_PREFERS_MCP],\n 'ts#react-website -> agentcore-gateway': [\n {\n side: 'target',\n option: 'protocol',\n value: 'http',\n reason:\n 'A website reaches a gateway’s agent targets over path-based http routing, so the gateway serves the http protocol.',\n },\n ],\n} as const satisfies Partial<\n Record<ConnectionKey, readonly ConnectionPreference[]>\n>;\n\n/**\n * Connections that must be generated after another, because the generator reads\n * state the earlier one records.\n *\n * The website→gateway generator publishes a route per agent already attached to\n * the gateway, reading them from the gateway project's connection metadata. Run\n * before the gateway→agent connections, it finds none and wires up nothing.\n *\n * Keyed by `ConnectionKey`, so a key that no longer names a supported connection\n * is a compile error.\n */\nexport const CONNECTION_ORDERING = {\n 'ts#react-website -> agentcore-gateway': {\n after: ['agentcore-gateway -> ts#agent', 'agentcore-gateway -> py#agent'],\n reason:\n 'The website connection publishes a route per agent attached to the gateway, so the gateway’s agents must be attached first.',\n },\n} as const satisfies Partial<\n Record<\n ConnectionKey,\n { readonly after: readonly ConnectionKey[]; readonly reason: string }\n >\n>;\n\n/**\n * Connections whose source and target must be distinct projects, because the\n * connection generator refuses to wire a project to itself.\n */\nexport const SELF_CONNECTION_DISALLOWED = [\n 'agentcore-gateway -> agentcore-gateway',\n] as const satisfies readonly ConnectionKey[];\n"],"names":["GeneratorsJson","type","SUPPORTED_CONNECTIONS","GENERATORS","generators","schemaPathOf","generatorId","entry","Error","schema","languageOf","id","includes","slice","indexOf","alike","a","b","replace","toLowerCase","findWrapper","endpointType","schemaOf","language","name","Object","entries","hidden","wrapperName","option","property","properties","value","enum","generator","options","undefined","deriveScaffoldRecipe","own","wrapper","kind","required","hostGenerator","label","host","fromEntries","filter","map","default","String","snakeCaseName","CONNECTION_ENDPOINT_TYPES","Set","flatMap","source","target","sort","buildScaffoldRecipes","AGENT_TO_AGENT","side","equals","reason","WEBSITE_TO_AGENT","notEquals","AGENT_TO_MCP","AGENT_TO_GATEWAY","GATEWAY_TO_MCP","GATEWAY_TO_AGENT","CONNECTION_CONSTRAINTS","ENDPOINT_FOLLOW_UPS","adds","GATEWAY_PREFERS_HTTP","GATEWAY_PREFERS_MCP","CONNECTION_PREFERENCES","CONNECTION_ORDERING","after","SELF_CONNECTION_DISALLOWED"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../packages/nx-plugin/src/connection/scaffold-catalog.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport GeneratorsJson from '../../generators.json' with { type: 'json' };\nimport {\n type ConnectionKey,\n SUPPORTED_CONNECTIONS,\n type SUPPORTED_PROJECT_TYPES,\n} from './supported-connections.js';\n\n/**\n * How to scaffold each end of a connection, derived from the plugin's own\n * metadata rather than hand-listed.\n *\n * Every connection endpoint type is also a generator id, which is what makes the\n * derivation possible:\n *\n * - **kind** — a generator whose schema `required`s a `project` adds a component\n * to an existing project; anything else creates a project of its own.\n * - **host** — a component lands in a project made by its language's base\n * generator (`ts#project` / `py#project`).\n * - **generator + options** — a type whose own generator is `hidden` is reached\n * through the public wrapper that selects it, found by matching the wrapper's\n * enum values against the type's name (`ts#trpc-api` ← `ts#api\n * --framework=trpc`). A visible generator is run directly.\n *\n * - **label** — the generator schema's own `x-label`.\n *\n * The result is that adding a generator and a connection for it needs no edit\n * here at all. The one thing still declared below is the option constraints,\n * which live as imperative guards inside each connection generator and so cannot\n * be read from metadata.\n */\n\n/**\n * Every type that can sit at either end of a connection: the project-level\n * types resolved by introspection, plus the component generator ids recorded in\n * component metadata.\n */\nexport type ConnectionEndpointType =\n | (typeof SUPPORTED_PROJECT_TYPES)[number]\n | (typeof SUPPORTED_CONNECTIONS)[number]['source']\n | (typeof SUPPORTED_CONNECTIONS)[number]['target'];\n\n/**\n * Whether scaffolding an endpoint creates a project of its own, or adds a\n * component to a project that must already exist.\n */\nexport type ScaffoldKind = 'project' | 'component';\n\n/** How to scaffold one end of a connection from the CLI. */\nexport interface ScaffoldRecipe {\n /** Human-readable name for this endpoint type. */\n readonly label: string;\n /** The generator id in `generators.json` that produces this endpoint. */\n readonly generator: string;\n /**\n * Options that select this endpoint type from its generator, for generators\n * producing more than one type (e.g. `framework`).\n */\n readonly options?: Readonly<Record<string, string>>;\n /** Whether the generator creates a project or adds a component to one. */\n readonly kind: ScaffoldKind;\n /**\n * The generator producing a project able to host this component, for\n * `component` recipes. Components are added to an existing project, so one\n * must be scaffolded first.\n */\n readonly host?: {\n readonly generator: string;\n readonly options?: Readonly<Record<string, string>>;\n /**\n * Whether the host project's name is referenced in snake_case. Python\n * project names are snake_cased when qualified, TypeScript ones are not.\n */\n readonly snakeCaseName?: boolean;\n };\n}\n\ntype GeneratorEntry = { schema: string; hidden?: boolean };\n/** The subset of JSON Schema the catalogue and the docs builder read. */\nexport type GeneratorSchema = {\n /**\n * Short display name for the thing this generator produces, used by the docs\n * graph builder's palette. Set it on any generator that can take part in a\n * connection.\n */\n 'x-label'?: string;\n properties?: Record<\n string,\n {\n type?: string;\n description?: string;\n enum?: string[];\n default?: unknown;\n 'x-priority'?: string;\n /** The option values this option applies under. */\n 'x-when'?: Record<string, string | string[]>;\n /** The same, per value, where one of an option's values applies sometimes. */\n 'x-value-when'?: Record<string, Record<string, string | string[]>>;\n }\n >;\n required?: string[];\n};\n\ntype Schema = GeneratorSchema;\n\nconst GENERATORS = GeneratorsJson.generators as Record<string, GeneratorEntry>;\n\n/**\n * Resolves a generator's JSON schema by generator id.\n *\n * Injected rather than fixed because the two callers load files differently: the\n * plugin reads from disk (see `./schema-resolver`), while the docs site bundles\n * the schemas for the browser, where `node:fs` does not exist. Keeping this\n * module free of `node:fs` is what lets the browser import it at all.\n */\nexport type SchemaResolver = (generatorId: string) => Schema;\n\n/** The path `generators.json` records for a generator, relative to the plugin root. */\nexport const schemaPathOf = (generatorId: string): string => {\n const entry = GENERATORS[generatorId];\n if (!entry) {\n throw new Error(\n `Scaffold catalog: '${generatorId}' is not in generators.json`,\n );\n }\n return entry.schema;\n};\n\n/** The language prefix of a generator id: `ts` for `ts#agent`, `` for `license`. */\nconst languageOf = (id: string): string =>\n id.includes('#') ? id.slice(0, id.indexOf('#')) : '';\n\n/** Compare ids ignoring the separators that differ between wrapper and variant. */\nconst alike = (a: string, b: string): boolean =>\n a.replace(/[^a-z0-9]/gi, '').toLowerCase() ===\n b.replace(/[^a-z0-9]/gi, '').toLowerCase();\n\n/**\n * The public generator and option value that select a hidden endpoint type.\n *\n * A wrapper like `ts#api` produces several endpoint types, choosing between them\n * with an enum option: `--framework=trpc` yields `ts#trpc-api`. The pairing is\n * found by looking for a same-language public generator with an enum value that\n * reconstructs the endpoint's own name.\n */\nconst findWrapper = (\n endpointType: string,\n schemaOf: SchemaResolver,\n): { generator: string; options: Record<string, string> } | undefined => {\n const language = languageOf(endpointType);\n const name = endpointType.slice(endpointType.indexOf('#') + 1);\n\n for (const [generatorId, entry] of Object.entries(GENERATORS)) {\n if (entry.hidden) continue;\n if (languageOf(generatorId) !== language) continue;\n const wrapperName = generatorId.slice(generatorId.indexOf('#') + 1);\n\n for (const [option, property] of Object.entries(\n schemaOf(generatorId).properties ?? {},\n )) {\n for (const value of property.enum ?? []) {\n // Either the value names the variant outright (`react` for\n // `react-website`), or it qualifies the wrapper's own name\n // (`trpc` + `api` for `trpc-api`).\n if (alike(value, name) || alike(`${value}${wrapperName}`, name)) {\n return { generator: generatorId, options: { [option]: value } };\n }\n }\n }\n }\n return undefined;\n};\n\n/**\n * Derive the recipe for one endpoint type. Exported so a test can assert the\n * derivation against every type the plugin supports.\n */\nexport const deriveScaffoldRecipe = (\n endpointType: string,\n schemaOf: SchemaResolver,\n): ScaffoldRecipe => {\n const own = GENERATORS[endpointType];\n if (!own) {\n throw new Error(\n `Scaffold catalog: connection endpoint '${endpointType}' is not a generator id`,\n );\n }\n\n // A hidden generator is an implementation detail reached through its public\n // wrapper, which is what a user would actually run.\n const wrapper = own.hidden ? findWrapper(endpointType, schemaOf) : undefined;\n if (own.hidden && !wrapper) {\n throw new Error(\n `Scaffold catalog: '${endpointType}' is hidden and no public generator selects it`,\n );\n }\n\n // A generator requiring a `project` adds a component to one; anything else\n // creates its own project.\n const kind: ScaffoldKind = (schemaOf(endpointType).required ?? []).includes(\n 'project',\n )\n ? 'component'\n : 'project';\n\n const language = languageOf(endpointType);\n const hostGenerator = `${language}#project`;\n if (kind === 'component' && !GENERATORS[hostGenerator]) {\n throw new Error(\n `Scaffold catalog: '${endpointType}' is a component but '${hostGenerator}' does not exist to host it`,\n );\n }\n\n return {\n // `x-label` is the short noun a palette entry needs; `title` and\n // `description` are prose aimed at CLI prompts (\"Create a relational database\n // project\"). A generator without one falls back to its id, so a new endpoint\n // type still appears rather than being dropped.\n label: schemaOf(endpointType)['x-label'] ?? endpointType,\n generator: wrapper?.generator ?? endpointType,\n ...(wrapper ? { options: wrapper.options } : {}),\n kind,\n ...(kind === 'component'\n ? {\n host: {\n generator: hostGenerator,\n // Only options the host's schema actually requires, so a base\n // project generator gaining a required option is handled here.\n options: Object.fromEntries(\n (schemaOf(hostGenerator).required ?? [])\n .filter((option) => option !== 'name')\n .map((option) => {\n const property = schemaOf(hostGenerator).properties?.[option];\n const value = property?.default ?? property?.enum?.[0];\n if (value === undefined) {\n throw new Error(\n `Scaffold catalog: '${hostGenerator}' requires '${option}' but its schema offers no value to use`,\n );\n }\n return [option, String(value)];\n }),\n ),\n // Python project names are snake_cased when Nx qualifies them.\n snakeCaseName: language === 'py',\n },\n }\n : {}),\n };\n};\n\n/** Every endpoint type appearing at either end of a supported connection. */\nexport const CONNECTION_ENDPOINT_TYPES: readonly string[] = [\n ...new Set(\n SUPPORTED_CONNECTIONS.flatMap(({ source, target }) => [source, target]),\n ),\n].sort();\n\n/**\n * How to scaffold each connection endpoint type, derived from the generator\n * metadata. A connection added to `SUPPORTED_CONNECTIONS` appears here with no\n * edit to this file.\n */\nexport const buildScaffoldRecipes = (\n schemaOf: SchemaResolver,\n): Readonly<Record<string, ScaffoldRecipe>> =>\n Object.fromEntries(\n CONNECTION_ENDPOINT_TYPES.map((type) => [\n type,\n deriveScaffoldRecipe(type, schemaOf),\n ]),\n );\n\n/**\n * An option value one end of a connection must hold for a constraint to apply,\n * narrowing a rule that only binds some of a connection's configurations.\n */\nexport interface ConnectionConstraintCondition {\n /** Which end of the connection the conditioning option belongs to. */\n readonly side: 'source' | 'target';\n /** The generator option whose value decides whether the constraint applies. */\n readonly option: string;\n /** The value that brings the constraint into effect. */\n readonly equals: string;\n}\n\n/**\n * A requirement one end of a connection places on the other's options, mirroring\n * the guard the corresponding connection generator enforces.\n *\n * Declared rather than derived: each guard is an imperative `throw` inside its\n * connection generator, reachable only by running it. Recording them here lets a\n * caller choosing options up front check them first, and the paired test asserts\n * every entry names a real option with a value its enum allows.\n */\nexport interface ConnectionConstraint {\n /** Which end of the connection the constrained option belongs to. */\n readonly side: 'source' | 'target';\n /** The generator option carrying the constrained value. */\n readonly option: string;\n /** The only value accepted, if the option is pinned to one. */\n readonly equals?: string;\n /** A value rejected, for options accepting all but one. */\n readonly notEquals?: string;\n /**\n * Limits the rule to connections whose endpoints read this way. Absent for a\n * rule binding every connection of its kind.\n */\n readonly when?: ConnectionConstraintCondition;\n /** Why the constraint exists, phrased for the user choosing the option. */\n readonly reason: string;\n}\n\n/** Reusable constraint shapes, so the map below states each rule once. */\nconst AGENT_TO_AGENT: readonly ConnectionConstraint[] = [\n {\n side: 'target',\n option: 'protocol',\n equals: 'a2a',\n reason: 'Only an A2A agent can be connected to another agent as a tool.',\n },\n {\n side: 'target',\n option: 'auth',\n equals: 'iam',\n reason: 'A2A agent connections authenticate with IAM.',\n },\n];\n\nconst WEBSITE_TO_AGENT: readonly ConnectionConstraint[] = [\n {\n side: 'target',\n option: 'protocol',\n notEquals: 'a2a',\n reason:\n 'A2A agents are reached by other agents, not by a website. Use the http or ag-ui protocol.',\n },\n];\n\nconst AGENT_TO_MCP: readonly ConnectionConstraint[] = [\n {\n side: 'target',\n option: 'auth',\n equals: 'iam',\n reason: 'An agent reaches an MCP server with IAM authentication.',\n },\n];\n\n// The agent's own `auth` governs inbound requests to it, so it places no\n// requirement here — the agent signs its outbound call to the gateway with\n// SigV4 from its execution role either way.\nconst AGENT_TO_GATEWAY: readonly ConnectionConstraint[] = [\n {\n side: 'target',\n option: 'auth',\n equals: 'iam',\n reason: 'Agent connections require the gateway to authenticate with IAM.',\n },\n {\n side: 'target',\n option: 'protocol',\n equals: 'mcp',\n reason:\n 'An agent reaches a gateway as an MCP client, so the gateway must serve the mcp protocol. Note a single gateway cannot both front an agent and be called by one, since fronting requires the http protocol.',\n },\n];\n\nconst GATEWAY_TO_MCP: readonly ConnectionConstraint[] = [\n {\n side: 'source',\n option: 'protocol',\n equals: 'mcp',\n reason:\n 'MCP server targets can only be attached to an mcp-protocol gateway.',\n },\n {\n side: 'target',\n option: 'auth',\n equals: 'iam',\n reason: 'A gateway reaches an MCP server target with IAM authentication.',\n },\n];\n\nconst GATEWAY_TO_AGENT: readonly ConnectionConstraint[] = [\n {\n side: 'source',\n option: 'protocol',\n equals: 'http',\n reason:\n 'Agent runtime targets can only be attached to an http-protocol gateway.',\n },\n {\n side: 'source',\n option: 'auth',\n equals: 'cognito',\n when: { side: 'target', option: 'auth', equals: 'cognito' },\n reason:\n \"A Cognito agent authorizes on the caller's forwarded JWT, which only a Cognito gateway receives. An IAM gateway can front an IAM agent, which it invokes with its own role.\",\n },\n];\n\n/**\n * The option-level requirements each connection places on its endpoints.\n *\n * Only connections carrying a requirement appear. Keyed by `ConnectionKey`, so a\n * key that no longer names a supported connection is a compile error.\n */\nexport const CONNECTION_CONSTRAINTS = {\n 'ts#react-website -> ts#agent': WEBSITE_TO_AGENT,\n 'ts#react-website -> py#agent': WEBSITE_TO_AGENT,\n 'ts#agent -> ts#agent': AGENT_TO_AGENT,\n 'ts#agent -> py#agent': AGENT_TO_AGENT,\n 'py#agent -> ts#agent': AGENT_TO_AGENT,\n 'py#agent -> py#agent': AGENT_TO_AGENT,\n 'ts#agent -> ts#mcp-server': AGENT_TO_MCP,\n 'ts#agent -> py#mcp-server': AGENT_TO_MCP,\n 'py#agent -> ts#mcp-server': AGENT_TO_MCP,\n 'py#agent -> py#mcp-server': AGENT_TO_MCP,\n 'ts#agent -> agentcore-gateway': AGENT_TO_GATEWAY,\n 'py#agent -> agentcore-gateway': AGENT_TO_GATEWAY,\n 'ts#react-website -> agentcore-gateway': [\n {\n side: 'target',\n option: 'protocol',\n equals: 'http',\n reason:\n 'A website connects to an http-protocol gateway, which proxies requests to its agent targets.',\n },\n ],\n 'agentcore-gateway -> ts#agent': [\n ...GATEWAY_TO_AGENT,\n {\n side: 'target',\n option: 'protocol',\n notEquals: 'http',\n reason:\n 'A TypeScript http agent serves tRPC over WebSocket, which AgentCore Gateway does not support. Use the ag-ui or a2a protocol.',\n },\n ],\n 'agentcore-gateway -> py#agent': GATEWAY_TO_AGENT,\n 'agentcore-gateway -> ts#mcp-server': GATEWAY_TO_MCP,\n 'agentcore-gateway -> py#mcp-server': GATEWAY_TO_MCP,\n 'agentcore-gateway -> agentcore-gateway': [\n {\n side: 'source',\n option: 'protocol',\n equals: 'mcp',\n reason:\n 'A gateway is aggregated into another as an MCP target, so both must be mcp-protocol gateways.',\n },\n {\n side: 'target',\n option: 'protocol',\n equals: 'mcp',\n reason:\n 'A gateway is aggregated into another as an MCP target, so both must be mcp-protocol gateways.',\n },\n {\n side: 'target',\n option: 'auth',\n equals: 'iam',\n reason:\n 'The source gateway signs its request with IAM, so the target gateway must accept IAM.',\n },\n ],\n} as const satisfies Partial<\n Record<ConnectionKey, readonly ConnectionConstraint[]>\n>;\n\n/**\n * A generator run automatically after an endpoint is scaffolded, adding something\n * that endpoint should always have.\n *\n * A website is only useful with authentication in front of it, and `ts#website`\n * does not add it — `ts#website#auth` is a separate follow-up generator. Declared\n * here so the docs graph builder emits it without hardcoding the pairing.\n */\nexport interface FollowUpGenerator {\n /** The generator id to run after the endpoint's own. */\n readonly generator: string;\n /** Options to pass, beyond the `--project` naming the endpoint. */\n readonly options?: Readonly<Record<string, string>>;\n /** What it adds, for the emitted command's comment. */\n readonly adds: string;\n}\n\n/**\n * Generators run automatically after an endpoint type is scaffolded, keyed by\n * endpoint type.\n */\nexport const ENDPOINT_FOLLOW_UPS: Readonly<\n Record<string, readonly FollowUpGenerator[]>\n> = {\n 'ts#react-website': [\n {\n generator: 'ts#website#auth',\n // `cognitoDomain` is derived from the npm scope and project name when\n // omitted, so the command stays short.\n adds: 'Cognito authentication',\n },\n ],\n};\n\n/**\n * An option value a connection works best against, without requiring it.\n *\n * Distinct from `CONNECTION_CONSTRAINTS`: a constraint is a rule the connection\n * generator enforces, whereas a preference is the setting most users want. A\n * React website can call an `http` agent perfectly well, but AG-UI is the\n * protocol built for driving a frontend, so that is what a new connection picks.\n *\n * A caller applies these only where the user has not chosen the option, so a\n * preference never overrides a deliberate decision.\n */\nexport interface ConnectionPreference {\n readonly side: 'source' | 'target';\n readonly option: string;\n readonly value: string;\n /** Why this is the better default, phrased for the user. */\n readonly reason: string;\n}\n\n/** An agent target only attaches to an http gateway, an MCP server only to an mcp one. */\nconst GATEWAY_PREFERS_HTTP: ConnectionPreference = {\n side: 'source',\n option: 'protocol',\n value: 'http',\n reason:\n 'Agent runtime targets are proxied by an http gateway, so attaching an agent selects that protocol.',\n};\n\nconst GATEWAY_PREFERS_MCP: ConnectionPreference = {\n side: 'source',\n option: 'protocol',\n value: 'mcp',\n reason:\n 'MCP server targets are aggregated by an mcp gateway, so attaching an MCP server selects that protocol.',\n};\n\n/**\n * Preferred option values per connection. Keyed by `ConnectionKey`, so a key that\n * no longer names a supported connection is a compile error.\n */\nexport const CONNECTION_PREFERENCES = {\n 'ts#react-website -> ts#agent': [\n {\n side: 'target',\n option: 'protocol',\n value: 'ag-ui',\n reason:\n 'AG-UI is the protocol built for driving a frontend, so a website connection selects it.',\n },\n ],\n 'ts#react-website -> py#agent': [\n {\n side: 'target',\n option: 'protocol',\n value: 'ag-ui',\n reason:\n 'AG-UI is the protocol built for driving a frontend, so a website connection selects it.',\n },\n ],\n // A gateway's protocol is decided by what it fronts, and the two are mutually\n // exclusive: agent runtime targets need an http gateway, MCP server targets an\n // mcp one. The gateway schema defaults to mcp, so only the agent side needs a\n // preference — but both are stated, so whichever target the user attaches\n // first settles the protocol.\n 'agentcore-gateway -> ts#agent': [GATEWAY_PREFERS_HTTP],\n 'agentcore-gateway -> py#agent': [GATEWAY_PREFERS_HTTP],\n 'agentcore-gateway -> ts#mcp-server': [GATEWAY_PREFERS_MCP],\n 'agentcore-gateway -> py#mcp-server': [GATEWAY_PREFERS_MCP],\n 'ts#react-website -> agentcore-gateway': [\n {\n side: 'target',\n option: 'protocol',\n value: 'http',\n reason:\n 'A website reaches a gateway’s agent targets over path-based http routing, so the gateway serves the http protocol.',\n },\n ],\n} as const satisfies Partial<\n Record<ConnectionKey, readonly ConnectionPreference[]>\n>;\n\n/**\n * Connections that must be generated after another, because the generator reads\n * state the earlier one records.\n *\n * The website→gateway generator publishes a route per agent already attached to\n * the gateway, reading them from the gateway project's connection metadata. Run\n * before the gateway→agent connections, it finds none and wires up nothing.\n *\n * Keyed by `ConnectionKey`, so a key that no longer names a supported connection\n * is a compile error.\n */\nexport const CONNECTION_ORDERING = {\n 'ts#react-website -> agentcore-gateway': {\n after: ['agentcore-gateway -> ts#agent', 'agentcore-gateway -> py#agent'],\n reason:\n 'The website connection publishes a route per agent attached to the gateway, so the gateway’s agents must be attached first.',\n },\n} as const satisfies Partial<\n Record<\n ConnectionKey,\n { readonly after: readonly ConnectionKey[]; readonly reason: string }\n >\n>;\n\n/**\n * Connections whose source and target must be distinct projects, because the\n * connection generator refuses to wire a project to itself.\n */\nexport const SELF_CONNECTION_DISALLOWED = [\n 'agentcore-gateway -> agentcore-gateway',\n] as const satisfies readonly ConnectionKey[];\n"],"names":["GeneratorsJson","type","SUPPORTED_CONNECTIONS","GENERATORS","generators","schemaPathOf","generatorId","entry","Error","schema","languageOf","id","includes","slice","indexOf","alike","a","b","replace","toLowerCase","findWrapper","endpointType","schemaOf","language","name","Object","entries","hidden","wrapperName","option","property","properties","value","enum","generator","options","undefined","deriveScaffoldRecipe","own","wrapper","kind","required","hostGenerator","label","host","fromEntries","filter","map","default","String","snakeCaseName","CONNECTION_ENDPOINT_TYPES","Set","flatMap","source","target","sort","buildScaffoldRecipes","AGENT_TO_AGENT","side","equals","reason","WEBSITE_TO_AGENT","notEquals","AGENT_TO_MCP","AGENT_TO_GATEWAY","GATEWAY_TO_MCP","GATEWAY_TO_AGENT","when","CONNECTION_CONSTRAINTS","ENDPOINT_FOLLOW_UPS","adds","GATEWAY_PREFERS_HTTP","GATEWAY_PREFERS_MCP","CONNECTION_PREFERENCES","CONNECTION_ORDERING","after","SELF_CONNECTION_DISALLOWED"],"mappings":"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"}
@@ -47,7 +47,7 @@ export declare const DEPENDENCIES: import("../../utils/declared-dependencies.js"
47
47
  readonly when: (m: import("../../utils/shared-constructs-constants.js").IacMetadata) => boolean;
48
48
  } & {
49
49
  versionOnly: true;
50
- }], readonly import("../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
50
+ }], readonly import("../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
51
51
  export declare const INFRA_APP_GENERATOR_INFO: NxGeneratorInfo;
52
52
  export declare function tsInfraGenerator(tree: Tree, schema: TsInfraGeneratorSchema): Promise<GeneratorCallback>;
53
53
  export default tsInfraGenerator;
@@ -17,7 +17,7 @@ export declare const DEPENDENCIES: import("../utils/declared-dependencies.js").D
17
17
  readonly name: "typescript";
18
18
  }, {
19
19
  readonly name: "@biomejs/biome";
20
- }], readonly import("../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
20
+ }], readonly import("../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
21
21
  export declare const INIT_GENERATOR_INFO: NxGeneratorInfo;
22
22
  /**
23
23
  * Configure an existing Nx workspace to use the @aws/nx-plugin.
@@ -12,7 +12,8 @@
12
12
  * 3. Component transforms — `<NxCommands>` / `<RunGenerator>` /
13
13
  * `<GeneratorParameters>` / `<CreateNxWorkspaceCommand>` /
14
14
  * `<InstallCommand>` / `<PackageManagerShortCommand>` /
15
- * `<PackageManagerExecCommand>` render down to markdown.
15
+ * `<PackageManagerExecCommand>` render down to markdown, and
16
+ * `<ArchitectureDiagram>` drops out as it has no text form.
16
17
  */
17
18
  import type { Root } from 'mdast';
18
19
  import type { NxGeneratorInfo } from '../utils/generators.js';
@@ -348,6 +348,12 @@ const renderComponent = (node, opts, pm, deps)=>{
348
348
  codeBlock(commands.map((c)=>buildPackageManagerExecCommand(pm, c)).join('\n'))
349
349
  ];
350
350
  }
351
+ // A diagram of the AWS resources a project deploys, drawn from the docs
352
+ // site's own artwork. There is nothing to render as text — the prose beside
353
+ // it describes the same architecture — so it is dropped rather than left as
354
+ // a stray tag.
355
+ case 'ArchitectureDiagram':
356
+ return [];
351
357
  default:
352
358
  return undefined;
353
359
  }