@aws/nx-plugin 1.0.0-rc.60 → 1.0.0-rc.61
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 +31 -26
- package/package.json +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/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.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/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/{modernize-function-props-cast → 0001-modernize-function-props-cast}/metadata.json +0 -0
- /package/src/migrations/v1.0.0-rc.50/{restrict-cors-to-custom-domains → 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.50/{terraform-bootstrap-adopt-existing-bucket → 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.57/ts-agent-session-management-support → v1.0.0-rc.50/0003-terraform-bootstrap-adopt-existing-bucket}/migration.d.ts +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
|
@@ -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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"}
|
|
@@ -72,13 +72,26 @@ export declare const readShippedMigrationVersions: (migrations: MigrationsJson,
|
|
|
72
72
|
* every generator entry, preserving any already present, and the pending version
|
|
73
73
|
* recorded on any `packageJsonUpdates` entry still holding `latest`.
|
|
74
74
|
*
|
|
75
|
+
* `nx migrate` sorts the run ascending by version and keeps the manifest's order
|
|
76
|
+
* among equal versions, so the order entries are emitted in is the run order
|
|
77
|
+
* within a release. Migrations sharing a version (a batch shipped together, or a
|
|
78
|
+
* whole `v<x.y.z>` folder replayed on a big version jump) are therefore ordered
|
|
79
|
+
* here by the commit that added them — an earlier-committed migration runs
|
|
80
|
+
* first — so a later migration can depend on an earlier one in the same batch.
|
|
81
|
+
* Every-migration entries are emitted last regardless, so they run after the
|
|
82
|
+
* release's own migrations (letting one add a dependency this then brings up to
|
|
83
|
+
* date). Entries with no rank fall back to the manifest's order, which
|
|
84
|
+
* `assembleMigrations` already sorts by key.
|
|
85
|
+
*
|
|
75
86
|
* @param migrations parsed migrations.json to stamp
|
|
76
87
|
* @param shippedVersions migration key -> version of the earliest release
|
|
77
88
|
* tag that registers it (absent for migrations that haven't shipped)
|
|
78
89
|
* @param pendingVersion version the release is about to publish, stamped onto
|
|
79
90
|
* unshipped migrations so their version is one that really shipped
|
|
91
|
+
* @param commitRanks migration key -> rank of the commit that added it (lower is
|
|
92
|
+
* earlier); absent entries fall back to the manifest's order
|
|
80
93
|
*/
|
|
81
|
-
export declare const stampMigrationVersions: (migrations: MigrationsJson, shippedVersions: Record<string, string>, pendingVersion: string) => MigrationsJson;
|
|
94
|
+
export declare const stampMigrationVersions: (migrations: MigrationsJson, shippedVersions: Record<string, string>, pendingVersion: string, commitRanks?: Record<string, number>) => MigrationsJson;
|
|
82
95
|
/** Directory a newly scaffolded migration lands in, before a release claims it. */
|
|
83
96
|
export declare const LATEST_MIGRATIONS_DIR = "latest";
|
|
84
97
|
/** Directory holding the migrations shipped by a given release. */
|
|
@@ -89,6 +102,13 @@ export declare const versionMigrationsDir: (version: string) => string;
|
|
|
89
102
|
* one that already shipped.
|
|
90
103
|
*/
|
|
91
104
|
export declare const migrationKey: (dir: string, name: string) => string;
|
|
105
|
+
/**
|
|
106
|
+
* Format a 1-based order into the folder-name prefix that beds it in. Backfill
|
|
107
|
+
* prefixes a released migration's folder with its commit order within the
|
|
108
|
+
* release (`0001-foo`), so the folder name alone sorts a version's migrations
|
|
109
|
+
* into commit order — stamping doesn't have to re-read git for them.
|
|
110
|
+
*/
|
|
111
|
+
export declare const orderPrefix: (order: number) => string;
|
|
92
112
|
/** A migration directory move the caller needs to make on disk. */
|
|
93
113
|
export interface MigrationDirMove {
|
|
94
114
|
name: string;
|
|
@@ -102,14 +122,23 @@ export interface MigrationDirMove {
|
|
|
102
122
|
* return the collection alongside the keys that changed and the directory moves
|
|
103
123
|
* to make on disk.
|
|
104
124
|
*
|
|
125
|
+
* A backfilled migration's new folder name is prefixed with its commit order
|
|
126
|
+
* within the release (`0001-foo`), so the folder layout beds in the order the
|
|
127
|
+
* release ran them: `assembleMigrations` sorts by key, so the prefix alone puts
|
|
128
|
+
* a version's migrations in commit order and stamping never has to re-read git
|
|
129
|
+
* for a released migration. Migrations sharing a commit (a squashed PR) fall
|
|
130
|
+
* back to alphabetical order, matching stamping.
|
|
131
|
+
*
|
|
105
132
|
* Unlike `stampMigrationVersions` this only records already-released versions,
|
|
106
133
|
* leaving the release to decide what a net-new migration gets.
|
|
107
134
|
*
|
|
108
135
|
* @param migrations parsed migrations.json to backfill
|
|
109
136
|
* @param shippedVersions migration key -> version of the earliest release tag
|
|
110
137
|
* that registers it (absent for migrations that haven't shipped)
|
|
138
|
+
* @param commitRanks migration key -> rank of the commit that added it (lower is
|
|
139
|
+
* earlier), used to order the migrations bedded into each release
|
|
111
140
|
*/
|
|
112
|
-
export declare const backfillMigrationVersions: (migrations: MigrationsJson, shippedVersions: Record<string, string>) => {
|
|
141
|
+
export declare const backfillMigrationVersions: (migrations: MigrationsJson, shippedVersions: Record<string, string>, commitRanks?: Record<string, number>) => {
|
|
113
142
|
migrations: MigrationsJson;
|
|
114
143
|
backfilled: string[];
|
|
115
144
|
moves: MigrationDirMove[];
|