@aws/nx-plugin 1.1.1 → 1.3.0
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/README.md +31 -29
- package/generators.json +16 -0
- package/migrations.json +6 -1
- package/package.json +1 -1
- package/src/agentcore-harness/generator.d.ts +1 -1
- package/src/greengrass/component/common.d.ts +60 -0
- package/src/greengrass/component/common.js +191 -0
- package/src/greengrass/component/common.js.map +1 -0
- package/src/greengrass/component/dependencies.d.ts +101 -0
- package/src/greengrass/component/dependencies.js +37 -0
- package/src/greengrass/component/dependencies.js.map +1 -0
- package/src/greengrass/component/generator.d.ts +174 -0
- package/src/greengrass/component/generator.js +32 -0
- package/src/greengrass/component/generator.js.map +1 -0
- package/src/greengrass/component/metadata.d.ts +2 -0
- package/src/greengrass/component/metadata.js +14 -0
- package/src/greengrass/component/metadata.js.map +1 -0
- package/src/greengrass/component/python/__snapshots__/generator.spec.ts.snap +450 -0
- package/src/greengrass/component/python/files/component/main.py.template +60 -0
- package/src/greengrass/component/python/files/component/recipe.yaml.template +30 -0
- package/src/greengrass/component/python/files/gdk/gdk-config.json.template +13 -0
- package/src/greengrass/component/python/files/tests/test___componentSnakeCase__.py.template +37 -0
- package/src/greengrass/component/python/generator.d.ts +15 -0
- package/src/greengrass/component/python/generator.js +192 -0
- package/src/greengrass/component/python/generator.js.map +1 -0
- package/src/greengrass/component/schema.d.js +6 -0
- package/src/greengrass/component/schema.d.js.map +1 -0
- package/src/greengrass/component/schema.d.ts +18 -0
- package/src/greengrass/component/schema.json +82 -0
- package/src/greengrass/component/typescript/__snapshots__/generator.spec.ts.snap +275 -0
- package/src/greengrass/component/typescript/files/component/recipe.yaml.template +41 -0
- package/src/greengrass/component/typescript/files/entrypoint/main.ts.template +58 -0
- package/src/greengrass/component/typescript/files/gdk/gdk-config.json.template +13 -0
- package/src/greengrass/component/typescript/files/scripts/vendor-crt-addon.ts.template +115 -0
- package/src/greengrass/component/typescript/generator.d.ts +16 -0
- package/src/greengrass/component/typescript/generator.js +194 -0
- package/src/greengrass/component/typescript/generator.js.map +1 -0
- package/src/infra/app/generator.d.ts +1 -1
- package/src/init/generator.d.ts +1 -1
- package/src/internal/test-matrix/generator.js +48 -1
- package/src/internal/test-matrix/generator.js.map +1 -1
- package/src/license/dependency-check/pre-approved.js +2 -1
- package/src/license/dependency-check/pre-approved.js.map +1 -1
- package/src/migrations/latest/ts-agent-guardrails-terraform-version-retention/metadata.json +3 -0
- package/src/migrations/latest/ts-agent-guardrails-terraform-version-retention/migration.d.ts +6 -0
- package/src/migrations/latest/ts-agent-guardrails-terraform-version-retention/migration.js +118 -0
- package/src/migrations/latest/ts-agent-guardrails-terraform-version-retention/migration.js.map +1 -0
- package/src/open-api/py-client/generator.d.ts +1 -1
- package/src/preset/__snapshots__/generator.spec.ts.snap +4 -0
- package/src/preset/generator.d.ts +1 -1
- package/src/py/agent/a2a-connection/generator.d.ts +1 -1
- package/src/py/agent/gateway-connection/generator.d.ts +1 -1
- package/src/py/agent/guardrails/__snapshots__/generator.spec.ts.snap +3813 -0
- package/src/py/agent/guardrails/files/langchain/guardrail.py.template +135 -0
- package/src/py/agent/guardrails/files/strands/guardrail.py.template +93 -0
- package/src/py/agent/guardrails/generator.d.ts +10 -0
- package/src/py/agent/guardrails/generator.js +175 -0
- package/src/py/agent/guardrails/generator.js.map +1 -0
- package/src/py/agent/guardrails/runtime-check/run_checks.py +250 -0
- package/src/py/agent/guardrails/schema.d.js +6 -0
- package/src/py/agent/guardrails/schema.d.js.map +1 -0
- package/src/py/agent/guardrails/schema.d.ts +9 -0
- package/src/py/agent/guardrails/schema.json +25 -0
- package/src/py/agent/mcp-connection/generator.d.ts +1 -1
- package/src/py/agent/react-connection/generator.d.ts +1 -1
- package/src/py/fast-api/react/generator.d.ts +1 -1
- package/src/py/project/generator.js +2 -0
- package/src/py/project/generator.js.map +1 -1
- package/src/sdk/greengrass.d.ts +6 -0
- package/src/sdk/greengrass.js +6 -0
- package/src/sdk/greengrass.js.map +1 -0
- package/src/sdk/py.d.ts +2 -0
- package/src/sdk/py.js +1 -0
- package/src/sdk/py.js.map +1 -1
- package/src/smithy/project/generator.d.ts +1 -1
- package/src/smithy/react-connection/generator.d.ts +1 -1
- package/src/terraform/project/generator.d.ts +1 -1
- package/src/trpc/react/generator.d.ts +1 -1
- package/src/ts/agent/a2a-connection/generator.d.ts +1 -1
- package/src/ts/agent/gateway-connection/generator.d.ts +1 -1
- package/src/ts/agent/guardrails/__snapshots__/generator.spec.ts.snap +54 -3
- package/src/ts/agent/guardrails/generator.js +2 -1
- package/src/ts/agent/guardrails/generator.js.map +1 -1
- package/src/ts/agent/mcp-connection/generator.d.ts +1 -1
- package/src/ts/agent/react-connection/generator.d.ts +1 -1
- package/src/ts/astro-docs/generator.d.ts +1 -1
- package/src/ts/dcr-proxy/generator.d.ts +1 -1
- package/src/ts/dynamodb/generator.d.ts +1 -1
- package/src/ts/lambda-function/generator.d.ts +1 -1
- package/src/ts/lib/generator.d.ts +1 -1
- package/src/ts/nx-generator/generator.d.ts +1 -1
- package/src/ts/nx-migration/generator.d.ts +1 -1
- package/src/ts/nx-plugin/generator.d.ts +1 -1
- package/src/ts/rdb/generator.d.ts +1 -1
- package/src/ts/react-website/agui/generator.d.ts +1 -1
- package/src/utils/__snapshots__/shared-greengrass-scripts.spec.ts.snap +1279 -0
- package/src/utils/files/common/scripts/src/greengrass/build-artifact.ts.template +236 -0
- package/src/utils/files/common/scripts/src/greengrass/component-logs.ts.template +48 -0
- package/src/utils/files/common/scripts/src/greengrass/deploy-local.ts.template +497 -0
- package/src/utils/files/common/scripts/src/greengrass/recipe-utils.ts.template +356 -0
- package/src/utils/files/common/scripts/src/greengrass/zip-writer.ts.template +121 -0
- package/src/utils/files/terraform/src/core/runtime-config/read/read.tf.template +3 -3
- package/src/utils/files/terraform/src/metrics/metrics.tf.template +1 -1
- package/src/utils/greengrass/constants.d.ts +58 -0
- package/src/utils/greengrass/constants.js +63 -0
- package/src/utils/greengrass/constants.js.map +1 -0
- package/src/utils/greengrass/naming.d.ts +46 -0
- package/src/utils/greengrass/naming.js +67 -0
- package/src/utils/greengrass/naming.js.map +1 -0
- package/src/utils/greengrass/recipe.d.ts +143 -0
- package/src/utils/greengrass/recipe.js +119 -0
- package/src/utils/greengrass/recipe.js.map +1 -0
- package/src/utils/greengrass-constructs/files/cdk/app/greengrass-component/__componentDirName__.ts.template +42 -0
- package/src/utils/greengrass-constructs/files/cdk/core/greengrass/artifact-bucket.ts.template +82 -0
- package/src/utils/greengrass-constructs/files/cdk/core/greengrass/component-version.ts.template +370 -0
- package/src/utils/greengrass-constructs/files/cdk/core/greengrass/deployment.ts.template +276 -0
- package/src/utils/greengrass-constructs/files/cdk/core/greengrass/index.ts.template +5 -0
- package/src/utils/greengrass-constructs/files/cdk/core/greengrass/next-version.ts.template +119 -0
- package/src/utils/greengrass-constructs/files/cdk/core/greengrass/recipe.ts.template +90 -0
- package/src/utils/greengrass-constructs/files/next-version/__nextVersionFileName__.template +195 -0
- package/src/utils/greengrass-constructs/files/terraform/app/greengrass-component/__componentDirName__/__componentDirName__.tf.template +26 -0
- package/src/utils/greengrass-constructs/files/terraform/core/greengrass/artifact-bucket/main.tf.template +204 -0
- package/src/utils/greengrass-constructs/files/terraform/core/greengrass/component-version/main.tf.template +156 -0
- package/src/utils/greengrass-constructs/files/terraform/core/greengrass/deployment/main.tf.template +186 -0
- package/src/utils/greengrass-constructs/greengrass-constructs.d.ts +57 -0
- package/src/utils/greengrass-constructs/greengrass-constructs.js +154 -0
- package/src/utils/greengrass-constructs/greengrass-constructs.js.map +1 -0
- package/src/utils/guardrail-constructs/files/terraform/app/guardrails/__nameKebabCase__/__nameKebabCase__-guardrail.tf.template +18 -1
- package/src/utils/guardrail-constructs/guardrail-constructs.d.ts +5 -0
- package/src/utils/guardrail-constructs/guardrail-constructs.js +8 -0
- package/src/utils/guardrail-constructs/guardrail-constructs.js.map +1 -1
- package/src/utils/guardrail-constructs/guardrail-wiring.d.ts +7 -0
- package/src/utils/guardrail-constructs/guardrail-wiring.js +6 -5
- package/src/utils/guardrail-constructs/guardrail-wiring.js.map +1 -1
- package/src/utils/nx.d.ts +15 -0
- package/src/utils/nx.js +32 -0
- package/src/utils/nx.js.map +1 -1
- package/src/utils/shared-greengrass-scripts.d.ts +21 -0
- package/src/utils/shared-greengrass-scripts.js +43 -0
- package/src/utils/shared-greengrass-scripts.js.map +1 -0
- package/src/utils/test/fake-aws/fake_aws.py +205 -0
- package/src/utils/test/python-dependencies.d.ts +6 -0
- package/src/utils/test/python-dependencies.js +19 -0
- package/src/utils/test/python-dependencies.js.map +1 -1
- package/src/utils/test/warm-python-cache.js +5 -1
- package/src/utils/test/warm-python-cache.js.map +1 -1
- package/src/utils/versions.d.ts +7 -0
- package/src/utils/versions.js +7 -0
- package/src/utils/versions.js.map +1 -1
- /package/src/{ts/agent/guardrails/files/agent → utils/guardrail-constructs/files/policy}/guardrail.json.template +0 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
#
|
|
5
|
+
"""Run a generated, guarded Python agent against fake_aws.py and report what
|
|
6
|
+
the real SDK sent. Used by guardrail-runtime.spec.ts.
|
|
7
|
+
|
|
8
|
+
Usage: python run_checks.py <project root> <connection root> <fake_aws.py> <framework>
|
|
9
|
+
<agent package> <agent-connection module> [<scenario>]
|
|
10
|
+
|
|
11
|
+
<project root> holds the agent project's module and pyproject.toml, and
|
|
12
|
+
<connection root> the agent-connection module, as in a workspace.
|
|
13
|
+
Without a scenario, every scenario runs in a fresh interpreter (so the
|
|
14
|
+
guardrail cache and warn-once state start clean), then the static checks, and
|
|
15
|
+
one line "RESULTS <json>" maps each name to its result.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import asyncio
|
|
19
|
+
import importlib
|
|
20
|
+
import importlib.util
|
|
21
|
+
import json
|
|
22
|
+
import logging
|
|
23
|
+
import os
|
|
24
|
+
import shutil
|
|
25
|
+
import subprocess
|
|
26
|
+
import sys
|
|
27
|
+
import tempfile
|
|
28
|
+
import time
|
|
29
|
+
from contextlib import contextmanager
|
|
30
|
+
from typing import Any
|
|
31
|
+
|
|
32
|
+
ROOT, CONNECTION_ROOT, FAKE_AWS, FRAMEWORK, AGENT_PACKAGE, CONNECTION_MODULE = sys.argv[1:7]
|
|
33
|
+
|
|
34
|
+
ENTRY = {"guardrailId": "grtest", "guardrailVersion": "1"}
|
|
35
|
+
# fake_aws.py blocks a guarded request whose checked text contains "stocks".
|
|
36
|
+
BLOCKED_PROMPT = "Which stocks should I buy this year?"
|
|
37
|
+
|
|
38
|
+
# scenario: (LOCAL_DEV, RUNTIME_CONFIG_APP_ID, guardrail entry or None, number of calls)
|
|
39
|
+
SCENARIOS: dict[str, tuple[bool, str | None, dict[str, str] | None, int]] = {
|
|
40
|
+
"guarded": (False, "fake-app", ENTRY, 1),
|
|
41
|
+
"missing": (False, "fake-app", None, 1),
|
|
42
|
+
"no-app-id": (False, None, ENTRY, 1),
|
|
43
|
+
"local-dev": (True, None, ENTRY, 2),
|
|
44
|
+
"local-dev-broken": (True, "broken", ENTRY, 2),
|
|
45
|
+
"local-dev-guarded": (True, "fake-app", ENTRY, 1),
|
|
46
|
+
"draft": (False, "fake-app", {**ENTRY, "guardrailVersion": "DRAFT"}, 1),
|
|
47
|
+
"draft-local": (True, "fake-app", {**ENTRY, "guardrailVersion": "DRAFT"}, 1),
|
|
48
|
+
"zero": (False, "fake-app", {**ENTRY, "guardrailVersion": "0"}, 1),
|
|
49
|
+
"zero-local": (True, "fake-app", {**ENTRY, "guardrailVersion": "0"}, 1),
|
|
50
|
+
"reread": (False, "fake-app", ENTRY, 0),
|
|
51
|
+
"concurrent": (False, "fake-app", ENTRY, 0),
|
|
52
|
+
"blocked-session": (False, "fake-app", ENTRY, 0),
|
|
53
|
+
"blocked-session-stream": (False, "fake-app", ENTRY, 0),
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def write_config(path: str, entry: dict[str, str] | None, class_name: str) -> None:
|
|
58
|
+
data: dict[str, Any] = {"agentRuntimes": {}}
|
|
59
|
+
if entry is not None:
|
|
60
|
+
data["guardrails"] = {class_name: entry}
|
|
61
|
+
with open(path, "w") as f:
|
|
62
|
+
json.dump(data, f)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def read_log(path: str) -> list[dict[str, Any]]:
|
|
66
|
+
if not os.path.exists(path):
|
|
67
|
+
return []
|
|
68
|
+
with open(path) as f:
|
|
69
|
+
return [json.loads(line) for line in f if line.strip()]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class WarningRecorder(logging.Handler):
|
|
73
|
+
def __init__(self) -> None:
|
|
74
|
+
super().__init__(logging.WARNING)
|
|
75
|
+
self.messages: list[str] = []
|
|
76
|
+
|
|
77
|
+
def emit(self, record: logging.LogRecord) -> None:
|
|
78
|
+
if record.name.endswith(".guardrail"):
|
|
79
|
+
self.messages.append(record.getMessage())
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def run_scenario(name: str) -> dict[str, Any]:
|
|
83
|
+
local_dev, app_id, entry, calls = SCENARIOS[name]
|
|
84
|
+
work = tempfile.mkdtemp(prefix=f"{name}-")
|
|
85
|
+
config_file, log_file = os.path.join(work, "config.json"), os.path.join(work, "requests.log")
|
|
86
|
+
# The vended local session storage is relative to the project root, two levels down.
|
|
87
|
+
cwd = os.path.join(work, "packages", "project")
|
|
88
|
+
os.makedirs(cwd)
|
|
89
|
+
os.chdir(cwd)
|
|
90
|
+
|
|
91
|
+
spec = importlib.util.spec_from_file_location("fake_aws", FAKE_AWS)
|
|
92
|
+
assert spec and spec.loader
|
|
93
|
+
fake_aws = importlib.util.module_from_spec(spec)
|
|
94
|
+
spec.loader.exec_module(fake_aws)
|
|
95
|
+
_server, port = fake_aws.start_server(config_file, log_file)
|
|
96
|
+
os.environ["AWS_ENDPOINT_URL_APPCONFIGDATA"] = f"http://127.0.0.1:{port}"
|
|
97
|
+
os.environ["AWS_ENDPOINT_URL_BEDROCK_RUNTIME"] = f"http://127.0.0.1:{port}"
|
|
98
|
+
os.environ.pop("LOCAL_DEV", None)
|
|
99
|
+
os.environ.pop("RUNTIME_CONFIG_APP_ID", None)
|
|
100
|
+
if local_dev:
|
|
101
|
+
os.environ["LOCAL_DEV"] = "true"
|
|
102
|
+
if app_id:
|
|
103
|
+
os.environ["RUNTIME_CONFIG_APP_ID"] = app_id
|
|
104
|
+
|
|
105
|
+
recorder = WarningRecorder()
|
|
106
|
+
logging.getLogger().addHandler(recorder)
|
|
107
|
+
|
|
108
|
+
sys.path[:0] = [ROOT, CONNECTION_ROOT]
|
|
109
|
+
agent_module = importlib.import_module(f"{AGENT_PACKAGE}.agent")
|
|
110
|
+
guardrail_module = importlib.import_module(f"{AGENT_PACKAGE}.guardrail")
|
|
111
|
+
class_name = guardrail_module.RUNTIME_CONFIG_KEY.split(".")[-1]
|
|
112
|
+
write_config(config_file, entry, class_name)
|
|
113
|
+
|
|
114
|
+
result: dict[str, Any] = {"calls": []}
|
|
115
|
+
|
|
116
|
+
def snapshot() -> dict[str, Any]:
|
|
117
|
+
log = read_log(log_file)
|
|
118
|
+
return {
|
|
119
|
+
"models": [r for r in log if "modelId" in r],
|
|
120
|
+
"appConfigCalls": len([r for r in log if "modelId" not in r]),
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async def scenario() -> None:
|
|
124
|
+
if FRAMEWORK == "strands":
|
|
125
|
+
connection = importlib.import_module(CONNECTION_MODULE)
|
|
126
|
+
|
|
127
|
+
@contextmanager
|
|
128
|
+
def agent_scope():
|
|
129
|
+
with connection.session_id_context("s1"), agent_module.get_agent() as agent:
|
|
130
|
+
yield agent
|
|
131
|
+
|
|
132
|
+
async def call(agent: Any, prompt: str = "2+2?") -> None:
|
|
133
|
+
await agent.invoke_async(prompt)
|
|
134
|
+
|
|
135
|
+
if name == "concurrent":
|
|
136
|
+
from strands import Agent
|
|
137
|
+
|
|
138
|
+
shared = guardrail_module.get_guardrailed_model()
|
|
139
|
+
agents = [Agent(model=shared, callback_handler=None) for _ in range(10)]
|
|
140
|
+
await asyncio.gather(*[a.invoke_async("2+2?") for a in agents])
|
|
141
|
+
return
|
|
142
|
+
with agent_scope() as agent:
|
|
143
|
+
await run_calls(agent, call)
|
|
144
|
+
else:
|
|
145
|
+
graph = agent_module.get_agent()
|
|
146
|
+
counter = iter(range(1000))
|
|
147
|
+
|
|
148
|
+
async def call(agent: Any, prompt: str | None = None) -> None:
|
|
149
|
+
# A call with a prompt continues one session; without, each call is a new session.
|
|
150
|
+
if name == "blocked-session-stream":
|
|
151
|
+
await stream(agent, prompt)
|
|
152
|
+
return
|
|
153
|
+
thread = {"configurable": {"thread_id": "session" if prompt else f"t{next(counter)}"}}
|
|
154
|
+
await agent.ainvoke({"messages": [{"role": "user", "content": prompt or "2+2?"}]}, thread)
|
|
155
|
+
|
|
156
|
+
async def stream(agent: Any, prompt: str | None = None) -> None:
|
|
157
|
+
thread = {"configurable": {"thread_id": "session" if prompt else f"t{next(counter)}"}}
|
|
158
|
+
async for _ in agent.astream(
|
|
159
|
+
{"messages": [{"role": "user", "content": prompt or "2+2?"}]}, thread, stream_mode="messages"
|
|
160
|
+
):
|
|
161
|
+
pass
|
|
162
|
+
|
|
163
|
+
if name == "concurrent":
|
|
164
|
+
await asyncio.gather(*[call(graph) for _ in range(10)])
|
|
165
|
+
return
|
|
166
|
+
await run_calls(graph, call)
|
|
167
|
+
if name == "guarded":
|
|
168
|
+
await stream(graph)
|
|
169
|
+
result["streamed"] = snapshot()["models"][-1:]
|
|
170
|
+
|
|
171
|
+
async def run_calls(agent: Any, call: Any) -> None:
|
|
172
|
+
if name.startswith("blocked-session"):
|
|
173
|
+
# A blocked message, then a normal one, in the same session.
|
|
174
|
+
for prompt in (BLOCKED_PROMPT, "2+2?"):
|
|
175
|
+
await call(agent, prompt)
|
|
176
|
+
result["calls"].append(snapshot())
|
|
177
|
+
return
|
|
178
|
+
if name == "reread":
|
|
179
|
+
await call(agent)
|
|
180
|
+
result["calls"].append(snapshot())
|
|
181
|
+
write_config(config_file, {**ENTRY, "guardrailVersion": "2"}, class_name)
|
|
182
|
+
await call(agent)
|
|
183
|
+
result["calls"].append(snapshot())
|
|
184
|
+
time.sleep(5.5)
|
|
185
|
+
await call(agent)
|
|
186
|
+
result["calls"].append(snapshot())
|
|
187
|
+
return
|
|
188
|
+
for _ in range(calls):
|
|
189
|
+
await call(agent)
|
|
190
|
+
result["calls"].append(snapshot())
|
|
191
|
+
|
|
192
|
+
try:
|
|
193
|
+
asyncio.run(scenario())
|
|
194
|
+
except Exception as e: # noqa: BLE001 - reported to the spec
|
|
195
|
+
result["error"] = {"type": type(e).__name__, "message": str(e)}
|
|
196
|
+
result.update(snapshot())
|
|
197
|
+
result["warnings"] = recorder.messages
|
|
198
|
+
shutil.rmtree(work, ignore_errors=True)
|
|
199
|
+
return result
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def run_static() -> dict[str, Any]:
|
|
203
|
+
package_dir = os.path.join(ROOT, *AGENT_PACKAGE.split("."))
|
|
204
|
+
files = [os.path.join(package_dir, f) for f in ("guardrail.py", "agent.py")]
|
|
205
|
+
# uv's --with environment layers several site-packages directories, which
|
|
206
|
+
# ty does not discover from the interpreter alone.
|
|
207
|
+
search_paths = [CONNECTION_ROOT, *(p for p in sys.path if p.endswith("site-packages"))]
|
|
208
|
+
commands = {
|
|
209
|
+
"ty": [
|
|
210
|
+
"ty",
|
|
211
|
+
"check",
|
|
212
|
+
"--python",
|
|
213
|
+
sys.executable,
|
|
214
|
+
*(arg for path in search_paths for arg in ("--extra-search-path", path)),
|
|
215
|
+
"--no-progress",
|
|
216
|
+
*files,
|
|
217
|
+
],
|
|
218
|
+
"ruffFormat": ["ruff", "format", "--check", *files],
|
|
219
|
+
"ruffCheck": ["ruff", "check", "--select", "E,F,UP,B,SIM,I", *files],
|
|
220
|
+
}
|
|
221
|
+
results = {}
|
|
222
|
+
for key, command in commands.items():
|
|
223
|
+
done = subprocess.run(command, cwd=ROOT, capture_output=True, text=True)
|
|
224
|
+
results[key] = {"code": done.returncode, "output": done.stdout + done.stderr}
|
|
225
|
+
return results
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
if __name__ == "__main__":
|
|
229
|
+
if len(sys.argv) > 7:
|
|
230
|
+
print("\nRESULT " + json.dumps(run_scenario(sys.argv[7])), flush=True)
|
|
231
|
+
# A failed LangChain call in local dev leaves the SQLite checkpointer's
|
|
232
|
+
# non-daemon thread running, which would keep the interpreter alive.
|
|
233
|
+
os._exit(0)
|
|
234
|
+
else:
|
|
235
|
+
results: dict[str, Any] = {}
|
|
236
|
+
for scenario_name in SCENARIOS:
|
|
237
|
+
done = subprocess.run(
|
|
238
|
+
[sys.executable, __file__, *sys.argv[1:7], scenario_name],
|
|
239
|
+
capture_output=True,
|
|
240
|
+
text=True,
|
|
241
|
+
timeout=180,
|
|
242
|
+
)
|
|
243
|
+
lines = [line for line in done.stdout.splitlines() if line.startswith("RESULT ")]
|
|
244
|
+
results[scenario_name] = (
|
|
245
|
+
json.loads(lines[-1][len("RESULT ") :])
|
|
246
|
+
if lines
|
|
247
|
+
else {"crashed": done.returncode, "stdout": done.stdout[-4000:], "stderr": done.stderr[-4000:]}
|
|
248
|
+
)
|
|
249
|
+
results["static"] = run_static()
|
|
250
|
+
print("RESULTS " + json.dumps(results), flush=True)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../packages/nx-plugin/src/py/agent/guardrails/schema.d.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport interface PyAgentGuardrailsGeneratorSchema {\n project: string;\n agent?: string;\n}\n"],"names":[],"mappings":"AAAA;;;CAGC,GAED,WAGC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/schema",
|
|
3
|
+
"$id": "py#agent#guardrails",
|
|
4
|
+
"title": "py#agent#guardrails",
|
|
5
|
+
"x-label": "Agent Guardrails",
|
|
6
|
+
"description": "Add an Amazon Bedrock Guardrail to a Python Agent",
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"project": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "The project containing the Python Agent",
|
|
12
|
+
"$default": {
|
|
13
|
+
"$source": "argv",
|
|
14
|
+
"index": 0
|
|
15
|
+
},
|
|
16
|
+
"x-prompt": "Select the project containing the Python Agent to guard",
|
|
17
|
+
"x-dropdown": "projects"
|
|
18
|
+
},
|
|
19
|
+
"agent": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "The name of the Agent component to guard. Required when the project contains more than one Python Agent."
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"required": ["project"]
|
|
25
|
+
}
|
|
@@ -10,7 +10,7 @@ import type { PyAgentMcpConnectionGeneratorSchema } from './schema';
|
|
|
10
10
|
export interface PyAgentMcpConnectionMetadata {
|
|
11
11
|
readonly framework: AgentFramework;
|
|
12
12
|
}
|
|
13
|
-
export declare const DEPENDENCIES: import("../../../utils/declared-dependencies.js").DependencyDeclaration<readonly import("../../../utils/declared-dependencies.js").DeclaredTsDependency<"@ag-ui/client" | "@ag-ui/core" | "@ag-ui/encoder" | "@biomejs/biome" | "vitest" | "@vitest/coverage-v8" | "@vitest/ui" | "@a2a-js/sdk" | "@aws/aws-distro-opentelemetry-node-autoinstrumentation" | "@opentelemetry/propagator-jaeger" | "minimatch" | "deepmerge-ts" | "mysql2" | "@aws-sdk/client-dynamodb" | "@aws-sdk/client-api-gateway" | "@aws-sdk/client-iam" | "@aws-sdk/client-bedrock-agentcore" | "@aws-sdk/client-bedrock-runtime" | "@aws-sdk/client-s3" | "@aws-sdk/client-sts" | "@aws-sdk/client-cognito-identity-provider" | "@aws-sdk/credential-providers" | "@aws-sdk/credential-provider-cognito-identity" | "@aws-sdk/client-secrets-manager" | "@aws-sdk/rds-signer" | "@smithy/server-apigateway" | "@smithy/server-node" | "@aws-lambda-powertools/logger" | "@aws-lambda-powertools/metrics" | "@aws-lambda-powertools/parameters" | "@aws-lambda-powertools/tracer" | "@aws-lambda-powertools/parser" | "@aws-sdk/client-appconfigdata" | "@middy/core" | "@nxlv/python" | "@nx-extend/terraform" | "nx" | "@nx/devkit" | "@nx/js" | "@nx/react" | "@nx/vite" | "@nx/vitest" | "@nx/workspace" | "create-nx-workspace" | "@swc-node/register" | "@swc/core" | "@modelcontextprotocol/sdk" | "@modelcontextprotocol/client" | "@modelcontextprotocol/inspector" | "@ag-ui/a2ui-toolkit" | "@ag-ui/aws-strands" | "agent-chat-cli" | "@copilotkit/react-core" | "rxjs" | "@strands-agents/sdk" | "@tanstack/react-router" | "@tanstack/router-plugin" | "@tanstack/router-generator" | "@tanstack/virtual-file-routes" | "@tanstack/router-utils" | "@cloudscape-design/board-components" | "@cloudscape-design/chat-components" | "@cloudscape-design/components" | "@cloudscape-design/global-styles" | "@tanstack/react-query" | "@tanstack/react-query-devtools" | "@trpc/tanstack-react-query" | "@trpc/client" | "@trpc/server" | "@types/node" | "@types/aws-lambda" | "@types/cors" | "@types/pg" | "@types/ws" | "@types/express" | "@smithy/config-resolver" | "@smithy/node-config-provider" | "@smithy/node-http-handler" | "@smithy/types" | "@astrojs/react" | "@astrojs/starlight" | "astro" | "cookie" | "aws4fetch" | "aws-cdk" | "aws-cdk-lib" | "aws-xray-sdk-core" | "constructs" | "cors" | "chalk" | "class-variance-authority" | "cn" | "commander" | "electrodb" | "esbuild" | "event-source-polyfill" | "@types/event-source-polyfill" | "@prisma/adapter-mariadb" | "@prisma/adapter-pg" | "@prisma/client" | "ejs" | "@types/ejs" | "express" | "fast-glob" | "husky" | "fs-extra" | "@types/fs-extra" | "mariadb" | "mise" | "npm" | "npm-check-updates" | "oidc-client-ts" | "pg" | "prisma" | "react-oidc-context" | "react" | "react-dom" | "rolldown" | "rolldown-plugin-dts" | "shx" | "simple-git" | "source-map-support" | "starlight-blog" | "tailwindcss" | "@tailwindcss/vite" | "tsx" | "lucide-react" | "radix-ui" | "shadcn" | "tw-animate-css" | "vite" | "typescript" | "jsdom" | "zod" | "ws", PyAgentMcpConnectionMetadata>[], readonly [{
|
|
13
|
+
export declare const DEPENDENCIES: import("../../../utils/declared-dependencies.js").DependencyDeclaration<readonly import("../../../utils/declared-dependencies.js").DeclaredTsDependency<"@ag-ui/client" | "@ag-ui/core" | "@ag-ui/encoder" | "@biomejs/biome" | "vitest" | "@vitest/coverage-v8" | "@vitest/ui" | "@a2a-js/sdk" | "@aws/aws-distro-opentelemetry-node-autoinstrumentation" | "@opentelemetry/propagator-jaeger" | "minimatch" | "deepmerge-ts" | "mysql2" | "@aws-sdk/client-dynamodb" | "@aws-sdk/client-api-gateway" | "@aws-sdk/client-iam" | "@aws-sdk/client-bedrock-agentcore" | "@aws-sdk/client-bedrock-runtime" | "@aws-sdk/client-greengrassv2" | "@aws-sdk/client-s3" | "@aws-sdk/client-sts" | "@aws-sdk/client-cognito-identity-provider" | "@aws-sdk/credential-providers" | "@aws-sdk/credential-provider-cognito-identity" | "@aws-sdk/client-secrets-manager" | "@aws-sdk/rds-signer" | "@smithy/server-apigateway" | "@smithy/server-node" | "@aws-lambda-powertools/logger" | "@aws-lambda-powertools/metrics" | "@aws-lambda-powertools/parameters" | "@aws-lambda-powertools/tracer" | "@aws-lambda-powertools/parser" | "@aws-sdk/client-appconfigdata" | "@middy/core" | "@nxlv/python" | "@nx-extend/terraform" | "nx" | "@nx/devkit" | "@nx/js" | "@nx/react" | "@nx/vite" | "@nx/vitest" | "@nx/workspace" | "create-nx-workspace" | "@swc-node/register" | "@swc/core" | "@modelcontextprotocol/sdk" | "@modelcontextprotocol/client" | "@modelcontextprotocol/inspector" | "@ag-ui/a2ui-toolkit" | "@ag-ui/aws-strands" | "agent-chat-cli" | "@copilotkit/react-core" | "rxjs" | "@strands-agents/sdk" | "@tanstack/react-router" | "@tanstack/router-plugin" | "@tanstack/router-generator" | "@tanstack/virtual-file-routes" | "@tanstack/router-utils" | "@cloudscape-design/board-components" | "@cloudscape-design/chat-components" | "@cloudscape-design/components" | "@cloudscape-design/global-styles" | "@tanstack/react-query" | "@tanstack/react-query-devtools" | "@trpc/tanstack-react-query" | "@trpc/client" | "@trpc/server" | "@types/node" | "@types/aws-lambda" | "@types/cors" | "@types/js-yaml" | "@types/pg" | "@types/ws" | "@types/express" | "@smithy/config-resolver" | "@smithy/node-config-provider" | "@smithy/node-http-handler" | "@smithy/types" | "@astrojs/react" | "@astrojs/starlight" | "astro" | "cookie" | "aws4fetch" | "aws-cdk" | "aws-cdk-lib" | "aws-iot-device-sdk-v2" | "aws-xray-sdk-core" | "constructs" | "cors" | "chalk" | "class-variance-authority" | "cn" | "commander" | "electrodb" | "esbuild" | "event-source-polyfill" | "@types/event-source-polyfill" | "@prisma/adapter-mariadb" | "@prisma/adapter-pg" | "@prisma/client" | "ejs" | "@types/ejs" | "express" | "fast-glob" | "husky" | "fs-extra" | "@types/fs-extra" | "js-yaml" | "mariadb" | "mise" | "npm" | "npm-check-updates" | "oidc-client-ts" | "pg" | "prisma" | "react-oidc-context" | "react" | "react-dom" | "rolldown" | "rolldown-plugin-dts" | "shx" | "simple-git" | "source-map-support" | "starlight-blog" | "tailwindcss" | "@tailwindcss/vite" | "tsx" | "lucide-react" | "radix-ui" | "shadcn" | "tw-animate-css" | "vite" | "typescript" | "jsdom" | "zod" | "ws", PyAgentMcpConnectionMetadata>[], readonly [{
|
|
14
14
|
readonly name: "boto3";
|
|
15
15
|
}, {
|
|
16
16
|
readonly name: "httpx";
|
|
@@ -174,7 +174,7 @@ export declare const DEPENDENCIES: import("../../../utils/declared-dependencies.
|
|
|
174
174
|
versionOnly: true;
|
|
175
175
|
}, "when"> & {
|
|
176
176
|
when: (m: PyAgentReactConnectionMetadata) => boolean;
|
|
177
|
-
}], readonly import("../../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", PyAgentReactConnectionMetadata>[]>;
|
|
177
|
+
}], readonly import("../../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "awsiotsdk" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", PyAgentReactConnectionMetadata>[]>;
|
|
178
178
|
export declare const PY_AGENT_REACT_CONNECTION_GENERATOR_INFO: NxGeneratorInfo;
|
|
179
179
|
export declare const pyAgentReactConnectionGenerator: (tree: Tree, options: ResolvedConnectionOptions & {
|
|
180
180
|
gatewayRoute?: AgentGatewayRoute;
|
|
@@ -19,7 +19,7 @@ export declare const DEPENDENCIES: import("../../../utils/declared-dependencies.
|
|
|
19
19
|
readonly name: "@tanstack/react-query-devtools";
|
|
20
20
|
}, {
|
|
21
21
|
readonly name: "@smithy/types";
|
|
22
|
-
}], readonly import("../../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
|
|
22
|
+
}], readonly import("../../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "awsiotsdk" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
|
|
23
23
|
export declare const FAST_API_REACT_GENERATOR_INFO: NxGeneratorInfo;
|
|
24
24
|
export declare const fastApiReactGenerator: (tree: Tree, options: FastApiReactGeneratorSchema) => Promise<() => Promise<void>>;
|
|
25
25
|
export default fastApiReactGenerator;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { addLicenseCheckToLintTarget, ensurePythonLicenseCollector } from "../../license/config.js";
|
|
6
6
|
import { addPyDependencies, addTsDependencies } from "../../utils/add-dependencies.js";
|
|
7
7
|
import { declareDependencies } from "../../utils/declared-dependencies.js";
|
|
8
|
+
import { formatFilesInSubtree } from "../../utils/format.js";
|
|
8
9
|
import { updateGitIgnore } from "../../utils/git.js";
|
|
9
10
|
import { installDependencies } from "../../utils/install.js";
|
|
10
11
|
import { addGeneratorMetricsIfApplicable } from "../../utils/metrics.js";
|
|
@@ -340,6 +341,7 @@ export const PYTHON_TEST_FILE_EXCLUSIONS = [
|
|
|
340
341
|
// the license generator wires up existing projects itself, so the dependency
|
|
341
342
|
// is added regardless of which generator runs first.
|
|
342
343
|
addLicenseCheckToLintTarget(tree, fullyQualifiedName);
|
|
344
|
+
await formatFilesInSubtree(tree, joinPathFragments(dir, 'project.json'));
|
|
343
345
|
return ()=>installDependencies(tree, schema.preferInstallDependencies, {
|
|
344
346
|
languages: [
|
|
345
347
|
'typescript',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/py/project/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n ensurePackage,\n type GeneratorCallback,\n joinPathFragments,\n readNxJson,\n readProjectConfiguration,\n type Tree,\n updateNxJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport {\n addLicenseCheckToLintTarget,\n ensurePythonLicenseCollector,\n} from '../../license/config.js';\nimport {\n addPyDependencies,\n addTsDependencies,\n} from '../../utils/add-dependencies.js';\nimport { declareDependencies } from '../../utils/declared-dependencies.js';\nimport { updateGitIgnore } from '../../utils/git.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { normalizeDistributionName, toSnakeCase } from '../../utils/names.js';\nimport { getNpmScope } from '../../utils/npm-scope.js';\nimport {\n addDependencyToTargetIfNotPresent,\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n} from '../../utils/nx.js';\nimport type { UVPyprojectToml } from '../../utils/nxlv-python.js';\nimport {\n migrateToSharedVenvGenerator,\n uvProjectGenerator,\n} from '../../utils/nxlv-python.js';\nimport { sortObjectKeys } from '../../utils/object.js';\nimport { updateToml } from '../../utils/toml.js';\nimport {\n pyenvPythonVersion,\n pyprojectPythonDependency,\n withVersions,\n} from '../../utils/versions.js';\nimport type { PyProjectGeneratorSchema } from './schema';\n\nexport const DEPENDENCIES = declareDependencies()({\n ts: [{ name: '@nxlv/python', dev: true, root: true }],\n py: [\n // The linting and type checking tools live in the workspace root pyproject.\n // Pinned to the version generation-time formatting uses, so generated files\n // stay `ruff format --check`-clean across ruff releases.\n { name: 'ruff', group: 'dev', root: true },\n { name: 'ty', group: 'dev', root: true },\n ],\n});\n\nexport const PY_PROJECT_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\n// Transient artifacts that pytest, coverage and ruff create and remove while\n// the test, typecheck and compile targets run concurrently. `.coverage.*` are\n// the per-process data files pytest-cov writes (`.coverage.<host>.<pid>.<rand>`)\n// before combining them. Both `ty` (which respects .gitignore) and the\n// `@nxlv/python:build` copy (which respects `ignorePaths`) would otherwise fail\n// when they read one of these mid-deletion.\nconst PYTHON_TRANSIENT_ARTIFACTS = [\n '__pycache__',\n '.coverage',\n '.coverage.*',\n '.pytest_cache',\n 'pytest-cache-files-*',\n '.ruff_cache',\n];\n\n// Python test files, excluded from the `production` named input so that editing\n// a test does not invalidate targets whose output cannot contain it.\n//\n// Anchored to the `tests` directory, which is where the generated project puts\n// them and the only path the build excludes (`ignorePaths` is matched against\n// the project root's top-level entries). An unanchored `**/test_*.py` would also\n// match a production module inside the packaged source directory — a\n// `test_data_loader.py` helper ships in the wheel, so excluding it would leave\n// the wheel stale after a fix to it.\nexport const PYTHON_TEST_FILE_EXCLUSIONS = ['!{projectRoot}/tests/**/*'];\n\n/**\n * Excludes Python test files from the `production` named input, preserving any\n * entries already present (including user additions).\n *\n * The input is created when absent: the Python targets reference `production`,\n * and Nx fails hard on a named input that is not defined.\n */\nexport const addPythonTestExclusionsToProductionInput = (tree: Tree) => {\n const nxJson = readNxJson(tree);\n if (!nxJson) {\n return;\n }\n const production = nxJson.namedInputs?.production ?? ['default'];\n const missing = PYTHON_TEST_FILE_EXCLUSIONS.filter(\n (exclusion) => !production.includes(exclusion),\n );\n if (missing.length === 0 && nxJson.namedInputs?.production) {\n return;\n }\n updateNxJson(tree, {\n ...nxJson,\n namedInputs: {\n ...nxJson.namedInputs,\n production: [...production, ...missing],\n },\n });\n};\n\nexport interface PyProjectDetails {\n /**\n * Fully qualified Nx project id including scope, in dot notation (eg foo.bar).\n * This is the identifier Nx uses (readProjectConfiguration, the project\n * graph, target references) and is intentionally kept dotted.\n */\n readonly fullyQualifiedName: string;\n /**\n * PEP 503 normalised Python distribution name (eg foo-bar). This is the name\n * written to the project's `[project].name`, the root `[tool.uv.sources]`\n * key, and any inter-project dependency string. It is hyphenated (not dotted)\n * so `uv` and `@nxlv/python` can match it: uv writes `uv.lock` keyed by the\n * PEP 503 hyphenated name, and `@nxlv/python`'s dependency inference splits a\n * dotted name on `.` and so would otherwise drop the edge entirely. Keeping\n * the distribution name decoupled from `fullyQualifiedName` is what lets the\n * workspace dependency edge appear in the Nx project graph.\n */\n readonly distributionName: string;\n /**\n * Directory of the library relative to the root\n */\n readonly dir: string;\n /**\n * Module name for the project\n */\n readonly normalizedModuleName: string;\n}\n\n/**\n * Returns details about the Python project to be created\n */\nexport const getPyProjectDetails = (\n tree: Tree,\n schema: {\n name: string;\n directory?: string;\n subDirectory?: string;\n moduleName?: string;\n },\n): PyProjectDetails => {\n const scope = toSnakeCase(getNpmScope(tree));\n const normalizedName = toSnakeCase(schema.name);\n const normalizedModuleName = toSnakeCase(\n schema.moduleName ?? `${scope}_${normalizedName}`,\n );\n const fullyQualifiedName = `${scope}.${normalizedName}`;\n // The Python distribution name is the PEP 503 normalised form of the\n // fully qualified name: hyphenated, never dotted. See PyProjectDetails.\n const distributionName = normalizeDistributionName(fullyQualifiedName);\n // NB: interactive nx generator cli can pass empty string\n const dir = joinPathFragments(\n schema.directory || '.',\n schema.subDirectory || normalizedName,\n );\n return { dir, fullyQualifiedName, distributionName, normalizedModuleName };\n};\n\n/**\n * Generates a Python project\n */\nexport const pyProjectGenerator = async (\n tree: Tree,\n schema: PyProjectGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const { dir, normalizedModuleName, fullyQualifiedName, distributionName } =\n getPyProjectDetails(tree, schema);\n\n addTsDependencies(tree, DEPENDENCIES);\n\n addPythonTestExclusionsToProductionInput(tree);\n\n const pythonPlugin = withVersions(DEPENDENCIES, ['@nxlv/python']);\n Object.entries(pythonPlugin).forEach(([name, version]) =>\n ensurePackage(name, version),\n );\n\n const nxJson = readNxJson(tree);\n\n // Only rewrite nx.json when the plugin needs adding, so re-running does not\n // reserialize (and reformat) the file when nothing has changed.\n if (\n !nxJson.plugins?.find((p) =>\n typeof p === 'string'\n ? p === '@nxlv/python'\n : p.plugin === '@nxlv/python',\n )\n ) {\n nxJson.plugins = [\n ...(nxJson.plugins ?? []),\n {\n plugin: '@nxlv/python',\n options: {\n packageManager: 'uv',\n },\n },\n ];\n updateNxJson(tree, nxJson);\n }\n\n // Only scaffold the project when it does not already exist so re-running with\n // the same name does not throw. The rest of the generator still runs to apply\n // any changed options to the existing project.\n if (!projectExists(tree, fullyQualifiedName)) {\n if (!tree.exists('uv.lock')) {\n await migrateToSharedVenvGenerator(tree, {\n autoActivate: true,\n packageManager: 'uv',\n moveDevDependencies: false,\n pyenvPythonVersion: pyenvPythonVersion(),\n pyprojectPythonDependency: pyprojectPythonDependency(),\n });\n }\n\n await uvProjectGenerator(tree, {\n // The Nx project id (and `uv.workspace.members` etc.) keys off `name`, so\n // keep it dotted. `packageName` is the separate PEP 503 distribution name\n // written to `[project].name` and the root `[tool.uv.sources]` key; it is\n // hyphenated so `@nxlv/python` infers the workspace dependency edge (it\n // splits a dotted name on `.` and would otherwise drop it). This split is\n // the whole fix (see PyProjectDetails.distributionName).\n name: fullyQualifiedName,\n packageName: distributionName,\n publishable: false,\n buildLockedVersions: true,\n buildBundleLocalDependencies: true,\n linter: 'ruff',\n rootPyprojectDependencyGroup: 'main',\n pyenvPythonVersion: pyenvPythonVersion(),\n pyprojectPythonDependency: pyprojectPythonDependency(),\n projectType: schema.type,\n projectNameAndRootFormat: 'as-provided',\n moduleName: normalizedModuleName,\n directory: dir,\n unitTestRunner: 'pytest',\n codeCoverage: true,\n codeCoverageHtmlReport: true,\n codeCoverageXmlReport: true,\n unitTestHtmlReport: true,\n unitTestJUnitReport: true,\n buildSystem: 'hatch',\n srcDir: false,\n });\n\n // Remove generated hello.py and test_hello.py as they are not needed\n [\n joinPathFragments(dir, normalizedModuleName, 'hello.py'),\n joinPathFragments(dir, 'tests', 'test_hello.py'),\n ].forEach((f) => tree.delete(f));\n\n // Add a placeholder test so pytest doesn't fail with \"no tests collected\"\n tree.write(\n joinPathFragments(dir, 'tests', 'test_noop.py'),\n 'def test_noop():\\n pass\\n',\n );\n }\n\n const outputPath = '{workspaceRoot}/dist/{projectRoot}';\n const buildOutputPath = joinPathFragments(outputPath, 'build');\n const projectConfiguration = readProjectConfiguration(\n tree,\n fullyQualifiedName,\n );\n projectConfiguration.name = fullyQualifiedName;\n // Derive the compile target from the uv build target, and rewrite build to\n // orchestrate the other targets. This only runs on first creation: on re-run\n // build has already been transformed, so re-deriving would corrupt compile\n // and duplicate the build dependencies.\n if (!projectConfiguration.targets.compile) {\n const buildTarget = projectConfiguration.targets.build;\n projectConfiguration.targets.compile = {\n ...buildTarget,\n // `tests` is in `ignorePaths` below, so test files cannot reach the built\n // distribution and must not invalidate it.\n inputs: ['production', '^production'],\n outputs: [buildOutputPath],\n options: {\n ...buildTarget.options,\n outputPath: buildOutputPath,\n // The build executor copies the project to a temp folder; exclude the\n // executor defaults plus transient artifacts so the copy does not race\n // a concurrent test/typecheck target deleting a file mid-copy.\n ignorePaths: ['.venv', '.tox', 'tests', ...PYTHON_TRANSIENT_ARTIFACTS],\n },\n };\n projectConfiguration.targets.build = {\n inputs: ['default', '^production'],\n dependsOn: [\n 'lint',\n 'compile',\n 'test',\n 'typecheck',\n ...(buildTarget.dependsOn ?? []),\n ],\n options: {\n outputPath,\n },\n };\n // The artifact-only sibling of build, which the deploy targets depend on.\n projectConfiguration.targets.assemble = {\n dependsOn: ['compile'],\n };\n }\n projectConfiguration.targets.typecheck = {\n cache: true,\n inputs: ['default', '^production'],\n executor: '@nxlv/python:run-commands',\n options: {\n command: 'uv run ty check',\n cwd: '{projectRoot}',\n },\n };\n\n // Set the default line length to 120, as 88 is a little too strict\n updateToml(\n tree,\n joinPathFragments(dir, 'pyproject.toml'),\n (pyProjectToml: UVPyprojectToml) => {\n if ((pyProjectToml.tool as any)?.ruff) {\n (pyProjectToml.tool as any).ruff['line-length'] = 120;\n }\n return pyProjectToml;\n },\n );\n\n addPyDependencies(tree, DEPENDENCIES);\n\n // Base format target checks rather than writes (so build/lint don't rewrite\n // source); `fix` writes, and `skip-lint` writes without failing so it stays\n // a no-op when propagated through the lint -> format dependency.\n projectConfiguration.targets.format = {\n ...projectConfiguration.targets.format,\n cache: true,\n inputs: ['default', '^production'],\n options: {\n ...projectConfiguration.targets.format?.options,\n check: true,\n },\n configurations: {\n ...projectConfiguration.targets.format?.configurations,\n fix: {\n check: false,\n },\n 'skip-lint': {\n check: false,\n },\n },\n };\n\n // Add a dependency on the format target for lint in order to reduce the number of\n // fixable lint errors (eg line too long)\n projectConfiguration.targets.lint = {\n ...projectConfiguration.targets.lint,\n cache: true,\n inputs: ['default', '^production'],\n configurations: {\n ...projectConfiguration.targets.lint?.configurations,\n fix: {\n fix: true,\n },\n 'skip-lint': {\n exitZero: true,\n },\n },\n };\n // Append `format` without moving an existing entry, so re-running does not\n // reorder lint dependencies (e.g. relative to a later-added license-check).\n addDependencyToTargetIfNotPresent(projectConfiguration, 'lint', 'format');\n\n projectConfiguration.targets = sortObjectKeys(projectConfiguration.targets);\n updateProjectConfiguration(tree, fullyQualifiedName, projectConfiguration);\n\n addGeneratorMetadata(tree, fullyQualifiedName, PY_PROJECT_GENERATOR_INFO);\n\n // Update root .gitignore\n updateGitIgnore(tree, '.', (patterns) => [...patterns, '/reports']);\n\n // Update project level .gitignore. The cache directories are also kept out\n // of type checking: `ty` respects .gitignore, and pytest creates and removes\n // transient `pytest-cache-files-*` directories while the test and typecheck\n // targets run concurrently, which would otherwise make `ty` fail with an I/O\n // error when it scans one mid-deletion.\n updateGitIgnore(tree, dir, (patterns) => [\n ...patterns,\n '**/__pycache__',\n ...PYTHON_TRANSIENT_ARTIFACTS.filter((p) => p !== '__pycache__'),\n ]);\n\n await addGeneratorMetricsIfApplicable(tree, [PY_PROJECT_GENERATOR_INFO]);\n\n await ensurePythonLicenseCollector(tree);\n\n // If license checking is configured, make this project's lint target depend\n // on the root license-check target. No-op if license checking isn't set up;\n // the license generator wires up existing projects itself, so the dependency\n // is added regardless of which generator runs first.\n addLicenseCheckToLintTarget(tree, fullyQualifiedName);\n\n return () =>\n installDependencies(tree, schema.preferInstallDependencies, {\n languages: ['typescript', 'python'],\n });\n};\nexport default pyProjectGenerator;\n"],"names":["ensurePackage","joinPathFragments","readNxJson","readProjectConfiguration","updateNxJson","updateProjectConfiguration","addLicenseCheckToLintTarget","ensurePythonLicenseCollector","addPyDependencies","addTsDependencies","declareDependencies","updateGitIgnore","installDependencies","addGeneratorMetricsIfApplicable","normalizeDistributionName","toSnakeCase","getNpmScope","addDependencyToTargetIfNotPresent","addGeneratorMetadata","getGeneratorInfo","projectExists","migrateToSharedVenvGenerator","uvProjectGenerator","sortObjectKeys","updateToml","pyenvPythonVersion","pyprojectPythonDependency","withVersions","DEPENDENCIES","ts","name","dev","root","py","group","PY_PROJECT_GENERATOR_INFO","filename","PYTHON_TRANSIENT_ARTIFACTS","PYTHON_TEST_FILE_EXCLUSIONS","addPythonTestExclusionsToProductionInput","tree","nxJson","production","namedInputs","missing","filter","exclusion","includes","length","getPyProjectDetails","schema","scope","normalizedName","normalizedModuleName","moduleName","fullyQualifiedName","distributionName","dir","directory","subDirectory","pyProjectGenerator","pythonPlugin","Object","entries","forEach","version","plugins","find","p","plugin","options","packageManager","exists","autoActivate","moveDevDependencies","packageName","publishable","buildLockedVersions","buildBundleLocalDependencies","linter","rootPyprojectDependencyGroup","projectType","type","projectNameAndRootFormat","unitTestRunner","codeCoverage","codeCoverageHtmlReport","codeCoverageXmlReport","unitTestHtmlReport","unitTestJUnitReport","buildSystem","srcDir","f","delete","write","outputPath","buildOutputPath","projectConfiguration","targets","compile","buildTarget","build","inputs","outputs","ignorePaths","dependsOn","assemble","typecheck","cache","executor","command","cwd","pyProjectToml","tool","ruff","format","check","configurations","fix","lint","exitZero","patterns","preferInstallDependencies","languages"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/py/project/generator.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n ensurePackage,\n type GeneratorCallback,\n joinPathFragments,\n readNxJson,\n readProjectConfiguration,\n type Tree,\n updateNxJson,\n updateProjectConfiguration,\n} from '@nx/devkit';\nimport {\n addLicenseCheckToLintTarget,\n ensurePythonLicenseCollector,\n} from '../../license/config.js';\nimport {\n addPyDependencies,\n addTsDependencies,\n} from '../../utils/add-dependencies.js';\nimport { declareDependencies } from '../../utils/declared-dependencies.js';\nimport { formatFilesInSubtree } from '../../utils/format.js';\nimport { updateGitIgnore } from '../../utils/git.js';\nimport { installDependencies } from '../../utils/install.js';\nimport { addGeneratorMetricsIfApplicable } from '../../utils/metrics.js';\nimport { normalizeDistributionName, toSnakeCase } from '../../utils/names.js';\nimport { getNpmScope } from '../../utils/npm-scope.js';\nimport {\n addDependencyToTargetIfNotPresent,\n addGeneratorMetadata,\n getGeneratorInfo,\n type NxGeneratorInfo,\n projectExists,\n} from '../../utils/nx.js';\nimport type { UVPyprojectToml } from '../../utils/nxlv-python.js';\nimport {\n migrateToSharedVenvGenerator,\n uvProjectGenerator,\n} from '../../utils/nxlv-python.js';\nimport { sortObjectKeys } from '../../utils/object.js';\nimport { updateToml } from '../../utils/toml.js';\nimport {\n pyenvPythonVersion,\n pyprojectPythonDependency,\n withVersions,\n} from '../../utils/versions.js';\nimport type { PyProjectGeneratorSchema } from './schema';\n\nexport const DEPENDENCIES = declareDependencies()({\n ts: [{ name: '@nxlv/python', dev: true, root: true }],\n py: [\n // The linting and type checking tools live in the workspace root pyproject.\n // Pinned to the version generation-time formatting uses, so generated files\n // stay `ruff format --check`-clean across ruff releases.\n { name: 'ruff', group: 'dev', root: true },\n { name: 'ty', group: 'dev', root: true },\n ],\n});\n\nexport const PY_PROJECT_GENERATOR_INFO: NxGeneratorInfo = getGeneratorInfo(\n import.meta.filename,\n);\n\n// Transient artifacts that pytest, coverage and ruff create and remove while\n// the test, typecheck and compile targets run concurrently. `.coverage.*` are\n// the per-process data files pytest-cov writes (`.coverage.<host>.<pid>.<rand>`)\n// before combining them. Both `ty` (which respects .gitignore) and the\n// `@nxlv/python:build` copy (which respects `ignorePaths`) would otherwise fail\n// when they read one of these mid-deletion.\nconst PYTHON_TRANSIENT_ARTIFACTS = [\n '__pycache__',\n '.coverage',\n '.coverage.*',\n '.pytest_cache',\n 'pytest-cache-files-*',\n '.ruff_cache',\n];\n\n// Python test files, excluded from the `production` named input so that editing\n// a test does not invalidate targets whose output cannot contain it.\n//\n// Anchored to the `tests` directory, which is where the generated project puts\n// them and the only path the build excludes (`ignorePaths` is matched against\n// the project root's top-level entries). An unanchored `**/test_*.py` would also\n// match a production module inside the packaged source directory — a\n// `test_data_loader.py` helper ships in the wheel, so excluding it would leave\n// the wheel stale after a fix to it.\nexport const PYTHON_TEST_FILE_EXCLUSIONS = ['!{projectRoot}/tests/**/*'];\n\n/**\n * Excludes Python test files from the `production` named input, preserving any\n * entries already present (including user additions).\n *\n * The input is created when absent: the Python targets reference `production`,\n * and Nx fails hard on a named input that is not defined.\n */\nexport const addPythonTestExclusionsToProductionInput = (tree: Tree) => {\n const nxJson = readNxJson(tree);\n if (!nxJson) {\n return;\n }\n const production = nxJson.namedInputs?.production ?? ['default'];\n const missing = PYTHON_TEST_FILE_EXCLUSIONS.filter(\n (exclusion) => !production.includes(exclusion),\n );\n if (missing.length === 0 && nxJson.namedInputs?.production) {\n return;\n }\n updateNxJson(tree, {\n ...nxJson,\n namedInputs: {\n ...nxJson.namedInputs,\n production: [...production, ...missing],\n },\n });\n};\n\nexport interface PyProjectDetails {\n /**\n * Fully qualified Nx project id including scope, in dot notation (eg foo.bar).\n * This is the identifier Nx uses (readProjectConfiguration, the project\n * graph, target references) and is intentionally kept dotted.\n */\n readonly fullyQualifiedName: string;\n /**\n * PEP 503 normalised Python distribution name (eg foo-bar). This is the name\n * written to the project's `[project].name`, the root `[tool.uv.sources]`\n * key, and any inter-project dependency string. It is hyphenated (not dotted)\n * so `uv` and `@nxlv/python` can match it: uv writes `uv.lock` keyed by the\n * PEP 503 hyphenated name, and `@nxlv/python`'s dependency inference splits a\n * dotted name on `.` and so would otherwise drop the edge entirely. Keeping\n * the distribution name decoupled from `fullyQualifiedName` is what lets the\n * workspace dependency edge appear in the Nx project graph.\n */\n readonly distributionName: string;\n /**\n * Directory of the library relative to the root\n */\n readonly dir: string;\n /**\n * Module name for the project\n */\n readonly normalizedModuleName: string;\n}\n\n/**\n * Returns details about the Python project to be created\n */\nexport const getPyProjectDetails = (\n tree: Tree,\n schema: {\n name: string;\n directory?: string;\n subDirectory?: string;\n moduleName?: string;\n },\n): PyProjectDetails => {\n const scope = toSnakeCase(getNpmScope(tree));\n const normalizedName = toSnakeCase(schema.name);\n const normalizedModuleName = toSnakeCase(\n schema.moduleName ?? `${scope}_${normalizedName}`,\n );\n const fullyQualifiedName = `${scope}.${normalizedName}`;\n // The Python distribution name is the PEP 503 normalised form of the\n // fully qualified name: hyphenated, never dotted. See PyProjectDetails.\n const distributionName = normalizeDistributionName(fullyQualifiedName);\n // NB: interactive nx generator cli can pass empty string\n const dir = joinPathFragments(\n schema.directory || '.',\n schema.subDirectory || normalizedName,\n );\n return { dir, fullyQualifiedName, distributionName, normalizedModuleName };\n};\n\n/**\n * Generates a Python project\n */\nexport const pyProjectGenerator = async (\n tree: Tree,\n schema: PyProjectGeneratorSchema,\n): Promise<GeneratorCallback> => {\n const { dir, normalizedModuleName, fullyQualifiedName, distributionName } =\n getPyProjectDetails(tree, schema);\n\n addTsDependencies(tree, DEPENDENCIES);\n\n addPythonTestExclusionsToProductionInput(tree);\n\n const pythonPlugin = withVersions(DEPENDENCIES, ['@nxlv/python']);\n Object.entries(pythonPlugin).forEach(([name, version]) =>\n ensurePackage(name, version),\n );\n\n const nxJson = readNxJson(tree);\n\n // Only rewrite nx.json when the plugin needs adding, so re-running does not\n // reserialize (and reformat) the file when nothing has changed.\n if (\n !nxJson.plugins?.find((p) =>\n typeof p === 'string'\n ? p === '@nxlv/python'\n : p.plugin === '@nxlv/python',\n )\n ) {\n nxJson.plugins = [\n ...(nxJson.plugins ?? []),\n {\n plugin: '@nxlv/python',\n options: {\n packageManager: 'uv',\n },\n },\n ];\n updateNxJson(tree, nxJson);\n }\n\n // Only scaffold the project when it does not already exist so re-running with\n // the same name does not throw. The rest of the generator still runs to apply\n // any changed options to the existing project.\n if (!projectExists(tree, fullyQualifiedName)) {\n if (!tree.exists('uv.lock')) {\n await migrateToSharedVenvGenerator(tree, {\n autoActivate: true,\n packageManager: 'uv',\n moveDevDependencies: false,\n pyenvPythonVersion: pyenvPythonVersion(),\n pyprojectPythonDependency: pyprojectPythonDependency(),\n });\n }\n\n await uvProjectGenerator(tree, {\n // The Nx project id (and `uv.workspace.members` etc.) keys off `name`, so\n // keep it dotted. `packageName` is the separate PEP 503 distribution name\n // written to `[project].name` and the root `[tool.uv.sources]` key; it is\n // hyphenated so `@nxlv/python` infers the workspace dependency edge (it\n // splits a dotted name on `.` and would otherwise drop it). This split is\n // the whole fix (see PyProjectDetails.distributionName).\n name: fullyQualifiedName,\n packageName: distributionName,\n publishable: false,\n buildLockedVersions: true,\n buildBundleLocalDependencies: true,\n linter: 'ruff',\n rootPyprojectDependencyGroup: 'main',\n pyenvPythonVersion: pyenvPythonVersion(),\n pyprojectPythonDependency: pyprojectPythonDependency(),\n projectType: schema.type,\n projectNameAndRootFormat: 'as-provided',\n moduleName: normalizedModuleName,\n directory: dir,\n unitTestRunner: 'pytest',\n codeCoverage: true,\n codeCoverageHtmlReport: true,\n codeCoverageXmlReport: true,\n unitTestHtmlReport: true,\n unitTestJUnitReport: true,\n buildSystem: 'hatch',\n srcDir: false,\n });\n\n // Remove generated hello.py and test_hello.py as they are not needed\n [\n joinPathFragments(dir, normalizedModuleName, 'hello.py'),\n joinPathFragments(dir, 'tests', 'test_hello.py'),\n ].forEach((f) => tree.delete(f));\n\n // Add a placeholder test so pytest doesn't fail with \"no tests collected\"\n tree.write(\n joinPathFragments(dir, 'tests', 'test_noop.py'),\n 'def test_noop():\\n pass\\n',\n );\n }\n\n const outputPath = '{workspaceRoot}/dist/{projectRoot}';\n const buildOutputPath = joinPathFragments(outputPath, 'build');\n const projectConfiguration = readProjectConfiguration(\n tree,\n fullyQualifiedName,\n );\n projectConfiguration.name = fullyQualifiedName;\n // Derive the compile target from the uv build target, and rewrite build to\n // orchestrate the other targets. This only runs on first creation: on re-run\n // build has already been transformed, so re-deriving would corrupt compile\n // and duplicate the build dependencies.\n if (!projectConfiguration.targets.compile) {\n const buildTarget = projectConfiguration.targets.build;\n projectConfiguration.targets.compile = {\n ...buildTarget,\n // `tests` is in `ignorePaths` below, so test files cannot reach the built\n // distribution and must not invalidate it.\n inputs: ['production', '^production'],\n outputs: [buildOutputPath],\n options: {\n ...buildTarget.options,\n outputPath: buildOutputPath,\n // The build executor copies the project to a temp folder; exclude the\n // executor defaults plus transient artifacts so the copy does not race\n // a concurrent test/typecheck target deleting a file mid-copy.\n ignorePaths: ['.venv', '.tox', 'tests', ...PYTHON_TRANSIENT_ARTIFACTS],\n },\n };\n projectConfiguration.targets.build = {\n inputs: ['default', '^production'],\n dependsOn: [\n 'lint',\n 'compile',\n 'test',\n 'typecheck',\n ...(buildTarget.dependsOn ?? []),\n ],\n options: {\n outputPath,\n },\n };\n // The artifact-only sibling of build, which the deploy targets depend on.\n projectConfiguration.targets.assemble = {\n dependsOn: ['compile'],\n };\n }\n projectConfiguration.targets.typecheck = {\n cache: true,\n inputs: ['default', '^production'],\n executor: '@nxlv/python:run-commands',\n options: {\n command: 'uv run ty check',\n cwd: '{projectRoot}',\n },\n };\n\n // Set the default line length to 120, as 88 is a little too strict\n updateToml(\n tree,\n joinPathFragments(dir, 'pyproject.toml'),\n (pyProjectToml: UVPyprojectToml) => {\n if ((pyProjectToml.tool as any)?.ruff) {\n (pyProjectToml.tool as any).ruff['line-length'] = 120;\n }\n return pyProjectToml;\n },\n );\n\n addPyDependencies(tree, DEPENDENCIES);\n\n // Base format target checks rather than writes (so build/lint don't rewrite\n // source); `fix` writes, and `skip-lint` writes without failing so it stays\n // a no-op when propagated through the lint -> format dependency.\n projectConfiguration.targets.format = {\n ...projectConfiguration.targets.format,\n cache: true,\n inputs: ['default', '^production'],\n options: {\n ...projectConfiguration.targets.format?.options,\n check: true,\n },\n configurations: {\n ...projectConfiguration.targets.format?.configurations,\n fix: {\n check: false,\n },\n 'skip-lint': {\n check: false,\n },\n },\n };\n\n // Add a dependency on the format target for lint in order to reduce the number of\n // fixable lint errors (eg line too long)\n projectConfiguration.targets.lint = {\n ...projectConfiguration.targets.lint,\n cache: true,\n inputs: ['default', '^production'],\n configurations: {\n ...projectConfiguration.targets.lint?.configurations,\n fix: {\n fix: true,\n },\n 'skip-lint': {\n exitZero: true,\n },\n },\n };\n // Append `format` without moving an existing entry, so re-running does not\n // reorder lint dependencies (e.g. relative to a later-added license-check).\n addDependencyToTargetIfNotPresent(projectConfiguration, 'lint', 'format');\n\n projectConfiguration.targets = sortObjectKeys(projectConfiguration.targets);\n updateProjectConfiguration(tree, fullyQualifiedName, projectConfiguration);\n\n addGeneratorMetadata(tree, fullyQualifiedName, PY_PROJECT_GENERATOR_INFO);\n\n // Update root .gitignore\n updateGitIgnore(tree, '.', (patterns) => [...patterns, '/reports']);\n\n // Update project level .gitignore. The cache directories are also kept out\n // of type checking: `ty` respects .gitignore, and pytest creates and removes\n // transient `pytest-cache-files-*` directories while the test and typecheck\n // targets run concurrently, which would otherwise make `ty` fail with an I/O\n // error when it scans one mid-deletion.\n updateGitIgnore(tree, dir, (patterns) => [\n ...patterns,\n '**/__pycache__',\n ...PYTHON_TRANSIENT_ARTIFACTS.filter((p) => p !== '__pycache__'),\n ]);\n\n await addGeneratorMetricsIfApplicable(tree, [PY_PROJECT_GENERATOR_INFO]);\n\n await ensurePythonLicenseCollector(tree);\n\n // If license checking is configured, make this project's lint target depend\n // on the root license-check target. No-op if license checking isn't set up;\n // the license generator wires up existing projects itself, so the dependency\n // is added regardless of which generator runs first.\n addLicenseCheckToLintTarget(tree, fullyQualifiedName);\n\n await formatFilesInSubtree(tree, joinPathFragments(dir, 'project.json'));\n\n return () =>\n installDependencies(tree, schema.preferInstallDependencies, {\n languages: ['typescript', 'python'],\n });\n};\nexport default pyProjectGenerator;\n"],"names":["ensurePackage","joinPathFragments","readNxJson","readProjectConfiguration","updateNxJson","updateProjectConfiguration","addLicenseCheckToLintTarget","ensurePythonLicenseCollector","addPyDependencies","addTsDependencies","declareDependencies","formatFilesInSubtree","updateGitIgnore","installDependencies","addGeneratorMetricsIfApplicable","normalizeDistributionName","toSnakeCase","getNpmScope","addDependencyToTargetIfNotPresent","addGeneratorMetadata","getGeneratorInfo","projectExists","migrateToSharedVenvGenerator","uvProjectGenerator","sortObjectKeys","updateToml","pyenvPythonVersion","pyprojectPythonDependency","withVersions","DEPENDENCIES","ts","name","dev","root","py","group","PY_PROJECT_GENERATOR_INFO","filename","PYTHON_TRANSIENT_ARTIFACTS","PYTHON_TEST_FILE_EXCLUSIONS","addPythonTestExclusionsToProductionInput","tree","nxJson","production","namedInputs","missing","filter","exclusion","includes","length","getPyProjectDetails","schema","scope","normalizedName","normalizedModuleName","moduleName","fullyQualifiedName","distributionName","dir","directory","subDirectory","pyProjectGenerator","pythonPlugin","Object","entries","forEach","version","plugins","find","p","plugin","options","packageManager","exists","autoActivate","moveDevDependencies","packageName","publishable","buildLockedVersions","buildBundleLocalDependencies","linter","rootPyprojectDependencyGroup","projectType","type","projectNameAndRootFormat","unitTestRunner","codeCoverage","codeCoverageHtmlReport","codeCoverageXmlReport","unitTestHtmlReport","unitTestJUnitReport","buildSystem","srcDir","f","delete","write","outputPath","buildOutputPath","projectConfiguration","targets","compile","buildTarget","build","inputs","outputs","ignorePaths","dependsOn","assemble","typecheck","cache","executor","command","cwd","pyProjectToml","tool","ruff","format","check","configurations","fix","lint","exitZero","patterns","preferInstallDependencies","languages"],"mappings":"AAAA;;;CAGC,GACD,SACEA,aAAa,EAEbC,iBAAiB,EACjBC,UAAU,EACVC,wBAAwB,EAExBC,YAAY,EACZC,0BAA0B,QACrB,aAAa;AACpB,SACEC,2BAA2B,EAC3BC,4BAA4B,QACvB,0BAA0B;AACjC,SACEC,iBAAiB,EACjBC,iBAAiB,QACZ,kCAAkC;AACzC,SAASC,mBAAmB,QAAQ,uCAAuC;AAC3E,SAASC,oBAAoB,QAAQ,wBAAwB;AAC7D,SAASC,eAAe,QAAQ,qBAAqB;AACrD,SAASC,mBAAmB,QAAQ,yBAAyB;AAC7D,SAASC,+BAA+B,QAAQ,yBAAyB;AACzE,SAASC,yBAAyB,EAAEC,WAAW,QAAQ,uBAAuB;AAC9E,SAASC,WAAW,QAAQ,2BAA2B;AACvD,SACEC,iCAAiC,EACjCC,oBAAoB,EACpBC,gBAAgB,EAEhBC,aAAa,QACR,oBAAoB;AAE3B,SACEC,4BAA4B,EAC5BC,kBAAkB,QACb,6BAA6B;AACpC,SAASC,cAAc,QAAQ,wBAAwB;AACvD,SAASC,UAAU,QAAQ,sBAAsB;AACjD,SACEC,kBAAkB,EAClBC,yBAAyB,EACzBC,YAAY,QACP,0BAA0B;AAGjC,OAAO,MAAMC,eAAenB,sBAAsB;IAChDoB,IAAI;QAAC;YAAEC,MAAM;YAAgBC,KAAK;YAAMC,MAAM;QAAK;KAAE;IACrDC,IAAI;QACF,4EAA4E;QAC5E,4EAA4E;QAC5E,yDAAyD;QACzD;YAAEH,MAAM;YAAQI,OAAO;YAAOF,MAAM;QAAK;QACzC;YAAEF,MAAM;YAAMI,OAAO;YAAOF,MAAM;QAAK;KACxC;AACH,GAAG;AAEH,OAAO,MAAMG,4BAA6ChB,iBACxD,YAAYiB,QAAQ,EACpB;AAEF,6EAA6E;AAC7E,8EAA8E;AAC9E,iFAAiF;AACjF,uEAAuE;AACvE,gFAAgF;AAChF,4CAA4C;AAC5C,MAAMC,6BAA6B;IACjC;IACA;IACA;IACA;IACA;IACA;CACD;AAED,gFAAgF;AAChF,qEAAqE;AACrE,EAAE;AACF,+EAA+E;AAC/E,8EAA8E;AAC9E,iFAAiF;AACjF,qEAAqE;AACrE,+EAA+E;AAC/E,qCAAqC;AACrC,OAAO,MAAMC,8BAA8B;IAAC;CAA4B,CAAC;AAEzE;;;;;;CAMC,GACD,OAAO,MAAMC,2CAA2C,CAACC;IACvD,MAAMC,SAASxC,WAAWuC;IAC1B,IAAI,CAACC,QAAQ;QACX;IACF;IACA,MAAMC,aAAaD,OAAOE,WAAW,EAAED,cAAc;QAAC;KAAU;IAChE,MAAME,UAAUN,4BAA4BO,MAAM,CAChD,CAACC,YAAc,CAACJ,WAAWK,QAAQ,CAACD;IAEtC,IAAIF,QAAQI,MAAM,KAAK,KAAKP,OAAOE,WAAW,EAAED,YAAY;QAC1D;IACF;IACAvC,aAAaqC,MAAM;QACjB,GAAGC,MAAM;QACTE,aAAa;YACX,GAAGF,OAAOE,WAAW;YACrBD,YAAY;mBAAIA;mBAAeE;aAAQ;QACzC;IACF;AACF,EAAE;AA8BF;;CAEC,GACD,OAAO,MAAMK,sBAAsB,CACjCT,MACAU;IAOA,MAAMC,QAAQpC,YAAYC,YAAYwB;IACtC,MAAMY,iBAAiBrC,YAAYmC,OAAOpB,IAAI;IAC9C,MAAMuB,uBAAuBtC,YAC3BmC,OAAOI,UAAU,IAAI,GAAGH,MAAM,CAAC,EAAEC,gBAAgB;IAEnD,MAAMG,qBAAqB,GAAGJ,MAAM,CAAC,EAAEC,gBAAgB;IACvD,qEAAqE;IACrE,wEAAwE;IACxE,MAAMI,mBAAmB1C,0BAA0ByC;IACnD,yDAAyD;IACzD,MAAME,MAAMzD,kBACVkD,OAAOQ,SAAS,IAAI,KACpBR,OAAOS,YAAY,IAAIP;IAEzB,OAAO;QAAEK;QAAKF;QAAoBC;QAAkBH;IAAqB;AAC3E,EAAE;AAEF;;CAEC,GACD,OAAO,MAAMO,qBAAqB,OAChCpB,MACAU;IAEA,MAAM,EAAEO,GAAG,EAAEJ,oBAAoB,EAAEE,kBAAkB,EAAEC,gBAAgB,EAAE,GACvEP,oBAAoBT,MAAMU;IAE5B1C,kBAAkBgC,MAAMZ;IAExBW,yCAAyCC;IAEzC,MAAMqB,eAAelC,aAAaC,cAAc;QAAC;KAAe;IAChEkC,OAAOC,OAAO,CAACF,cAAcG,OAAO,CAAC,CAAC,CAAClC,MAAMmC,QAAQ,GACnDlE,cAAc+B,MAAMmC;IAGtB,MAAMxB,SAASxC,WAAWuC;IAE1B,4EAA4E;IAC5E,gEAAgE;IAChE,IACE,CAACC,OAAOyB,OAAO,EAAEC,KAAK,CAACC,IACrB,OAAOA,MAAM,WACTA,MAAM,iBACNA,EAAEC,MAAM,KAAK,iBAEnB;QACA5B,OAAOyB,OAAO,GAAG;eACXzB,OAAOyB,OAAO,IAAI,EAAE;YACxB;gBACEG,QAAQ;gBACRC,SAAS;oBACPC,gBAAgB;gBAClB;YACF;SACD;QACDpE,aAAaqC,MAAMC;IACrB;IAEA,8EAA8E;IAC9E,8EAA8E;IAC9E,+CAA+C;IAC/C,IAAI,CAACrB,cAAcoB,MAAMe,qBAAqB;QAC5C,IAAI,CAACf,KAAKgC,MAAM,CAAC,YAAY;YAC3B,MAAMnD,6BAA6BmB,MAAM;gBACvCiC,cAAc;gBACdF,gBAAgB;gBAChBG,qBAAqB;gBACrBjD,oBAAoBA;gBACpBC,2BAA2BA;YAC7B;QACF;QAEA,MAAMJ,mBAAmBkB,MAAM;YAC7B,0EAA0E;YAC1E,0EAA0E;YAC1E,0EAA0E;YAC1E,wEAAwE;YACxE,0EAA0E;YAC1E,yDAAyD;YACzDV,MAAMyB;YACNoB,aAAanB;YACboB,aAAa;YACbC,qBAAqB;YACrBC,8BAA8B;YAC9BC,QAAQ;YACRC,8BAA8B;YAC9BvD,oBAAoBA;YACpBC,2BAA2BA;YAC3BuD,aAAa/B,OAAOgC,IAAI;YACxBC,0BAA0B;YAC1B7B,YAAYD;YACZK,WAAWD;YACX2B,gBAAgB;YAChBC,cAAc;YACdC,wBAAwB;YACxBC,uBAAuB;YACvBC,oBAAoB;YACpBC,qBAAqB;YACrBC,aAAa;YACbC,QAAQ;QACV;QAEA,qEAAqE;QACrE;YACE3F,kBAAkByD,KAAKJ,sBAAsB;YAC7CrD,kBAAkByD,KAAK,SAAS;SACjC,CAACO,OAAO,CAAC,CAAC4B,IAAMpD,KAAKqD,MAAM,CAACD;QAE7B,0EAA0E;QAC1EpD,KAAKsD,KAAK,CACR9F,kBAAkByD,KAAK,SAAS,iBAChC;IAEJ;IAEA,MAAMsC,aAAa;IACnB,MAAMC,kBAAkBhG,kBAAkB+F,YAAY;IACtD,MAAME,uBAAuB/F,yBAC3BsC,MACAe;IAEF0C,qBAAqBnE,IAAI,GAAGyB;IAC5B,2EAA2E;IAC3E,6EAA6E;IAC7E,2EAA2E;IAC3E,wCAAwC;IACxC,IAAI,CAAC0C,qBAAqBC,OAAO,CAACC,OAAO,EAAE;QACzC,MAAMC,cAAcH,qBAAqBC,OAAO,CAACG,KAAK;QACtDJ,qBAAqBC,OAAO,CAACC,OAAO,GAAG;YACrC,GAAGC,WAAW;YACd,0EAA0E;YAC1E,2CAA2C;YAC3CE,QAAQ;gBAAC;gBAAc;aAAc;YACrCC,SAAS;gBAACP;aAAgB;YAC1B1B,SAAS;gBACP,GAAG8B,YAAY9B,OAAO;gBACtByB,YAAYC;gBACZ,sEAAsE;gBACtE,uEAAuE;gBACvE,+DAA+D;gBAC/DQ,aAAa;oBAAC;oBAAS;oBAAQ;uBAAYnE;iBAA2B;YACxE;QACF;QACA4D,qBAAqBC,OAAO,CAACG,KAAK,GAAG;YACnCC,QAAQ;gBAAC;gBAAW;aAAc;YAClCG,WAAW;gBACT;gBACA;gBACA;gBACA;mBACIL,YAAYK,SAAS,IAAI,EAAE;aAChC;YACDnC,SAAS;gBACPyB;YACF;QACF;QACA,0EAA0E;QAC1EE,qBAAqBC,OAAO,CAACQ,QAAQ,GAAG;YACtCD,WAAW;gBAAC;aAAU;QACxB;IACF;IACAR,qBAAqBC,OAAO,CAACS,SAAS,GAAG;QACvCC,OAAO;QACPN,QAAQ;YAAC;YAAW;SAAc;QAClCO,UAAU;QACVvC,SAAS;YACPwC,SAAS;YACTC,KAAK;QACP;IACF;IAEA,mEAAmE;IACnEvF,WACEgB,MACAxC,kBAAkByD,KAAK,mBACvB,CAACuD;QACC,IAAKA,cAAcC,IAAI,EAAUC,MAAM;YACpCF,cAAcC,IAAI,CAASC,IAAI,CAAC,cAAc,GAAG;QACpD;QACA,OAAOF;IACT;IAGFzG,kBAAkBiC,MAAMZ;IAExB,4EAA4E;IAC5E,4EAA4E;IAC5E,iEAAiE;IACjEqE,qBAAqBC,OAAO,CAACiB,MAAM,GAAG;QACpC,GAAGlB,qBAAqBC,OAAO,CAACiB,MAAM;QACtCP,OAAO;QACPN,QAAQ;YAAC;YAAW;SAAc;QAClChC,SAAS;YACP,GAAG2B,qBAAqBC,OAAO,CAACiB,MAAM,EAAE7C,OAAO;YAC/C8C,OAAO;QACT;QACAC,gBAAgB;YACd,GAAGpB,qBAAqBC,OAAO,CAACiB,MAAM,EAAEE,cAAc;YACtDC,KAAK;gBACHF,OAAO;YACT;YACA,aAAa;gBACXA,OAAO;YACT;QACF;IACF;IAEA,kFAAkF;IAClF,yCAAyC;IACzCnB,qBAAqBC,OAAO,CAACqB,IAAI,GAAG;QAClC,GAAGtB,qBAAqBC,OAAO,CAACqB,IAAI;QACpCX,OAAO;QACPN,QAAQ;YAAC;YAAW;SAAc;QAClCe,gBAAgB;YACd,GAAGpB,qBAAqBC,OAAO,CAACqB,IAAI,EAAEF,cAAc;YACpDC,KAAK;gBACHA,KAAK;YACP;YACA,aAAa;gBACXE,UAAU;YACZ;QACF;IACF;IACA,2EAA2E;IAC3E,4EAA4E;IAC5EvG,kCAAkCgF,sBAAsB,QAAQ;IAEhEA,qBAAqBC,OAAO,GAAG3E,eAAe0E,qBAAqBC,OAAO;IAC1E9F,2BAA2BoC,MAAMe,oBAAoB0C;IAErD/E,qBAAqBsB,MAAMe,oBAAoBpB;IAE/C,yBAAyB;IACzBxB,gBAAgB6B,MAAM,KAAK,CAACiF,WAAa;eAAIA;YAAU;SAAW;IAElE,2EAA2E;IAC3E,6EAA6E;IAC7E,4EAA4E;IAC5E,6EAA6E;IAC7E,wCAAwC;IACxC9G,gBAAgB6B,MAAMiB,KAAK,CAACgE,WAAa;eACpCA;YACH;eACGpF,2BAA2BQ,MAAM,CAAC,CAACuB,IAAMA,MAAM;SACnD;IAED,MAAMvD,gCAAgC2B,MAAM;QAACL;KAA0B;IAEvE,MAAM7B,6BAA6BkC;IAEnC,4EAA4E;IAC5E,4EAA4E;IAC5E,6EAA6E;IAC7E,qDAAqD;IACrDnC,4BAA4BmC,MAAMe;IAElC,MAAM7C,qBAAqB8B,MAAMxC,kBAAkByD,KAAK;IAExD,OAAO,IACL7C,oBAAoB4B,MAAMU,OAAOwE,yBAAyB,EAAE;YAC1DC,WAAW;gBAAC;gBAAc;aAAS;QACrC;AACJ,EAAE;AACF,eAAe/D,mBAAmB"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
export { greengrassComponentGenerator } from '../greengrass/component/generator.js';
|
|
6
|
+
export type { GreengrassComponentGeneratorSchema } from '../greengrass/component/schema.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx-plugin/src/sdk/greengrass.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nexport { greengrassComponentGenerator } from '../greengrass/component/generator.js';\nexport type { GreengrassComponentGeneratorSchema } from '../greengrass/component/schema.js';\n"],"names":["greengrassComponentGenerator"],"mappings":"AAAA;;;CAGC,GACD,SAASA,4BAA4B,QAAQ,uCAAuC"}
|
package/src/sdk/py.d.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/
|
|
5
5
|
export { pyAgentGenerator } from '../py/agent/generator.js';
|
|
6
|
+
export { pyAgentGuardrailsGenerator } from '../py/agent/guardrails/generator.js';
|
|
7
|
+
export type { PyAgentGuardrailsGeneratorSchema } from '../py/agent/guardrails/schema';
|
|
6
8
|
export type { PyAgentGeneratorSchema } from '../py/agent/schema';
|
|
7
9
|
export { pyApiGenerator } from '../py/api/generator.js';
|
|
8
10
|
export type { PyApiGeneratorSchema } from '../py/api/schema';
|
package/src/sdk/py.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
3
|
* SPDX-License-Identifier: Apache-2.0
|
|
4
4
|
*/ export { pyAgentGenerator } from "../py/agent/generator.js";
|
|
5
|
+
export { pyAgentGuardrailsGenerator } from "../py/agent/guardrails/generator.js";
|
|
5
6
|
export { pyApiGenerator } from "../py/api/generator.js";
|
|
6
7
|
export { pyDynamoDBGenerator } from "../py/dynamodb/generator.js";
|
|
7
8
|
export { pyLambdaFunctionGenerator } from "../py/lambda-function/generator.js";
|
package/src/sdk/py.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../packages/nx-plugin/src/sdk/py.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport { pyAgentGenerator } from '../py/agent/generator.js';\nexport type { PyAgentGeneratorSchema } from '../py/agent/schema';\n\nexport { pyApiGenerator } from '../py/api/generator.js';\nexport type { PyApiGeneratorSchema } from '../py/api/schema';\n\nexport { pyDynamoDBGenerator } from '../py/dynamodb/generator.js';\nexport type { PyDynamoDBGeneratorSchema } from '../py/dynamodb/schema';\n\nexport { pyLambdaFunctionGenerator } from '../py/lambda-function/generator.js';\nexport type { PyLambdaFunctionGeneratorSchema } from '../py/lambda-function/schema';\n\nexport { pyMcpServerGenerator } from '../py/mcp-server/generator.js';\nexport type { PyMcpServerGeneratorSchema } from '../py/mcp-server/schema';\nexport { pyProjectGenerator } from '../py/project/generator.js';\nexport type { PyProjectGeneratorSchema } from '../py/project/schema';\n\nexport { pyRdbGenerator } from '../py/rdb/generator.js';\nexport type { PyRdbGeneratorSchema } from '../py/rdb/schema';\n"],"names":["pyAgentGenerator","pyApiGenerator","pyDynamoDBGenerator","pyLambdaFunctionGenerator","pyMcpServerGenerator","pyProjectGenerator","pyRdbGenerator"],"mappings":"AAAA;;;CAGC,GAED,SAASA,gBAAgB,QAAQ,2BAA2B;
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx-plugin/src/sdk/py.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport { pyAgentGenerator } from '../py/agent/generator.js';\nexport { pyAgentGuardrailsGenerator } from '../py/agent/guardrails/generator.js';\nexport type { PyAgentGuardrailsGeneratorSchema } from '../py/agent/guardrails/schema';\nexport type { PyAgentGeneratorSchema } from '../py/agent/schema';\n\nexport { pyApiGenerator } from '../py/api/generator.js';\nexport type { PyApiGeneratorSchema } from '../py/api/schema';\n\nexport { pyDynamoDBGenerator } from '../py/dynamodb/generator.js';\nexport type { PyDynamoDBGeneratorSchema } from '../py/dynamodb/schema';\n\nexport { pyLambdaFunctionGenerator } from '../py/lambda-function/generator.js';\nexport type { PyLambdaFunctionGeneratorSchema } from '../py/lambda-function/schema';\n\nexport { pyMcpServerGenerator } from '../py/mcp-server/generator.js';\nexport type { PyMcpServerGeneratorSchema } from '../py/mcp-server/schema';\nexport { pyProjectGenerator } from '../py/project/generator.js';\nexport type { PyProjectGeneratorSchema } from '../py/project/schema';\n\nexport { pyRdbGenerator } from '../py/rdb/generator.js';\nexport type { PyRdbGeneratorSchema } from '../py/rdb/schema';\n"],"names":["pyAgentGenerator","pyAgentGuardrailsGenerator","pyApiGenerator","pyDynamoDBGenerator","pyLambdaFunctionGenerator","pyMcpServerGenerator","pyProjectGenerator","pyRdbGenerator"],"mappings":"AAAA;;;CAGC,GAED,SAASA,gBAAgB,QAAQ,2BAA2B;AAC5D,SAASC,0BAA0B,QAAQ,sCAAsC;AAIjF,SAASC,cAAc,QAAQ,yBAAyB;AAGxD,SAASC,mBAAmB,QAAQ,8BAA8B;AAGlE,SAASC,yBAAyB,QAAQ,qCAAqC;AAG/E,SAASC,oBAAoB,QAAQ,gCAAgC;AAErE,SAASC,kBAAkB,QAAQ,6BAA6B;AAGhE,SAASC,cAAc,QAAQ,yBAAyB"}
|
|
@@ -38,7 +38,7 @@ export declare const DEPENDENCIES: import("../../utils/declared-dependencies.js"
|
|
|
38
38
|
readonly dev: true;
|
|
39
39
|
readonly root: true;
|
|
40
40
|
readonly when: (metadata: SmithyProjectMetadata) => boolean;
|
|
41
|
-
}], readonly import("../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", SmithyProjectMetadata>[]>;
|
|
41
|
+
}], readonly import("../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "awsiotsdk" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", SmithyProjectMetadata>[]>;
|
|
42
42
|
export declare const SMITHY_PROJECT_GENERATOR_INFO: NxGeneratorInfo;
|
|
43
43
|
/**
|
|
44
44
|
* The commands that build a Smithy project's model, run from the workspace root.
|
|
@@ -19,7 +19,7 @@ export declare const DEPENDENCIES: import("../../utils/declared-dependencies.js"
|
|
|
19
19
|
readonly name: "@tanstack/react-query-devtools";
|
|
20
20
|
}, {
|
|
21
21
|
readonly name: "@smithy/types";
|
|
22
|
-
}], readonly import("../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
|
|
22
|
+
}], readonly import("../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "awsiotsdk" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
|
|
23
23
|
export declare const SMITHY_REACT_CONNECTION_GENERATOR_INFO: NxGeneratorInfo;
|
|
24
24
|
export declare const smithyReactConnectionGenerator: (tree: Tree, options: SmithyReactConnectionGeneratorSchema) => Promise<GeneratorCallback>;
|
|
25
25
|
export default smithyReactConnectionGenerator;
|
|
@@ -54,7 +54,7 @@ export declare const DEPENDENCIES: import("../../utils/declared-dependencies.js"
|
|
|
54
54
|
readonly name: "@types/node";
|
|
55
55
|
} & {
|
|
56
56
|
versionOnly: true;
|
|
57
|
-
}], readonly import("../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
|
|
57
|
+
}], readonly import("../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "awsiotsdk" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", Record<string, never>>[]>;
|
|
58
58
|
export declare const TERRAFORM_PROJECT_GENERATOR_INFO: NxGeneratorInfo;
|
|
59
59
|
/**
|
|
60
60
|
* Checks formatting, mirroring the TypeScript and Python `format` targets: the
|
|
@@ -41,7 +41,7 @@ export declare const DEPENDENCIES: import("../../utils/declared-dependencies.js"
|
|
|
41
41
|
readonly name: "@types/event-source-polyfill";
|
|
42
42
|
readonly when: (m: TrpcReactMetadata) => boolean;
|
|
43
43
|
readonly dev: true;
|
|
44
|
-
}], readonly import("../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", TrpcReactMetadata>[]>;
|
|
44
|
+
}], readonly import("../../utils/declared-dependencies.js").DeclaredPyDependency<"ruff" | "a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aiosqlite" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "awsiotsdk" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "langgraph-checkpoint-aws" | "langgraph-checkpoint-sqlite" | "mcp" | "pip-check-updates" | "pip-licenses" | "pydantic" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", TrpcReactMetadata>[]>;
|
|
45
45
|
export declare const TRPC_REACT_GENERATOR_INFO: NxGeneratorInfo;
|
|
46
46
|
export declare function reactGenerator(tree: Tree, options: ReactGeneratorSchema): Promise<() => Promise<void>>;
|
|
47
47
|
export default reactGenerator;
|