@aws/nx-plugin 1.0.0-rc.60 → 1.0.0-rc.62
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/migrations.json +36 -26
- package/package.json +1 -1
- package/src/mcp-server/tools/general-guidance.js +1 -1
- package/src/mcp-server/tools/general-guidance.js.map +1 -1
- package/src/migrations/latest/py-agent-lifespan-construction/metadata.json +3 -0
- package/src/migrations/latest/py-agent-lifespan-construction/migration.js +412 -0
- package/src/migrations/latest/py-agent-lifespan-construction/migration.js.map +1 -0
- package/src/migrations/latest/rename-load-runtime-config-target/metadata.json +3 -0
- package/src/migrations/latest/rename-load-runtime-config-target/migration.js +33 -0
- package/src/migrations/latest/rename-load-runtime-config-target/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.50/0001-modernize-function-props-cast/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.50/0002-restrict-cors-to-custom-domains/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.50/0003-terraform-bootstrap-adopt-existing-bucket/migration.d.ts +6 -0
- package/src/migrations/v1.0.0-rc.50/0003-terraform-bootstrap-adopt-existing-bucket/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.52/0001-user-identity-waf-allow-localhost-callback/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.54/0001-order-access-log-delivery-after-bucket-policy/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.55/0001-backfill-generator-metadata/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.56/0001-dynamodb-local-remove-optimize-flag/migration.js.map +1 -0
- package/src/migrations/v1.0.0-rc.57/0001-ts-agent-session-management-support/migration.d.ts +6 -0
- package/src/migrations/v1.0.0-rc.57/0001-ts-agent-session-management-support/migration.js.map +1 -0
- package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +2 -10
- package/src/py/agent/__snapshots__/generator.frameworks.spec.ts.snap +12 -8
- package/src/py/agent/files/{ag-ui-langchain → langchain/ag-ui}/main.py.template +12 -8
- package/src/py/agent/files/{http → langchain/http}/init.py.template +10 -0
- package/src/py/agent/files/{http-langchain → langchain/http}/main.py.template +1 -4
- package/src/py/agent/files/strands/ag-ui/main.py.template +89 -0
- package/src/py/agent/files/strands/http/init.py.template +97 -0
- package/src/py/agent/files/{http → strands/http}/main.py.template +2 -10
- package/src/py/agent/generator.js +9 -19
- package/src/py/agent/generator.js.map +1 -1
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +6 -6
- package/src/ts/react-website/app/files/app/common/README.md.template +1 -1
- package/src/ts/react-website/app/generator.js +4 -4
- package/src/ts/react-website/app/generator.js.map +1 -1
- package/src/utils/migration-versions.d.ts +31 -2
- package/src/utils/migration-versions.js +74 -10
- package/src/utils/migration-versions.js.map +1 -1
- package/src/migrations/v1.0.0-rc.50/modernize-function-props-cast/migration.js.map +0 -1
- package/src/migrations/v1.0.0-rc.50/restrict-cors-to-custom-domains/migration.js.map +0 -1
- package/src/migrations/v1.0.0-rc.50/terraform-bootstrap-adopt-existing-bucket/migration.js.map +0 -1
- package/src/migrations/v1.0.0-rc.52/user-identity-waf-allow-localhost-callback/migration.js.map +0 -1
- package/src/migrations/v1.0.0-rc.54/order-access-log-delivery-after-bucket-policy/migration.js.map +0 -1
- package/src/migrations/v1.0.0-rc.55/backfill-generator-metadata/migration.js.map +0 -1
- package/src/migrations/v1.0.0-rc.56/dynamodb-local-remove-optimize-flag/migration.js.map +0 -1
- package/src/migrations/v1.0.0-rc.57/ts-agent-session-management-support/migration.js.map +0 -1
- package/src/py/agent/files/ag-ui/main.py.template +0 -37
- /package/src/migrations/{v1.0.0-rc.50/modernize-function-props-cast → latest/py-agent-lifespan-construction}/migration.d.ts +0 -0
- /package/src/migrations/{v1.0.0-rc.50/restrict-cors-to-custom-domains → latest/rename-load-runtime-config-target}/migration.d.ts +0 -0
- /package/src/migrations/v1.0.0-rc.50/{modernize-function-props-cast → 0001-modernize-function-props-cast}/metadata.json +0 -0
- /package/src/migrations/v1.0.0-rc.50/{terraform-bootstrap-adopt-existing-bucket → 0001-modernize-function-props-cast}/migration.d.ts +0 -0
- /package/src/migrations/v1.0.0-rc.50/{modernize-function-props-cast → 0001-modernize-function-props-cast}/migration.js +0 -0
- /package/src/migrations/v1.0.0-rc.50/{restrict-cors-to-custom-domains → 0002-restrict-cors-to-custom-domains}/metadata.json +0 -0
- /package/src/migrations/{v1.0.0-rc.57/ts-agent-session-management-support → v1.0.0-rc.50/0002-restrict-cors-to-custom-domains}/migration.d.ts +0 -0
- /package/src/migrations/v1.0.0-rc.50/{restrict-cors-to-custom-domains → 0002-restrict-cors-to-custom-domains}/migration.js +0 -0
- /package/src/migrations/v1.0.0-rc.50/{terraform-bootstrap-adopt-existing-bucket → 0003-terraform-bootstrap-adopt-existing-bucket}/metadata.json +0 -0
- /package/src/migrations/v1.0.0-rc.50/{terraform-bootstrap-adopt-existing-bucket → 0003-terraform-bootstrap-adopt-existing-bucket}/migration.js +0 -0
- /package/src/migrations/v1.0.0-rc.52/{user-identity-waf-allow-localhost-callback → 0001-user-identity-waf-allow-localhost-callback}/metadata.json +0 -0
- /package/src/migrations/v1.0.0-rc.52/{user-identity-waf-allow-localhost-callback → 0001-user-identity-waf-allow-localhost-callback}/migration.d.ts +0 -0
- /package/src/migrations/v1.0.0-rc.52/{user-identity-waf-allow-localhost-callback → 0001-user-identity-waf-allow-localhost-callback}/migration.js +0 -0
- /package/src/migrations/v1.0.0-rc.54/{order-access-log-delivery-after-bucket-policy → 0001-order-access-log-delivery-after-bucket-policy}/metadata.json +0 -0
- /package/src/migrations/v1.0.0-rc.54/{order-access-log-delivery-after-bucket-policy → 0001-order-access-log-delivery-after-bucket-policy}/migration.d.ts +0 -0
- /package/src/migrations/v1.0.0-rc.54/{order-access-log-delivery-after-bucket-policy → 0001-order-access-log-delivery-after-bucket-policy}/migration.js +0 -0
- /package/src/migrations/v1.0.0-rc.55/{backfill-generator-metadata → 0001-backfill-generator-metadata}/metadata.json +0 -0
- /package/src/migrations/v1.0.0-rc.55/{backfill-generator-metadata → 0001-backfill-generator-metadata}/migration.d.ts +0 -0
- /package/src/migrations/v1.0.0-rc.55/{backfill-generator-metadata → 0001-backfill-generator-metadata}/migration.js +0 -0
- /package/src/migrations/v1.0.0-rc.56/{dynamodb-local-remove-optimize-flag → 0001-dynamodb-local-remove-optimize-flag}/metadata.json +0 -0
- /package/src/migrations/v1.0.0-rc.56/{dynamodb-local-remove-optimize-flag → 0001-dynamodb-local-remove-optimize-flag}/migration.d.ts +0 -0
- /package/src/migrations/v1.0.0-rc.56/{dynamodb-local-remove-optimize-flag → 0001-dynamodb-local-remove-optimize-flag}/migration.js +0 -0
- /package/src/migrations/v1.0.0-rc.57/{ts-agent-session-management-support → 0001-ts-agent-session-management-support}/metadata.json +0 -0
- /package/src/migrations/v1.0.0-rc.57/{ts-agent-session-management-support → 0001-ts-agent-session-management-support}/migration.js +0 -0
- /package/src/py/agent/files/{a2a-langchain → langchain/a2a}/main.py.template +0 -0
- /package/src/py/agent/files/{common-langchain → langchain/common}/agent.py.template +0 -0
- /package/src/py/agent/files/{a2a → strands/a2a}/main.py.template +0 -0
- /package/src/py/agent/files/{common → strands/common}/__init__.py.template +0 -0
- /package/src/py/agent/files/{common → strands/common}/agent.py.template +0 -0
|
@@ -609,6 +609,7 @@ exports[`py#agent generator > langchain framework > should match snapshot for la
|
|
|
609
609
|
"import logging
|
|
610
610
|
import time
|
|
611
611
|
import uuid
|
|
612
|
+
from contextlib import asynccontextmanager
|
|
612
613
|
|
|
613
614
|
from ag_ui.core import EventType, RunAgentInput, RunErrorEvent
|
|
614
615
|
from ag_ui.encoder import EventEncoder
|
|
@@ -625,13 +626,16 @@ logging.basicConfig(level=logging.INFO)
|
|
|
625
626
|
|
|
626
627
|
SESSION_ID_HEADER = "x-amzn-bedrock-agentcore-runtime-session-id"
|
|
627
628
|
|
|
628
|
-
_graph = get_agent()
|
|
629
629
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
graph=
|
|
633
|
-
|
|
634
|
-
|
|
630
|
+
@asynccontextmanager
|
|
631
|
+
async def lifespan(app: FastAPI):
|
|
632
|
+
graph = get_agent()
|
|
633
|
+
app.state.agui_agent = LangGraphAgent(
|
|
634
|
+
name="SnapshotAgent",
|
|
635
|
+
graph=graph,
|
|
636
|
+
description="A LangChain/LangGraph Agent exposed via the AG-UI protocol.",
|
|
637
|
+
)
|
|
638
|
+
yield
|
|
635
639
|
|
|
636
640
|
|
|
637
641
|
class _SessionIdMiddleware(BaseHTTPMiddleware):
|
|
@@ -643,7 +647,7 @@ class _SessionIdMiddleware(BaseHTTPMiddleware):
|
|
|
643
647
|
return await call_next(request)
|
|
644
648
|
|
|
645
649
|
|
|
646
|
-
app = FastAPI(title="SnapshotAgent")
|
|
650
|
+
app = FastAPI(title="SnapshotAgent", lifespan=lifespan)
|
|
647
651
|
# Allow browser-based AG-UI clients (e.g. a connected React website) to call
|
|
648
652
|
# this agent cross-origin, including the CORS preflight.
|
|
649
653
|
app.add_middleware(
|
|
@@ -682,7 +686,7 @@ async def invocations(request: Request):
|
|
|
682
686
|
# Re-bind the session: the streaming body runs outside the middleware.
|
|
683
687
|
with session_id_context(session_id or str(uuid.uuid4())):
|
|
684
688
|
try:
|
|
685
|
-
async for event in agui_agent.run(input_data):
|
|
689
|
+
async for event in request.app.state.agui_agent.run(input_data):
|
|
686
690
|
yield encoder.encode(event)
|
|
687
691
|
except Exception as e:
|
|
688
692
|
yield encoder.encode(
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import time
|
|
3
3
|
import uuid
|
|
4
|
+
from contextlib import asynccontextmanager
|
|
4
5
|
|
|
5
6
|
from ag_ui.core import EventType, RunAgentInput, RunErrorEvent
|
|
6
7
|
from ag_ui.encoder import EventEncoder
|
|
@@ -17,13 +18,16 @@ logging.basicConfig(level=logging.INFO)
|
|
|
17
18
|
|
|
18
19
|
SESSION_ID_HEADER = "x-amzn-bedrock-agentcore-runtime-session-id"
|
|
19
20
|
|
|
20
|
-
_graph = get_agent()
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
graph=
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
@asynccontextmanager
|
|
23
|
+
async def lifespan(app: FastAPI):
|
|
24
|
+
graph = get_agent()
|
|
25
|
+
app.state.agui_agent = LangGraphAgent(
|
|
26
|
+
name="<%= agentNameClassName %>",
|
|
27
|
+
graph=graph,
|
|
28
|
+
description="A LangChain/LangGraph Agent exposed via the AG-UI protocol.",
|
|
29
|
+
)
|
|
30
|
+
yield
|
|
27
31
|
|
|
28
32
|
|
|
29
33
|
class _SessionIdMiddleware(BaseHTTPMiddleware):
|
|
@@ -35,7 +39,7 @@ class _SessionIdMiddleware(BaseHTTPMiddleware):
|
|
|
35
39
|
return await call_next(request)
|
|
36
40
|
|
|
37
41
|
|
|
38
|
-
app = FastAPI(title="<%= agentNameClassName %>")
|
|
42
|
+
app = FastAPI(title="<%= agentNameClassName %>", lifespan=lifespan)
|
|
39
43
|
# Allow browser-based AG-UI clients (e.g. a connected React website) to call
|
|
40
44
|
# this agent cross-origin, including the CORS preflight.
|
|
41
45
|
app.add_middleware(
|
|
@@ -70,7 +74,7 @@ async def invocations(request: Request):
|
|
|
70
74
|
# Re-bind the session: the streaming body runs outside the middleware.
|
|
71
75
|
with session_id_context(session_id or str(uuid.uuid4())):
|
|
72
76
|
try:
|
|
73
|
-
async for event in agui_agent.run(input_data):
|
|
77
|
+
async for event in request.app.state.agui_agent.run(input_data):
|
|
74
78
|
yield encoder.encode(event)
|
|
75
79
|
except Exception as e:
|
|
76
80
|
yield encoder.encode(RunErrorEvent(type=EventType.RUN_ERROR, message=str(e)[:300], code="AGENT_ERROR"))
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from collections.abc import AsyncIterator
|
|
3
|
+
from contextlib import asynccontextmanager
|
|
3
4
|
from typing import Any
|
|
4
5
|
|
|
5
6
|
from fastapi import FastAPI
|
|
@@ -8,6 +9,8 @@ from fastapi.responses import JSONResponse, StreamingResponse
|
|
|
8
9
|
from pydantic import BaseModel
|
|
9
10
|
from starlette.middleware.exceptions import ExceptionMiddleware
|
|
10
11
|
|
|
12
|
+
from .agent import get_agent
|
|
13
|
+
|
|
11
14
|
|
|
12
15
|
class InternalServerErrorDetails(BaseModel):
|
|
13
16
|
detail: str
|
|
@@ -60,10 +63,17 @@ class JsonStreamingResponse(StreamingResponse):
|
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
|
|
66
|
+
@asynccontextmanager
|
|
67
|
+
async def lifespan(app: FastAPI):
|
|
68
|
+
app.state.graph = get_agent()
|
|
69
|
+
yield
|
|
70
|
+
|
|
71
|
+
|
|
63
72
|
app = FastAPI(
|
|
64
73
|
title="<%= agentNameClassName %>",
|
|
65
74
|
responses={500: {"model": InternalServerErrorDetails}},
|
|
66
75
|
generate_unique_id_function=lambda route: route.name,
|
|
76
|
+
lifespan=lifespan,
|
|
67
77
|
)
|
|
68
78
|
|
|
69
79
|
# Add cors middleware
|
|
@@ -7,13 +7,10 @@ from pydantic import BaseModel, Field
|
|
|
7
7
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
8
8
|
from <%- agentConnectionModuleName %> import get_current_session_id, session_id_context
|
|
9
9
|
|
|
10
|
-
from .agent import get_agent
|
|
11
10
|
from .init import JsonStreamingResponse, app
|
|
12
11
|
|
|
13
12
|
SESSION_ID_HEADER = "x-amzn-bedrock-agentcore-runtime-session-id"
|
|
14
13
|
|
|
15
|
-
_graph = get_agent()
|
|
16
|
-
|
|
17
14
|
|
|
18
15
|
class InvokeInput(BaseModel):
|
|
19
16
|
prompt: str = Field(max_length=100000)
|
|
@@ -40,7 +37,7 @@ async def handle_invoke(input: InvokeInput, session_id: str):
|
|
|
40
37
|
config = {"configurable": {"thread_id": session_id}}
|
|
41
38
|
# Re-bind the session: the streaming body runs outside the middleware scope.
|
|
42
39
|
with session_id_context(session_id):
|
|
43
|
-
stream =
|
|
40
|
+
stream = app.state.graph.astream(
|
|
44
41
|
{"messages": [{"role": "user", "content": input.prompt}]},
|
|
45
42
|
config,
|
|
46
43
|
stream_mode="messages",
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import uuid
|
|
3
|
+
from contextlib import asynccontextmanager
|
|
4
|
+
|
|
5
|
+
from ag_ui.core import EventType, RunAgentInput, RunErrorEvent
|
|
6
|
+
from ag_ui.encoder import EventEncoder
|
|
7
|
+
from ag_ui_strands import StrandsAgent
|
|
8
|
+
from fastapi import FastAPI, Request
|
|
9
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
10
|
+
from fastapi.responses import StreamingResponse
|
|
11
|
+
from <%- agentConnectionModuleName %> import get_current_session_id, session_id_context
|
|
12
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
|
13
|
+
|
|
14
|
+
from .agent import get_agent
|
|
15
|
+
|
|
16
|
+
logging.basicConfig(level=logging.INFO)
|
|
17
|
+
|
|
18
|
+
SESSION_ID_HEADER = "x-amzn-bedrock-agentcore-runtime-session-id"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@asynccontextmanager
|
|
22
|
+
async def lifespan(app: FastAPI):
|
|
23
|
+
with get_agent() as agent:
|
|
24
|
+
app.state.agui_agent = StrandsAgent(
|
|
25
|
+
agent=agent,
|
|
26
|
+
name="<%= agentNameClassName %>",
|
|
27
|
+
description="A Strands Agent exposed via the AG-UI protocol.",
|
|
28
|
+
)
|
|
29
|
+
yield
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class _SessionIdMiddleware(BaseHTTPMiddleware):
|
|
33
|
+
"""Bind the session ID for this request so downstream MCP / A2A clients forward it on outbound calls."""
|
|
34
|
+
|
|
35
|
+
async def dispatch(self, request: Request, call_next):
|
|
36
|
+
session_id = request.headers.get(SESSION_ID_HEADER) or str(uuid.uuid4())
|
|
37
|
+
with session_id_context(session_id):
|
|
38
|
+
return await call_next(request)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
app = FastAPI(title="AWS Strands - <%= agentNameClassName %>", lifespan=lifespan)
|
|
42
|
+
app.add_middleware(
|
|
43
|
+
CORSMiddleware,
|
|
44
|
+
allow_origins=["*"],
|
|
45
|
+
allow_credentials=True,
|
|
46
|
+
allow_methods=["*"],
|
|
47
|
+
allow_headers=["*"],
|
|
48
|
+
)
|
|
49
|
+
app.add_middleware(_SessionIdMiddleware)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@app.post("/invocations")
|
|
53
|
+
async def invocations(request: Request):
|
|
54
|
+
# Validate the body manually since AgentCore may omit Content-Type.
|
|
55
|
+
encoder = EventEncoder(accept=request.headers.get("accept") or "")
|
|
56
|
+
raw = await request.body()
|
|
57
|
+
try:
|
|
58
|
+
input_data = RunAgentInput.model_validate_json(raw)
|
|
59
|
+
except Exception as exc:
|
|
60
|
+
message = f"Invalid RunAgentInput: {str(exc)[:200]}"
|
|
61
|
+
|
|
62
|
+
async def _bad():
|
|
63
|
+
yield encoder.encode(RunErrorEvent(type=EventType.RUN_ERROR, message=message, code="BAD_REQUEST"))
|
|
64
|
+
|
|
65
|
+
return StreamingResponse(_bad(), media_type=encoder.get_content_type())
|
|
66
|
+
|
|
67
|
+
session_id = request.headers.get(SESSION_ID_HEADER) or get_current_session_id()
|
|
68
|
+
|
|
69
|
+
async def event_generator():
|
|
70
|
+
# Re-bind the session: the streaming body runs outside the middleware.
|
|
71
|
+
with session_id_context(session_id or str(uuid.uuid4())):
|
|
72
|
+
async for event in request.app.state.agui_agent.run(input_data):
|
|
73
|
+
try:
|
|
74
|
+
yield encoder.encode(event)
|
|
75
|
+
except Exception as e:
|
|
76
|
+
error_event = RunErrorEvent(
|
|
77
|
+
type=EventType.RUN_ERROR,
|
|
78
|
+
message=f"Encoding error: {e}",
|
|
79
|
+
code="ENCODING_ERROR",
|
|
80
|
+
)
|
|
81
|
+
yield encoder.encode(error_event)
|
|
82
|
+
break
|
|
83
|
+
|
|
84
|
+
return StreamingResponse(event_generator(), media_type=encoder.get_content_type())
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@app.get("/ping")
|
|
88
|
+
async def ping():
|
|
89
|
+
return {"status": "healthy"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from collections.abc import AsyncIterator
|
|
3
|
+
from contextlib import asynccontextmanager
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from fastapi import FastAPI
|
|
7
|
+
from fastapi.middleware.cors import CORSMiddleware
|
|
8
|
+
from fastapi.responses import JSONResponse, StreamingResponse
|
|
9
|
+
from <%- agentConnectionModuleName %> import with_session_id
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
from starlette.middleware.exceptions import ExceptionMiddleware
|
|
12
|
+
|
|
13
|
+
from .agent import get_agent
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class InternalServerErrorDetails(BaseModel):
|
|
17
|
+
detail: str
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class JsonStreamingResponse(StreamingResponse):
|
|
21
|
+
"""A streaming response that serializes items to JSON Lines format."""
|
|
22
|
+
|
|
23
|
+
media_type = "application/jsonl"
|
|
24
|
+
|
|
25
|
+
def __init__(
|
|
26
|
+
self,
|
|
27
|
+
content: AsyncIterator[BaseModel],
|
|
28
|
+
status_code: int = 200,
|
|
29
|
+
headers: dict[str, str] | None = None,
|
|
30
|
+
**kwargs: Any,
|
|
31
|
+
) -> None:
|
|
32
|
+
"""Stream json lines from an async iterator yielding Pydantic models"""
|
|
33
|
+
super().__init__(
|
|
34
|
+
content=self._serialize(content),
|
|
35
|
+
status_code=status_code,
|
|
36
|
+
headers=headers,
|
|
37
|
+
media_type=self.media_type,
|
|
38
|
+
**kwargs,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
@staticmethod
|
|
42
|
+
async def _serialize(
|
|
43
|
+
content: AsyncIterator[BaseModel],
|
|
44
|
+
) -> AsyncIterator[bytes]:
|
|
45
|
+
"""Serialize Pydantic models to JSON Lines format."""
|
|
46
|
+
async for item in content:
|
|
47
|
+
yield (item.model_dump_json() + "\n").encode("utf-8")
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def openapi_response(
|
|
51
|
+
item_model: type[BaseModel],
|
|
52
|
+
description: str = "Streaming response",
|
|
53
|
+
) -> dict[str, Any]:
|
|
54
|
+
"""Generate an OpenAPI application/jsonl response for a stream of the given model"""
|
|
55
|
+
return {
|
|
56
|
+
"description": description,
|
|
57
|
+
"content": {
|
|
58
|
+
"application/jsonl": {
|
|
59
|
+
"itemSchema": {"$ref": f"#/components/schemas/{item_model.__name__}"},
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
# Include the model so FastAPI registers the schema in components/schemas
|
|
63
|
+
"model": item_model,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@asynccontextmanager
|
|
68
|
+
async def lifespan(app: FastAPI):
|
|
69
|
+
with with_session_id(
|
|
70
|
+
get_agent,
|
|
71
|
+
name="<%= agentNameClassName %>",
|
|
72
|
+
description="A Strands Agent exposed via HTTP streaming.",
|
|
73
|
+
) as agent:
|
|
74
|
+
app.state.agent = agent
|
|
75
|
+
yield
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
app = FastAPI(
|
|
79
|
+
title="<%= agentNameClassName %>",
|
|
80
|
+
responses={500: {"model": InternalServerErrorDetails}},
|
|
81
|
+
generate_unique_id_function=lambda route: route.name,
|
|
82
|
+
lifespan=lifespan,
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Add cors middleware
|
|
86
|
+
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])
|
|
87
|
+
|
|
88
|
+
# Add exception middleware(s)
|
|
89
|
+
app.add_middleware(ExceptionMiddleware, handlers=app.exception_handlers)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@app.exception_handler(Exception)
|
|
93
|
+
async def unhandled_exception_handler(request, err):
|
|
94
|
+
logging.exception("Unhandled exception while handling request")
|
|
95
|
+
return JSONResponse(
|
|
96
|
+
status_code=500, content=InternalServerErrorDetails(detail="Internal Server Error").model_dump()
|
|
97
|
+
)
|
|
@@ -5,20 +5,12 @@ from bedrock_agentcore.runtime.models import PingStatus
|
|
|
5
5
|
from fastapi import Request
|
|
6
6
|
from pydantic import BaseModel, Field
|
|
7
7
|
from starlette.middleware.base import BaseHTTPMiddleware
|
|
8
|
-
from <%- agentConnectionModuleName %> import session_id_context
|
|
8
|
+
from <%- agentConnectionModuleName %> import session_id_context
|
|
9
9
|
|
|
10
|
-
from .agent import get_agent
|
|
11
10
|
from .init import JsonStreamingResponse, app
|
|
12
11
|
|
|
13
12
|
SESSION_ID_HEADER = "x-amzn-bedrock-agentcore-runtime-session-id"
|
|
14
13
|
|
|
15
|
-
_agent_ctx = with_session_id(
|
|
16
|
-
get_agent,
|
|
17
|
-
name="<%= agentNameClassName %>",
|
|
18
|
-
description="A Strands Agent exposed via HTTP streaming.",
|
|
19
|
-
)
|
|
20
|
-
_agent = _agent_ctx.__enter__()
|
|
21
|
-
|
|
22
14
|
|
|
23
15
|
class InvokeInput(BaseModel):
|
|
24
16
|
prompt: str = Field(max_length=100000)
|
|
@@ -30,7 +22,7 @@ class StreamChunk(BaseModel):
|
|
|
30
22
|
|
|
31
23
|
async def handle_invoke(input: InvokeInput):
|
|
32
24
|
"""Streaming handler for agent invocation"""
|
|
33
|
-
stream =
|
|
25
|
+
stream = app.state.agent.stream_async(input.prompt)
|
|
34
26
|
async for event in stream:
|
|
35
27
|
text = event.get("event", {}).get("contentBlockDelta", {}).get("delta", {}).get("text")
|
|
36
28
|
if text is not None:
|
|
@@ -220,35 +220,25 @@ export const pyAgentGenerator = async (tree, options)=>{
|
|
|
220
220
|
// is framework-specific (Strands yields a contextmanaged Agent; LangChain
|
|
221
221
|
// returns a compiled create_agent graph), so it comes from a per-framework
|
|
222
222
|
// dir. The package __init__.py is framework-agnostic (it stays in `common`).
|
|
223
|
-
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', framework
|
|
223
|
+
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', framework, 'common'), targetSourceDir, templateContext, {
|
|
224
224
|
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
225
225
|
});
|
|
226
226
|
if (framework === 'langchain') {
|
|
227
|
-
// common
|
|
228
|
-
// framework-agnostic, so emit it from the
|
|
229
|
-
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'common'), targetSourceDir, templateContext, {
|
|
227
|
+
// langchain/common only carries agent.py; the empty package __init__.py is
|
|
228
|
+
// framework-agnostic, so emit it from the strands `common` dir.
|
|
229
|
+
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'strands', 'common'), targetSourceDir, templateContext, {
|
|
230
230
|
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
231
231
|
});
|
|
232
232
|
}
|
|
233
|
-
// Generate protocol-specific files. Each protocol's server entry point
|
|
233
|
+
// Generate protocol-specific files. Each protocol's server entry point (and,
|
|
234
|
+
// for HTTP, its init.py building the FastAPI app + lifespan) is
|
|
234
235
|
// framework-specific (Strands yields a contextmanaged Agent; LangChain drives
|
|
235
|
-
// a compiled create_agent graph), so it comes from a per-framework
|
|
236
|
-
//
|
|
236
|
+
// a compiled create_agent graph), so it comes from a per-framework,
|
|
237
|
+
// per-protocol dir: `files/<framework>/<protocol>`.
|
|
237
238
|
const protocolLower = protocol.toLowerCase();
|
|
238
|
-
|
|
239
|
-
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', protocolTemplateDir), targetSourceDir, templateContext, {
|
|
239
|
+
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', framework, protocolLower), targetSourceDir, templateContext, {
|
|
240
240
|
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
241
241
|
});
|
|
242
|
-
// The HTTP server's init.py (the FastAPI app + JsonStreamingResponse) is
|
|
243
|
-
// framework-agnostic and the LangChain http main.py reuses it, so emit it
|
|
244
|
-
// from the shared `http` dir. Emitted after the langchain main.py above so
|
|
245
|
-
// KeepExisting preserves that main.py and only adds init.py (the shared dir's
|
|
246
|
-
// own Strands main.py is skipped).
|
|
247
|
-
if (protocolLower === 'http' && framework === 'langchain') {
|
|
248
|
-
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'http'), targetSourceDir, templateContext, {
|
|
249
|
-
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
242
|
if (infra === 'agentcore') {
|
|
253
243
|
const containers = await resolveContainers(tree, 'inherit');
|
|
254
244
|
const dockerImageTag = `${getNpmScope(tree)}-${name}:latest`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/py/agent/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 type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { ensureLicenseExceptions } from '../../license/config';\nimport { AG_UI_LANGGRAPH_EXCEPTIONS } from '../../license/known-exceptions';\nimport {\n addPyDependencies,\n addTsDependencies,\n} from '../../utils/add-dependencies';\nimport { addAgentChatScripts } from '../../utils/agent-chat/agent-chat';\nimport {\n AGENT_CONNECTION_PY_DEPENDENCIES,\n addPythonFrameworkBase,\n ensurePythonAgentConnectionProject,\n getPythonAgentConnectionModuleName,\n getPythonAgentConnectionProject,\n} from '../../utils/agent-connection/agent-connection';\nimport { addAgentInfra } from '../../utils/agent-core-constructs/agent-core-constructs';\nimport { addPythonBundleTarget } from '../../utils/bundle/bundle';\nimport { resolveContainers } from '../../utils/containers';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../utils/declared-dependencies';\nimport { addDockerScanTarget, DOCKER_DEPENDENCIES } from '../../utils/docker';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { FS_DEPENDENCIES, FsCommands } from '../../utils/fs';\nimport { updateGitIgnore } from '../../utils/git';\nimport { resolveIac } from '../../utils/iac';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport { kebabCase, toClassName, toSnakeCase } from '../../utils/names';\nimport { getNpmScope } from '../../utils/npm-scope';\nimport {\n addComponentDevTarget,\n addComponentGeneratorMetadata,\n addDependencyToTargetIfNotPresent,\n getGeneratorInfo,\n type NxGeneratorInfo,\n normalizeTargetKeyOrder,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx';\nimport { sortObjectKeys } from '../../utils/object';\nimport { toProjectRelativePath } from '../../utils/paths';\nimport { assignPort } from '../../utils/port';\nimport { addWorkspaceDependencyToPyProject } from '../../utils/py';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../../utils/shared-constructs';\nimport type { IacMetadata } from '../../utils/shared-constructs-constants';\nimport { BASE_IMAGES } from '../../utils/versions';\nimport type {\n AgentProtocol,\n PyAgentFramework,\n PyAgentGeneratorSchema,\n} from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface PyAgentMetadata extends IacMetadata {\n readonly port: number;\n readonly rc: string;\n readonly auth: string;\n readonly protocol: AgentProtocol;\n /**\n * The mcp / gateway connection generators dispatch on this field to pick the\n * Strands vs LangChain Layer-2 client + agent.py transform.\n */\n readonly framework: PyAgentFramework;\n}\n\n/** Whether the chat CLI signs its requests, which only IAM auth needs. */\nconst isIam = (m: PyAgentMetadata) => m.auth === 'iam';\n\n// Each entry names the framework and protocol branch it belongs to, so the same\n// declaration drives both adding and the version sync.\nexport const DEPENDENCIES = declareDependencies<PyAgentMetadata>()({\n ts: [\n // The chat CLI, which runs standalone via tsx for every protocol and\n // resolves the deployed agent from AppConfig. `agent-chat-cli` transitively\n // bundles the protocol clients (@a2a-js/sdk, @ag-ui/client).\n { name: 'agent-chat-cli', dev: true, root: true },\n { name: 'tsx', dev: true, root: true },\n { name: '@types/node', dev: true, root: true },\n { name: '@aws-lambda-powertools/parameters', dev: true, root: true },\n { name: '@aws-sdk/client-appconfigdata', dev: true, root: true },\n { name: 'aws4fetch', when: isIam, dev: true, root: true },\n {\n name: '@aws-sdk/credential-providers',\n when: isIam,\n dev: true,\n root: true,\n },\n {\n name: '@a2a-js/sdk',\n when: (m) => m.protocol === 'a2a',\n dev: true,\n root: true,\n },\n // Added by the helpers that own the projects they belong to.\n ...ownedElsewhere(FS_DEPENDENCIES),\n ...ownedElsewhere(DOCKER_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n py: [\n { name: 'aws-lambda-powertools' },\n { name: 'aws-opentelemetry-distro' },\n { name: 'bedrock-agentcore' },\n { name: 'boto3' },\n { name: 'fastapi' },\n { name: 'mcp' },\n // langchain pulls no Strands dependencies — the langchain model binding\n // plus the per-protocol server adapter: ag-ui-langgraph for AG-UI, a2a-sdk\n // for A2A, nothing extra for HTTP (FastAPI is added for every agent).\n { name: 'langchain', when: (m) => m.framework === 'langchain' },\n { name: 'langchain-aws', when: (m) => m.framework === 'langchain' },\n { name: 'langgraph', when: (m) => m.framework === 'langchain' },\n {\n name: 'ag-ui-protocol',\n when: (m) => m.framework === 'langchain' && m.protocol === 'ag-ui',\n },\n {\n name: 'ag-ui-langgraph',\n when: (m) => m.framework === 'langchain' && m.protocol === 'ag-ui',\n },\n {\n name: 'a2a-sdk',\n when: (m) => m.framework === 'langchain' && m.protocol === 'a2a',\n },\n {\n name: 'strands-agents[a2a]',\n when: (m) => m.framework !== 'langchain' && m.protocol === 'a2a',\n },\n {\n name: 'strands-agents',\n when: (m) => m.framework !== 'langchain' && m.protocol !== 'a2a',\n },\n {\n name: 'strands-agents-tools',\n when: (m) => m.framework !== 'langchain',\n },\n // Declared again here so a Strands AG-UI agent lists it in the same order\n // the generated pyproject.toml had before.\n {\n name: 'ag-ui-protocol',\n when: (m) => m.framework !== 'langchain' && m.protocol === 'ag-ui',\n },\n {\n name: 'ag-ui-strands',\n when: (m) => m.framework !== 'langchain' && m.protocol === 'ag-ui',\n },\n { name: 'uvicorn' },\n // `fastapi dev` runs the local server for every protocol.\n { name: 'fastapi[standard]', group: 'dev' },\n // The agent-connection helper adds these to its own project.\n ...ownedElsewhere(AGENT_CONNECTION_PY_DEPENDENCIES),\n ],\n});\n\nexport const PY_AGENT_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const pyAgentGenerator = async (\n tree: Tree,\n options: PyAgentGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const project = readProjectConfigurationUnqualified(tree, options.project);\n\n const pyProjectPath = joinPathFragments(project.root, 'pyproject.toml');\n\n // Check if the project has a pyproject.toml file\n if (!pyProjectPath) {\n throw new Error(\n `Unsupported project ${options.project}. Expected a Python project (with a pyproject.toml)`,\n );\n }\n\n if (!project.sourceRoot) {\n throw new Error(\n `This project does not have a source root. Please add a source root to the project configuration before running this generator.`,\n );\n }\n\n // Module name is the last part of the source root,\n const sourceParts = project.sourceRoot.split('/');\n const moduleName = sourceParts[sourceParts.length - 1];\n\n const name = kebabCase(\n options.name || `${kebabCase(project.name.split('.').pop())}-agent`,\n );\n const agentTargetPrefix = options.name ? name : 'agent';\n\n const agentNameSnakeCase = toSnakeCase(options.name || 'agent');\n const agentNameClassName = toClassName(name);\n\n const targetSourceDir = joinPathFragments(\n project.sourceRoot,\n agentNameSnakeCase,\n );\n\n const infra = options.infra ?? 'agentcore';\n const protocol = options.protocol ?? 'http';\n const framework = options.framework ?? 'strands';\n\n // Recorded in the metadata below so the version sync can tell a CDK\n // project from a Terraform one; undefined when no infrastructure was\n // generated, in which case neither provider's packages were added.\n const iac =\n infra !== 'none' ? await resolveIac(tree, options.iac) : undefined;\n\n if (infra === 'none' && options.auth && options.auth !== 'iam') {\n console.warn(\n 'Warning: auth is ignored when no infrastructure is configured (no infrastructure is generated)',\n );\n }\n\n const auth = options.auth ?? 'iam';\n\n // Only 'in-memory' is currently supported for Python agents (session manager\n // support for Python is not yet implemented).\n const session = options.session ?? 'in-memory';\n\n // Ensure the shared agent-connection project exists so the server entry\n // point can import `session_id_context` and propagate the AgentCore\n // session ID to any downstream MCP / A2A clients a later connection\n // generator wires into this agent.\n await ensurePythonAgentConnectionProject(tree, DEPENDENCIES);\n // The agent server imports the framework base helpers (session cache + model\n // error logging) regardless of whether a connection client is wired in. The\n // langchain framework has no base layer (its AG-UI foundation reuses only the\n // framework-agnostic session context), so this is a no-op for langchain.\n await addPythonFrameworkBase(tree, DEPENDENCIES, framework);\n const agentConnectionModuleName = getPythonAgentConnectionModuleName(tree);\n addWorkspaceDependencyToPyProject(\n tree,\n project,\n getPythonAgentConnectionProject(tree),\n );\n\n const templateContext = {\n name,\n agentNameSnakeCase,\n agentNameClassName,\n moduleName,\n agentConnectionModuleName,\n framework,\n };\n\n // Generate common files shared by both protocols. The agent module (agent.py)\n // is framework-specific (Strands yields a contextmanaged Agent; LangChain\n // returns a compiled create_agent graph), so it comes from a per-framework\n // dir. The package __init__.py is framework-agnostic (it stays in `common`).\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'files',\n framework === 'langchain' ? 'common-langchain' : 'common',\n ),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n if (framework === 'langchain') {\n // common-langchain only carries agent.py; the empty package __init__.py is\n // framework-agnostic, so emit it from the shared `common` dir.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'common'),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n }\n\n // Generate protocol-specific files. Each protocol's server entry point is\n // framework-specific (Strands yields a contextmanaged Agent; LangChain drives\n // a compiled create_agent graph), so it comes from a per-framework dir\n // `<protocol>-langchain` for LangChain, or `<protocol>` for Strands.\n const protocolLower = protocol.toLowerCase();\n const protocolTemplateDir =\n framework === 'langchain' ? `${protocolLower}-langchain` : protocolLower;\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', protocolTemplateDir),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n // The HTTP server's init.py (the FastAPI app + JsonStreamingResponse) is\n // framework-agnostic and the LangChain http main.py reuses it, so emit it\n // from the shared `http` dir. Emitted after the langchain main.py above so\n // KeepExisting preserves that main.py and only adds init.py (the shared dir's\n // own Strands main.py is skipped).\n if (protocolLower === 'http' && framework === 'langchain') {\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'http'),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n }\n\n if (infra === 'agentcore') {\n const containers = await resolveContainers(tree, 'inherit');\n const dockerImageTag = `${getNpmScope(tree)}-${name}:latest`;\n\n // Add bundle target\n const { bundleTargetName, bundleOutputDir } = addPythonBundleTarget(\n project,\n {\n pythonPlatform: 'aarch64-manylinux_2_28',\n },\n );\n\n // Add the Dockerfile\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'deploy'),\n targetSourceDir,\n {\n agentNameSnakeCase,\n moduleName,\n bundleOutputDir,\n protocol,\n pythonBaseImage: BASE_IMAGES.python,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n const dockerOutputDir = joinPathFragments(\n 'dist',\n project.root,\n 'docker',\n name,\n );\n const dockerTargetName = `${agentTargetPrefix}-docker`;\n\n // Add a docker target that prepares the docker context and builds the image\n const fs = new FsCommands(tree, DEPENDENCIES);\n project.targets[dockerTargetName] = {\n cache: true,\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(dockerOutputDir),\n fs.mkdir(dockerOutputDir),\n fs.cp(bundleOutputDir, dockerOutputDir),\n fs.cp(\n `${targetSourceDir}/Dockerfile`,\n `${dockerOutputDir}/Dockerfile`,\n ),\n `${containers} build --platform linux/arm64 -t ${dockerImageTag} ${dockerOutputDir}`,\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName],\n };\n\n addDependencyToTargetIfNotPresent(project, 'docker', dockerTargetName);\n addDependencyToTargetIfNotPresent(project, 'build', 'docker');\n\n addDockerScanTarget(\n tree,\n {\n project,\n containerEngine: containers,\n trivyTargetName: `${agentTargetPrefix}-trivy`,\n dockerTargetName,\n imageTags: [dockerImageTag],\n },\n DEPENDENCIES,\n );\n\n // Add shared constructs\n await sharedConstructsGenerator(tree, { iac }, DEPENDENCIES);\n\n // Add the construct to deploy the agent.\n // AG-UI uses HTTP as the AgentCore protocol type (AG-UI is HTTP-based with SSE over POST).\n const infraProtocol =\n protocol === 'ag-ui' ? ('http' as const) : (protocol as 'http' | 'a2a');\n await addAgentInfra(tree, {\n agentNameKebabCase: name,\n agentNameClassName,\n dockerImageTag,\n dockerOutputDir,\n iac,\n projectName: project.name,\n auth,\n session,\n serverProtocol: infraProtocol,\n containers,\n });\n }\n\n // A2A servers use port 9000 as per the Strands A2A SDK default and AgentCore A2A contract.\n // HTTP and AG-UI agents use port 8081+ to avoid conflict with VS Code server on 8080.\n const localDevPortStart = protocol === 'a2a' ? 9000 : 8081;\n const localDevPort = assignPort(tree, project, localDevPortStart, {\n component: { info: PY_AGENT_GENERATOR_INFO, name: agentTargetPrefix },\n });\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 metadata: PyAgentMetadata = {\n port: localDevPort,\n rc: agentNameClassName,\n auth,\n protocol,\n framework,\n ...(iac ? { iac } : {}),\n };\n\n addPyDependencies(tree, DEPENDENCIES, {\n metadata,\n projectRoot: project.root,\n });\n addTsDependencies(tree, DEPENDENCIES, { metadata });\n\n // All protocols use fastapi dev for hot reload:\n // - HTTP: FastAPI app directly defined in init.py\n // - A2A: A2AServer.to_fastapi_app() creates a FastAPI app in main.py\n // - AG-UI: create_strands_app() creates a FastAPI app in main.py\n const serveCommand = `uv run fastapi dev ${moduleName}/${agentNameSnakeCase}/main.py --port ${localDevPort}`;\n\n // HTTP chat uses the type-safe TypeScript client generated from the\n // agent's OpenAPI spec (same generated client the react-connection\n // generator produces). A2A and AG-UI speak standard protocols, so\n // we can run `agent-chat-cli` directly as a binary.\n const openApiTargetName = `${agentTargetPrefix}-openapi`;\n const clientGenTargetName = `${agentTargetPrefix}-generate-client`;\n\n const scriptsDir = joinPathFragments(\n project.root,\n 'scripts',\n agentTargetPrefix,\n );\n\n if (protocol === 'http') {\n // Emit the OpenAPI spec generator script (shared with react-connection)\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'react-connection',\n 'files',\n 'agent',\n ),\n project.root,\n {\n moduleName,\n agentNameSnakeCase,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // Ignore the generated client directory\n updateGitIgnore(tree, project.root, (patterns) => [\n ...patterns,\n `scripts/${agentTargetPrefix}/generated/`,\n ]);\n }\n\n // Every protocol gets a standalone `chat.ts`. It connects to the local\n // `dev` server by default, or to the deployed agent (with the\n // appropriate auth) when `RUNTIME_CONFIG_APP_ID` is set.\n addAgentChatScripts(tree, {\n scriptsDir,\n protocol,\n language: 'py',\n agentNameClassName,\n auth,\n });\n\n const chatUrl =\n protocol === 'ag-ui'\n ? `http://localhost:${localDevPort}/invocations`\n : `http://localhost:${localDevPort}`;\n const chatCommand = `tsx ./scripts/${agentTargetPrefix}/chat.ts`;\n\n const httpOnlyTargets =\n protocol === 'http'\n ? {\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 [clientGenTargetName]: {\n cache: true,\n executor: 'nx:run-commands',\n dependsOn: [openApiTargetName],\n inputs: [\n {\n dependentTasksOutputFiles: '**/*.json',\n },\n ],\n outputs: [`{projectRoot}/scripts/${agentTargetPrefix}/generated`],\n options: {\n commands: [\n `nx g @aws/nx-plugin:open-api#ts-client --openApiSpecPath=\"dist/${project.root}/openapi/${agentNameSnakeCase}/openapi.json\" --outputPath=\"${project.root}/scripts/${agentTargetPrefix}/generated\" --no-interactive`,\n ],\n },\n },\n }\n : {};\n\n const agentTargets = {\n ...project.targets,\n ...httpOnlyTargets,\n [`${agentTargetPrefix}-serve`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [serveCommand],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n },\n },\n },\n [`${agentTargetPrefix}-dev`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [serveCommand],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n LOCAL_DEV: 'true',\n },\n },\n },\n // HTTP chat imports the generated client, so ensure it's built first.\n // No dev dependency — chat runs standalone against a local or\n // deployed agent. normalizeTargetKeyOrder keeps the conditional dependsOn\n // in Nx 23's serialization order so re-runs stay byte-identical.\n [`${agentTargetPrefix}-chat`]: normalizeTargetKeyOrder({\n executor: 'nx:run-commands',\n options: {\n commands: [chatCommand],\n cwd: '{projectRoot}',\n env: {\n URL: chatUrl,\n },\n },\n ...(protocol === 'http' ? { dependsOn: [clientGenTargetName] } : {}),\n }),\n };\n\n // Aggregate `<agent>-dev` under the project-level `dev` target.\n addComponentDevTarget(agentTargets, `${agentTargetPrefix}-dev`);\n\n updateProjectConfiguration(tree, project.name, {\n ...project,\n targets: sortObjectKeys(agentTargets),\n });\n\n addComponentGeneratorMetadata(\n tree,\n project.name,\n PY_AGENT_GENERATOR_INFO,\n toProjectRelativePath(project, targetSourceDir),\n agentTargetPrefix,\n metadata,\n );\n\n await addGeneratorMetricsIfApplicable(tree, [PY_AGENT_GENERATOR_INFO]);\n\n // langchain-core (pulled by every langchain agent regardless of protocol)\n // brings jsonpatch/jsonpointer, whose wheels ship without resolvable SPDX\n // license metadata, so register those exceptions so the workspace license\n // check still passes.\n if (framework === 'langchain') {\n await ensureLicenseExceptions(tree, AG_UI_LANGGRAPH_EXCEPTIONS);\n }\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript', 'python'],\n });\n};\n\nexport default pyAgentGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","ensureLicenseExceptions","AG_UI_LANGGRAPH_EXCEPTIONS","addPyDependencies","addTsDependencies","addAgentChatScripts","AGENT_CONNECTION_PY_DEPENDENCIES","addPythonFrameworkBase","ensurePythonAgentConnectionProject","getPythonAgentConnectionModuleName","getPythonAgentConnectionProject","addAgentInfra","addPythonBundleTarget","resolveContainers","declareDependencies","ownedElsewhere","addDockerScanTarget","DOCKER_DEPENDENCIES","formatFilesInSubtree","FS_DEPENDENCIES","FsCommands","updateGitIgnore","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toSnakeCase","getNpmScope","addComponentDevTarget","addComponentGeneratorMetadata","addDependencyToTargetIfNotPresent","getGeneratorInfo","normalizeTargetKeyOrder","readProjectConfigurationUnqualified","sortObjectKeys","toProjectRelativePath","assignPort","addWorkspaceDependencyToPyProject","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","BASE_IMAGES","isIam","m","auth","DEPENDENCIES","ts","name","dev","root","when","protocol","py","framework","group","PY_AGENT_GENERATOR_INFO","filename","pyAgentGenerator","tree","options","project","pyProjectPath","Error","sourceRoot","sourceParts","split","moduleName","length","pop","agentTargetPrefix","agentNameSnakeCase","agentNameClassName","targetSourceDir","infra","iac","undefined","console","warn","session","agentConnectionModuleName","templateContext","dirname","overwriteStrategy","KeepExisting","protocolLower","toLowerCase","protocolTemplateDir","containers","dockerImageTag","bundleTargetName","bundleOutputDir","pythonPlatform","pythonBaseImage","python","dockerOutputDir","dockerTargetName","fs","targets","cache","executor","commands","rm","mkdir","cp","parallel","dependsOn","containerEngine","trivyTargetName","imageTags","infraProtocol","agentNameKebabCase","projectName","serverProtocol","localDevPortStart","localDevPort","component","info","metadata","port","rc","projectRoot","serveCommand","openApiTargetName","clientGenTargetName","scriptsDir","patterns","language","chatUrl","chatCommand","httpOnlyTargets","outputs","inputs","dependentTasksOutputFiles","agentTargets","continuous","cwd","env","PORT","LOCAL_DEV","URL","preferInstallDependencies","languages"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/py/agent/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 type Tree,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport { ensureLicenseExceptions } from '../../license/config';\nimport { AG_UI_LANGGRAPH_EXCEPTIONS } from '../../license/known-exceptions';\nimport {\n addPyDependencies,\n addTsDependencies,\n} from '../../utils/add-dependencies';\nimport { addAgentChatScripts } from '../../utils/agent-chat/agent-chat';\nimport {\n AGENT_CONNECTION_PY_DEPENDENCIES,\n addPythonFrameworkBase,\n ensurePythonAgentConnectionProject,\n getPythonAgentConnectionModuleName,\n getPythonAgentConnectionProject,\n} from '../../utils/agent-connection/agent-connection';\nimport { addAgentInfra } from '../../utils/agent-core-constructs/agent-core-constructs';\nimport { addPythonBundleTarget } from '../../utils/bundle/bundle';\nimport { resolveContainers } from '../../utils/containers';\nimport {\n declareDependencies,\n ownedElsewhere,\n} from '../../utils/declared-dependencies';\nimport { addDockerScanTarget, DOCKER_DEPENDENCIES } from '../../utils/docker';\nimport { formatFilesInSubtree } from '../../utils/format';\nimport { FS_DEPENDENCIES, FsCommands } from '../../utils/fs';\nimport { updateGitIgnore } from '../../utils/git';\nimport { resolveIac } from '../../utils/iac';\nimport { installDependencies } from '../../utils/install';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics';\nimport { kebabCase, toClassName, toSnakeCase } from '../../utils/names';\nimport { getNpmScope } from '../../utils/npm-scope';\nimport {\n addComponentDevTarget,\n addComponentGeneratorMetadata,\n addDependencyToTargetIfNotPresent,\n getGeneratorInfo,\n type NxGeneratorInfo,\n normalizeTargetKeyOrder,\n readProjectConfigurationUnqualified,\n} from '../../utils/nx';\nimport { sortObjectKeys } from '../../utils/object';\nimport { toProjectRelativePath } from '../../utils/paths';\nimport { assignPort } from '../../utils/port';\nimport { addWorkspaceDependencyToPyProject } from '../../utils/py';\nimport {\n SHARED_CONSTRUCTS_DEPENDENCIES,\n sharedConstructsGenerator,\n} from '../../utils/shared-constructs';\nimport type { IacMetadata } from '../../utils/shared-constructs-constants';\nimport { BASE_IMAGES } from '../../utils/versions';\nimport type {\n AgentProtocol,\n PyAgentFramework,\n PyAgentGeneratorSchema,\n} from './schema';\n\n/** The metadata this generator records, which its predicates read. */\nexport interface PyAgentMetadata extends IacMetadata {\n readonly port: number;\n readonly rc: string;\n readonly auth: string;\n readonly protocol: AgentProtocol;\n /**\n * The mcp / gateway connection generators dispatch on this field to pick the\n * Strands vs LangChain Layer-2 client + agent.py transform.\n */\n readonly framework: PyAgentFramework;\n}\n\n/** Whether the chat CLI signs its requests, which only IAM auth needs. */\nconst isIam = (m: PyAgentMetadata) => m.auth === 'iam';\n\n// Each entry names the framework and protocol branch it belongs to, so the same\n// declaration drives both adding and the version sync.\nexport const DEPENDENCIES = declareDependencies<PyAgentMetadata>()({\n ts: [\n // The chat CLI, which runs standalone via tsx for every protocol and\n // resolves the deployed agent from AppConfig. `agent-chat-cli` transitively\n // bundles the protocol clients (@a2a-js/sdk, @ag-ui/client).\n { name: 'agent-chat-cli', dev: true, root: true },\n { name: 'tsx', dev: true, root: true },\n { name: '@types/node', dev: true, root: true },\n { name: '@aws-lambda-powertools/parameters', dev: true, root: true },\n { name: '@aws-sdk/client-appconfigdata', dev: true, root: true },\n { name: 'aws4fetch', when: isIam, dev: true, root: true },\n {\n name: '@aws-sdk/credential-providers',\n when: isIam,\n dev: true,\n root: true,\n },\n {\n name: '@a2a-js/sdk',\n when: (m) => m.protocol === 'a2a',\n dev: true,\n root: true,\n },\n // Added by the helpers that own the projects they belong to.\n ...ownedElsewhere(FS_DEPENDENCIES),\n ...ownedElsewhere(DOCKER_DEPENDENCIES),\n ...ownedElsewhere(SHARED_CONSTRUCTS_DEPENDENCIES),\n ],\n py: [\n { name: 'aws-lambda-powertools' },\n { name: 'aws-opentelemetry-distro' },\n { name: 'bedrock-agentcore' },\n { name: 'boto3' },\n { name: 'fastapi' },\n { name: 'mcp' },\n // langchain pulls no Strands dependencies — the langchain model binding\n // plus the per-protocol server adapter: ag-ui-langgraph for AG-UI, a2a-sdk\n // for A2A, nothing extra for HTTP (FastAPI is added for every agent).\n { name: 'langchain', when: (m) => m.framework === 'langchain' },\n { name: 'langchain-aws', when: (m) => m.framework === 'langchain' },\n { name: 'langgraph', when: (m) => m.framework === 'langchain' },\n {\n name: 'ag-ui-protocol',\n when: (m) => m.framework === 'langchain' && m.protocol === 'ag-ui',\n },\n {\n name: 'ag-ui-langgraph',\n when: (m) => m.framework === 'langchain' && m.protocol === 'ag-ui',\n },\n {\n name: 'a2a-sdk',\n when: (m) => m.framework === 'langchain' && m.protocol === 'a2a',\n },\n {\n name: 'strands-agents[a2a]',\n when: (m) => m.framework !== 'langchain' && m.protocol === 'a2a',\n },\n {\n name: 'strands-agents',\n when: (m) => m.framework !== 'langchain' && m.protocol !== 'a2a',\n },\n {\n name: 'strands-agents-tools',\n when: (m) => m.framework !== 'langchain',\n },\n // Declared again here so a Strands AG-UI agent lists it in the same order\n // the generated pyproject.toml had before.\n {\n name: 'ag-ui-protocol',\n when: (m) => m.framework !== 'langchain' && m.protocol === 'ag-ui',\n },\n {\n name: 'ag-ui-strands',\n when: (m) => m.framework !== 'langchain' && m.protocol === 'ag-ui',\n },\n { name: 'uvicorn' },\n // `fastapi dev` runs the local server for every protocol.\n { name: 'fastapi[standard]', group: 'dev' },\n // The agent-connection helper adds these to its own project.\n ...ownedElsewhere(AGENT_CONNECTION_PY_DEPENDENCIES),\n ],\n});\n\nexport const PY_AGENT_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\nexport const pyAgentGenerator = async (\n tree: Tree,\n options: PyAgentGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const project = readProjectConfigurationUnqualified(tree, options.project);\n\n const pyProjectPath = joinPathFragments(project.root, 'pyproject.toml');\n\n // Check if the project has a pyproject.toml file\n if (!pyProjectPath) {\n throw new Error(\n `Unsupported project ${options.project}. Expected a Python project (with a pyproject.toml)`,\n );\n }\n\n if (!project.sourceRoot) {\n throw new Error(\n `This project does not have a source root. Please add a source root to the project configuration before running this generator.`,\n );\n }\n\n // Module name is the last part of the source root,\n const sourceParts = project.sourceRoot.split('/');\n const moduleName = sourceParts[sourceParts.length - 1];\n\n const name = kebabCase(\n options.name || `${kebabCase(project.name.split('.').pop())}-agent`,\n );\n const agentTargetPrefix = options.name ? name : 'agent';\n\n const agentNameSnakeCase = toSnakeCase(options.name || 'agent');\n const agentNameClassName = toClassName(name);\n\n const targetSourceDir = joinPathFragments(\n project.sourceRoot,\n agentNameSnakeCase,\n );\n\n const infra = options.infra ?? 'agentcore';\n const protocol = options.protocol ?? 'http';\n const framework = options.framework ?? 'strands';\n\n // Recorded in the metadata below so the version sync can tell a CDK\n // project from a Terraform one; undefined when no infrastructure was\n // generated, in which case neither provider's packages were added.\n const iac =\n infra !== 'none' ? await resolveIac(tree, options.iac) : undefined;\n\n if (infra === 'none' && options.auth && options.auth !== 'iam') {\n console.warn(\n 'Warning: auth is ignored when no infrastructure is configured (no infrastructure is generated)',\n );\n }\n\n const auth = options.auth ?? 'iam';\n\n // Only 'in-memory' is currently supported for Python agents (session manager\n // support for Python is not yet implemented).\n const session = options.session ?? 'in-memory';\n\n // Ensure the shared agent-connection project exists so the server entry\n // point can import `session_id_context` and propagate the AgentCore\n // session ID to any downstream MCP / A2A clients a later connection\n // generator wires into this agent.\n await ensurePythonAgentConnectionProject(tree, DEPENDENCIES);\n // The agent server imports the framework base helpers (session cache + model\n // error logging) regardless of whether a connection client is wired in. The\n // langchain framework has no base layer (its AG-UI foundation reuses only the\n // framework-agnostic session context), so this is a no-op for langchain.\n await addPythonFrameworkBase(tree, DEPENDENCIES, framework);\n const agentConnectionModuleName = getPythonAgentConnectionModuleName(tree);\n addWorkspaceDependencyToPyProject(\n tree,\n project,\n getPythonAgentConnectionProject(tree),\n );\n\n const templateContext = {\n name,\n agentNameSnakeCase,\n agentNameClassName,\n moduleName,\n agentConnectionModuleName,\n framework,\n };\n\n // Generate common files shared by both protocols. The agent module (agent.py)\n // is framework-specific (Strands yields a contextmanaged Agent; LangChain\n // returns a compiled create_agent graph), so it comes from a per-framework\n // dir. The package __init__.py is framework-agnostic (it stays in `common`).\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', framework, 'common'),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n if (framework === 'langchain') {\n // langchain/common only carries agent.py; the empty package __init__.py is\n // framework-agnostic, so emit it from the strands `common` dir.\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'strands', 'common'),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n }\n\n // Generate protocol-specific files. Each protocol's server entry point (and,\n // for HTTP, its init.py building the FastAPI app + lifespan) is\n // framework-specific (Strands yields a contextmanaged Agent; LangChain drives\n // a compiled create_agent graph), so it comes from a per-framework,\n // per-protocol dir: `files/<framework>/<protocol>`.\n const protocolLower = protocol.toLowerCase();\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', framework, protocolLower),\n targetSourceDir,\n templateContext,\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n if (infra === 'agentcore') {\n const containers = await resolveContainers(tree, 'inherit');\n const dockerImageTag = `${getNpmScope(tree)}-${name}:latest`;\n\n // Add bundle target\n const { bundleTargetName, bundleOutputDir } = addPythonBundleTarget(\n project,\n {\n pythonPlatform: 'aarch64-manylinux_2_28',\n },\n );\n\n // Add the Dockerfile\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'deploy'),\n targetSourceDir,\n {\n agentNameSnakeCase,\n moduleName,\n bundleOutputDir,\n protocol,\n pythonBaseImage: BASE_IMAGES.python,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n const dockerOutputDir = joinPathFragments(\n 'dist',\n project.root,\n 'docker',\n name,\n );\n const dockerTargetName = `${agentTargetPrefix}-docker`;\n\n // Add a docker target that prepares the docker context and builds the image\n const fs = new FsCommands(tree, DEPENDENCIES);\n project.targets[dockerTargetName] = {\n cache: true,\n executor: 'nx:run-commands',\n options: {\n commands: [\n fs.rm(dockerOutputDir),\n fs.mkdir(dockerOutputDir),\n fs.cp(bundleOutputDir, dockerOutputDir),\n fs.cp(\n `${targetSourceDir}/Dockerfile`,\n `${dockerOutputDir}/Dockerfile`,\n ),\n `${containers} build --platform linux/arm64 -t ${dockerImageTag} ${dockerOutputDir}`,\n ],\n parallel: false,\n },\n dependsOn: [bundleTargetName],\n };\n\n addDependencyToTargetIfNotPresent(project, 'docker', dockerTargetName);\n addDependencyToTargetIfNotPresent(project, 'build', 'docker');\n\n addDockerScanTarget(\n tree,\n {\n project,\n containerEngine: containers,\n trivyTargetName: `${agentTargetPrefix}-trivy`,\n dockerTargetName,\n imageTags: [dockerImageTag],\n },\n DEPENDENCIES,\n );\n\n // Add shared constructs\n await sharedConstructsGenerator(tree, { iac }, DEPENDENCIES);\n\n // Add the construct to deploy the agent.\n // AG-UI uses HTTP as the AgentCore protocol type (AG-UI is HTTP-based with SSE over POST).\n const infraProtocol =\n protocol === 'ag-ui' ? ('http' as const) : (protocol as 'http' | 'a2a');\n await addAgentInfra(tree, {\n agentNameKebabCase: name,\n agentNameClassName,\n dockerImageTag,\n dockerOutputDir,\n iac,\n projectName: project.name,\n auth,\n session,\n serverProtocol: infraProtocol,\n containers,\n });\n }\n\n // A2A servers use port 9000 as per the Strands A2A SDK default and AgentCore A2A contract.\n // HTTP and AG-UI agents use port 8081+ to avoid conflict with VS Code server on 8080.\n const localDevPortStart = protocol === 'a2a' ? 9000 : 8081;\n const localDevPort = assignPort(tree, project, localDevPortStart, {\n component: { info: PY_AGENT_GENERATOR_INFO, name: agentTargetPrefix },\n });\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 metadata: PyAgentMetadata = {\n port: localDevPort,\n rc: agentNameClassName,\n auth,\n protocol,\n framework,\n ...(iac ? { iac } : {}),\n };\n\n addPyDependencies(tree, DEPENDENCIES, {\n metadata,\n projectRoot: project.root,\n });\n addTsDependencies(tree, DEPENDENCIES, { metadata });\n\n // All protocols use fastapi dev for hot reload:\n // - HTTP: FastAPI app directly defined in init.py\n // - A2A: A2AServer.to_fastapi_app() creates a FastAPI app in main.py\n // - AG-UI: create_strands_app() creates a FastAPI app in main.py\n const serveCommand = `uv run fastapi dev ${moduleName}/${agentNameSnakeCase}/main.py --port ${localDevPort}`;\n\n // HTTP chat uses the type-safe TypeScript client generated from the\n // agent's OpenAPI spec (same generated client the react-connection\n // generator produces). A2A and AG-UI speak standard protocols, so\n // we can run `agent-chat-cli` directly as a binary.\n const openApiTargetName = `${agentTargetPrefix}-openapi`;\n const clientGenTargetName = `${agentTargetPrefix}-generate-client`;\n\n const scriptsDir = joinPathFragments(\n project.root,\n 'scripts',\n agentTargetPrefix,\n );\n\n if (protocol === 'http') {\n // Emit the OpenAPI spec generator script (shared with react-connection)\n generateFiles(\n tree,\n joinPathFragments(\n import.meta.dirname,\n 'react-connection',\n 'files',\n 'agent',\n ),\n project.root,\n {\n moduleName,\n agentNameSnakeCase,\n },\n { overwriteStrategy: OverwriteStrategy.KeepExisting },\n );\n\n // Ignore the generated client directory\n updateGitIgnore(tree, project.root, (patterns) => [\n ...patterns,\n `scripts/${agentTargetPrefix}/generated/`,\n ]);\n }\n\n // Every protocol gets a standalone `chat.ts`. It connects to the local\n // `dev` server by default, or to the deployed agent (with the\n // appropriate auth) when `RUNTIME_CONFIG_APP_ID` is set.\n addAgentChatScripts(tree, {\n scriptsDir,\n protocol,\n language: 'py',\n agentNameClassName,\n auth,\n });\n\n const chatUrl =\n protocol === 'ag-ui'\n ? `http://localhost:${localDevPort}/invocations`\n : `http://localhost:${localDevPort}`;\n const chatCommand = `tsx ./scripts/${agentTargetPrefix}/chat.ts`;\n\n const httpOnlyTargets =\n protocol === 'http'\n ? {\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 [clientGenTargetName]: {\n cache: true,\n executor: 'nx:run-commands',\n dependsOn: [openApiTargetName],\n inputs: [\n {\n dependentTasksOutputFiles: '**/*.json',\n },\n ],\n outputs: [`{projectRoot}/scripts/${agentTargetPrefix}/generated`],\n options: {\n commands: [\n `nx g @aws/nx-plugin:open-api#ts-client --openApiSpecPath=\"dist/${project.root}/openapi/${agentNameSnakeCase}/openapi.json\" --outputPath=\"${project.root}/scripts/${agentTargetPrefix}/generated\" --no-interactive`,\n ],\n },\n },\n }\n : {};\n\n const agentTargets = {\n ...project.targets,\n ...httpOnlyTargets,\n [`${agentTargetPrefix}-serve`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [serveCommand],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n },\n },\n },\n [`${agentTargetPrefix}-dev`]: {\n executor: 'nx:run-commands',\n continuous: true,\n options: {\n commands: [serveCommand],\n cwd: '{projectRoot}',\n env: {\n PORT: `${localDevPort}`,\n LOCAL_DEV: 'true',\n },\n },\n },\n // HTTP chat imports the generated client, so ensure it's built first.\n // No dev dependency — chat runs standalone against a local or\n // deployed agent. normalizeTargetKeyOrder keeps the conditional dependsOn\n // in Nx 23's serialization order so re-runs stay byte-identical.\n [`${agentTargetPrefix}-chat`]: normalizeTargetKeyOrder({\n executor: 'nx:run-commands',\n options: {\n commands: [chatCommand],\n cwd: '{projectRoot}',\n env: {\n URL: chatUrl,\n },\n },\n ...(protocol === 'http' ? { dependsOn: [clientGenTargetName] } : {}),\n }),\n };\n\n // Aggregate `<agent>-dev` under the project-level `dev` target.\n addComponentDevTarget(agentTargets, `${agentTargetPrefix}-dev`);\n\n updateProjectConfiguration(tree, project.name, {\n ...project,\n targets: sortObjectKeys(agentTargets),\n });\n\n addComponentGeneratorMetadata(\n tree,\n project.name,\n PY_AGENT_GENERATOR_INFO,\n toProjectRelativePath(project, targetSourceDir),\n agentTargetPrefix,\n metadata,\n );\n\n await addGeneratorMetricsIfApplicable(tree, [PY_AGENT_GENERATOR_INFO]);\n\n // langchain-core (pulled by every langchain agent regardless of protocol)\n // brings jsonpatch/jsonpointer, whose wheels ship without resolvable SPDX\n // license metadata, so register those exceptions so the workspace license\n // check still passes.\n if (framework === 'langchain') {\n await ensureLicenseExceptions(tree, AG_UI_LANGGRAPH_EXCEPTIONS);\n }\n\n await formatFilesInSubtree(tree);\n return () =>\n installDependencies(tree, options.preferInstallDependencies, {\n languages: ['typescript', 'python'],\n });\n};\n\nexport default pyAgentGenerator;\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateProjectConfiguration","ensureLicenseExceptions","AG_UI_LANGGRAPH_EXCEPTIONS","addPyDependencies","addTsDependencies","addAgentChatScripts","AGENT_CONNECTION_PY_DEPENDENCIES","addPythonFrameworkBase","ensurePythonAgentConnectionProject","getPythonAgentConnectionModuleName","getPythonAgentConnectionProject","addAgentInfra","addPythonBundleTarget","resolveContainers","declareDependencies","ownedElsewhere","addDockerScanTarget","DOCKER_DEPENDENCIES","formatFilesInSubtree","FS_DEPENDENCIES","FsCommands","updateGitIgnore","resolveIac","installDependencies","addGeneratorMetricsIfApplicable","kebabCase","toClassName","toSnakeCase","getNpmScope","addComponentDevTarget","addComponentGeneratorMetadata","addDependencyToTargetIfNotPresent","getGeneratorInfo","normalizeTargetKeyOrder","readProjectConfigurationUnqualified","sortObjectKeys","toProjectRelativePath","assignPort","addWorkspaceDependencyToPyProject","SHARED_CONSTRUCTS_DEPENDENCIES","sharedConstructsGenerator","BASE_IMAGES","isIam","m","auth","DEPENDENCIES","ts","name","dev","root","when","protocol","py","framework","group","PY_AGENT_GENERATOR_INFO","filename","pyAgentGenerator","tree","options","project","pyProjectPath","Error","sourceRoot","sourceParts","split","moduleName","length","pop","agentTargetPrefix","agentNameSnakeCase","agentNameClassName","targetSourceDir","infra","iac","undefined","console","warn","session","agentConnectionModuleName","templateContext","dirname","overwriteStrategy","KeepExisting","protocolLower","toLowerCase","containers","dockerImageTag","bundleTargetName","bundleOutputDir","pythonPlatform","pythonBaseImage","python","dockerOutputDir","dockerTargetName","fs","targets","cache","executor","commands","rm","mkdir","cp","parallel","dependsOn","containerEngine","trivyTargetName","imageTags","infraProtocol","agentNameKebabCase","projectName","serverProtocol","localDevPortStart","localDevPort","component","info","metadata","port","rc","projectRoot","serveCommand","openApiTargetName","clientGenTargetName","scriptsDir","patterns","language","chatUrl","chatCommand","httpOnlyTargets","outputs","inputs","dependentTasksOutputFiles","agentTargets","continuous","cwd","env","PORT","LOCAL_DEV","URL","preferInstallDependencies","languages"],"mappings":"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"}
|
|
@@ -2231,7 +2231,7 @@ You can also automatically fix some lint errors by running the following command
|
|
|
2231
2231
|
|
|
2232
2232
|
In order to integrate with cognito or trpc backends, you need to have a \`runtime-config.json\` file in your \`/public\` website directory. You can fetch this is follows:
|
|
2233
2233
|
|
|
2234
|
-
\`pnpm nx
|
|
2234
|
+
\`pnpm nx load-runtime-config @proj/test-app\`
|
|
2235
2235
|
|
|
2236
2236
|
> [!IMPORTANT]
|
|
2237
2237
|
> Ensure you have AWS CLI and curl installed
|
|
@@ -2354,10 +2354,10 @@ exports[`react-website generator > Tanstack router integration > should generate
|
|
|
2354
2354
|
},
|
|
2355
2355
|
"dependsOn": ["format"]
|
|
2356
2356
|
},
|
|
2357
|
-
"load
|
|
2357
|
+
"load-runtime-config": {
|
|
2358
2358
|
"executor": "nx:run-commands",
|
|
2359
2359
|
"metadata": {
|
|
2360
|
-
"description": "Load runtime config from your deployed stack for dev purposes. You must set your AWS CLI credentials whilst calling 'pnpm nx
|
|
2360
|
+
"description": "Load runtime config from your deployed stack for dev purposes. You must set your AWS CLI credentials whilst calling 'pnpm nx load-runtime-config @proj/test-app'"
|
|
2361
2361
|
},
|
|
2362
2362
|
"options": {
|
|
2363
2363
|
"command": "aws s3 cp s3://\`aws cloudformation describe-stacks --query \\"Stacks[?starts_with(StackName, 'proj-')][].Outputs[] | [?contains(OutputKey, 'TestAppWebsiteBucketName')].OutputValue\\" --output text\`/runtime-config.json \\"{projectRoot}/public/runtime-config.json\\""
|
|
@@ -4061,7 +4061,7 @@ You can also automatically fix some lint errors by running the following command
|
|
|
4061
4061
|
|
|
4062
4062
|
In order to integrate with cognito or trpc backends, you need to have a \`runtime-config.json\` file in your \`/public\` website directory. You can fetch this is follows:
|
|
4063
4063
|
|
|
4064
|
-
\`pnpm nx
|
|
4064
|
+
\`pnpm nx load-runtime-config @proj/test-app\`
|
|
4065
4065
|
|
|
4066
4066
|
> [!IMPORTANT]
|
|
4067
4067
|
> Ensure you have AWS CLI and curl installed
|
|
@@ -4185,10 +4185,10 @@ exports[`react-website generator > Tanstack router integration > should generate
|
|
|
4185
4185
|
},
|
|
4186
4186
|
"dependsOn": ["format"]
|
|
4187
4187
|
},
|
|
4188
|
-
"load
|
|
4188
|
+
"load-runtime-config": {
|
|
4189
4189
|
"executor": "nx:run-commands",
|
|
4190
4190
|
"metadata": {
|
|
4191
|
-
"description": "Load runtime config from your deployed stack for dev purposes. You must set your AWS CLI credentials whilst calling 'pnpm nx
|
|
4191
|
+
"description": "Load runtime config from your deployed stack for dev purposes. You must set your AWS CLI credentials whilst calling 'pnpm nx load-runtime-config @proj/test-app'"
|
|
4192
4192
|
},
|
|
4193
4193
|
"options": {
|
|
4194
4194
|
"command": "aws s3 cp s3://\`aws cloudformation describe-stacks --query \\"Stacks[?starts_with(StackName, 'proj-')][].Outputs[] | [?contains(OutputKey, 'TestAppWebsiteBucketName')].OutputValue\\" --output text\`/runtime-config.json \\"{projectRoot}/public/runtime-config.json\\""
|