@aws/nx-plugin 1.0.0-rc.58 → 1.0.0-rc.59
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/generators.json +17 -1
- package/migrations.json +12 -7
- package/package.json +1 -1
- package/src/agentcore-gateway/__snapshots__/generator.spec.ts.snap +273 -0
- package/src/agentcore-gateway/agent-connection/generator.d.ts +19 -0
- package/src/agentcore-gateway/agent-connection/generator.js +90 -0
- package/src/agentcore-gateway/agent-connection/generator.js.map +1 -0
- package/src/agentcore-gateway/agent-connection/schema.d.js +6 -0
- package/src/agentcore-gateway/agent-connection/schema.d.js.map +1 -0
- package/src/agentcore-gateway/agent-connection/schema.d.ts +13 -0
- package/src/agentcore-gateway/agent-connection/schema.json +31 -0
- package/src/agentcore-gateway/attach-upstream.d.ts +16 -0
- package/src/agentcore-gateway/attach-upstream.js +32 -11
- package/src/agentcore-gateway/attach-upstream.js.map +1 -1
- package/src/agentcore-gateway/files/project/http/local-dev.ts.template +77 -0
- package/src/agentcore-gateway/generator.d.ts +1 -0
- package/src/agentcore-gateway/generator.js +22 -10
- package/src/agentcore-gateway/generator.js.map +1 -1
- package/src/agentcore-gateway/react-connection/__snapshots__/generator.spec.ts.snap +68 -0
- package/src/agentcore-gateway/react-connection/generator.d.ts +19 -0
- package/src/agentcore-gateway/react-connection/generator.js +119 -0
- package/src/agentcore-gateway/react-connection/generator.js.map +1 -0
- package/src/agentcore-gateway/react-connection/schema.d.js +6 -0
- package/src/agentcore-gateway/react-connection/schema.d.js.map +1 -0
- package/src/agentcore-gateway/react-connection/schema.d.ts +13 -0
- package/src/agentcore-gateway/react-connection/schema.json +31 -0
- package/src/agentcore-gateway/schema.d.js.map +1 -1
- package/src/agentcore-gateway/schema.d.ts +1 -1
- package/src/agentcore-gateway/schema.json +2 -2
- package/src/connection/agent-local-dev.d.ts +16 -0
- package/src/connection/agent-local-dev.js +44 -2
- package/src/connection/agent-local-dev.js.map +1 -1
- package/src/connection/gateway-runtime-config.d.ts +19 -0
- package/src/connection/gateway-runtime-config.js +47 -0
- package/src/connection/gateway-runtime-config.js.map +1 -0
- package/src/connection/generator.js +5 -0
- package/src/connection/generator.js.map +1 -1
- package/src/connection/scaffold-catalog.d.ts +107 -0
- package/src/connection/scaffold-catalog.js +140 -0
- package/src/connection/scaffold-catalog.js.map +1 -1
- package/src/connection/supported-connections.d.ts +9 -0
- package/src/connection/supported-connections.js +12 -0
- package/src/connection/supported-connections.js.map +1 -1
- package/src/internal/test-matrix/generator.js +39 -1
- package/src/internal/test-matrix/generator.js.map +1 -1
- package/src/migrations/latest/gateway-agent-targets/__snapshots__/migration.spec.ts.snap +223 -0
- package/src/migrations/latest/gateway-agent-targets/metadata.json +3 -0
- package/src/migrations/latest/gateway-agent-targets/migration.d.ts +6 -0
- package/src/migrations/latest/gateway-agent-targets/migration.js +217 -0
- package/src/migrations/latest/gateway-agent-targets/migration.js.map +1 -0
- package/src/migrations/latest/smithy-ssdk-bundle-pins/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.50/modernize-function-props-cast/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.50/restrict-cors-to-custom-domains/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.50/terraform-bootstrap-adopt-existing-bucket/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.52/user-identity-waf-allow-localhost-callback/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.54/order-access-log-delivery-after-bucket-policy/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.55/backfill-generator-metadata/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.56/dynamodb-local-remove-optimize-flag/metadata.json +3 -0
- package/src/migrations/v1.0.0-rc.57/ts-agent-session-management-support/metadata.json +3 -0
- package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +2 -0
- package/src/py/agent/react-connection/generator.d.ts +4 -1
- package/src/py/agent/react-connection/generator.js +35 -14
- package/src/py/agent/react-connection/generator.js.map +1 -1
- package/src/ts/agent/__snapshots__/generator.spec.ts.snap +4 -0
- package/src/ts/agent/react-connection/generator.d.ts +16 -1
- package/src/ts/agent/react-connection/generator.js +21 -8
- package/src/ts/agent/react-connection/generator.js.map +1 -1
- package/src/ts/nx-migration/generator.js +40 -27
- package/src/ts/nx-migration/generator.js.map +1 -1
- package/src/ts/react-website/agui/files/common/src/hooks/useAgui__agentNameClassName__.tsx.template +16 -0
- package/src/ts/react-website/agui/generator.d.ts +11 -0
- package/src/ts/react-website/agui/generator.js +11 -7
- package/src/ts/react-website/agui/generator.js.map +1 -1
- package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +5 -0
- package/src/utils/agent-core-constructs/agent-core-constructs.js +2 -0
- 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 +3 -0
- package/src/utils/agent-core-constructs/files/cdk/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.ts.template +6 -4
- package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +119 -3
- package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.tf.template +17 -0
- package/src/utils/config/utils.d.ts +5 -0
- package/src/utils/config/utils.js +7 -1
- package/src/utils/config/utils.js.map +1 -1
- package/src/utils/connection/open-api/files/components/__apiNameClassName__Provider.tsx.template +13 -2
- package/src/utils/connection/open-api/react.d.ts +10 -1
- package/src/utils/connection/open-api/react.js +3 -2
- package/src/utils/connection/open-api/react.js.map +1 -1
- package/src/utils/migration-manifest.d.ts +58 -0
- package/src/utils/migration-manifest.js +76 -0
- package/src/utils/migration-manifest.js.map +1 -0
- package/src/utils/migration-versions.d.ts +2 -0
- package/src/utils/migration-versions.js.map +1 -1
- package/src/utils/version-upgrade-migration/register.d.ts +4 -2
- package/src/utils/version-upgrade-migration/register.js +13 -13
- package/src/utils/version-upgrade-migration/register.js.map +1 -1
- /package/src/agentcore-gateway/files/project/{local-dev.ts.template → mcp/local-dev.ts.template} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/py/agent/react-connection/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { addAgentRuntimeToConnectionNamespace } from '../../../connection/agent-runtime-config';\nimport type { ResolvedConnectionOptions } from '../../../connection/generator';\nimport {\n DEPENDENCIES as AGUI_DEPENDENCIES,\n type AgUiAuth,\n addAgUiReactConnection,\n resolveAgUiTheme,\n} from '../../../ts/react-website/agui/generator';\nimport {\n addOpenApiReactClient,\n OPEN_API_REACT_DEPENDENCIES,\n} from '../../../utils/connection/open-api/react';\nimport {\n declareDependencies,\n onlyWhen,\n} from '../../../utils/declared-dependencies';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { installDependencies } from '../../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics';\nimport { kebabCase, toClassName, toSnakeCase } from '../../../utils/names';\nimport {\n addComponentGeneratorMetadata,\n type ComponentMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../../utils/nx';\nimport { sortObjectKeys } from '../../../utils/object';\nimport { toProjectRelativePath } from '../../../utils/paths';\nimport {\n addPyAgentTargetToLocalDev,\n openApiClientLocalDevDeps,\n} from './local-dev';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface PyAgentReactConnectionMetadata {\n readonly protocol: string;\n readonly auth: string;\n /** The AG-UI theme module, which the website's `ux` selects. */\n readonly theme: string;\n}\n\n/** The OpenAPI-over-HTTP path, which the AG-UI path takes none of. */\nconst isHttp = (m: PyAgentReactConnectionMetadata) => m.protocol !== 'ag-ui';\n\n/** The AG-UI path, whose packages `addAgUiReactConnection` adds. */\nconst isAgUi = (m: PyAgentReactConnectionMetadata) => !isHttp(m);\n\n// Each entry names the protocol path it belongs to: the HTTP path's OpenAPI\n// client packages are added by `addOpenApiReactClient`, the AG-UI path's by\n// `addAgUiReactConnection`, both on this generator's behalf. The AG-UI entries\n// keep their own theme and auth conditions, which the metadata below records.\nexport const DEPENDENCIES =\n declareDependencies<PyAgentReactConnectionMetadata>()({\n ts: [\n ...onlyWhen(OPEN_API_REACT_DEPENDENCIES, isHttp),\n ...onlyWhen(AGUI_DEPENDENCIES.ts, isAgUi),\n ],\n });\n\nexport const PY_AGENT_REACT_CONNECTION_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\nexport const pyAgentReactConnectionGenerator = async (\n tree: Tree,\n options: ResolvedConnectionOptions,\n) => {\n const frontendProjectConfig = readProjectConfigurationUnqualified(\n tree,\n options.sourceProject,\n );\n const agentProjectConfig = readProjectConfigurationUnqualified(\n tree,\n options.targetProject,\n );\n\n const targetComponent: ComponentMetadata | undefined =\n options.targetComponent;\n\n // Extract agent metadata from the target component or project metadata\n const metadata = agentProjectConfig.metadata as any;\n const agentName = targetComponent?.name ?? 'agent';\n const agentNameClassName = targetComponent?.rc ?? toClassName(agentName);\n const agentPort = targetComponent?.port ?? metadata?.ports?.[0] ?? 8081;\n const auth = (targetComponent?.auth ?? metadata?.auth ?? 'iam').toLowerCase();\n const protocol = (targetComponent?.protocol ?? 'http').toLowerCase();\n\n // Recorded below and read by the declaration's predicates, so the packages\n // added here are exactly the ones the version sync will own.\n const connectionMetadata: PyAgentReactConnectionMetadata = {\n protocol,\n auth,\n theme: resolveAgUiTheme(frontendProjectConfig),\n };\n\n if (protocol === 'a2a') {\n throw new Error(\n `Cannot connect a React website to an A2A agent. ` +\n `Consider generating an agent with the HTTP or AG-UI protocol instead.`,\n );\n }\n\n let additionalLocalDevDeps: string[] = [];\n\n if (protocol === 'ag-ui') {\n await addAgUiReactConnection(tree, {\n frontendProjectConfig,\n agentName,\n agentNameClassName,\n auth: auth as AgUiAuth,\n });\n } else {\n const moduleName = getModuleName(agentProjectConfig);\n const agentNameSnakeCase = toSnakeCase(agentName);\n const agentTargetPrefix = targetComponent?.name ? agentName : 'agent';\n\n // Add OpenAPI spec generation script scoped to this agent\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files/agent'),\n agentProjectConfig.root,\n {\n moduleName,\n agentNameSnakeCase,\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Instrument the OpenAPI spec generation as a target on the agent project\n const openApiTargetName = `${agentTargetPrefix}-openapi`;\n const openApiDist = joinPathFragments(\n 'dist',\n agentProjectConfig.root,\n 'openapi',\n agentNameSnakeCase,\n );\n const specPath = joinPathFragments(openApiDist, 'openapi.json');\n\n updateProjectConfiguration(tree, agentProjectConfig.name, {\n ...agentProjectConfig,\n targets: sortObjectKeys({\n ...agentProjectConfig.targets,\n [openApiTargetName]: {\n cache: true,\n executor: 'nx:run-commands',\n outputs: [\n `{workspaceRoot}/dist/{projectRoot}/openapi/${agentNameSnakeCase}`,\n ],\n options: {\n commands: [\n `uv run python {projectRoot}/scripts/${agentNameSnakeCase}_openapi.py \"dist/{projectRoot}/openapi/${agentNameSnakeCase}/openapi.json\"`,\n ],\n },\n },\n }),\n });\n\n // Use the shared OpenAPI react client utility for hooks, providers, and build targets.\n // The dev target is handled separately below using the agent-specific dev target.\n await addOpenApiReactClient(\n tree,\n {\n apiName: agentNameClassName,\n frontendProjectConfig,\n backendProjectConfig: agentProjectConfig,\n specBuildProject: agentProjectConfig,\n specPath,\n specBuildTargetName: `${agentProjectConfig.name}:${openApiTargetName}`,\n auth,\n port: agentPort,\n isAgentRuntime: true,\n skipLocalDev: true,\n },\n DEPENDENCIES,\n );\n\n additionalLocalDevDeps = openApiClientLocalDevDeps(agentNameClassName);\n\n // HTTP only — the AG-UI branch handles this inside addAgUiReactConnection.\n // Agent constructs publish their runtime ARN to the 'agentcore' namespace\n // by default, which isn't exposed to the website; patch them to also\n // publish under 'connection' so the browser can read it.\n await addAgentRuntimeToConnectionNamespace(tree, {\n agentNameKebabCase: kebabCase(agentNameClassName),\n agentNameClassName,\n });\n }\n\n await addPyAgentTargetToLocalDev(\n tree,\n frontendProjectConfig.name,\n agentProjectConfig.name,\n {\n agentName,\n agentNameClassName,\n port: agentPort,\n targetComponent,\n additionalDependencyTargets: additionalLocalDevDeps,\n },\n );\n\n // Recorded so the version sync knows this connection's dependencies are ours.\n addComponentGeneratorMetadata(\n tree,\n frontendProjectConfig.name,\n PY_AGENT_REACT_CONNECTION_GENERATOR_INFO,\n toProjectRelativePath(\n frontendProjectConfig,\n protocol === 'ag-ui'\n ? joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'hooks',\n `useAgui${agentNameClassName}`,\n )\n : joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'components',\n `${agentNameClassName}Provider`,\n ),\n ),\n agentNameClassName,\n connectionMetadata,\n );\n\n await addGeneratorMetricsIfApplicable(tree, [\n PY_AGENT_REACT_CONNECTION_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\n/**\n * Determine the Python module name from the project configuration\n */\nconst getModuleName = (\n projectConfig: ReturnType<typeof readProjectConfigurationUnqualified>,\n): string => {\n if (projectConfig.sourceRoot) {\n const sourceRootParts = projectConfig.sourceRoot.split('/');\n return sourceRootParts[sourceRootParts.length - 1];\n }\n throw new Error(\n `Could not determine sourceRoot for project ${projectConfig.name}`,\n );\n};\n\nexport default pyAgentReactConnectionGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","addAgentRuntimeToConnectionNamespace","DEPENDENCIES","AGUI_DEPENDENCIES","addAgUiReactConnection","resolveAgUiTheme","addOpenApiReactClient","OPEN_API_REACT_DEPENDENCIES","declareDependencies","onlyWhen","formatFilesInSubtree","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toSnakeCase","addComponentGeneratorMetadata","getGeneratorInfo","readProjectConfigurationUnqualified","sortObjectKeys","toProjectRelativePath","addPyAgentTargetToLocalDev","openApiClientLocalDevDeps","isHttp","m","protocol","isAgUi","ts","PY_AGENT_REACT_CONNECTION_GENERATOR_INFO","filename","pyAgentReactConnectionGenerator","tree","options","frontendProjectConfig","sourceProject","agentProjectConfig","targetProject","targetComponent","metadata","agentName","name","agentNameClassName","rc","agentPort","port","ports","auth","toLowerCase","connectionMetadata","theme","Error","additionalLocalDevDeps","moduleName","getModuleName","agentNameSnakeCase","agentTargetPrefix","dirname","root","overwriteStrategy","KeepExisting","openApiTargetName","openApiDist","specPath","targets","cache","executor","outputs","commands","apiName","backendProjectConfig","specBuildProject","specBuildTargetName","isAgentRuntime","skipLocalDev","agentNameKebabCase","additionalDependencyTargets","sourceRoot","preferInstallDependencies","languages","projectConfig","sourceRootParts","split","length"],"mappings":"AAAA;;;CAGC,GACD,SACEA,aAAa,EACbC,iBAAiB,EACjBC,iBAAiB,EAEjBC,0BAA0B,QACrB,aAAa;AACpB,SAASC,oCAAoC,QAAQ,8CAA2C;AAEhG,SACEC,gBAAgBC,iBAAiB,EAEjCC,sBAAsB,EACtBC,gBAAgB,QACX,8CAA2C;AAClD,SACEC,qBAAqB,EACrBC,2BAA2B,QACtB,8CAA2C;AAClD,SACEC,mBAAmB,EACnBC,QAAQ,QACH,0CAAuC;AAC9C,SAASC,oBAAoB,QAAQ,2BAAwB;AAC7D,SAASC,mBAAmB,QAAQ,4BAAyB;AAC7D,SAASC,+BAA+B,QAAQ,4BAAyB;AACzE,SAASC,SAAS,EAAEC,WAAW,EAAEC,WAAW,QAAQ,0BAAuB;AAC3E,SACEC,6BAA6B,EAE7BC,gBAAgB,EAEhBC,mCAAmC,QAC9B,uBAAoB;AAC3B,SAASC,cAAc,QAAQ,2BAAwB;AACvD,SAASC,qBAAqB,QAAQ,0BAAuB;AAC7D,SACEC,0BAA0B,EAC1BC,yBAAyB,QACpB,iBAAc;AAUrB,oEAAoE,GACpE,MAAMC,SAAS,CAACC,IAAsCA,EAAEC,QAAQ,KAAK;AAErE,kEAAkE,GAClE,MAAMC,SAAS,CAACF,IAAsC,CAACD,OAAOC;AAE9D,4EAA4E;AAC5E,4EAA4E;AAC5E,+EAA+E;AAC/E,8EAA8E;AAC9E,OAAO,MAAMtB,eACXM,sBAAsD;IACpDmB,IAAI;WACClB,SAASF,6BAA6BgB;WACtCd,SAASN,kBAAkBwB,EAAE,EAAED;KACnC;AACH,GAAG;AAEL,OAAO,MAAME,2CACXX,iBAAiB,YAAYY,QAAQ,EAAE;AAEzC,OAAO,MAAMC,kCAAkC,OAC7CC,MACAC;IAEA,MAAMC,wBAAwBf,oCAC5Ba,MACAC,QAAQE,aAAa;IAEvB,MAAMC,qBAAqBjB,oCACzBa,MACAC,QAAQI,aAAa;IAGvB,MAAMC,kBACJL,QAAQK,eAAe;IAEzB,uEAAuE;IACvE,MAAMC,WAAWH,mBAAmBG,QAAQ;IAC5C,MAAMC,YAAYF,iBAAiBG,QAAQ;IAC3C,MAAMC,qBAAqBJ,iBAAiBK,MAAM5B,YAAYyB;IAC9D,MAAMI,YAAYN,iBAAiBO,QAAQN,UAAUO,OAAO,CAAC,EAAE,IAAI;IACnE,MAAMC,OAAO,AAACT,CAAAA,iBAAiBS,QAAQR,UAAUQ,QAAQ,KAAI,EAAGC,WAAW;IAC3E,MAAMtB,WAAW,AAACY,CAAAA,iBAAiBZ,YAAY,MAAK,EAAGsB,WAAW;IAElE,2EAA2E;IAC3E,6DAA6D;IAC7D,MAAMC,qBAAqD;QACzDvB;QACAqB;QACAG,OAAO5C,iBAAiB4B;IAC1B;IAEA,IAAIR,aAAa,OAAO;QACtB,MAAM,IAAIyB,MACR,CAAC,gDAAgD,CAAC,GAChD,CAAC,qEAAqE,CAAC;IAE7E;IAEA,IAAIC,yBAAmC,EAAE;IAEzC,IAAI1B,aAAa,SAAS;QACxB,MAAMrB,uBAAuB2B,MAAM;YACjCE;YACAM;YACAE;YACAK,MAAMA;QACR;IACF,OAAO;QACL,MAAMM,aAAaC,cAAclB;QACjC,MAAMmB,qBAAqBvC,YAAYwB;QACvC,MAAMgB,oBAAoBlB,iBAAiBG,OAAOD,YAAY;QAE9D,0DAA0D;QAC1D1C,cACEkC,MACAjC,kBAAkB,YAAY0D,OAAO,EAAE,gBACvCrB,mBAAmBsB,IAAI,EACvB;YACEL;YACAE;QACF,GACA;YACEI,mBAAmB3D,kBAAkB4D,YAAY;QACnD;QAGF,0EAA0E;QAC1E,MAAMC,oBAAoB,GAAGL,kBAAkB,QAAQ,CAAC;QACxD,MAAMM,cAAc/D,kBAClB,QACAqC,mBAAmBsB,IAAI,EACvB,WACAH;QAEF,MAAMQ,WAAWhE,kBAAkB+D,aAAa;QAEhD7D,2BAA2B+B,MAAMI,mBAAmBK,IAAI,EAAE;YACxD,GAAGL,kBAAkB;YACrB4B,SAAS5C,eAAe;gBACtB,GAAGgB,mBAAmB4B,OAAO;gBAC7B,CAACH,kBAAkB,EAAE;oBACnBI,OAAO;oBACPC,UAAU;oBACVC,SAAS;wBACP,CAAC,2CAA2C,EAAEZ,oBAAoB;qBACnE;oBACDtB,SAAS;wBACPmC,UAAU;4BACR,CAAC,oCAAoC,EAAEb,mBAAmB,wCAAwC,EAAEA,mBAAmB,cAAc,CAAC;yBACvI;oBACH;gBACF;YACF;QACF;QAEA,uFAAuF;QACvF,kFAAkF;QAClF,MAAMhD,sBACJyB,MACA;YACEqC,SAAS3B;YACTR;YACAoC,sBAAsBlC;YACtBmC,kBAAkBnC;YAClB2B;YACAS,qBAAqB,GAAGpC,mBAAmBK,IAAI,CAAC,CAAC,EAAEoB,mBAAmB;YACtEd;YACAF,MAAMD;YACN6B,gBAAgB;YAChBC,cAAc;QAChB,GACAvE;QAGFiD,yBAAyB7B,0BAA0BmB;QAEnD,2EAA2E;QAC3E,0EAA0E;QAC1E,qEAAqE;QACrE,yDAAyD;QACzD,MAAMxC,qCAAqC8B,MAAM;YAC/C2C,oBAAoB7D,UAAU4B;YAC9BA;QACF;IACF;IAEA,MAAMpB,2BACJU,MACAE,sBAAsBO,IAAI,EAC1BL,mBAAmBK,IAAI,EACvB;QACED;QACAE;QACAG,MAAMD;QACNN;QACAsC,6BAA6BxB;IAC/B;IAGF,8EAA8E;IAC9EnC,8BACEe,MACAE,sBAAsBO,IAAI,EAC1BZ,0CACAR,sBACEa,uBACAR,aAAa,UACT3B,kBACEmC,sBAAsB2C,UAAU,EAChC,SACA,CAAC,OAAO,EAAEnC,oBAAoB,IAEhC3C,kBACEmC,sBAAsB2C,UAAU,EAChC,cACA,GAAGnC,mBAAmB,QAAQ,CAAC,IAGvCA,oBACAO;IAGF,MAAMpC,gCAAgCmB,MAAM;QAC1CH;KACD;IAED,MAAMlB,qBAAqBqB;IAC3B,OAAO,IACLpB,oBAAoBoB,MAAMC,QAAQ6C,yBAAyB,EAAE;YAC3DC,WAAW;gBAAC;aAAa;QAC3B;AACJ,EAAE;AAEF;;CAEC,GACD,MAAMzB,gBAAgB,CACpB0B;IAEA,IAAIA,cAAcH,UAAU,EAAE;QAC5B,MAAMI,kBAAkBD,cAAcH,UAAU,CAACK,KAAK,CAAC;QACvD,OAAOD,eAAe,CAACA,gBAAgBE,MAAM,GAAG,EAAE;IACpD;IACA,MAAM,IAAIhC,MACR,CAAC,2CAA2C,EAAE6B,cAAcvC,IAAI,EAAE;AAEtE;AAEA,eAAeV,gCAAgC"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/py/agent/react-connection/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { addAgentRuntimeToConnectionNamespace } from '../../../connection/agent-runtime-config';\nimport type { ResolvedConnectionOptions } from '../../../connection/generator';\nimport type { AgentGatewayRoute } from '../../../ts/agent/react-connection/generator';\nimport {\n DEPENDENCIES as AGUI_DEPENDENCIES,\n type AgUiAuth,\n addAgUiReactConnection,\n resolveAgUiTheme,\n} from '../../../ts/react-website/agui/generator';\nimport {\n addOpenApiReactClient,\n OPEN_API_REACT_DEPENDENCIES,\n} from '../../../utils/connection/open-api/react';\nimport {\n declareDependencies,\n onlyWhen,\n} from '../../../utils/declared-dependencies';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { installDependencies } from '../../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics';\nimport { kebabCase, toClassName, toSnakeCase } from '../../../utils/names';\nimport {\n addComponentGeneratorMetadata,\n addDependencyToTargetIfNotPresent,\n type ComponentMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../../utils/nx';\nimport { sortObjectKeys } from '../../../utils/object';\nimport { toProjectRelativePath } from '../../../utils/paths';\nimport {\n addPyAgentTargetToLocalDev,\n openApiClientLocalDevDeps,\n} from './local-dev';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface PyAgentReactConnectionMetadata {\n readonly protocol: string;\n readonly auth: string;\n /** The AG-UI theme module, which the website's `ux` selects. */\n readonly theme: string;\n}\n\n/** The OpenAPI-over-HTTP path, which the AG-UI path takes none of. */\nconst isHttp = (m: PyAgentReactConnectionMetadata) => m.protocol !== 'ag-ui';\n\n/** The AG-UI path, whose packages `addAgUiReactConnection` adds. */\nconst isAgUi = (m: PyAgentReactConnectionMetadata) => !isHttp(m);\n\n// Each entry names the protocol path it belongs to: the HTTP path's OpenAPI\n// client packages are added by `addOpenApiReactClient`, the AG-UI path's by\n// `addAgUiReactConnection`, both on this generator's behalf. The AG-UI entries\n// keep their own theme and auth conditions, which the metadata below records.\nexport const DEPENDENCIES =\n declareDependencies<PyAgentReactConnectionMetadata>()({\n ts: [\n ...onlyWhen(OPEN_API_REACT_DEPENDENCIES, isHttp),\n ...onlyWhen(AGUI_DEPENDENCIES.ts, isAgUi),\n ],\n });\n\nexport const PY_AGENT_REACT_CONNECTION_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\nexport const pyAgentReactConnectionGenerator = async (\n tree: Tree,\n options: ResolvedConnectionOptions & { gatewayRoute?: AgentGatewayRoute },\n) => {\n const frontendProjectConfig = readProjectConfigurationUnqualified(\n tree,\n options.sourceProject,\n );\n const agentProjectConfig = readProjectConfigurationUnqualified(\n tree,\n options.targetProject,\n );\n\n const targetComponent: ComponentMetadata | undefined =\n options.targetComponent;\n\n // Extract agent metadata from the target component or project metadata\n const metadata = agentProjectConfig.metadata as any;\n const agentName = targetComponent?.name ?? 'agent';\n const agentNameClassName = targetComponent?.rc ?? toClassName(agentName);\n const agentPort = targetComponent?.port ?? metadata?.ports?.[0] ?? 8081;\n // Behind a gateway the browser authenticates with the gateway, not the agent.\n const auth = (\n options.gatewayRoute?.gatewayAuth ??\n targetComponent?.auth ??\n metadata?.auth ??\n 'iam'\n ).toLowerCase();\n const protocol = (targetComponent?.protocol ?? 'http').toLowerCase();\n\n // Recorded below and read by the declaration's predicates, so the packages\n // added here are exactly the ones the version sync will own.\n const connectionMetadata: PyAgentReactConnectionMetadata = {\n protocol,\n auth,\n theme: resolveAgUiTheme(frontendProjectConfig),\n };\n\n if (protocol === 'a2a') {\n throw new Error(\n `Cannot connect a React website to an A2A agent. ` +\n `Consider generating an agent with the HTTP or AG-UI protocol instead.`,\n );\n }\n\n let additionalLocalDevDeps: string[] = [];\n\n if (protocol === 'ag-ui') {\n await addAgUiReactConnection(tree, {\n frontendProjectConfig,\n agentName,\n agentNameClassName,\n auth: auth as AgUiAuth,\n gatewayRoute: options.gatewayRoute,\n });\n } else {\n const moduleName = getModuleName(agentProjectConfig);\n const agentNameSnakeCase = toSnakeCase(agentName);\n const agentTargetPrefix = targetComponent?.name ? agentName : 'agent';\n\n // Add OpenAPI spec generation script scoped to this agent\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files/agent'),\n agentProjectConfig.root,\n {\n moduleName,\n agentNameSnakeCase,\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Instrument the OpenAPI spec generation as a target on the agent project\n const openApiTargetName = `${agentTargetPrefix}-openapi`;\n const openApiDist = joinPathFragments(\n 'dist',\n agentProjectConfig.root,\n 'openapi',\n agentNameSnakeCase,\n );\n const specPath = joinPathFragments(openApiDist, 'openapi.json');\n\n updateProjectConfiguration(tree, agentProjectConfig.name, {\n ...agentProjectConfig,\n targets: sortObjectKeys({\n ...agentProjectConfig.targets,\n [openApiTargetName]: {\n cache: true,\n executor: 'nx:run-commands',\n outputs: [\n `{workspaceRoot}/dist/{projectRoot}/openapi/${agentNameSnakeCase}`,\n ],\n options: {\n commands: [\n `uv run python {projectRoot}/scripts/${agentNameSnakeCase}_openapi.py \"dist/{projectRoot}/openapi/${agentNameSnakeCase}/openapi.json\"`,\n ],\n },\n },\n }),\n });\n\n // Use the shared OpenAPI react client utility for hooks, providers, and build targets.\n // The dev target is handled separately below using the agent-specific dev target.\n await addOpenApiReactClient(\n tree,\n {\n apiName: agentNameClassName,\n frontendProjectConfig,\n backendProjectConfig: agentProjectConfig,\n specBuildProject: agentProjectConfig,\n specPath,\n specBuildTargetName: `${agentProjectConfig.name}:${openApiTargetName}`,\n auth,\n port: agentPort,\n isAgentRuntime: true,\n gatewayRoute: options.gatewayRoute,\n skipLocalDev: true,\n },\n DEPENDENCIES,\n );\n\n additionalLocalDevDeps = openApiClientLocalDevDeps(agentNameClassName);\n\n // HTTP only — the AG-UI branch handles this inside addAgUiReactConnection.\n // Agent constructs publish their runtime ARN to the 'agentcore' namespace\n // by default, which isn't exposed to the website; patch them to also\n // publish under 'connection' so the browser can read it. When routing via\n // a gateway, the gateway publishes its own URL instead.\n if (!options.gatewayRoute) {\n await addAgentRuntimeToConnectionNamespace(tree, {\n agentNameKebabCase: kebabCase(agentNameClassName),\n agentNameClassName,\n });\n }\n }\n\n if (options.gatewayRoute) {\n // The gateway react-connection wires the website's dev target to the\n // local gateway (which proxies to the agent); only the OpenAPI client\n // generation targets are still needed here.\n if (additionalLocalDevDeps.length > 0) {\n const websiteConfig = readProjectConfigurationUnqualified(\n tree,\n frontendProjectConfig.name,\n );\n if (websiteConfig.targets?.['dev']) {\n for (const additional of additionalLocalDevDeps) {\n addDependencyToTargetIfNotPresent(websiteConfig, 'dev', additional);\n }\n updateProjectConfiguration(tree, websiteConfig.name, websiteConfig);\n }\n }\n } else {\n await addPyAgentTargetToLocalDev(\n tree,\n frontendProjectConfig.name,\n agentProjectConfig.name,\n {\n agentName,\n agentNameClassName,\n port: agentPort,\n targetComponent,\n additionalDependencyTargets: additionalLocalDevDeps,\n },\n );\n }\n\n // Recorded so the version sync knows this connection's dependencies are ours.\n addComponentGeneratorMetadata(\n tree,\n frontendProjectConfig.name,\n PY_AGENT_REACT_CONNECTION_GENERATOR_INFO,\n toProjectRelativePath(\n frontendProjectConfig,\n protocol === 'ag-ui'\n ? joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'hooks',\n `useAgui${agentNameClassName}`,\n )\n : joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'components',\n `${agentNameClassName}Provider`,\n ),\n ),\n agentNameClassName,\n connectionMetadata,\n );\n\n await addGeneratorMetricsIfApplicable(tree, [\n PY_AGENT_REACT_CONNECTION_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n};\n\n/**\n * Determine the Python module name from the project configuration\n */\nconst getModuleName = (\n projectConfig: ReturnType<typeof readProjectConfigurationUnqualified>,\n): string => {\n if (projectConfig.sourceRoot) {\n const sourceRootParts = projectConfig.sourceRoot.split('/');\n return sourceRootParts[sourceRootParts.length - 1];\n }\n throw new Error(\n `Could not determine sourceRoot for project ${projectConfig.name}`,\n );\n};\n\nexport default pyAgentReactConnectionGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","addAgentRuntimeToConnectionNamespace","DEPENDENCIES","AGUI_DEPENDENCIES","addAgUiReactConnection","resolveAgUiTheme","addOpenApiReactClient","OPEN_API_REACT_DEPENDENCIES","declareDependencies","onlyWhen","formatFilesInSubtree","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toSnakeCase","addComponentGeneratorMetadata","addDependencyToTargetIfNotPresent","getGeneratorInfo","readProjectConfigurationUnqualified","sortObjectKeys","toProjectRelativePath","addPyAgentTargetToLocalDev","openApiClientLocalDevDeps","isHttp","m","protocol","isAgUi","ts","PY_AGENT_REACT_CONNECTION_GENERATOR_INFO","filename","pyAgentReactConnectionGenerator","tree","options","frontendProjectConfig","sourceProject","agentProjectConfig","targetProject","targetComponent","metadata","agentName","name","agentNameClassName","rc","agentPort","port","ports","auth","gatewayRoute","gatewayAuth","toLowerCase","connectionMetadata","theme","Error","additionalLocalDevDeps","moduleName","getModuleName","agentNameSnakeCase","agentTargetPrefix","dirname","root","overwriteStrategy","KeepExisting","openApiTargetName","openApiDist","specPath","targets","cache","executor","outputs","commands","apiName","backendProjectConfig","specBuildProject","specBuildTargetName","isAgentRuntime","skipLocalDev","agentNameKebabCase","length","websiteConfig","additional","additionalDependencyTargets","sourceRoot","preferInstallDependencies","languages","projectConfig","sourceRootParts","split"],"mappings":"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"}
|
|
@@ -722,6 +722,8 @@ export class SnapshotBedrockAgent
|
|
|
722
722
|
{
|
|
723
723
|
public readonly dockerImage: AgentRuntimeArtifact;
|
|
724
724
|
public readonly agentCoreRuntime: Runtime;
|
|
725
|
+
/** Default Gateway target name for this agent. */
|
|
726
|
+
public readonly agentName = 'snapshot-bedrock-agent';
|
|
725
727
|
|
|
726
728
|
constructor(scope: Construct, id: string, props?: SnapshotBedrockAgentProps) {
|
|
727
729
|
super(scope, id);
|
|
@@ -2355,6 +2357,8 @@ export class InMemoryAgent
|
|
|
2355
2357
|
{
|
|
2356
2358
|
public readonly dockerImage: AgentRuntimeArtifact;
|
|
2357
2359
|
public readonly agentCoreRuntime: Runtime;
|
|
2360
|
+
/** Default Gateway target name for this agent. */
|
|
2361
|
+
public readonly agentName = 'in-memory-agent';
|
|
2358
2362
|
|
|
2359
2363
|
constructor(scope: Construct, id: string, props?: InMemoryAgentProps) {
|
|
2360
2364
|
super(scope, id);
|
|
@@ -192,5 +192,20 @@ export declare const DEPENDENCIES: import("../../../utils/declared-dependencies"
|
|
|
192
192
|
versionOnly: true;
|
|
193
193
|
}], readonly import("../../../utils/declared-dependencies").DeclaredPyDependency<"a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "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" | "mcp" | "pip-check-updates" | "pip-licenses" | "ruff" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", TsAgentReactConnectionMetadata>[]>;
|
|
194
194
|
export declare const TS_AGENT_REACT_CONNECTION_GENERATOR_INFO: NxGeneratorInfo;
|
|
195
|
-
|
|
195
|
+
/**
|
|
196
|
+
* Options for routing the website's requests to the agent through an
|
|
197
|
+
* AgentCore Gateway rather than invoking the runtime directly. The gateway
|
|
198
|
+
* react-connection generator dispatches here once per fronted agent.
|
|
199
|
+
*/
|
|
200
|
+
export interface AgentGatewayRoute {
|
|
201
|
+
/** The gateway's class name, keying its URL in runtime config. */
|
|
202
|
+
gatewayClassName: string;
|
|
203
|
+
/** The agent's gateway target name, forming its path on the gateway. */
|
|
204
|
+
targetName: string;
|
|
205
|
+
/** The gateway's inbound auth, which is what the browser authenticates with. */
|
|
206
|
+
gatewayAuth: string;
|
|
207
|
+
}
|
|
208
|
+
export declare function tsAgentReactConnectionGenerator(tree: Tree, options: ResolvedConnectionOptions & {
|
|
209
|
+
gatewayRoute?: AgentGatewayRoute;
|
|
210
|
+
}): Promise<() => Promise<void>>;
|
|
196
211
|
export default tsAgentReactConnectionGenerator;
|
|
@@ -75,7 +75,8 @@ export async function tsAgentReactConnectionGenerator(tree, options) {
|
|
|
75
75
|
const agentName = targetComponent?.name ?? 'agent';
|
|
76
76
|
const agentNameClassName = targetComponent?.rc ?? toClassName(agentName);
|
|
77
77
|
const agentPort = targetComponent?.port ?? metadata?.ports?.[0] ?? 8081;
|
|
78
|
-
|
|
78
|
+
// Behind a gateway the browser authenticates with the gateway, not the agent.
|
|
79
|
+
const auth = (options.gatewayRoute?.gatewayAuth ?? targetComponent?.auth ?? metadata?.auth ?? 'iam').toLowerCase();
|
|
79
80
|
const agentProjectAlias = agentProjectConfig.name;
|
|
80
81
|
const agentPath = targetComponent?.path ?? 'src/agent';
|
|
81
82
|
// Recorded below and read by the declaration's predicates, so the packages
|
|
@@ -88,19 +89,31 @@ export async function tsAgentReactConnectionGenerator(tree, options) {
|
|
|
88
89
|
if ((targetComponent?.protocol ?? '').toLowerCase() === 'a2a') {
|
|
89
90
|
throw new Error(`Cannot connect a React website to an A2A agent. ` + `Consider generating an agent with the HTTP or AG-UI protocol instead.`);
|
|
90
91
|
}
|
|
92
|
+
// A TypeScript HTTP agent serves tRPC over WebSocket, which AgentCore
|
|
93
|
+
// Gateway does not support, so only AG-UI agents can be reached via a
|
|
94
|
+
// gateway route.
|
|
95
|
+
if (options.gatewayRoute && targetComponent?.protocol !== 'ag-ui') {
|
|
96
|
+
throw new Error(`Cannot connect a React website to agent '${agentName}' via a gateway: a TypeScript HTTP agent serves tRPC over WebSocket, which AgentCore Gateway does not support. Consider the ag-ui protocol instead.`);
|
|
97
|
+
}
|
|
91
98
|
if (targetComponent?.protocol === 'ag-ui') {
|
|
92
99
|
await addAgUiReactConnection(tree, {
|
|
93
100
|
frontendProjectConfig,
|
|
94
101
|
agentName,
|
|
95
102
|
agentNameClassName,
|
|
96
|
-
auth: auth
|
|
97
|
-
|
|
98
|
-
await addTsAgentTargetToLocalDev(tree, frontendProjectConfig.name, agentProjectConfig.name, {
|
|
99
|
-
agentName,
|
|
100
|
-
agentNameClassName,
|
|
101
|
-
port: agentPort,
|
|
102
|
-
targetComponent
|
|
103
|
+
auth: auth,
|
|
104
|
+
gatewayRoute: options.gatewayRoute
|
|
103
105
|
});
|
|
106
|
+
// When routing via a gateway, the gateway react-connection wires the
|
|
107
|
+
// website's dev target to the local gateway (which proxies to the agent)
|
|
108
|
+
// instead of to the agent directly.
|
|
109
|
+
if (!options.gatewayRoute) {
|
|
110
|
+
await addTsAgentTargetToLocalDev(tree, frontendProjectConfig.name, agentProjectConfig.name, {
|
|
111
|
+
agentName,
|
|
112
|
+
agentNameClassName,
|
|
113
|
+
port: agentPort,
|
|
114
|
+
targetComponent
|
|
115
|
+
});
|
|
116
|
+
}
|
|
104
117
|
// Recorded so the version sync knows this connection's dependencies are ours.
|
|
105
118
|
addComponentGeneratorMetadata(tree, frontendProjectConfig.name, TS_AGENT_REACT_CONNECTION_GENERATOR_INFO, toProjectRelativePath(frontendProjectConfig, joinPathFragments(frontendProjectConfig.sourceRoot, 'hooks', `useAgui${agentNameClassName}`)), agentNameClassName, connectionMetadata);
|
|
106
119
|
await addGeneratorMetricsIfApplicable(tree, [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/ts/agent/react-connection/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { addAgentRuntimeToConnectionNamespace } from '../../../connection/agent-runtime-config';\nimport type { ResolvedConnectionOptions } from '../../../connection/generator';\nimport { addTsDependencies } from '../../../utils/add-dependencies';\nimport { addSingleImport, applyGritQL } from '../../../utils/ast';\nimport {\n declareDependencies,\n onlyWhen,\n ownedElsewhere,\n} from '../../../utils/declared-dependencies';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { installDependencies } from '../../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics';\nimport { kebabCase, toClassName } from '../../../utils/names';\nimport {\n addComponentGeneratorMetadata,\n type ComponentMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../../utils/nx';\nimport { toProjectRelativePath } from '../../../utils/paths';\nimport {\n DEPENDENCIES as AGUI_DEPENDENCIES,\n type AgUiAuth,\n addAgUiReactConnection,\n resolveAgUiTheme,\n} from '../../react-website/agui/generator';\nimport { runtimeConfigGenerator } from '../../react-website/runtime-config/generator';\nimport { addTsAgentTargetToLocalDev } from './local-dev';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface TsAgentReactConnectionMetadata {\n readonly auth: string;\n readonly protocol: string;\n /** The AG-UI theme module, which the website's `ux` selects. */\n readonly theme: string;\n}\n\n/** The tRPC-over-HTTP path, which the AG-UI path takes none of. */\nconst isHttp = (m: TsAgentReactConnectionMetadata) => m.protocol !== 'ag-ui';\n\n/** The AG-UI path, whose packages `addAgUiReactConnection` adds. */\nconst isAgUi = (m: TsAgentReactConnectionMetadata) => !isHttp(m);\n\n// Each entry names the protocol path it belongs to: the HTTP path's client and\n// auth packages are added here, the AG-UI path's by `addAgUiReactConnection` on\n// this generator's behalf.\nexport const DEPENDENCIES =\n declareDependencies<TsAgentReactConnectionMetadata>()({\n ts: [\n { name: '@trpc/client', when: isHttp },\n { name: '@tanstack/react-query', when: isHttp },\n { name: '@tanstack/react-query-devtools', when: isHttp },\n { name: '@trpc/tanstack-react-query', when: isHttp },\n { name: 'oidc-client-ts', when: (m) => isHttp(m) && m.auth === 'iam' },\n { name: 'aws4fetch', when: (m) => isHttp(m) && m.auth === 'iam' },\n {\n name: '@aws-sdk/credential-provider-cognito-identity',\n when: (m) => isHttp(m) && m.auth === 'iam',\n },\n {\n name: 'react-oidc-context',\n when: (m) => isHttp(m) && (m.auth === 'iam' || m.auth === 'cognito'),\n },\n { name: '@smithy/types', when: isHttp, dev: true },\n // `addAgUiReactConnection` adds these itself, so they are declared for\n // ownership only. Gated on the AG-UI path, and within it on each entry's\n // own theme or auth condition, which the metadata below records.\n ...ownedElsewhere(onlyWhen(AGUI_DEPENDENCIES.ts, isAgUi)),\n ],\n });\n\nexport const TS_AGENT_REACT_CONNECTION_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\nexport async function tsAgentReactConnectionGenerator(\n tree: Tree,\n options: ResolvedConnectionOptions,\n) {\n const frontendProjectConfig = readProjectConfigurationUnqualified(\n tree,\n options.sourceProject,\n );\n const agentProjectConfig = readProjectConfigurationUnqualified(\n tree,\n options.targetProject,\n );\n\n const targetComponent: ComponentMetadata | undefined =\n options.targetComponent;\n\n // Extract agent metadata from the target component or project metadata\n const metadata = agentProjectConfig.metadata as any;\n const agentName = targetComponent?.name ?? 'agent';\n const agentNameClassName = targetComponent?.rc ?? toClassName(agentName);\n const agentPort = targetComponent?.port ?? metadata?.ports?.[0] ?? 8081;\n const auth = (targetComponent?.auth ?? metadata?.auth ?? 'iam').toLowerCase();\n const agentProjectAlias = agentProjectConfig.name;\n const agentPath = targetComponent?.path ?? 'src/agent';\n\n // Recorded below and read by the declaration's predicates, so the packages\n // added here are exactly the ones the version sync will own.\n const connectionMetadata: TsAgentReactConnectionMetadata = {\n auth,\n protocol: targetComponent?.protocol ?? 'http',\n theme: resolveAgUiTheme(frontendProjectConfig),\n };\n\n if ((targetComponent?.protocol ?? '').toLowerCase() === 'a2a') {\n throw new Error(\n `Cannot connect a React website to an A2A agent. ` +\n `Consider generating an agent with the HTTP or AG-UI protocol instead.`,\n );\n }\n\n if (targetComponent?.protocol === 'ag-ui') {\n await addAgUiReactConnection(tree, {\n frontendProjectConfig,\n agentName,\n agentNameClassName,\n auth: auth as AgUiAuth,\n });\n\n await addTsAgentTargetToLocalDev(\n tree,\n frontendProjectConfig.name,\n agentProjectConfig.name,\n {\n agentName,\n agentNameClassName,\n port: agentPort,\n targetComponent,\n },\n );\n\n // Recorded so the version sync knows this connection's dependencies are ours.\n addComponentGeneratorMetadata(\n tree,\n frontendProjectConfig.name,\n TS_AGENT_REACT_CONNECTION_GENERATOR_INFO,\n toProjectRelativePath(\n frontendProjectConfig,\n joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'hooks',\n `useAgui${agentNameClassName}`,\n ),\n ),\n agentNameClassName,\n connectionMetadata,\n );\n\n await addGeneratorMetricsIfApplicable(tree, [\n TS_AGENT_REACT_CONNECTION_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n }\n\n // Ensure the agent project has a wildcard path entry in tsconfig.base.json\n // so that deep imports (e.g., for the router type) resolve correctly\n ensureWildcardPathEntry(\n tree,\n agentProjectConfig.name,\n agentProjectConfig.root,\n );\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files'),\n frontendProjectConfig.root,\n {\n agentName,\n agentNameClassName,\n auth,\n agentProjectAlias,\n agentPath,\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Generate the tanstack query provider if it does not exist already\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n '../../../utils/files/website/components/tanstack-query',\n ),\n joinPathFragments(frontendProjectConfig.sourceRoot, 'components'),\n {},\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n if (auth === 'iam') {\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n '../../../utils/files/website/hooks/sigv4',\n ),\n joinPathFragments(frontendProjectConfig.sourceRoot, 'hooks'),\n {},\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n }\n\n await runtimeConfigGenerator(tree, {\n project: frontendProjectConfig.name,\n preferInstallDependencies: false,\n });\n\n // update main.tsx\n const mainTsxPath = joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'main.tsx',\n );\n await addSingleImport(\n tree,\n mainTsxPath,\n 'QueryClientProvider',\n './components/QueryClientProvider',\n );\n\n const clientProviderName = `${agentNameClassName}AgentClientProvider`;\n await addSingleImport(\n tree,\n mainTsxPath,\n clientProviderName,\n `./components/${clientProviderName}`,\n );\n\n // Wrap <App /> in QueryClientProvider if not already present\n await applyGritQL(\n tree,\n mainTsxPath,\n '`<App />` => `<QueryClientProvider><App /></QueryClientProvider>` where { $program <: not contains `<QueryClientProvider>$_</QueryClientProvider>` }',\n );\n\n // Wrap <App /> in the agent client provider if not already present\n await applyGritQL(\n tree,\n mainTsxPath,\n `\\`<App />\\` => \\`<${clientProviderName}><App /></${clientProviderName}>\\` where { $program <: not contains \\`<${clientProviderName}>$_</${clientProviderName}>\\` }`,\n );\n\n await addTsAgentTargetToLocalDev(\n tree,\n frontendProjectConfig.name,\n agentProjectConfig.name,\n {\n agentName,\n agentNameClassName,\n port: agentPort,\n targetComponent,\n },\n );\n\n // Expose the agent's runtime ARN to the frontend via the 'connection'\n // namespace (which is published to runtime-config.json). The agent construct\n // itself only registers to the 'agentcore' namespace by default.\n await addAgentRuntimeToConnectionNamespace(tree, {\n agentNameKebabCase: kebabCase(agentNameClassName),\n agentNameClassName,\n });\n\n addTsDependencies(tree, DEPENDENCIES, {\n metadata: connectionMetadata,\n projectRoot: frontendProjectConfig.root,\n });\n\n // Recorded so the version sync knows this connection's dependencies are ours.\n addComponentGeneratorMetadata(\n tree,\n frontendProjectConfig.name,\n TS_AGENT_REACT_CONNECTION_GENERATOR_INFO,\n toProjectRelativePath(\n frontendProjectConfig,\n joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'components',\n clientProviderName,\n ),\n ),\n agentNameClassName,\n connectionMetadata,\n );\n\n await addGeneratorMetricsIfApplicable(tree, [\n TS_AGENT_REACT_CONNECTION_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n}\nexport default tsAgentReactConnectionGenerator;\n\n/**\n * Ensures a wildcard path entry exists in tsconfig.base.json for the given project,\n * allowing deep imports (e.g., `@scope/project/src/agent/router.js`).\n */\nfunction ensureWildcardPathEntry(\n tree: Tree,\n projectName: string,\n projectRoot: string,\n) {\n const tsconfigPath = ['tsconfig.base.json', 'tsconfig.json'].find((p) =>\n tree.exists(p),\n );\n if (!tsconfigPath) return;\n\n updateJson(tree, tsconfigPath, (json) => {\n const paths = json.compilerOptions?.paths ?? {};\n const wildcardKey = `${projectName}/*`;\n if (!paths[wildcardKey]) {\n paths[wildcardKey] = [`./${projectRoot}/*`];\n }\n json.compilerOptions = {\n ...json.compilerOptions,\n paths,\n };\n return json;\n });\n}\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateJson","addAgentRuntimeToConnectionNamespace","addTsDependencies","addSingleImport","applyGritQL","declareDependencies","onlyWhen","ownedElsewhere","formatFilesInSubtree","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","addComponentGeneratorMetadata","getGeneratorInfo","readProjectConfigurationUnqualified","toProjectRelativePath","DEPENDENCIES","AGUI_DEPENDENCIES","addAgUiReactConnection","resolveAgUiTheme","runtimeConfigGenerator","addTsAgentTargetToLocalDev","isHttp","m","protocol","isAgUi","ts","name","when","auth","dev","TS_AGENT_REACT_CONNECTION_GENERATOR_INFO","filename","tsAgentReactConnectionGenerator","tree","options","frontendProjectConfig","sourceProject","agentProjectConfig","targetProject","targetComponent","metadata","agentName","agentNameClassName","rc","agentPort","port","ports","toLowerCase","agentProjectAlias","agentPath","path","connectionMetadata","theme","Error","sourceRoot","preferInstallDependencies","languages","ensureWildcardPathEntry","root","dirname","overwriteStrategy","KeepExisting","project","mainTsxPath","clientProviderName","agentNameKebabCase","projectRoot","projectName","tsconfigPath","find","p","exists","json","paths","compilerOptions","wildcardKey"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/ts/agent/react-connection/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { addAgentRuntimeToConnectionNamespace } from '../../../connection/agent-runtime-config';\nimport type { ResolvedConnectionOptions } from '../../../connection/generator';\nimport { addTsDependencies } from '../../../utils/add-dependencies';\nimport { addSingleImport, applyGritQL } from '../../../utils/ast';\nimport {\n declareDependencies,\n onlyWhen,\n ownedElsewhere,\n} from '../../../utils/declared-dependencies';\nimport { formatFilesInSubtree } from '../../../utils/format';\nimport { installDependencies } from '../../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../../utils/metrics';\nimport { kebabCase, toClassName } from '../../../utils/names';\nimport {\n addComponentGeneratorMetadata,\n type ComponentMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n readProjectConfigurationUnqualified,\n} from '../../../utils/nx';\nimport { toProjectRelativePath } from '../../../utils/paths';\nimport {\n DEPENDENCIES as AGUI_DEPENDENCIES,\n type AgUiAuth,\n addAgUiReactConnection,\n resolveAgUiTheme,\n} from '../../react-website/agui/generator';\nimport { runtimeConfigGenerator } from '../../react-website/runtime-config/generator';\nimport { addTsAgentTargetToLocalDev } from './local-dev';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface TsAgentReactConnectionMetadata {\n readonly auth: string;\n readonly protocol: string;\n /** The AG-UI theme module, which the website's `ux` selects. */\n readonly theme: string;\n}\n\n/** The tRPC-over-HTTP path, which the AG-UI path takes none of. */\nconst isHttp = (m: TsAgentReactConnectionMetadata) => m.protocol !== 'ag-ui';\n\n/** The AG-UI path, whose packages `addAgUiReactConnection` adds. */\nconst isAgUi = (m: TsAgentReactConnectionMetadata) => !isHttp(m);\n\n// Each entry names the protocol path it belongs to: the HTTP path's client and\n// auth packages are added here, the AG-UI path's by `addAgUiReactConnection` on\n// this generator's behalf.\nexport const DEPENDENCIES =\n declareDependencies<TsAgentReactConnectionMetadata>()({\n ts: [\n { name: '@trpc/client', when: isHttp },\n { name: '@tanstack/react-query', when: isHttp },\n { name: '@tanstack/react-query-devtools', when: isHttp },\n { name: '@trpc/tanstack-react-query', when: isHttp },\n { name: 'oidc-client-ts', when: (m) => isHttp(m) && m.auth === 'iam' },\n { name: 'aws4fetch', when: (m) => isHttp(m) && m.auth === 'iam' },\n {\n name: '@aws-sdk/credential-provider-cognito-identity',\n when: (m) => isHttp(m) && m.auth === 'iam',\n },\n {\n name: 'react-oidc-context',\n when: (m) => isHttp(m) && (m.auth === 'iam' || m.auth === 'cognito'),\n },\n { name: '@smithy/types', when: isHttp, dev: true },\n // `addAgUiReactConnection` adds these itself, so they are declared for\n // ownership only. Gated on the AG-UI path, and within it on each entry's\n // own theme or auth condition, which the metadata below records.\n ...ownedElsewhere(onlyWhen(AGUI_DEPENDENCIES.ts, isAgUi)),\n ],\n });\n\nexport const TS_AGENT_REACT_CONNECTION_GENERATOR_INFO: NxGeneratorInfo =\n getGeneratorInfo(import.meta.filename);\n\n/**\n * Options for routing the website's requests to the agent through an\n * AgentCore Gateway rather than invoking the runtime directly. The gateway\n * react-connection generator dispatches here once per fronted agent.\n */\nexport interface AgentGatewayRoute {\n /** The gateway's class name, keying its URL in runtime config. */\n gatewayClassName: string;\n /** The agent's gateway target name, forming its path on the gateway. */\n targetName: string;\n /** The gateway's inbound auth, which is what the browser authenticates with. */\n gatewayAuth: string;\n}\n\nexport async function tsAgentReactConnectionGenerator(\n tree: Tree,\n options: ResolvedConnectionOptions & { gatewayRoute?: AgentGatewayRoute },\n) {\n const frontendProjectConfig = readProjectConfigurationUnqualified(\n tree,\n options.sourceProject,\n );\n const agentProjectConfig = readProjectConfigurationUnqualified(\n tree,\n options.targetProject,\n );\n\n const targetComponent: ComponentMetadata | undefined =\n options.targetComponent;\n\n // Extract agent metadata from the target component or project metadata\n const metadata = agentProjectConfig.metadata as any;\n const agentName = targetComponent?.name ?? 'agent';\n const agentNameClassName = targetComponent?.rc ?? toClassName(agentName);\n const agentPort = targetComponent?.port ?? metadata?.ports?.[0] ?? 8081;\n // Behind a gateway the browser authenticates with the gateway, not the agent.\n const auth = (\n options.gatewayRoute?.gatewayAuth ??\n targetComponent?.auth ??\n metadata?.auth ??\n 'iam'\n ).toLowerCase();\n const agentProjectAlias = agentProjectConfig.name;\n const agentPath = targetComponent?.path ?? 'src/agent';\n\n // Recorded below and read by the declaration's predicates, so the packages\n // added here are exactly the ones the version sync will own.\n const connectionMetadata: TsAgentReactConnectionMetadata = {\n auth,\n protocol: targetComponent?.protocol ?? 'http',\n theme: resolveAgUiTheme(frontendProjectConfig),\n };\n\n if ((targetComponent?.protocol ?? '').toLowerCase() === 'a2a') {\n throw new Error(\n `Cannot connect a React website to an A2A agent. ` +\n `Consider generating an agent with the HTTP or AG-UI protocol instead.`,\n );\n }\n\n // A TypeScript HTTP agent serves tRPC over WebSocket, which AgentCore\n // Gateway does not support, so only AG-UI agents can be reached via a\n // gateway route.\n if (options.gatewayRoute && targetComponent?.protocol !== 'ag-ui') {\n throw new Error(\n `Cannot connect a React website to agent '${agentName}' via a gateway: a TypeScript HTTP agent serves tRPC over WebSocket, which AgentCore Gateway does not support. Consider the ag-ui protocol instead.`,\n );\n }\n\n if (targetComponent?.protocol === 'ag-ui') {\n await addAgUiReactConnection(tree, {\n frontendProjectConfig,\n agentName,\n agentNameClassName,\n auth: auth as AgUiAuth,\n gatewayRoute: options.gatewayRoute,\n });\n\n // When routing via a gateway, the gateway react-connection wires the\n // website's dev target to the local gateway (which proxies to the agent)\n // instead of to the agent directly.\n if (!options.gatewayRoute) {\n await addTsAgentTargetToLocalDev(\n tree,\n frontendProjectConfig.name,\n agentProjectConfig.name,\n {\n agentName,\n agentNameClassName,\n port: agentPort,\n targetComponent,\n },\n );\n }\n\n // Recorded so the version sync knows this connection's dependencies are ours.\n addComponentGeneratorMetadata(\n tree,\n frontendProjectConfig.name,\n TS_AGENT_REACT_CONNECTION_GENERATOR_INFO,\n toProjectRelativePath(\n frontendProjectConfig,\n joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'hooks',\n `useAgui${agentNameClassName}`,\n ),\n ),\n agentNameClassName,\n connectionMetadata,\n );\n\n await addGeneratorMetricsIfApplicable(tree, [\n TS_AGENT_REACT_CONNECTION_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n }\n\n // Ensure the agent project has a wildcard path entry in tsconfig.base.json\n // so that deep imports (e.g., for the router type) resolve correctly\n ensureWildcardPathEntry(\n tree,\n agentProjectConfig.name,\n agentProjectConfig.root,\n );\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files'),\n frontendProjectConfig.root,\n {\n agentName,\n agentNameClassName,\n auth,\n agentProjectAlias,\n agentPath,\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n // Generate the tanstack query provider if it does not exist already\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n '../../../utils/files/website/components/tanstack-query',\n ),\n joinPathFragments(frontendProjectConfig.sourceRoot, 'components'),\n {},\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n if (auth === 'iam') {\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n '../../../utils/files/website/hooks/sigv4',\n ),\n joinPathFragments(frontendProjectConfig.sourceRoot, 'hooks'),\n {},\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n }\n\n await runtimeConfigGenerator(tree, {\n project: frontendProjectConfig.name,\n preferInstallDependencies: false,\n });\n\n // update main.tsx\n const mainTsxPath = joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'main.tsx',\n );\n await addSingleImport(\n tree,\n mainTsxPath,\n 'QueryClientProvider',\n './components/QueryClientProvider',\n );\n\n const clientProviderName = `${agentNameClassName}AgentClientProvider`;\n await addSingleImport(\n tree,\n mainTsxPath,\n clientProviderName,\n `./components/${clientProviderName}`,\n );\n\n // Wrap <App /> in QueryClientProvider if not already present\n await applyGritQL(\n tree,\n mainTsxPath,\n '`<App />` => `<QueryClientProvider><App /></QueryClientProvider>` where { $program <: not contains `<QueryClientProvider>$_</QueryClientProvider>` }',\n );\n\n // Wrap <App /> in the agent client provider if not already present\n await applyGritQL(\n tree,\n mainTsxPath,\n `\\`<App />\\` => \\`<${clientProviderName}><App /></${clientProviderName}>\\` where { $program <: not contains \\`<${clientProviderName}>$_</${clientProviderName}>\\` }`,\n );\n\n await addTsAgentTargetToLocalDev(\n tree,\n frontendProjectConfig.name,\n agentProjectConfig.name,\n {\n agentName,\n agentNameClassName,\n port: agentPort,\n targetComponent,\n },\n );\n\n // Expose the agent's runtime ARN to the frontend via the 'connection'\n // namespace (which is published to runtime-config.json). The agent construct\n // itself only registers to the 'agentcore' namespace by default.\n await addAgentRuntimeToConnectionNamespace(tree, {\n agentNameKebabCase: kebabCase(agentNameClassName),\n agentNameClassName,\n });\n\n addTsDependencies(tree, DEPENDENCIES, {\n metadata: connectionMetadata,\n projectRoot: frontendProjectConfig.root,\n });\n\n // Recorded so the version sync knows this connection's dependencies are ours.\n addComponentGeneratorMetadata(\n tree,\n frontendProjectConfig.name,\n TS_AGENT_REACT_CONNECTION_GENERATOR_INFO,\n toProjectRelativePath(\n frontendProjectConfig,\n joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'components',\n clientProviderName,\n ),\n ),\n agentNameClassName,\n connectionMetadata,\n );\n\n await addGeneratorMetricsIfApplicable(tree, [\n TS_AGENT_REACT_CONNECTION_GENERATOR_INFO,\n ]);\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n });\n}\nexport default tsAgentReactConnectionGenerator;\n\n/**\n * Ensures a wildcard path entry exists in tsconfig.base.json for the given project,\n * allowing deep imports (e.g., `@scope/project/src/agent/router.js`).\n */\nfunction ensureWildcardPathEntry(\n tree: Tree,\n projectName: string,\n projectRoot: string,\n) {\n const tsconfigPath = ['tsconfig.base.json', 'tsconfig.json'].find((p) =>\n tree.exists(p),\n );\n if (!tsconfigPath) return;\n\n updateJson(tree, tsconfigPath, (json) => {\n const paths = json.compilerOptions?.paths ?? {};\n const wildcardKey = `${projectName}/*`;\n if (!paths[wildcardKey]) {\n paths[wildcardKey] = [`./${projectRoot}/*`];\n }\n json.compilerOptions = {\n ...json.compilerOptions,\n paths,\n };\n return json;\n });\n}\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateJson","addAgentRuntimeToConnectionNamespace","addTsDependencies","addSingleImport","applyGritQL","declareDependencies","onlyWhen","ownedElsewhere","formatFilesInSubtree","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","addComponentGeneratorMetadata","getGeneratorInfo","readProjectConfigurationUnqualified","toProjectRelativePath","DEPENDENCIES","AGUI_DEPENDENCIES","addAgUiReactConnection","resolveAgUiTheme","runtimeConfigGenerator","addTsAgentTargetToLocalDev","isHttp","m","protocol","isAgUi","ts","name","when","auth","dev","TS_AGENT_REACT_CONNECTION_GENERATOR_INFO","filename","tsAgentReactConnectionGenerator","tree","options","frontendProjectConfig","sourceProject","agentProjectConfig","targetProject","targetComponent","metadata","agentName","agentNameClassName","rc","agentPort","port","ports","gatewayRoute","gatewayAuth","toLowerCase","agentProjectAlias","agentPath","path","connectionMetadata","theme","Error","sourceRoot","preferInstallDependencies","languages","ensureWildcardPathEntry","root","dirname","overwriteStrategy","KeepExisting","project","mainTsxPath","clientProviderName","agentNameKebabCase","projectRoot","projectName","tsconfigPath","find","p","exists","json","paths","compilerOptions","wildcardKey"],"mappings":"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"}
|
|
@@ -76,33 +76,46 @@ export const NX_MIGRATION_GENERATOR_INFO = getGeneratorInfo(import.meta.filename
|
|
|
76
76
|
if (!hasPrompt) {
|
|
77
77
|
tree.delete(joinPathFragments(migrationDir, 'prompt.md'));
|
|
78
78
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
79
|
+
if (isNxPluginForAws) {
|
|
80
|
+
// In the plugin's own repo migrations.json is assembled from these folders
|
|
81
|
+
// at build time (see utils/migration-manifest.ts), so registration is just
|
|
82
|
+
// the description beside the code — its kind comes from the files present.
|
|
83
|
+
// Two migration PRs then touch disjoint files rather than one shared manifest.
|
|
84
|
+
const metadataPath = joinPathFragments(migrationDir, 'metadata.json');
|
|
85
|
+
if (!tree.exists(metadataPath)) {
|
|
86
|
+
writeJson(tree, metadataPath, {
|
|
87
|
+
description
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
// Elsewhere, register the migration under its folder-prefixed key. The fields
|
|
92
|
+
// present discriminate the kind for nx, and paths are relative to
|
|
93
|
+
// migrations.json. No version is written, but an already-stamped one is kept.
|
|
94
|
+
const migrationsJsonPath = joinPathFragments(plugin.root, 'migrations.json');
|
|
95
|
+
const migrationsJson = tree.exists(migrationsJsonPath) ? readJson(tree, migrationsJsonPath) : {
|
|
96
|
+
$schema: 'http://json-schema.org/schema',
|
|
97
|
+
name: readJson(tree, pluginPackageJsonPath).name ?? plugin.name,
|
|
98
|
+
generators: {}
|
|
99
|
+
};
|
|
100
|
+
writeJson(tree, migrationsJsonPath, {
|
|
101
|
+
...migrationsJson,
|
|
102
|
+
generators: sortObjectKeys({
|
|
103
|
+
...migrationsJson.generators,
|
|
104
|
+
[key]: {
|
|
105
|
+
...migrationsJson.generators?.[key]?.version ? {
|
|
106
|
+
version: migrationsJson.generators[key].version
|
|
107
|
+
} : {},
|
|
108
|
+
description,
|
|
109
|
+
...hasImplementation ? {
|
|
110
|
+
implementation: `./${migrationPath}/migration`
|
|
111
|
+
} : {},
|
|
112
|
+
...hasPrompt ? {
|
|
113
|
+
prompt: `./${migrationPath}/prompt.md`
|
|
114
|
+
} : {}
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
});
|
|
118
|
+
}
|
|
106
119
|
// Codemods import @nx/devkit and the @aws/nx-plugin SDK, both of which must
|
|
107
120
|
// resolve for nx to run them
|
|
108
121
|
if (hasImplementation) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/ts/nx-migration/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n readJson,\n type Tree,\n writeJson,\n} from '@nx/devkit';\nimport PackageJson from '../../../package.json' with { type: 'json' };\nimport { declareDependencies } from '../../utils/declared-dependencies';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport {\n LATEST_MIGRATIONS_DIR,\n migrationKey,\n} from '../../utils/migration-versions';\nimport { kebabCase } from '../../utils/names';\nimport {\n getGeneratorInfo,\n isNxPluginForAwsWorkspace,\n type NxGeneratorInfo,\n} from '../../utils/nx';\nimport { sortObjectKeys } from '../../utils/object';\nimport {\n addNxPluginDependencies,\n configureNxPluginPackageJson,\n NX_PLUGIN_DEPENDENCIES,\n readNxPluginProject,\n} from '../nx-plugin/utils';\nimport type { TsNxMigrationGeneratorSchema } from './schema';\n\nexport const DEPENDENCIES = declareDependencies()({\n ts: [...NX_PLUGIN_DEPENDENCIES],\n});\n\nexport const NX_MIGRATION_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\n/**\n * Scaffolds a migration in an Nx Plugin project and registers it in the\n * plugin's `migrations.json` (creating the manifest and wiring the\n * `nx-migrations` field into the plugin's `package.json` if absent), so\n * `nx migrate` applies it when users upgrade the plugin.\n *\n * Supports all three migration kinds:\n * - `deterministic`: a codemod (`implementation`).\n * - `agentic`: a `prompt` markdown file applied by the user's agent.\n * - `hybrid`: both — the codemod does the mechanical part and returns\n * `agentContext`, then the prompt hands off to the agent for the rest.\n *\n * No `version` is written — the plugin author stamps versions at release time.\n */\nexport const tsNxMigrationGenerator = async (\n tree: Tree,\n options: TsNxMigrationGeneratorSchema,\n): Promise<GeneratorCallback | void> => {\n const name = kebabCase(options.name);\n // Shown by `nx migrate` when the migration runs, so it needs to say something\n const description =\n options.description ?? 'TODO: Add short description of the migration';\n const kind = options.kind ?? 'deterministic';\n\n const hasImplementation = kind === 'deterministic' || kind === 'hybrid';\n const hasPrompt = kind === 'agentic' || kind === 'hybrid';\n const isHybrid = kind === 'hybrid';\n\n const plugin = readNxPluginProject(tree, options.project);\n\n const sourceRoot = plugin.sourceRoot ?? joinPathFragments(plugin.root, 'src');\n const srcDir = sourceRoot.split('/').filter(Boolean).pop();\n // Migrations are grouped by the release that ships them. A new one lands in\n // `latest` — the release that picks it up moves it into its version folder.\n const migrationPath = `${srcDir}/migrations/${LATEST_MIGRATIONS_DIR}/${name}`;\n const migrationDir = joinPathFragments(\n sourceRoot,\n 'migrations',\n LATEST_MIGRATIONS_DIR,\n name,\n );\n const key = migrationKey(LATEST_MIGRATIONS_DIR, name);\n\n const isNxPluginForAws = isNxPluginForAwsWorkspace(tree);\n\n // Point the plugin at its migrations manifest so `nx migrate` finds them\n const pluginPackageJsonPath = configureNxPluginPackageJson(\n tree,\n plugin,\n 'nx-migrations',\n { migrations: './migrations.json' },\n );\n\n // Migrations sit three levels below the source root, so in this repo the\n // shared utils are relative. Elsewhere they come from the SDK.\n const formatImportPath = isNxPluginForAws\n ? '../../../utils/format'\n : `${PackageJson.name}/sdk/utils/format`;\n const testImportPath = isNxPluginForAws\n ? '../../../utils/test'\n : `${PackageJson.name}/sdk/utils/test`;\n\n // One template set covers all kinds — scaffold it, then prune what this kind\n // doesn't use.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files'),\n migrationDir,\n { name, description, isHybrid, formatImportPath, testImportPath },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n if (!hasImplementation) {\n tree.delete(joinPathFragments(migrationDir, 'migration.ts'));\n tree.delete(joinPathFragments(migrationDir, 'migration.spec.ts'));\n }\n if (!hasPrompt) {\n tree.delete(joinPathFragments(migrationDir, 'prompt.md'));\n }\n\n // Register the migration under its folder-prefixed key. The fields present\n // discriminate the kind for nx, and paths are relative to migrations.json.\n // No version is written, but an already-stamped one is preserved.\n const migrationsJsonPath = joinPathFragments(plugin.root, 'migrations.json');\n const migrationsJson = tree.exists(migrationsJsonPath)\n ? readJson(tree, migrationsJsonPath)\n : {\n $schema: 'http://json-schema.org/schema',\n name: readJson(tree, pluginPackageJsonPath).name ?? plugin.name,\n generators: {},\n };\n writeJson(tree, migrationsJsonPath, {\n ...migrationsJson,\n generators: sortObjectKeys({\n ...migrationsJson.generators,\n [key]: {\n ...(migrationsJson.generators?.[key]?.version\n ? { version: migrationsJson.generators[key].version }\n : {}),\n description,\n ...(hasImplementation\n ? { implementation: `./${migrationPath}/migration` }\n : {}),\n ...(hasPrompt ? { prompt: `./${migrationPath}/prompt.md` } : {}),\n },\n }),\n });\n\n // Codemods import @nx/devkit and the @aws/nx-plugin SDK, both of which must\n // resolve for nx to run them\n if (hasImplementation) {\n addNxPluginDependencies(tree, pluginPackageJsonPath, DEPENDENCIES);\n }\n\n await addGeneratorMetricsIfApplicable(tree, [NX_MIGRATION_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n\n if (hasImplementation && !isNxPluginForAws) {\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n ensureResolvable: ['@nx/devkit'],\n });\n }\n};\n\nexport default tsNxMigrationGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","readJson","writeJson","PackageJson","type","declareDependencies","formatFilesInSubtree","installDependencies","addGeneratorMetricsIfApplicable","LATEST_MIGRATIONS_DIR","migrationKey","kebabCase","getGeneratorInfo","isNxPluginForAwsWorkspace","sortObjectKeys","addNxPluginDependencies","configureNxPluginPackageJson","NX_PLUGIN_DEPENDENCIES","readNxPluginProject","DEPENDENCIES","ts","NX_MIGRATION_GENERATOR_INFO","filename","tsNxMigrationGenerator","tree","options","name","description","kind","hasImplementation","hasPrompt","isHybrid","plugin","project","sourceRoot","root","srcDir","split","filter","Boolean","pop","migrationPath","migrationDir","key","isNxPluginForAws","pluginPackageJsonPath","migrations","formatImportPath","testImportPath","dirname","overwriteStrategy","KeepExisting","delete","migrationsJsonPath","migrationsJson","exists","$schema","generators","version","implementation","prompt","preferInstallDependencies","languages","ensureResolvable"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/ts/nx-migration/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n type GeneratorCallback,\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n readJson,\n type Tree,\n writeJson,\n} from '@nx/devkit';\nimport PackageJson from '../../../package.json' with { type: 'json' };\nimport { declareDependencies } from '../../utils/declared-dependencies';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport {\n LATEST_MIGRATIONS_DIR,\n migrationKey,\n} from '../../utils/migration-versions';\nimport { kebabCase } from '../../utils/names';\nimport {\n getGeneratorInfo,\n isNxPluginForAwsWorkspace,\n type NxGeneratorInfo,\n} from '../../utils/nx';\nimport { sortObjectKeys } from '../../utils/object';\nimport {\n addNxPluginDependencies,\n configureNxPluginPackageJson,\n NX_PLUGIN_DEPENDENCIES,\n readNxPluginProject,\n} from '../nx-plugin/utils';\nimport type { TsNxMigrationGeneratorSchema } from './schema';\n\nexport const DEPENDENCIES = declareDependencies()({\n ts: [...NX_PLUGIN_DEPENDENCIES],\n});\n\nexport const NX_MIGRATION_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\n/**\n * Scaffolds a migration in an Nx Plugin project and registers it in the\n * plugin's `migrations.json` (creating the manifest and wiring the\n * `nx-migrations` field into the plugin's `package.json` if absent), so\n * `nx migrate` applies it when users upgrade the plugin.\n *\n * Supports all three migration kinds:\n * - `deterministic`: a codemod (`implementation`).\n * - `agentic`: a `prompt` markdown file applied by the user's agent.\n * - `hybrid`: both — the codemod does the mechanical part and returns\n * `agentContext`, then the prompt hands off to the agent for the rest.\n *\n * No `version` is written — the plugin author stamps versions at release time.\n */\nexport const tsNxMigrationGenerator = async (\n tree: Tree,\n options: TsNxMigrationGeneratorSchema,\n): Promise<GeneratorCallback | void> => {\n const name = kebabCase(options.name);\n // Shown by `nx migrate` when the migration runs, so it needs to say something\n const description =\n options.description ?? 'TODO: Add short description of the migration';\n const kind = options.kind ?? 'deterministic';\n\n const hasImplementation = kind === 'deterministic' || kind === 'hybrid';\n const hasPrompt = kind === 'agentic' || kind === 'hybrid';\n const isHybrid = kind === 'hybrid';\n\n const plugin = readNxPluginProject(tree, options.project);\n\n const sourceRoot = plugin.sourceRoot ?? joinPathFragments(plugin.root, 'src');\n const srcDir = sourceRoot.split('/').filter(Boolean).pop();\n // Migrations are grouped by the release that ships them. A new one lands in\n // `latest` — the release that picks it up moves it into its version folder.\n const migrationPath = `${srcDir}/migrations/${LATEST_MIGRATIONS_DIR}/${name}`;\n const migrationDir = joinPathFragments(\n sourceRoot,\n 'migrations',\n LATEST_MIGRATIONS_DIR,\n name,\n );\n const key = migrationKey(LATEST_MIGRATIONS_DIR, name);\n\n const isNxPluginForAws = isNxPluginForAwsWorkspace(tree);\n\n // Point the plugin at its migrations manifest so `nx migrate` finds them\n const pluginPackageJsonPath = configureNxPluginPackageJson(\n tree,\n plugin,\n 'nx-migrations',\n { migrations: './migrations.json' },\n );\n\n // Migrations sit three levels below the source root, so in this repo the\n // shared utils are relative. Elsewhere they come from the SDK.\n const formatImportPath = isNxPluginForAws\n ? '../../../utils/format'\n : `${PackageJson.name}/sdk/utils/format`;\n const testImportPath = isNxPluginForAws\n ? '../../../utils/test'\n : `${PackageJson.name}/sdk/utils/test`;\n\n // One template set covers all kinds — scaffold it, then prune what this kind\n // doesn't use.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files'),\n migrationDir,\n { name, description, isHybrid, formatImportPath, testImportPath },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n if (!hasImplementation) {\n tree.delete(joinPathFragments(migrationDir, 'migration.ts'));\n tree.delete(joinPathFragments(migrationDir, 'migration.spec.ts'));\n }\n if (!hasPrompt) {\n tree.delete(joinPathFragments(migrationDir, 'prompt.md'));\n }\n\n if (isNxPluginForAws) {\n // In the plugin's own repo migrations.json is assembled from these folders\n // at build time (see utils/migration-manifest.ts), so registration is just\n // the description beside the code — its kind comes from the files present.\n // Two migration PRs then touch disjoint files rather than one shared manifest.\n const metadataPath = joinPathFragments(migrationDir, 'metadata.json');\n if (!tree.exists(metadataPath)) {\n writeJson(tree, metadataPath, { description });\n }\n } else {\n // Elsewhere, register the migration under its folder-prefixed key. The fields\n // present discriminate the kind for nx, and paths are relative to\n // migrations.json. No version is written, but an already-stamped one is kept.\n const migrationsJsonPath = joinPathFragments(\n plugin.root,\n 'migrations.json',\n );\n const migrationsJson = tree.exists(migrationsJsonPath)\n ? readJson(tree, migrationsJsonPath)\n : {\n $schema: 'http://json-schema.org/schema',\n name: readJson(tree, pluginPackageJsonPath).name ?? plugin.name,\n generators: {},\n };\n writeJson(tree, migrationsJsonPath, {\n ...migrationsJson,\n generators: sortObjectKeys({\n ...migrationsJson.generators,\n [key]: {\n ...(migrationsJson.generators?.[key]?.version\n ? { version: migrationsJson.generators[key].version }\n : {}),\n description,\n ...(hasImplementation\n ? { implementation: `./${migrationPath}/migration` }\n : {}),\n ...(hasPrompt ? { prompt: `./${migrationPath}/prompt.md` } : {}),\n },\n }),\n });\n }\n\n // Codemods import @nx/devkit and the @aws/nx-plugin SDK, both of which must\n // resolve for nx to run them\n if (hasImplementation) {\n addNxPluginDependencies(tree, pluginPackageJsonPath, DEPENDENCIES);\n }\n\n await addGeneratorMetricsIfApplicable(tree, [NX_MIGRATION_GENERATOR_INFO]);\n\n await formatFilesInSubtree(tree);\n\n if (hasImplementation && !isNxPluginForAws) {\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript'],\n ensureResolvable: ['@nx/devkit'],\n });\n }\n};\n\nexport default tsNxMigrationGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","readJson","writeJson","PackageJson","type","declareDependencies","formatFilesInSubtree","installDependencies","addGeneratorMetricsIfApplicable","LATEST_MIGRATIONS_DIR","migrationKey","kebabCase","getGeneratorInfo","isNxPluginForAwsWorkspace","sortObjectKeys","addNxPluginDependencies","configureNxPluginPackageJson","NX_PLUGIN_DEPENDENCIES","readNxPluginProject","DEPENDENCIES","ts","NX_MIGRATION_GENERATOR_INFO","filename","tsNxMigrationGenerator","tree","options","name","description","kind","hasImplementation","hasPrompt","isHybrid","plugin","project","sourceRoot","root","srcDir","split","filter","Boolean","pop","migrationPath","migrationDir","key","isNxPluginForAws","pluginPackageJsonPath","migrations","formatImportPath","testImportPath","dirname","overwriteStrategy","KeepExisting","delete","metadataPath","exists","migrationsJsonPath","migrationsJson","$schema","generators","version","implementation","prompt","preferInstallDependencies","languages","ensureResolvable"],"mappings":"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"}
|
package/src/ts/react-website/agui/files/common/src/hooks/useAgui__agentNameClassName__.tsx.template
CHANGED
|
@@ -17,10 +17,18 @@ import { useMemo } from 'react';
|
|
|
17
17
|
import { useRuntimeConfig } from './useRuntimeConfig';
|
|
18
18
|
<%_ } _%>
|
|
19
19
|
|
|
20
|
+
<%_ if (gatewayRoute) { _%>
|
|
21
|
+
// The agent sits behind an AgentCore Gateway, which proxies
|
|
22
|
+
// `/<targetName>/invocations` to the agent runtime.
|
|
23
|
+
function buildGatewayUrl(gatewayUrl: string): string {
|
|
24
|
+
return `${new URL(gatewayUrl).origin}/<%= gatewayRoute.targetName %>/invocations`;
|
|
25
|
+
}
|
|
26
|
+
<%_ } else { _%>
|
|
20
27
|
function buildAgentCoreUrl(agentRuntimeArn: string): string {
|
|
21
28
|
const region = agentRuntimeArn.split(':')[3];
|
|
22
29
|
return `https://bedrock-agentcore.${region}.amazonaws.com/runtimes/${encodeURIComponent(agentRuntimeArn)}/invocations?qualifier=DEFAULT`;
|
|
23
30
|
}
|
|
31
|
+
<%_ } _%>
|
|
24
32
|
|
|
25
33
|
// AgentCore session ids must be at least 33 characters.
|
|
26
34
|
function agentCoreSessionId(input: RunAgentInput): string {
|
|
@@ -98,13 +106,20 @@ class AgentCoreHttpAgent extends HttpAgent {
|
|
|
98
106
|
|
|
99
107
|
export const useAgui<%= agentNameClassName %> = (): Record<string, AbstractAgent> => {
|
|
100
108
|
const runtimeConfig = useRuntimeConfig();
|
|
109
|
+
<%_ if (gatewayRoute) { _%>
|
|
110
|
+
const gatewayUrl = runtimeConfig.gateways.<%= gatewayRoute.gatewayClassName %>;
|
|
111
|
+
<%_ } else { _%>
|
|
101
112
|
const agentRuntimeValue = runtimeConfig.agentRuntimes.<%= agentNameClassName %>;
|
|
113
|
+
<%_ } _%>
|
|
102
114
|
<%_ if (auth === 'iam') { _%>
|
|
103
115
|
const sigv4 = useSigV4();
|
|
104
116
|
<%_ } else if (auth === 'cognito') { _%>
|
|
105
117
|
const auth = useAuth();
|
|
106
118
|
<%_ } _%>
|
|
107
119
|
|
|
120
|
+
<%_ if (gatewayRoute) { _%>
|
|
121
|
+
const url = useMemo(() => buildGatewayUrl(gatewayUrl), [gatewayUrl]);
|
|
122
|
+
<%_ } else { _%>
|
|
108
123
|
const url = useMemo(
|
|
109
124
|
() =>
|
|
110
125
|
agentRuntimeValue.startsWith('arn:')
|
|
@@ -112,6 +127,7 @@ export const useAgui<%= agentNameClassName %> = (): Record<string, AbstractAgent
|
|
|
112
127
|
: agentRuntimeValue,
|
|
113
128
|
[agentRuntimeValue],
|
|
114
129
|
);
|
|
130
|
+
<%_ } _%>
|
|
115
131
|
|
|
116
132
|
return useMemo((): Record<string, AbstractAgent> => {
|
|
117
133
|
<%_ if (auth === 'iam') { _%>
|
|
@@ -93,6 +93,17 @@ export interface AgUiReactConnectionOptions {
|
|
|
93
93
|
agentNameClassName: string;
|
|
94
94
|
/** Auth scheme used by the agent */
|
|
95
95
|
auth: AgUiAuth;
|
|
96
|
+
/**
|
|
97
|
+
* When set, the generated hook reads the gateway's URL from
|
|
98
|
+
* runtimeConfig.gateways and routes to the agent via the gateway's
|
|
99
|
+
* path-based `/<targetName>/invocations` route instead of invoking the
|
|
100
|
+
* runtime directly. The gateway publishes its own URL to the website, so
|
|
101
|
+
* the agent's construct is left unpatched.
|
|
102
|
+
*/
|
|
103
|
+
gatewayRoute?: {
|
|
104
|
+
gatewayClassName: string;
|
|
105
|
+
targetName: string;
|
|
106
|
+
};
|
|
96
107
|
}
|
|
97
108
|
/**
|
|
98
109
|
* Wires a React website up to an AG-UI agent using CopilotKit and
|
|
@@ -67,7 +67,7 @@ export const DEPENDENCIES = declareDependencies()({
|
|
|
67
67
|
* Also vends a `src/components/copilot` theme module picked from the
|
|
68
68
|
* website's `metadata.ux` (cloudscape / shadcn / default).
|
|
69
69
|
*/ export const addAgUiReactConnection = async (tree, options)=>{
|
|
70
|
-
const { frontendProjectConfig, agentName, agentNameClassName, auth } = options;
|
|
70
|
+
const { frontendProjectConfig, agentName, agentNameClassName, auth, gatewayRoute } = options;
|
|
71
71
|
const theme = resolveAgUiTheme(frontendProjectConfig);
|
|
72
72
|
// The values the declaration's predicates read. Callers record the same pair,
|
|
73
73
|
// so what is added here is exactly what the version sync owns.
|
|
@@ -82,7 +82,8 @@ export const DEPENDENCIES = declareDependencies()({
|
|
|
82
82
|
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'common'), frontendProjectConfig.root, {
|
|
83
83
|
agentName,
|
|
84
84
|
agentNameClassName,
|
|
85
|
-
auth
|
|
85
|
+
auth,
|
|
86
|
+
gatewayRoute
|
|
86
87
|
}, {
|
|
87
88
|
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
88
89
|
});
|
|
@@ -124,11 +125,14 @@ export const DEPENDENCIES = declareDependencies()({
|
|
|
124
125
|
// Agents only publish their runtime ARN to the 'agentcore' namespace by
|
|
125
126
|
// default, which isn't exposed to the website. Patch the agent's CDK/TF
|
|
126
127
|
// construct to also publish under 'connection' so the browser can read it
|
|
127
|
-
// from runtime-config.json.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
128
|
+
// from runtime-config.json. When routing via a gateway, the gateway
|
|
129
|
+
// publishes its own URL instead.
|
|
130
|
+
if (!gatewayRoute) {
|
|
131
|
+
await addAgentRuntimeToConnectionNamespace(tree, {
|
|
132
|
+
agentNameKebabCase: kebabCase(agentNameClassName),
|
|
133
|
+
agentNameClassName
|
|
134
|
+
});
|
|
135
|
+
}
|
|
132
136
|
};
|
|
133
137
|
/**
|
|
134
138
|
* The theme module this helper vends, from the website's `metadata.ux`. Callers
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/ts/react-website/agui/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n} from '@nx/devkit';\nimport { addAgentRuntimeToConnectionNamespace } from '../../../connection/agent-runtime-config';\nimport { addTsDependencies } from '../../../utils/add-dependencies';\nimport {\n addDestructuredImport,\n addSingleImport,\n applyGritQL,\n} from '../../../utils/ast';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../../utils/declared-dependencies';\nimport { kebabCase } from '../../../utils/names';\nimport { getNpmScopePrefix } from '../../../utils/npm-scope';\nimport { registerPnpmBuiltDependencies } from '../../../utils/pnpm-workspace';\nimport {\n SHADCN_DEPENDENCIES,\n sharedShadcnGenerator,\n} from '../../../utils/shared-shadcn';\nimport { runtimeConfigGenerator } from '../runtime-config/generator';\n\n/**\n * The values this helper's predicates read. Its callers record them, so the\n * theme and auth branches taken here can be confirmed at upgrade time.\n */\nexport interface AgUiMetadata {\n readonly theme: string;\n readonly auth: string;\n}\n\n// Each entry names the theme or auth branch it belongs to, so the same\n// declaration drives both adding and the version sync.\nexport const DEPENDENCIES = declareDependencies<AgUiMetadata>()({\n ts: [\n { name: '@copilotkit/react-core' },\n { name: '@ag-ui/client' },\n {\n name: '@cloudscape-design/chat-components',\n when: (m) => m.theme === 'cloudscape',\n },\n { name: 'lucide-react', when: (m) => m.theme === 'shadcn' },\n { name: 'oidc-client-ts', when: (m) => m.auth === 'iam' },\n { name: 'aws4fetch', when: (m) => m.auth === 'iam' },\n {\n name: '@aws-sdk/credential-provider-cognito-identity',\n when: (m) => m.auth === 'iam',\n },\n {\n name: 'react-oidc-context',\n when: (m) => m.auth === 'iam' || m.auth === 'cognito',\n },\n { name: '@smithy/types', when: (m) => m.auth === 'iam', dev: true },\n // `sharedShadcnGenerator` adds these to the shared shadcn project it\n // creates, not to the website.\n ...ownedElsewhere(SHADCN_DEPENDENCIES),\n ],\n});\n\nexport type AgUiAuth = 'iam' | 'cognito' | 'none';\n\nexport type AgUiTheme = 'cloudscape' | 'shadcn' | 'default';\n\nexport interface AgUiReactConnectionOptions {\n /** The React website project to connect FROM */\n frontendProjectConfig: ProjectConfiguration;\n /** The AG-UI agent's exposed name (used as CopilotKit's agent key) */\n agentName: string;\n /** PascalCase class name used for component names and runtime config keys */\n agentNameClassName: string;\n /** Auth scheme used by the agent */\n auth: AgUiAuth;\n}\n\n/**\n * Wires a React website up to an AG-UI agent using CopilotKit and\n * @ag-ui/client's HttpAgent. Agent-server-language agnostic.\n *\n * On first invocation creates a shared `AguiProvider` component (with an empty\n * `selfManagedAgents` registry) and wraps `<App />` in it. Each invocation\n * AST-patches `AguiProvider` to register one more agent hook — running the\n * generator multiple times is idempotent and additive.\n *\n * Also vends a `src/components/copilot` theme module picked from the\n * website's `metadata.ux` (cloudscape / shadcn / default).\n */\nexport const addAgUiReactConnection = async (\n tree: Tree,\n options: AgUiReactConnectionOptions,\n) => {\n const { frontendProjectConfig, agentName, agentNameClassName, auth } =\n options;\n\n const theme = resolveAgUiTheme(frontendProjectConfig);\n // The values the declaration's predicates read. Callers record the same pair,\n // so what is added here is exactly what the version sync owns.\n const metadata: AgUiMetadata = { theme, auth };\n const scopeAlias = getNpmScopePrefix(tree);\n\n // Generates `src/components/AguiProvider.tsx` (if absent) and\n // `src/hooks/useAgui<AgentName>.tsx`. Existing files are kept so re-running\n // the generator is idempotent.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'common'),\n frontendProjectConfig.root,\n { agentName, agentNameClassName, auth },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // Shadcn theme imports from the shared shadcn library, so it must exist.\n if (theme === 'shadcn') {\n await sharedShadcnGenerator(tree, DEPENDENCIES);\n }\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', theme),\n frontendProjectConfig.root,\n { scopeAlias },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n if (auth === 'iam') {\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n '../../../utils/files/website/hooks/sigv4',\n ),\n joinPathFragments(frontendProjectConfig.sourceRoot, 'hooks'),\n {},\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n }\n\n await runtimeConfigGenerator(tree, {\n project: frontendProjectConfig.name,\n });\n\n // AST-patch AguiProvider to register this agent's hook\n await registerAgentHookInProvider(\n tree,\n frontendProjectConfig,\n agentNameClassName,\n );\n\n // Wrap <App /> in <AguiProvider> in main.tsx (idempotent)\n const mainTsxPath = joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'main.tsx',\n );\n await addSingleImport(\n tree,\n mainTsxPath,\n 'AguiProvider',\n './components/AguiProvider',\n );\n await applyGritQL(\n tree,\n mainTsxPath,\n `\\`<App />\\` => \\`<AguiProvider><App /></AguiProvider>\\` where { $program <: not contains \\`<AguiProvider>$_</AguiProvider>\\` }`,\n );\n\n // @copilotkit/react-core transitively pulls in @scarf/scarf (telemetry),\n // which has a postinstall script. Under pnpm 11's default\n // `strictDepBuilds=true` that script is treated as an unreviewed build and\n // fails the install. Register it as an explicitly-rejected build so pnpm\n // knows we've seen it and will skip it instead of erroring.\n registerPnpmBuiltDependencies(tree, { '@scarf/scarf': false });\n\n addTsDependencies(tree, DEPENDENCIES, {\n metadata,\n projectRoot: frontendProjectConfig.root,\n });\n\n // Agents only publish their runtime ARN to the 'agentcore' namespace by\n // default, which isn't exposed to the website. Patch the agent's CDK/TF\n // construct to also publish under 'connection' so the browser can read it\n // from runtime-config.json.\n await addAgentRuntimeToConnectionNamespace(tree, {\n agentNameKebabCase: kebabCase(agentNameClassName),\n agentNameClassName,\n });\n};\n\n/**\n * The theme module this helper vends, from the website's `metadata.ux`. Callers\n * record the resolved value, so the theme predicates read what the code branches\n * on.\n */\nexport const resolveAgUiTheme = (\n frontendProjectConfig: ProjectConfiguration,\n): AgUiTheme => {\n const ux = (\n (frontendProjectConfig.metadata as any)?.ux as string | undefined\n )?.toLowerCase();\n switch (ux) {\n case 'cloudscape':\n return 'cloudscape';\n case 'shadcn':\n return 'shadcn';\n default:\n return 'default';\n }\n};\n\n/**\n * Register this agent's hook in the shared `AguiProvider` using GritQL AST\n * patches. The provider starts out with an empty `selfManagedAgents` registry\n * (from the template); each call appends:\n * - `import { useAgui<Name> } from '../hooks/useAgui<Name>';`\n * - `const <varName> = useAgui<Name>();` before the `useMemo` call\n * - `...<varName>` into the memoised object literal\n * - `<varName>` into the `useMemo` deps array\n *\n * All steps are guarded so re-running produces byte-identical output.\n */\nconst registerAgentHookInProvider = async (\n tree: Tree,\n frontendProjectConfig: ProjectConfiguration,\n agentNameClassName: string,\n) => {\n const providerPath = joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'components',\n 'AguiProvider.tsx',\n );\n const hookName = `useAgui${agentNameClassName}`;\n // useAguiStoryAgent -> storyAgentAgents\n const varName = `${agentNameClassName.charAt(0).toLowerCase()}${agentNameClassName.slice(1)}Agents`;\n\n // 1. Add the hook import\n await addDestructuredImport(\n tree,\n providerPath,\n [hookName],\n `../hooks/${hookName}`,\n );\n\n // 2. Insert `const <varName> = <hookName>();` before the useMemo declaration\n await applyGritQL(\n tree,\n providerPath,\n `\\`const selfManagedAgents = useMemo<Record<string, AbstractAgent>>($body, $deps);\\` => ` +\n `\\`const ${varName} = ${hookName}();\\nconst selfManagedAgents = useMemo<Record<string, AbstractAgent>>($body, $deps);\\` ` +\n `where { $program <: not contains \\`const ${varName} = ${hookName}()\\` }`,\n );\n\n // 3. Spread `...<varName>` into the memoised object and add `<varName>` to\n // the deps array. Branches on `{}`/`[]` vs populated so both the\n // first-agent and nth-agent cases produce clean output.\n await applyGritQL(\n tree,\n providerPath,\n `\\`useMemo<Record<string, AbstractAgent>>(() => ($obj), $deps)\\` where {` +\n ` $obj <: not contains \\`...${varName}\\`,` +\n ` if ($obj <: \\`{}\\`) { $obj => \\`{ ...${varName} }\\` }` +\n ` else { $obj <: \\`{$items}\\` where { $items += \\`, ...${varName}\\` } },` +\n ` if ($deps <: \\`[]\\`) { $deps => \\`[${varName}]\\` }` +\n ` else { $deps <: \\`[$dd]\\` where { $dd += \\`, ${varName}\\` } }` +\n ` }`,\n );\n};\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","addAgentRuntimeToConnectionNamespace","addTsDependencies","addDestructuredImport","addSingleImport","applyGritQL","declareDependencies","ownedElsewhere","kebabCase","getNpmScopePrefix","registerPnpmBuiltDependencies","SHADCN_DEPENDENCIES","sharedShadcnGenerator","runtimeConfigGenerator","DEPENDENCIES","ts","name","when","m","theme","auth","dev","addAgUiReactConnection","tree","options","frontendProjectConfig","agentName","agentNameClassName","resolveAgUiTheme","metadata","scopeAlias","dirname","root","overwriteStrategy","KeepExisting","sourceRoot","project","registerAgentHookInProvider","mainTsxPath","projectRoot","agentNameKebabCase","ux","toLowerCase","providerPath","hookName","varName","charAt","slice"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/ts/react-website/agui/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n} from '@nx/devkit';\nimport { addAgentRuntimeToConnectionNamespace } from '../../../connection/agent-runtime-config';\nimport { addTsDependencies } from '../../../utils/add-dependencies';\nimport {\n addDestructuredImport,\n addSingleImport,\n applyGritQL,\n} from '../../../utils/ast';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../../utils/declared-dependencies';\nimport { kebabCase } from '../../../utils/names';\nimport { getNpmScopePrefix } from '../../../utils/npm-scope';\nimport { registerPnpmBuiltDependencies } from '../../../utils/pnpm-workspace';\nimport {\n SHADCN_DEPENDENCIES,\n sharedShadcnGenerator,\n} from '../../../utils/shared-shadcn';\nimport { runtimeConfigGenerator } from '../runtime-config/generator';\n\n/**\n * The values this helper's predicates read. Its callers record them, so the\n * theme and auth branches taken here can be confirmed at upgrade time.\n */\nexport interface AgUiMetadata {\n readonly theme: string;\n readonly auth: string;\n}\n\n// Each entry names the theme or auth branch it belongs to, so the same\n// declaration drives both adding and the version sync.\nexport const DEPENDENCIES = declareDependencies<AgUiMetadata>()({\n ts: [\n { name: '@copilotkit/react-core' },\n { name: '@ag-ui/client' },\n {\n name: '@cloudscape-design/chat-components',\n when: (m) => m.theme === 'cloudscape',\n },\n { name: 'lucide-react', when: (m) => m.theme === 'shadcn' },\n { name: 'oidc-client-ts', when: (m) => m.auth === 'iam' },\n { name: 'aws4fetch', when: (m) => m.auth === 'iam' },\n {\n name: '@aws-sdk/credential-provider-cognito-identity',\n when: (m) => m.auth === 'iam',\n },\n {\n name: 'react-oidc-context',\n when: (m) => m.auth === 'iam' || m.auth === 'cognito',\n },\n { name: '@smithy/types', when: (m) => m.auth === 'iam', dev: true },\n // `sharedShadcnGenerator` adds these to the shared shadcn project it\n // creates, not to the website.\n ...ownedElsewhere(SHADCN_DEPENDENCIES),\n ],\n});\n\nexport type AgUiAuth = 'iam' | 'cognito' | 'none';\n\nexport type AgUiTheme = 'cloudscape' | 'shadcn' | 'default';\n\nexport interface AgUiReactConnectionOptions {\n /** The React website project to connect FROM */\n frontendProjectConfig: ProjectConfiguration;\n /** The AG-UI agent's exposed name (used as CopilotKit's agent key) */\n agentName: string;\n /** PascalCase class name used for component names and runtime config keys */\n agentNameClassName: string;\n /** Auth scheme used by the agent */\n auth: AgUiAuth;\n /**\n * When set, the generated hook reads the gateway's URL from\n * runtimeConfig.gateways and routes to the agent via the gateway's\n * path-based `/<targetName>/invocations` route instead of invoking the\n * runtime directly. The gateway publishes its own URL to the website, so\n * the agent's construct is left unpatched.\n */\n gatewayRoute?: {\n gatewayClassName: string;\n targetName: string;\n };\n}\n\n/**\n * Wires a React website up to an AG-UI agent using CopilotKit and\n * @ag-ui/client's HttpAgent. Agent-server-language agnostic.\n *\n * On first invocation creates a shared `AguiProvider` component (with an empty\n * `selfManagedAgents` registry) and wraps `<App />` in it. Each invocation\n * AST-patches `AguiProvider` to register one more agent hook — running the\n * generator multiple times is idempotent and additive.\n *\n * Also vends a `src/components/copilot` theme module picked from the\n * website's `metadata.ux` (cloudscape / shadcn / default).\n */\nexport const addAgUiReactConnection = async (\n tree: Tree,\n options: AgUiReactConnectionOptions,\n) => {\n const {\n frontendProjectConfig,\n agentName,\n agentNameClassName,\n auth,\n gatewayRoute,\n } = options;\n\n const theme = resolveAgUiTheme(frontendProjectConfig);\n // The values the declaration's predicates read. Callers record the same pair,\n // so what is added here is exactly what the version sync owns.\n const metadata: AgUiMetadata = { theme, auth };\n const scopeAlias = getNpmScopePrefix(tree);\n\n // Generates `src/components/AguiProvider.tsx` (if absent) and\n // `src/hooks/useAgui<AgentName>.tsx`. Existing files are kept so re-running\n // the generator is idempotent.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'common'),\n frontendProjectConfig.root,\n { agentName, agentNameClassName, auth, gatewayRoute },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // Shadcn theme imports from the shared shadcn library, so it must exist.\n if (theme === 'shadcn') {\n await sharedShadcnGenerator(tree, DEPENDENCIES);\n }\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', theme),\n frontendProjectConfig.root,\n { scopeAlias },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n if (auth === 'iam') {\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n '../../../utils/files/website/hooks/sigv4',\n ),\n joinPathFragments(frontendProjectConfig.sourceRoot, 'hooks'),\n {},\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n }\n\n await runtimeConfigGenerator(tree, {\n project: frontendProjectConfig.name,\n });\n\n // AST-patch AguiProvider to register this agent's hook\n await registerAgentHookInProvider(\n tree,\n frontendProjectConfig,\n agentNameClassName,\n );\n\n // Wrap <App /> in <AguiProvider> in main.tsx (idempotent)\n const mainTsxPath = joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'main.tsx',\n );\n await addSingleImport(\n tree,\n mainTsxPath,\n 'AguiProvider',\n './components/AguiProvider',\n );\n await applyGritQL(\n tree,\n mainTsxPath,\n `\\`<App />\\` => \\`<AguiProvider><App /></AguiProvider>\\` where { $program <: not contains \\`<AguiProvider>$_</AguiProvider>\\` }`,\n );\n\n // @copilotkit/react-core transitively pulls in @scarf/scarf (telemetry),\n // which has a postinstall script. Under pnpm 11's default\n // `strictDepBuilds=true` that script is treated as an unreviewed build and\n // fails the install. Register it as an explicitly-rejected build so pnpm\n // knows we've seen it and will skip it instead of erroring.\n registerPnpmBuiltDependencies(tree, { '@scarf/scarf': false });\n\n addTsDependencies(tree, DEPENDENCIES, {\n metadata,\n projectRoot: frontendProjectConfig.root,\n });\n\n // Agents only publish their runtime ARN to the 'agentcore' namespace by\n // default, which isn't exposed to the website. Patch the agent's CDK/TF\n // construct to also publish under 'connection' so the browser can read it\n // from runtime-config.json. When routing via a gateway, the gateway\n // publishes its own URL instead.\n if (!gatewayRoute) {\n await addAgentRuntimeToConnectionNamespace(tree, {\n agentNameKebabCase: kebabCase(agentNameClassName),\n agentNameClassName,\n });\n }\n};\n\n/**\n * The theme module this helper vends, from the website's `metadata.ux`. Callers\n * record the resolved value, so the theme predicates read what the code branches\n * on.\n */\nexport const resolveAgUiTheme = (\n frontendProjectConfig: ProjectConfiguration,\n): AgUiTheme => {\n const ux = (\n (frontendProjectConfig.metadata as any)?.ux as string | undefined\n )?.toLowerCase();\n switch (ux) {\n case 'cloudscape':\n return 'cloudscape';\n case 'shadcn':\n return 'shadcn';\n default:\n return 'default';\n }\n};\n\n/**\n * Register this agent's hook in the shared `AguiProvider` using GritQL AST\n * patches. The provider starts out with an empty `selfManagedAgents` registry\n * (from the template); each call appends:\n * - `import { useAgui<Name> } from '../hooks/useAgui<Name>';`\n * - `const <varName> = useAgui<Name>();` before the `useMemo` call\n * - `...<varName>` into the memoised object literal\n * - `<varName>` into the `useMemo` deps array\n *\n * All steps are guarded so re-running produces byte-identical output.\n */\nconst registerAgentHookInProvider = async (\n tree: Tree,\n frontendProjectConfig: ProjectConfiguration,\n agentNameClassName: string,\n) => {\n const providerPath = joinPathFragments(\n frontendProjectConfig.sourceRoot,\n 'components',\n 'AguiProvider.tsx',\n );\n const hookName = `useAgui${agentNameClassName}`;\n // useAguiStoryAgent -> storyAgentAgents\n const varName = `${agentNameClassName.charAt(0).toLowerCase()}${agentNameClassName.slice(1)}Agents`;\n\n // 1. Add the hook import\n await addDestructuredImport(\n tree,\n providerPath,\n [hookName],\n `../hooks/${hookName}`,\n );\n\n // 2. Insert `const <varName> = <hookName>();` before the useMemo declaration\n await applyGritQL(\n tree,\n providerPath,\n `\\`const selfManagedAgents = useMemo<Record<string, AbstractAgent>>($body, $deps);\\` => ` +\n `\\`const ${varName} = ${hookName}();\\nconst selfManagedAgents = useMemo<Record<string, AbstractAgent>>($body, $deps);\\` ` +\n `where { $program <: not contains \\`const ${varName} = ${hookName}()\\` }`,\n );\n\n // 3. Spread `...<varName>` into the memoised object and add `<varName>` to\n // the deps array. Branches on `{}`/`[]` vs populated so both the\n // first-agent and nth-agent cases produce clean output.\n await applyGritQL(\n tree,\n providerPath,\n `\\`useMemo<Record<string, AbstractAgent>>(() => ($obj), $deps)\\` where {` +\n ` $obj <: not contains \\`...${varName}\\`,` +\n ` if ($obj <: \\`{}\\`) { $obj => \\`{ ...${varName} }\\` }` +\n ` else { $obj <: \\`{$items}\\` where { $items += \\`, ...${varName}\\` } },` +\n ` if ($deps <: \\`[]\\`) { $deps => \\`[${varName}]\\` }` +\n ` else { $deps <: \\`[$dd]\\` where { $dd += \\`, ${varName}\\` } }` +\n ` }`,\n );\n};\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","addAgentRuntimeToConnectionNamespace","addTsDependencies","addDestructuredImport","addSingleImport","applyGritQL","declareDependencies","ownedElsewhere","kebabCase","getNpmScopePrefix","registerPnpmBuiltDependencies","SHADCN_DEPENDENCIES","sharedShadcnGenerator","runtimeConfigGenerator","DEPENDENCIES","ts","name","when","m","theme","auth","dev","addAgUiReactConnection","tree","options","frontendProjectConfig","agentName","agentNameClassName","gatewayRoute","resolveAgUiTheme","metadata","scopeAlias","dirname","root","overwriteStrategy","KeepExisting","sourceRoot","project","registerAgentHookInProvider","mainTsxPath","projectRoot","agentNameKebabCase","ux","toLowerCase","providerPath","hookName","varName","charAt","slice"],"mappings":"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"}
|
|
@@ -94,6 +94,11 @@ export interface AddAgentCoreGatewayInfraProps {
|
|
|
94
94
|
projectDirectory: string;
|
|
95
95
|
cedarPolicy: boolean;
|
|
96
96
|
auth: AgentCoreAuth;
|
|
97
|
+
/**
|
|
98
|
+
* The gateway's protocol: mcp aggregates MCP server targets, http proxies
|
|
99
|
+
* agent runtime targets via path-based routing.
|
|
100
|
+
*/
|
|
101
|
+
protocol: 'mcp' | 'http';
|
|
97
102
|
}
|
|
98
103
|
export declare const addAgentCoreGatewayInfra: <const D extends DependencyDeclaration>(tree: Tree, options: AddAgentCoreGatewayInfraProps & IACProvider, declaration: D & MustDeclare<typeof AGENT_CORE_CONSTRUCTS_DEPENDENCIES, D>) => Promise<void>;
|
|
99
104
|
export {};
|