@aws/agentcore 1.0.0-preview.10 → 1.0.0-preview.12
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/dist/agent-inspector/index.css +1 -1
- package/dist/agent-inspector/index.js +83 -78
- package/dist/assets/__tests__/__snapshots__/assets.snapshot.test.ts.snap +452 -146
- package/dist/assets/__tests__/__snapshots__/dockerfile-render.test.ts.snap +2 -2
- package/dist/assets/cdk/bin/cdk.ts +4 -0
- package/dist/assets/cdk/lib/cdk-stack.ts +2 -0
- package/dist/assets/cdk/package.json +1 -1
- package/dist/assets/container/python/Dockerfile +1 -1
- package/dist/assets/python/a2a/googleadk/base/main.py +24 -16
- package/dist/assets/python/a2a/googleadk/base/pyproject.toml +1 -1
- package/dist/assets/python/a2a/langchain_langgraph/base/main.py +24 -16
- package/dist/assets/python/a2a/langchain_langgraph/base/pyproject.toml +1 -0
- package/dist/assets/python/a2a/strands/base/main.py +23 -17
- package/dist/assets/python/agui/googleadk/base/main.py +62 -2
- package/dist/assets/python/agui/googleadk/base/pyproject.toml +1 -1
- package/dist/assets/python/agui/langchain_langgraph/base/main.py +56 -0
- package/dist/assets/python/agui/langchain_langgraph/base/pyproject.toml +1 -0
- package/dist/assets/python/agui/strands/base/main.py +63 -1
- package/dist/assets/python/http/autogen/base/main.py +27 -19
- package/dist/assets/python/http/googleadk/base/main.py +24 -16
- package/dist/assets/python/http/googleadk/base/pyproject.toml +1 -0
- package/dist/assets/python/http/langchain_langgraph/base/main.py +24 -16
- package/dist/assets/python/http/langchain_langgraph/base/pyproject.toml +1 -0
- package/dist/assets/python/http/openaiagents/base/main.py +24 -16
- package/dist/assets/python/http/strands/base/main.py +23 -17
- package/dist/assets/python/mcp/standalone/base/main.py +58 -0
- package/dist/cli/index.mjs +707 -634
- package/dist/lib/errors/types.d.ts +9 -0
- package/dist/lib/errors/types.d.ts.map +1 -1
- package/dist/lib/errors/types.js +19 -1
- package/dist/lib/errors/types.js.map +1 -1
- package/dist/lib/errors/zod.js +1 -1
- package/dist/lib/errors/zod.js.map +1 -1
- package/dist/lib/packaging/helpers.d.ts.map +1 -1
- package/dist/lib/packaging/helpers.js +6 -10
- package/dist/lib/packaging/helpers.js.map +1 -1
- package/dist/lib/result.d.ts +21 -4
- package/dist/lib/result.d.ts.map +1 -1
- package/dist/lib/result.js +19 -0
- package/dist/lib/result.js.map +1 -1
- package/dist/lib/schemas/io/global-config.d.ts +28 -21
- package/dist/lib/schemas/io/global-config.d.ts.map +1 -1
- package/dist/lib/schemas/io/global-config.js +57 -28
- package/dist/lib/schemas/io/global-config.js.map +1 -1
- package/dist/lib/utils/index.d.ts +1 -1
- package/dist/lib/utils/index.d.ts.map +1 -1
- package/dist/lib/utils/index.js +2 -1
- package/dist/lib/utils/index.js.map +1 -1
- package/dist/lib/utils/zod.d.ts +16 -0
- package/dist/lib/utils/zod.d.ts.map +1 -1
- package/dist/lib/utils/zod.js +45 -0
- package/dist/lib/utils/zod.js.map +1 -1
- package/dist/schema/schemas/agent-env.d.ts +50 -4
- package/dist/schema/schemas/agent-env.d.ts.map +1 -1
- package/dist/schema/schemas/agent-env.js +102 -4
- package/dist/schema/schemas/agent-env.js.map +1 -1
- package/dist/schema/schemas/agentcore-project.d.ts +12 -2
- package/dist/schema/schemas/agentcore-project.d.ts.map +1 -1
- package/dist/schema/schemas/primitives/harness.d.ts +8 -0
- package/dist/schema/schemas/primitives/harness.d.ts.map +1 -1
- package/dist/schema/schemas/primitives/harness.js +23 -0
- package/dist/schema/schemas/primitives/harness.js.map +1 -1
- package/npm-shrinkwrap.json +281 -366
- package/package.json +12 -7
- package/scripts/bump-version.ts +1 -1
|
@@ -111,6 +111,8 @@ async function main() {
|
|
|
111
111
|
codeLocation?: string;
|
|
112
112
|
tools?: { type: string; name: string }[];
|
|
113
113
|
apiKeyArn?: string;
|
|
114
|
+
efsAccessPoints?: { accessPointArn: string; mountPath: string }[];
|
|
115
|
+
s3AccessPoints?: { accessPointArn: string; mountPath: string }[];
|
|
114
116
|
}[] = [];
|
|
115
117
|
for (const entry of specAny.harnesses ?? []) {
|
|
116
118
|
const harnessDir = path.resolve(projectRoot, entry.path);
|
|
@@ -127,6 +129,8 @@ async function main() {
|
|
|
127
129
|
codeLocation: harnessSpec.dockerfile ? harnessDir : undefined,
|
|
128
130
|
tools: harnessSpec.tools,
|
|
129
131
|
apiKeyArn: harnessSpec.model?.apiKeyArn,
|
|
132
|
+
efsAccessPoints: harnessSpec.efsAccessPoints,
|
|
133
|
+
s3AccessPoints: harnessSpec.s3AccessPoints,
|
|
130
134
|
});
|
|
131
135
|
} catch (err) {
|
|
132
136
|
throw new Error(
|
|
@@ -312,6 +316,8 @@ export interface HarnessConfig {
|
|
|
312
316
|
codeLocation?: string;
|
|
313
317
|
tools?: { type: string; name: string }[];
|
|
314
318
|
apiKeyArn?: string;
|
|
319
|
+
efsAccessPoints?: { accessPointArn: string; mountPath: string }[];
|
|
320
|
+
s3AccessPoints?: { accessPointArn: string; mountPath: string }[];
|
|
315
321
|
}
|
|
316
322
|
|
|
317
323
|
export interface AgentCoreStackProps extends StackProps {
|
|
@@ -408,7 +414,7 @@ exports[`Assets Directory Snapshots > CDK assets > cdk/cdk/package.json should m
|
|
|
408
414
|
"@types/node": "^24.10.1",
|
|
409
415
|
"jest": "^29.7.0",
|
|
410
416
|
"ts-jest": "^29.2.5",
|
|
411
|
-
"aws-cdk": "2.
|
|
417
|
+
"aws-cdk": "2.1126.0",
|
|
412
418
|
"prettier": "^3.4.2",
|
|
413
419
|
"typescript": "~5.9.3"
|
|
414
420
|
},
|
|
@@ -1063,7 +1069,9 @@ Thumbs.db
|
|
|
1063
1069
|
`;
|
|
1064
1070
|
|
|
1065
1071
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/a2a/googleadk/base/main.py should match snapshot 1`] = `
|
|
1066
|
-
"
|
|
1072
|
+
"{{#if needsOs}}
|
|
1073
|
+
import os
|
|
1074
|
+
{{/if}}
|
|
1067
1075
|
from google.adk.agents import Agent
|
|
1068
1076
|
from google.adk.a2a.executor.a2a_agent_executor import A2aAgentExecutor
|
|
1069
1077
|
from google.adk.runners import Runner
|
|
@@ -1082,18 +1090,21 @@ def add_numbers(a: int, b: int) -> int:
|
|
|
1082
1090
|
|
|
1083
1091
|
tools = [add_numbers]
|
|
1084
1092
|
|
|
1085
|
-
{{#if
|
|
1086
|
-
|
|
1093
|
+
{{#if needsOs}}
|
|
1094
|
+
_MOUNT_PATHS = [
|
|
1095
|
+
{{#if sessionStorageMountPath}}"{{sessionStorageMountPath}}",{{/if}}
|
|
1096
|
+
{{#each efsMounts}}"{{mountPath}}",{{/each}}
|
|
1097
|
+
{{#each s3Mounts}}"{{mountPath}}",{{/each}}
|
|
1098
|
+
]
|
|
1087
1099
|
|
|
1088
1100
|
def _safe_resolve(path: str) -> str:
|
|
1089
|
-
|
|
1090
|
-
resolved
|
|
1091
|
-
|
|
1092
|
-
raise ValueError(f"Path '{path}' is outside the storage boundary")
|
|
1101
|
+
resolved = os.path.realpath(path)
|
|
1102
|
+
if not any(resolved == os.path.realpath(m) or resolved.startswith(os.path.realpath(m) + os.sep) for m in _MOUNT_PATHS):
|
|
1103
|
+
raise ValueError(f"Path '{path}' is not within any configured mount ({', '.join(_MOUNT_PATHS)})")
|
|
1093
1104
|
return resolved
|
|
1094
1105
|
|
|
1095
1106
|
def file_read(path: str) -> str:
|
|
1096
|
-
"""Read a file from
|
|
1107
|
+
"""Read a file from a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
1097
1108
|
try:
|
|
1098
1109
|
full_path = _safe_resolve(path)
|
|
1099
1110
|
with open(full_path) as f:
|
|
@@ -1104,7 +1115,7 @@ def file_read(path: str) -> str:
|
|
|
1104
1115
|
return f"Error reading '{path}': {e.strerror}"
|
|
1105
1116
|
|
|
1106
1117
|
def file_write(path: str, content: str) -> str:
|
|
1107
|
-
"""Write
|
|
1118
|
+
"""Write a file to a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
1108
1119
|
try:
|
|
1109
1120
|
full_path = _safe_resolve(path)
|
|
1110
1121
|
parent = os.path.dirname(full_path)
|
|
@@ -1118,25 +1129,28 @@ def file_write(path: str, content: str) -> str:
|
|
|
1118
1129
|
except OSError as e:
|
|
1119
1130
|
return f"Error writing '{path}': {e.strerror}"
|
|
1120
1131
|
|
|
1121
|
-
def list_files(
|
|
1122
|
-
"""List files in
|
|
1132
|
+
def list_files(path: str) -> str:
|
|
1133
|
+
"""List files in a mounted filesystem directory. Use the absolute path (e.g. /mnt/tools)."""
|
|
1123
1134
|
try:
|
|
1124
|
-
|
|
1125
|
-
entries = os.listdir(
|
|
1135
|
+
full_path = _safe_resolve(path)
|
|
1136
|
+
entries = os.listdir(full_path)
|
|
1126
1137
|
return "\\n".join(entries) if entries else "(empty directory)"
|
|
1127
1138
|
except ValueError as e:
|
|
1128
1139
|
return str(e)
|
|
1129
1140
|
except OSError as e:
|
|
1130
|
-
return f"Error listing '{
|
|
1141
|
+
return f"Error listing '{path}': {e.strerror}"
|
|
1131
1142
|
|
|
1132
1143
|
tools.extend([file_read, file_write, list_files])
|
|
1133
1144
|
{{/if}}
|
|
1134
1145
|
|
|
1135
1146
|
AGENT_INSTRUCTION = """
|
|
1136
1147
|
You are a helpful assistant. Use tools when appropriate.
|
|
1137
|
-
{{#if
|
|
1138
|
-
You have
|
|
1139
|
-
{{
|
|
1148
|
+
{{#if needsOs}}
|
|
1149
|
+
You have access to the following mounted filesystems. Use file_read, file_write, and list_files with full absolute paths:
|
|
1150
|
+
{{#if sessionStorageMountPath}}- {{sessionStorageMountPath}}: ephemeral session storage (lost when session ends)
|
|
1151
|
+
{{/if}}{{#each efsMounts}}- {{mountPath}}: EFS persistent storage (persists across sessions and agent restarts)
|
|
1152
|
+
{{/each}}{{#each s3Mounts}}- {{mountPath}}: S3 Files persistent storage (durable, backed by S3)
|
|
1153
|
+
{{/each}}{{/if}}
|
|
1140
1154
|
"""
|
|
1141
1155
|
|
|
1142
1156
|
agent = Agent(
|
|
@@ -1242,7 +1256,7 @@ dependencies = [
|
|
|
1242
1256
|
"aws-opentelemetry-distro",
|
|
1243
1257
|
"bedrock-agentcore[a2a] >= 1.0.3",
|
|
1244
1258
|
"google-adk >= 1.0.0, < 2.0.0",
|
|
1245
|
-
"google-genai >= 1.0.0",
|
|
1259
|
+
"google-genai >= 1.0.0, < 2.0.0",
|
|
1246
1260
|
]
|
|
1247
1261
|
|
|
1248
1262
|
[tool.hatch.build.targets.wheel]
|
|
@@ -1322,7 +1336,9 @@ Thumbs.db
|
|
|
1322
1336
|
`;
|
|
1323
1337
|
|
|
1324
1338
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/a2a/langchain_langgraph/base/main.py should match snapshot 1`] = `
|
|
1325
|
-
"
|
|
1339
|
+
"{{#if needsOs}}
|
|
1340
|
+
import os
|
|
1341
|
+
{{/if}}
|
|
1326
1342
|
from langchain_core.tools import tool
|
|
1327
1343
|
from langgraph.prebuilt import create_react_agent
|
|
1328
1344
|
from opentelemetry.instrumentation.langchain import LangchainInstrumentor
|
|
@@ -1345,19 +1361,22 @@ def add_numbers(a: int, b: int) -> int:
|
|
|
1345
1361
|
|
|
1346
1362
|
tools = [add_numbers]
|
|
1347
1363
|
|
|
1348
|
-
{{#if
|
|
1349
|
-
|
|
1364
|
+
{{#if needsOs}}
|
|
1365
|
+
_MOUNT_PATHS = [
|
|
1366
|
+
{{#if sessionStorageMountPath}}"{{sessionStorageMountPath}}",{{/if}}
|
|
1367
|
+
{{#each efsMounts}}"{{mountPath}}",{{/each}}
|
|
1368
|
+
{{#each s3Mounts}}"{{mountPath}}",{{/each}}
|
|
1369
|
+
]
|
|
1350
1370
|
|
|
1351
1371
|
def _safe_resolve(path: str) -> str:
|
|
1352
|
-
|
|
1353
|
-
resolved
|
|
1354
|
-
|
|
1355
|
-
raise ValueError(f"Path '{path}' is outside the storage boundary")
|
|
1372
|
+
resolved = os.path.realpath(path)
|
|
1373
|
+
if not any(resolved == os.path.realpath(m) or resolved.startswith(os.path.realpath(m) + os.sep) for m in _MOUNT_PATHS):
|
|
1374
|
+
raise ValueError(f"Path '{path}' is not within any configured mount ({', '.join(_MOUNT_PATHS)})")
|
|
1356
1375
|
return resolved
|
|
1357
1376
|
|
|
1358
1377
|
@tool
|
|
1359
1378
|
def file_read(path: str) -> str:
|
|
1360
|
-
"""Read a file from
|
|
1379
|
+
"""Read a file from a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
1361
1380
|
try:
|
|
1362
1381
|
full_path = _safe_resolve(path)
|
|
1363
1382
|
with open(full_path) as f:
|
|
@@ -1369,7 +1388,7 @@ def file_read(path: str) -> str:
|
|
|
1369
1388
|
|
|
1370
1389
|
@tool
|
|
1371
1390
|
def file_write(path: str, content: str) -> str:
|
|
1372
|
-
"""Write
|
|
1391
|
+
"""Write a file to a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
1373
1392
|
try:
|
|
1374
1393
|
full_path = _safe_resolve(path)
|
|
1375
1394
|
parent = os.path.dirname(full_path)
|
|
@@ -1384,25 +1403,28 @@ def file_write(path: str, content: str) -> str:
|
|
|
1384
1403
|
return f"Error writing '{path}': {e.strerror}"
|
|
1385
1404
|
|
|
1386
1405
|
@tool
|
|
1387
|
-
def list_files(
|
|
1388
|
-
"""List files in
|
|
1406
|
+
def list_files(path: str) -> str:
|
|
1407
|
+
"""List files in a mounted filesystem directory. Use the absolute path (e.g. /mnt/tools)."""
|
|
1389
1408
|
try:
|
|
1390
|
-
|
|
1391
|
-
entries = os.listdir(
|
|
1409
|
+
full_path = _safe_resolve(path)
|
|
1410
|
+
entries = os.listdir(full_path)
|
|
1392
1411
|
return "\\n".join(entries) if entries else "(empty directory)"
|
|
1393
1412
|
except ValueError as e:
|
|
1394
1413
|
return str(e)
|
|
1395
1414
|
except OSError as e:
|
|
1396
|
-
return f"Error listing '{
|
|
1415
|
+
return f"Error listing '{path}': {e.strerror}"
|
|
1397
1416
|
|
|
1398
1417
|
tools.extend([file_read, file_write, list_files])
|
|
1399
1418
|
{{/if}}
|
|
1400
1419
|
|
|
1401
1420
|
SYSTEM_PROMPT = """
|
|
1402
1421
|
You are a helpful assistant. Use tools when appropriate.
|
|
1403
|
-
{{#if
|
|
1404
|
-
You have
|
|
1405
|
-
{{
|
|
1422
|
+
{{#if needsOs}}
|
|
1423
|
+
You have access to the following mounted filesystems. Use file_read, file_write, and list_files with full absolute paths:
|
|
1424
|
+
{{#if sessionStorageMountPath}}- {{sessionStorageMountPath}}: ephemeral session storage (lost when session ends)
|
|
1425
|
+
{{/if}}{{#each efsMounts}}- {{mountPath}}: EFS persistent storage (persists across sessions and agent restarts)
|
|
1426
|
+
{{/each}}{{#each s3Mounts}}- {{mountPath}}: S3 Files persistent storage (durable, backed by S3)
|
|
1427
|
+
{{/each}}{{/if}}
|
|
1406
1428
|
"""
|
|
1407
1429
|
|
|
1408
1430
|
model = load_model()
|
|
@@ -1603,6 +1625,7 @@ dependencies = [
|
|
|
1603
1625
|
{{#if (eq modelProvider "Anthropic")}}"langchain-anthropic >= 0.3.0",
|
|
1604
1626
|
{{/if}}{{#if (eq modelProvider "Bedrock")}}"langchain-aws >= 0.2.0",
|
|
1605
1627
|
{{/if}}{{#if (eq modelProvider "Gemini")}}"langchain-google-genai >= 2.0.0",
|
|
1628
|
+
"google-genai >= 1.0.0, < 2.0.0",
|
|
1606
1629
|
{{/if}}{{#if (eq modelProvider "OpenAI")}}"langchain-openai >= 0.2.0",
|
|
1607
1630
|
{{/if}}"aws-opentelemetry-distro",
|
|
1608
1631
|
"opentelemetry-instrumentation-langchain >= 0.59.0",
|
|
@@ -1695,7 +1718,7 @@ from model.load import load_model
|
|
|
1695
1718
|
{{#if hasMemory}}
|
|
1696
1719
|
from memory.session import get_memory_session_manager
|
|
1697
1720
|
{{/if}}
|
|
1698
|
-
{{#if
|
|
1721
|
+
{{#if needsOs}}
|
|
1699
1722
|
import os
|
|
1700
1723
|
{{/if}}
|
|
1701
1724
|
|
|
@@ -1708,19 +1731,22 @@ def add_numbers(a: int, b: int) -> int:
|
|
|
1708
1731
|
|
|
1709
1732
|
tools = [add_numbers]
|
|
1710
1733
|
|
|
1711
|
-
{{#if
|
|
1712
|
-
|
|
1734
|
+
{{#if needsOs}}
|
|
1735
|
+
_MOUNT_PATHS = [
|
|
1736
|
+
{{#if sessionStorageMountPath}}"{{sessionStorageMountPath}}",{{/if}}
|
|
1737
|
+
{{#each efsMounts}}"{{mountPath}}",{{/each}}
|
|
1738
|
+
{{#each s3Mounts}}"{{mountPath}}",{{/each}}
|
|
1739
|
+
]
|
|
1713
1740
|
|
|
1714
1741
|
def _safe_resolve(path: str) -> str:
|
|
1715
|
-
|
|
1716
|
-
resolved
|
|
1717
|
-
|
|
1718
|
-
raise ValueError(f"Path '{path}' is outside the storage boundary")
|
|
1742
|
+
resolved = os.path.realpath(path)
|
|
1743
|
+
if not any(resolved == os.path.realpath(m) or resolved.startswith(os.path.realpath(m) + os.sep) for m in _MOUNT_PATHS):
|
|
1744
|
+
raise ValueError(f"Path '{path}' is not within any configured mount ({', '.join(_MOUNT_PATHS)})")
|
|
1719
1745
|
return resolved
|
|
1720
1746
|
|
|
1721
1747
|
@tool
|
|
1722
1748
|
def file_read(path: str) -> str:
|
|
1723
|
-
"""Read a file from
|
|
1749
|
+
"""Read a file from a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
1724
1750
|
try:
|
|
1725
1751
|
full_path = _safe_resolve(path)
|
|
1726
1752
|
with open(full_path) as f:
|
|
@@ -1732,7 +1758,7 @@ def file_read(path: str) -> str:
|
|
|
1732
1758
|
|
|
1733
1759
|
@tool
|
|
1734
1760
|
def file_write(path: str, content: str) -> str:
|
|
1735
|
-
"""Write
|
|
1761
|
+
"""Write a file to a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
1736
1762
|
try:
|
|
1737
1763
|
full_path = _safe_resolve(path)
|
|
1738
1764
|
parent = os.path.dirname(full_path)
|
|
@@ -1747,25 +1773,28 @@ def file_write(path: str, content: str) -> str:
|
|
|
1747
1773
|
return f"Error writing '{path}': {e.strerror}"
|
|
1748
1774
|
|
|
1749
1775
|
@tool
|
|
1750
|
-
def list_files(
|
|
1751
|
-
"""List files in
|
|
1776
|
+
def list_files(path: str) -> str:
|
|
1777
|
+
"""List files in a mounted filesystem directory. Use the absolute path (e.g. /mnt/tools)."""
|
|
1752
1778
|
try:
|
|
1753
|
-
|
|
1754
|
-
entries = os.listdir(
|
|
1779
|
+
full_path = _safe_resolve(path)
|
|
1780
|
+
entries = os.listdir(full_path)
|
|
1755
1781
|
return "\\n".join(entries) if entries else "(empty directory)"
|
|
1756
1782
|
except ValueError as e:
|
|
1757
1783
|
return str(e)
|
|
1758
1784
|
except OSError as e:
|
|
1759
|
-
return f"Error listing '{
|
|
1785
|
+
return f"Error listing '{path}': {e.strerror}"
|
|
1760
1786
|
|
|
1761
1787
|
tools.extend([file_read, file_write, list_files])
|
|
1762
1788
|
{{/if}}
|
|
1763
1789
|
|
|
1764
1790
|
SYSTEM_PROMPT = """
|
|
1765
1791
|
You are a helpful assistant. Use tools when appropriate.
|
|
1766
|
-
{{#if
|
|
1767
|
-
You have
|
|
1768
|
-
{{
|
|
1792
|
+
{{#if needsOs}}
|
|
1793
|
+
You have access to the following mounted filesystems. Use file_read, file_write, and list_files with full absolute paths:
|
|
1794
|
+
{{#if sessionStorageMountPath}}- {{sessionStorageMountPath}}: ephemeral session storage (lost when session ends)
|
|
1795
|
+
{{/if}}{{#each efsMounts}}- {{mountPath}}: EFS persistent storage (persists across sessions and agent restarts)
|
|
1796
|
+
{{/each}}{{#each s3Mounts}}- {{mountPath}}: S3 Files persistent storage (durable, backed by S3)
|
|
1797
|
+
{{/each}}{{/if}}
|
|
1769
1798
|
"""
|
|
1770
1799
|
|
|
1771
1800
|
{{#if hasMemory}}
|
|
@@ -2092,16 +2121,76 @@ exports[`Assets Directory Snapshots > Python framework assets > python/python/ag
|
|
|
2092
2121
|
"import os
|
|
2093
2122
|
import uvicorn
|
|
2094
2123
|
from google.adk.agents import LlmAgent
|
|
2124
|
+
from google.adk.tools import FunctionTool
|
|
2095
2125
|
from ag_ui_adk import ADKAgent, AGUIToolset, create_adk_app
|
|
2096
2126
|
from model.load import load_model
|
|
2097
2127
|
|
|
2098
2128
|
load_model()
|
|
2099
2129
|
|
|
2130
|
+
{{#if needsOs}}
|
|
2131
|
+
_MOUNT_PATHS = [
|
|
2132
|
+
{{#if sessionStorageMountPath}}"{{sessionStorageMountPath}}",{{/if}}
|
|
2133
|
+
{{#each efsMounts}}"{{mountPath}}",{{/each}}
|
|
2134
|
+
{{#each s3Mounts}}"{{mountPath}}",{{/each}}
|
|
2135
|
+
]
|
|
2136
|
+
|
|
2137
|
+
def _safe_resolve(path: str) -> str:
|
|
2138
|
+
resolved = os.path.realpath(path)
|
|
2139
|
+
if not any(resolved == os.path.realpath(m) or resolved.startswith(os.path.realpath(m) + os.sep) for m in _MOUNT_PATHS):
|
|
2140
|
+
raise ValueError(f"Path '{path}' is not within any configured mount ({', '.join(_MOUNT_PATHS)})")
|
|
2141
|
+
return resolved
|
|
2142
|
+
|
|
2143
|
+
def file_read(path: str) -> str:
|
|
2144
|
+
"""Read a file from a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
2145
|
+
try:
|
|
2146
|
+
full_path = _safe_resolve(path)
|
|
2147
|
+
with open(full_path) as f:
|
|
2148
|
+
return f.read()
|
|
2149
|
+
except ValueError as e:
|
|
2150
|
+
return str(e)
|
|
2151
|
+
except OSError as e:
|
|
2152
|
+
return f"Error reading '{path}': {e.strerror}"
|
|
2153
|
+
|
|
2154
|
+
def file_write(path: str, content: str) -> str:
|
|
2155
|
+
"""Write a file to a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
2156
|
+
try:
|
|
2157
|
+
full_path = _safe_resolve(path)
|
|
2158
|
+
parent = os.path.dirname(full_path)
|
|
2159
|
+
if parent:
|
|
2160
|
+
os.makedirs(parent, exist_ok=True)
|
|
2161
|
+
with open(full_path, "w") as f:
|
|
2162
|
+
f.write(content)
|
|
2163
|
+
return f"Written to {path}"
|
|
2164
|
+
except ValueError as e:
|
|
2165
|
+
return str(e)
|
|
2166
|
+
except OSError as e:
|
|
2167
|
+
return f"Error writing '{path}': {e.strerror}"
|
|
2168
|
+
|
|
2169
|
+
def list_files(path: str) -> str:
|
|
2170
|
+
"""List files in a mounted filesystem directory. Use the absolute path (e.g. /mnt/tools)."""
|
|
2171
|
+
try:
|
|
2172
|
+
full_path = _safe_resolve(path)
|
|
2173
|
+
entries = os.listdir(full_path)
|
|
2174
|
+
return "\\n".join(entries) if entries else "(empty directory)"
|
|
2175
|
+
except ValueError as e:
|
|
2176
|
+
return str(e)
|
|
2177
|
+
except OSError as e:
|
|
2178
|
+
return f"Error listing '{path}': {e.strerror}"
|
|
2179
|
+
|
|
2180
|
+
_fs_tools = [FunctionTool(file_read), FunctionTool(file_write), FunctionTool(list_files)]
|
|
2181
|
+
{{/if}}
|
|
2182
|
+
|
|
2100
2183
|
agent = LlmAgent(
|
|
2101
2184
|
name="{{ name }}",
|
|
2102
2185
|
model="gemini-2.5-flash",
|
|
2103
|
-
instruction="You are a helpful assistant.
|
|
2104
|
-
|
|
2186
|
+
instruction="""You are a helpful assistant.
|
|
2187
|
+
{{#if needsOs}}
|
|
2188
|
+
You have access to the following mounted filesystems. Use file_read, file_write, and list_files with full absolute paths:
|
|
2189
|
+
{{#if sessionStorageMountPath}}- {{sessionStorageMountPath}}: ephemeral session storage (lost when session ends)
|
|
2190
|
+
{{/if}}{{#each efsMounts}}- {{mountPath}}: EFS persistent storage (persists across sessions and agent restarts)
|
|
2191
|
+
{{/each}}{{#each s3Mounts}}- {{mountPath}}: S3 Files persistent storage (durable, backed by S3)
|
|
2192
|
+
{{/each}}{{/if}}""",
|
|
2193
|
+
tools=[AGUIToolset(), {{#if needsOs}}*_fs_tools{{/if}}],
|
|
2105
2194
|
)
|
|
2106
2195
|
|
|
2107
2196
|
adk_agent = ADKAgent(
|
|
@@ -2190,7 +2279,7 @@ dependencies = [
|
|
|
2190
2279
|
"bedrock-agentcore >= 1.0.3",
|
|
2191
2280
|
"fastapi >= 0.115.12",
|
|
2192
2281
|
"google-adk >= 1.16.0, < 2.0.0",
|
|
2193
|
-
"google-genai >= 1.0.0",
|
|
2282
|
+
"google-genai >= 1.0.0, < 2.0.0",
|
|
2194
2283
|
"opentelemetry-distro",
|
|
2195
2284
|
"opentelemetry-exporter-otlp",
|
|
2196
2285
|
"uvicorn >= 0.34.3",
|
|
@@ -2300,6 +2389,62 @@ def add_numbers(a: int, b: int) -> int:
|
|
|
2300
2389
|
|
|
2301
2390
|
|
|
2302
2391
|
backend_tools = [add_numbers]
|
|
2392
|
+
|
|
2393
|
+
{{#if needsOs}}
|
|
2394
|
+
_MOUNT_PATHS = [
|
|
2395
|
+
{{#if sessionStorageMountPath}}"{{sessionStorageMountPath}}",{{/if}}
|
|
2396
|
+
{{#each efsMounts}}"{{mountPath}}",{{/each}}
|
|
2397
|
+
{{#each s3Mounts}}"{{mountPath}}",{{/each}}
|
|
2398
|
+
]
|
|
2399
|
+
|
|
2400
|
+
def _safe_resolve(path: str) -> str:
|
|
2401
|
+
resolved = os.path.realpath(path)
|
|
2402
|
+
if not any(resolved == os.path.realpath(m) or resolved.startswith(os.path.realpath(m) + os.sep) for m in _MOUNT_PATHS):
|
|
2403
|
+
raise ValueError(f"Path '{path}' is not within any configured mount ({', '.join(_MOUNT_PATHS)})")
|
|
2404
|
+
return resolved
|
|
2405
|
+
|
|
2406
|
+
@tool
|
|
2407
|
+
def file_read(path: str) -> str:
|
|
2408
|
+
"""Read a file from a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
2409
|
+
try:
|
|
2410
|
+
full_path = _safe_resolve(path)
|
|
2411
|
+
with open(full_path) as f:
|
|
2412
|
+
return f.read()
|
|
2413
|
+
except ValueError as e:
|
|
2414
|
+
return str(e)
|
|
2415
|
+
except OSError as e:
|
|
2416
|
+
return f"Error reading '{path}': {e.strerror}"
|
|
2417
|
+
|
|
2418
|
+
@tool
|
|
2419
|
+
def file_write(path: str, content: str) -> str:
|
|
2420
|
+
"""Write a file to a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
2421
|
+
try:
|
|
2422
|
+
full_path = _safe_resolve(path)
|
|
2423
|
+
parent = os.path.dirname(full_path)
|
|
2424
|
+
if parent:
|
|
2425
|
+
os.makedirs(parent, exist_ok=True)
|
|
2426
|
+
with open(full_path, "w") as f:
|
|
2427
|
+
f.write(content)
|
|
2428
|
+
return f"Written to {path}"
|
|
2429
|
+
except ValueError as e:
|
|
2430
|
+
return str(e)
|
|
2431
|
+
except OSError as e:
|
|
2432
|
+
return f"Error writing '{path}': {e.strerror}"
|
|
2433
|
+
|
|
2434
|
+
@tool
|
|
2435
|
+
def list_files(path: str) -> str:
|
|
2436
|
+
"""List files in a mounted filesystem directory. Use the absolute path (e.g. /mnt/tools)."""
|
|
2437
|
+
try:
|
|
2438
|
+
full_path = _safe_resolve(path)
|
|
2439
|
+
entries = os.listdir(full_path)
|
|
2440
|
+
return "\\n".join(entries) if entries else "(empty directory)"
|
|
2441
|
+
except ValueError as e:
|
|
2442
|
+
return str(e)
|
|
2443
|
+
except OSError as e:
|
|
2444
|
+
return f"Error listing '{path}': {e.strerror}"
|
|
2445
|
+
|
|
2446
|
+
backend_tools.extend([file_read, file_write, list_files])
|
|
2447
|
+
{{/if}}
|
|
2303
2448
|
model = load_model()
|
|
2304
2449
|
|
|
2305
2450
|
|
|
@@ -2499,6 +2644,7 @@ dependencies = [
|
|
|
2499
2644
|
{{#if (eq modelProvider "Anthropic")}}"langchain-anthropic >= 0.3.0",
|
|
2500
2645
|
{{/if}}{{#if (eq modelProvider "Bedrock")}}"langchain-aws >= 0.2.0",
|
|
2501
2646
|
{{/if}}{{#if (eq modelProvider "Gemini")}}"langchain-google-genai >= 2.0.0",
|
|
2647
|
+
"google-genai >= 1.0.0, < 2.0.0",
|
|
2502
2648
|
{{/if}}{{#if (eq modelProvider "OpenAI")}}"langchain-openai >= 0.2.0",
|
|
2503
2649
|
{{/if}}"aws-opentelemetry-distro",
|
|
2504
2650
|
"opentelemetry-instrumentation-langchain >= 0.59.0",
|
|
@@ -2611,9 +2757,71 @@ def add_numbers(a: int, b: int) -> int:
|
|
|
2611
2757
|
|
|
2612
2758
|
tools = [add_numbers]
|
|
2613
2759
|
|
|
2760
|
+
{{#if needsOs}}
|
|
2761
|
+
_MOUNT_PATHS = [
|
|
2762
|
+
{{#if sessionStorageMountPath}}"{{sessionStorageMountPath}}",{{/if}}
|
|
2763
|
+
{{#each efsMounts}}"{{mountPath}}",{{/each}}
|
|
2764
|
+
{{#each s3Mounts}}"{{mountPath}}",{{/each}}
|
|
2765
|
+
]
|
|
2766
|
+
|
|
2767
|
+
def _safe_resolve(path: str) -> str:
|
|
2768
|
+
resolved = os.path.realpath(path)
|
|
2769
|
+
if not any(resolved == os.path.realpath(m) or resolved.startswith(os.path.realpath(m) + os.sep) for m in _MOUNT_PATHS):
|
|
2770
|
+
raise ValueError(f"Path '{path}' is not within any configured mount ({', '.join(_MOUNT_PATHS)})")
|
|
2771
|
+
return resolved
|
|
2772
|
+
|
|
2773
|
+
@tool
|
|
2774
|
+
def file_read(path: str) -> str:
|
|
2775
|
+
"""Read a file from a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
2776
|
+
try:
|
|
2777
|
+
full_path = _safe_resolve(path)
|
|
2778
|
+
with open(full_path) as f:
|
|
2779
|
+
return f.read()
|
|
2780
|
+
except ValueError as e:
|
|
2781
|
+
return str(e)
|
|
2782
|
+
except OSError as e:
|
|
2783
|
+
return f"Error reading '{path}': {e.strerror}"
|
|
2784
|
+
|
|
2785
|
+
@tool
|
|
2786
|
+
def file_write(path: str, content: str) -> str:
|
|
2787
|
+
"""Write a file to a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
2788
|
+
try:
|
|
2789
|
+
full_path = _safe_resolve(path)
|
|
2790
|
+
parent = os.path.dirname(full_path)
|
|
2791
|
+
if parent:
|
|
2792
|
+
os.makedirs(parent, exist_ok=True)
|
|
2793
|
+
with open(full_path, "w") as f:
|
|
2794
|
+
f.write(content)
|
|
2795
|
+
return f"Written to {path}"
|
|
2796
|
+
except ValueError as e:
|
|
2797
|
+
return str(e)
|
|
2798
|
+
except OSError as e:
|
|
2799
|
+
return f"Error writing '{path}': {e.strerror}"
|
|
2800
|
+
|
|
2801
|
+
@tool
|
|
2802
|
+
def list_files(path: str) -> str:
|
|
2803
|
+
"""List files in a mounted filesystem directory. Use the absolute path (e.g. /mnt/tools)."""
|
|
2804
|
+
try:
|
|
2805
|
+
full_path = _safe_resolve(path)
|
|
2806
|
+
entries = os.listdir(full_path)
|
|
2807
|
+
return "\\n".join(entries) if entries else "(empty directory)"
|
|
2808
|
+
except ValueError as e:
|
|
2809
|
+
return str(e)
|
|
2810
|
+
except OSError as e:
|
|
2811
|
+
return f"Error listing '{path}': {e.strerror}"
|
|
2812
|
+
|
|
2813
|
+
tools.extend([file_read, file_write, list_files])
|
|
2814
|
+
{{/if}}
|
|
2815
|
+
|
|
2614
2816
|
agent = Agent(
|
|
2615
2817
|
model=load_model(),
|
|
2616
|
-
system_prompt="You are a helpful assistant. Use tools when appropriate.
|
|
2818
|
+
system_prompt="""You are a helpful assistant. Use tools when appropriate.
|
|
2819
|
+
{{#if needsOs}}
|
|
2820
|
+
You have access to the following mounted filesystems. Use file_read, file_write, and list_files with full absolute paths:
|
|
2821
|
+
{{#if sessionStorageMountPath}}- {{sessionStorageMountPath}}: ephemeral session storage (lost when session ends)
|
|
2822
|
+
{{/if}}{{#each efsMounts}}- {{mountPath}}: EFS persistent storage (persists across sessions and agent restarts)
|
|
2823
|
+
{{/each}}{{#each s3Mounts}}- {{mountPath}}: S3 Files persistent storage (durable, backed by S3)
|
|
2824
|
+
{{/each}}{{/if}}""",
|
|
2617
2825
|
tools=tools,
|
|
2618
2826
|
)
|
|
2619
2827
|
|
|
@@ -2938,7 +3146,9 @@ Thumbs.db
|
|
|
2938
3146
|
`;
|
|
2939
3147
|
|
|
2940
3148
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/http/autogen/base/main.py should match snapshot 1`] = `
|
|
2941
|
-
"
|
|
3149
|
+
"{{#if needsOs}}
|
|
3150
|
+
import os
|
|
3151
|
+
{{/if}}
|
|
2942
3152
|
from autogen_agentchat.agents import AssistantAgent
|
|
2943
3153
|
from autogen_core.tools import FunctionTool
|
|
2944
3154
|
from bedrock_agentcore.runtime import BedrockAgentCoreApp
|
|
@@ -2962,18 +3172,21 @@ add_numbers_tool = FunctionTool(
|
|
|
2962
3172
|
# Define a collection of tools used by the model
|
|
2963
3173
|
tools = [add_numbers_tool]
|
|
2964
3174
|
|
|
2965
|
-
{{#if
|
|
2966
|
-
|
|
3175
|
+
{{#if needsOs}}
|
|
3176
|
+
_MOUNT_PATHS = [
|
|
3177
|
+
{{#if sessionStorageMountPath}}"{{sessionStorageMountPath}}",{{/if}}
|
|
3178
|
+
{{#each efsMounts}}"{{mountPath}}",{{/each}}
|
|
3179
|
+
{{#each s3Mounts}}"{{mountPath}}",{{/each}}
|
|
3180
|
+
]
|
|
2967
3181
|
|
|
2968
3182
|
def _safe_resolve(path: str) -> str:
|
|
2969
|
-
|
|
2970
|
-
resolved
|
|
2971
|
-
|
|
2972
|
-
raise ValueError(f"Path '{path}' is outside the storage boundary")
|
|
3183
|
+
resolved = os.path.realpath(path)
|
|
3184
|
+
if not any(resolved == os.path.realpath(m) or resolved.startswith(os.path.realpath(m) + os.sep) for m in _MOUNT_PATHS):
|
|
3185
|
+
raise ValueError(f"Path '{path}' is not within any configured mount ({', '.join(_MOUNT_PATHS)})")
|
|
2973
3186
|
return resolved
|
|
2974
3187
|
|
|
2975
3188
|
def file_read(path: str) -> str:
|
|
2976
|
-
"""Read a file from
|
|
3189
|
+
"""Read a file from a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
2977
3190
|
try:
|
|
2978
3191
|
full_path = _safe_resolve(path)
|
|
2979
3192
|
with open(full_path) as f:
|
|
@@ -2984,7 +3197,7 @@ def file_read(path: str) -> str:
|
|
|
2984
3197
|
return f"Error reading '{path}': {e.strerror}"
|
|
2985
3198
|
|
|
2986
3199
|
def file_write(path: str, content: str) -> str:
|
|
2987
|
-
"""Write
|
|
3200
|
+
"""Write a file to a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
2988
3201
|
try:
|
|
2989
3202
|
full_path = _safe_resolve(path)
|
|
2990
3203
|
parent = os.path.dirname(full_path)
|
|
@@ -2998,29 +3211,32 @@ def file_write(path: str, content: str) -> str:
|
|
|
2998
3211
|
except OSError as e:
|
|
2999
3212
|
return f"Error writing '{path}': {e.strerror}"
|
|
3000
3213
|
|
|
3001
|
-
def list_files(
|
|
3002
|
-
"""List files in
|
|
3214
|
+
def list_files(path: str) -> str:
|
|
3215
|
+
"""List files in a mounted filesystem directory. Use the absolute path (e.g. /mnt/tools)."""
|
|
3003
3216
|
try:
|
|
3004
|
-
|
|
3005
|
-
entries = os.listdir(
|
|
3217
|
+
full_path = _safe_resolve(path)
|
|
3218
|
+
entries = os.listdir(full_path)
|
|
3006
3219
|
return "\\n".join(entries) if entries else "(empty directory)"
|
|
3007
3220
|
except ValueError as e:
|
|
3008
3221
|
return str(e)
|
|
3009
3222
|
except OSError as e:
|
|
3010
|
-
return f"Error listing '{
|
|
3223
|
+
return f"Error listing '{path}': {e.strerror}"
|
|
3011
3224
|
|
|
3012
3225
|
tools.extend([
|
|
3013
|
-
FunctionTool(file_read, description="Read a file from
|
|
3014
|
-
FunctionTool(file_write, description="Write
|
|
3015
|
-
FunctionTool(list_files, description="List files in
|
|
3226
|
+
FunctionTool(file_read, description="Read a file from a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."),
|
|
3227
|
+
FunctionTool(file_write, description="Write a file to a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."),
|
|
3228
|
+
FunctionTool(list_files, description="List files in a mounted filesystem directory. Use the absolute path (e.g. /mnt/tools)."),
|
|
3016
3229
|
])
|
|
3017
3230
|
{{/if}}
|
|
3018
3231
|
|
|
3019
3232
|
SYSTEM_MESSAGE = """
|
|
3020
3233
|
You are a helpful assistant. Use tools when appropriate.
|
|
3021
|
-
{{#if
|
|
3022
|
-
You have
|
|
3023
|
-
{{
|
|
3234
|
+
{{#if needsOs}}
|
|
3235
|
+
You have access to the following mounted filesystems. Use file_read, file_write, and list_files with full absolute paths:
|
|
3236
|
+
{{#if sessionStorageMountPath}}- {{sessionStorageMountPath}}: ephemeral session storage (lost when session ends)
|
|
3237
|
+
{{/if}}{{#each efsMounts}}- {{mountPath}}: EFS persistent storage (persists across sessions and agent restarts)
|
|
3238
|
+
{{/each}}{{#each s3Mounts}}- {{mountPath}}: S3 Files persistent storage (durable, backed by S3)
|
|
3239
|
+
{{/each}}{{/if}}
|
|
3024
3240
|
"""
|
|
3025
3241
|
|
|
3026
3242
|
@app.entrypoint
|
|
@@ -3362,7 +3578,9 @@ Thumbs.db
|
|
|
3362
3578
|
`;
|
|
3363
3579
|
|
|
3364
3580
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/http/googleadk/base/main.py should match snapshot 1`] = `
|
|
3365
|
-
"
|
|
3581
|
+
"{{#if needsOs}}
|
|
3582
|
+
import os
|
|
3583
|
+
{{/if}}
|
|
3366
3584
|
from google.adk.agents import Agent
|
|
3367
3585
|
from google.adk.runners import Runner
|
|
3368
3586
|
from google.adk.sessions import InMemorySessionService
|
|
@@ -3393,18 +3611,21 @@ def add_numbers(a: int, b: int) -> int:
|
|
|
3393
3611
|
# Define a collection of tools used by the model
|
|
3394
3612
|
tools = [add_numbers]
|
|
3395
3613
|
|
|
3396
|
-
{{#if
|
|
3397
|
-
|
|
3614
|
+
{{#if needsOs}}
|
|
3615
|
+
_MOUNT_PATHS = [
|
|
3616
|
+
{{#if sessionStorageMountPath}}"{{sessionStorageMountPath}}",{{/if}}
|
|
3617
|
+
{{#each efsMounts}}"{{mountPath}}",{{/each}}
|
|
3618
|
+
{{#each s3Mounts}}"{{mountPath}}",{{/each}}
|
|
3619
|
+
]
|
|
3398
3620
|
|
|
3399
3621
|
def _safe_resolve(path: str) -> str:
|
|
3400
|
-
|
|
3401
|
-
resolved
|
|
3402
|
-
|
|
3403
|
-
raise ValueError(f"Path '{path}' is outside the storage boundary")
|
|
3622
|
+
resolved = os.path.realpath(path)
|
|
3623
|
+
if not any(resolved == os.path.realpath(m) or resolved.startswith(os.path.realpath(m) + os.sep) for m in _MOUNT_PATHS):
|
|
3624
|
+
raise ValueError(f"Path '{path}' is not within any configured mount ({', '.join(_MOUNT_PATHS)})")
|
|
3404
3625
|
return resolved
|
|
3405
3626
|
|
|
3406
3627
|
def file_read(path: str) -> str:
|
|
3407
|
-
"""Read a file from
|
|
3628
|
+
"""Read a file from a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
3408
3629
|
try:
|
|
3409
3630
|
full_path = _safe_resolve(path)
|
|
3410
3631
|
with open(full_path) as f:
|
|
@@ -3415,7 +3636,7 @@ def file_read(path: str) -> str:
|
|
|
3415
3636
|
return f"Error reading '{path}': {e.strerror}"
|
|
3416
3637
|
|
|
3417
3638
|
def file_write(path: str, content: str) -> str:
|
|
3418
|
-
"""Write
|
|
3639
|
+
"""Write a file to a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
3419
3640
|
try:
|
|
3420
3641
|
full_path = _safe_resolve(path)
|
|
3421
3642
|
parent = os.path.dirname(full_path)
|
|
@@ -3429,25 +3650,28 @@ def file_write(path: str, content: str) -> str:
|
|
|
3429
3650
|
except OSError as e:
|
|
3430
3651
|
return f"Error writing '{path}': {e.strerror}"
|
|
3431
3652
|
|
|
3432
|
-
def list_files(
|
|
3433
|
-
"""List files in
|
|
3653
|
+
def list_files(path: str) -> str:
|
|
3654
|
+
"""List files in a mounted filesystem directory. Use the absolute path (e.g. /mnt/tools)."""
|
|
3434
3655
|
try:
|
|
3435
|
-
|
|
3436
|
-
entries = os.listdir(
|
|
3656
|
+
full_path = _safe_resolve(path)
|
|
3657
|
+
entries = os.listdir(full_path)
|
|
3437
3658
|
return "\\n".join(entries) if entries else "(empty directory)"
|
|
3438
3659
|
except ValueError as e:
|
|
3439
3660
|
return str(e)
|
|
3440
3661
|
except OSError as e:
|
|
3441
|
-
return f"Error listing '{
|
|
3662
|
+
return f"Error listing '{path}': {e.strerror}"
|
|
3442
3663
|
|
|
3443
3664
|
tools.extend([file_read, file_write, list_files])
|
|
3444
3665
|
{{/if}}
|
|
3445
3666
|
|
|
3446
3667
|
AGENT_INSTRUCTION = """
|
|
3447
3668
|
I can answer your questions using the knowledge I have!
|
|
3448
|
-
{{#if
|
|
3449
|
-
You have
|
|
3450
|
-
{{
|
|
3669
|
+
{{#if needsOs}}
|
|
3670
|
+
You have access to the following mounted filesystems. Use file_read, file_write, and list_files with full absolute paths:
|
|
3671
|
+
{{#if sessionStorageMountPath}}- {{sessionStorageMountPath}}: ephemeral session storage (lost when session ends)
|
|
3672
|
+
{{/if}}{{#each efsMounts}}- {{mountPath}}: EFS persistent storage (persists across sessions and agent restarts)
|
|
3673
|
+
{{/each}}{{#each s3Mounts}}- {{mountPath}}: S3 Files persistent storage (durable, backed by S3)
|
|
3674
|
+
{{/each}}{{/if}}
|
|
3451
3675
|
"""
|
|
3452
3676
|
|
|
3453
3677
|
# Get MCP Toolset
|
|
@@ -3674,6 +3898,7 @@ dependencies = [
|
|
|
3674
3898
|
"opentelemetry-distro",
|
|
3675
3899
|
"opentelemetry-exporter-otlp",
|
|
3676
3900
|
"google-adk >= 1.17.0, < 2.0.0",
|
|
3901
|
+
"google-genai >= 1.0.0, < 2.0.0",
|
|
3677
3902
|
"bedrock-agentcore >= 1.0.3",
|
|
3678
3903
|
"botocore[crt] >= 1.35.0",
|
|
3679
3904
|
{{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
|
|
@@ -3774,7 +3999,9 @@ Thumbs.db
|
|
|
3774
3999
|
`;
|
|
3775
4000
|
|
|
3776
4001
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/http/langchain_langgraph/base/main.py should match snapshot 1`] = `
|
|
3777
|
-
"
|
|
4002
|
+
"{{#if needsOs}}
|
|
4003
|
+
import os
|
|
4004
|
+
{{/if}}
|
|
3778
4005
|
from typing import Any
|
|
3779
4006
|
|
|
3780
4007
|
from langchain_core.messages import HumanMessage{{#if hasConfigBundle}}, SystemMessage{{/if}}
|
|
@@ -3809,9 +4036,12 @@ def get_or_create_model():
|
|
|
3809
4036
|
|
|
3810
4037
|
DEFAULT_SYSTEM_PROMPT = """
|
|
3811
4038
|
You are a helpful assistant. Use tools when appropriate.
|
|
3812
|
-
{{#if
|
|
3813
|
-
You have
|
|
3814
|
-
{{
|
|
4039
|
+
{{#if needsOs}}
|
|
4040
|
+
You have access to the following mounted filesystems. Use file_read, file_write, and list_files with full absolute paths:
|
|
4041
|
+
{{#if sessionStorageMountPath}}- {{sessionStorageMountPath}}: ephemeral session storage (lost when session ends)
|
|
4042
|
+
{{/if}}{{#each efsMounts}}- {{mountPath}}: EFS persistent storage (persists across sessions and agent restarts)
|
|
4043
|
+
{{/each}}{{#each s3Mounts}}- {{mountPath}}: S3 Files persistent storage (durable, backed by S3)
|
|
4044
|
+
{{/each}}{{/if}}
|
|
3815
4045
|
"""
|
|
3816
4046
|
|
|
3817
4047
|
|
|
@@ -3825,19 +4055,22 @@ def add_numbers(a: int, b: int) -> int:
|
|
|
3825
4055
|
# Define a collection of tools used by the model
|
|
3826
4056
|
tools = [add_numbers]
|
|
3827
4057
|
|
|
3828
|
-
{{#if
|
|
3829
|
-
|
|
4058
|
+
{{#if needsOs}}
|
|
4059
|
+
_MOUNT_PATHS = [
|
|
4060
|
+
{{#if sessionStorageMountPath}}"{{sessionStorageMountPath}}",{{/if}}
|
|
4061
|
+
{{#each efsMounts}}"{{mountPath}}",{{/each}}
|
|
4062
|
+
{{#each s3Mounts}}"{{mountPath}}",{{/each}}
|
|
4063
|
+
]
|
|
3830
4064
|
|
|
3831
4065
|
def _safe_resolve(path: str) -> str:
|
|
3832
|
-
|
|
3833
|
-
resolved
|
|
3834
|
-
|
|
3835
|
-
raise ValueError(f"Path '{path}' is outside the storage boundary")
|
|
4066
|
+
resolved = os.path.realpath(path)
|
|
4067
|
+
if not any(resolved == os.path.realpath(m) or resolved.startswith(os.path.realpath(m) + os.sep) for m in _MOUNT_PATHS):
|
|
4068
|
+
raise ValueError(f"Path '{path}' is not within any configured mount ({', '.join(_MOUNT_PATHS)})")
|
|
3836
4069
|
return resolved
|
|
3837
4070
|
|
|
3838
4071
|
@tool
|
|
3839
4072
|
def file_read(path: str) -> str:
|
|
3840
|
-
"""Read a file from
|
|
4073
|
+
"""Read a file from a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
3841
4074
|
try:
|
|
3842
4075
|
full_path = _safe_resolve(path)
|
|
3843
4076
|
with open(full_path) as f:
|
|
@@ -3849,7 +4082,7 @@ def file_read(path: str) -> str:
|
|
|
3849
4082
|
|
|
3850
4083
|
@tool
|
|
3851
4084
|
def file_write(path: str, content: str) -> str:
|
|
3852
|
-
"""Write
|
|
4085
|
+
"""Write a file to a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
3853
4086
|
try:
|
|
3854
4087
|
full_path = _safe_resolve(path)
|
|
3855
4088
|
parent = os.path.dirname(full_path)
|
|
@@ -3864,16 +4097,16 @@ def file_write(path: str, content: str) -> str:
|
|
|
3864
4097
|
return f"Error writing '{path}': {e.strerror}"
|
|
3865
4098
|
|
|
3866
4099
|
@tool
|
|
3867
|
-
def list_files(
|
|
3868
|
-
"""List files in
|
|
4100
|
+
def list_files(path: str) -> str:
|
|
4101
|
+
"""List files in a mounted filesystem directory. Use the absolute path (e.g. /mnt/tools)."""
|
|
3869
4102
|
try:
|
|
3870
|
-
|
|
3871
|
-
entries = os.listdir(
|
|
4103
|
+
full_path = _safe_resolve(path)
|
|
4104
|
+
entries = os.listdir(full_path)
|
|
3872
4105
|
return "\\n".join(entries) if entries else "(empty directory)"
|
|
3873
4106
|
except ValueError as e:
|
|
3874
4107
|
return str(e)
|
|
3875
4108
|
except OSError as e:
|
|
3876
|
-
return f"Error listing '{
|
|
4109
|
+
return f"Error listing '{path}': {e.strerror}"
|
|
3877
4110
|
|
|
3878
4111
|
tools.extend([file_read, file_write, list_files])
|
|
3879
4112
|
{{/if}}
|
|
@@ -4202,6 +4435,7 @@ dependencies = [
|
|
|
4202
4435
|
{{/if}}
|
|
4203
4436
|
{{#if (eq modelProvider "Gemini")}}
|
|
4204
4437
|
"langchain-google-genai >= 3.0.3",
|
|
4438
|
+
"google-genai >= 1.0.0, < 2.0.0",
|
|
4205
4439
|
{{/if}}
|
|
4206
4440
|
{{#if hasGateway}}{{#if (includes gatewayAuthTypes "AWS_IAM")}}"mcp-proxy-for-aws >= 1.1.0",
|
|
4207
4441
|
{{/if}}{{/if}}
|
|
@@ -4301,7 +4535,9 @@ Thumbs.db
|
|
|
4301
4535
|
`;
|
|
4302
4536
|
|
|
4303
4537
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/http/openaiagents/base/main.py should match snapshot 1`] = `
|
|
4304
|
-
"
|
|
4538
|
+
"{{#if needsOs}}
|
|
4539
|
+
import os
|
|
4540
|
+
{{/if}}
|
|
4305
4541
|
from agents import Agent, Runner, function_tool
|
|
4306
4542
|
from bedrock_agentcore.runtime import BedrockAgentCoreApp
|
|
4307
4543
|
from model.load import load_model
|
|
@@ -4340,19 +4576,22 @@ def add_numbers(a: int, b: int) -> int:
|
|
|
4340
4576
|
|
|
4341
4577
|
tools = [add_numbers]
|
|
4342
4578
|
|
|
4343
|
-
{{#if
|
|
4344
|
-
|
|
4579
|
+
{{#if needsOs}}
|
|
4580
|
+
_MOUNT_PATHS = [
|
|
4581
|
+
{{#if sessionStorageMountPath}}"{{sessionStorageMountPath}}",{{/if}}
|
|
4582
|
+
{{#each efsMounts}}"{{mountPath}}",{{/each}}
|
|
4583
|
+
{{#each s3Mounts}}"{{mountPath}}",{{/each}}
|
|
4584
|
+
]
|
|
4345
4585
|
|
|
4346
4586
|
def _safe_resolve(path: str) -> str:
|
|
4347
|
-
|
|
4348
|
-
resolved
|
|
4349
|
-
|
|
4350
|
-
raise ValueError(f"Path '{path}' is outside the storage boundary")
|
|
4587
|
+
resolved = os.path.realpath(path)
|
|
4588
|
+
if not any(resolved == os.path.realpath(m) or resolved.startswith(os.path.realpath(m) + os.sep) for m in _MOUNT_PATHS):
|
|
4589
|
+
raise ValueError(f"Path '{path}' is not within any configured mount ({', '.join(_MOUNT_PATHS)})")
|
|
4351
4590
|
return resolved
|
|
4352
4591
|
|
|
4353
4592
|
@function_tool
|
|
4354
4593
|
def file_read(path: str) -> str:
|
|
4355
|
-
"""Read a file from
|
|
4594
|
+
"""Read a file from a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
4356
4595
|
try:
|
|
4357
4596
|
full_path = _safe_resolve(path)
|
|
4358
4597
|
with open(full_path) as f:
|
|
@@ -4364,7 +4603,7 @@ def file_read(path: str) -> str:
|
|
|
4364
4603
|
|
|
4365
4604
|
@function_tool
|
|
4366
4605
|
def file_write(path: str, content: str) -> str:
|
|
4367
|
-
"""Write
|
|
4606
|
+
"""Write a file to a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
4368
4607
|
try:
|
|
4369
4608
|
full_path = _safe_resolve(path)
|
|
4370
4609
|
parent = os.path.dirname(full_path)
|
|
@@ -4379,25 +4618,28 @@ def file_write(path: str, content: str) -> str:
|
|
|
4379
4618
|
return f"Error writing '{path}': {e.strerror}"
|
|
4380
4619
|
|
|
4381
4620
|
@function_tool
|
|
4382
|
-
def list_files(
|
|
4383
|
-
"""List files in
|
|
4621
|
+
def list_files(path: str) -> str:
|
|
4622
|
+
"""List files in a mounted filesystem directory. Use the absolute path (e.g. /mnt/tools)."""
|
|
4384
4623
|
try:
|
|
4385
|
-
|
|
4386
|
-
entries = os.listdir(
|
|
4624
|
+
full_path = _safe_resolve(path)
|
|
4625
|
+
entries = os.listdir(full_path)
|
|
4387
4626
|
return "\\n".join(entries) if entries else "(empty directory)"
|
|
4388
4627
|
except ValueError as e:
|
|
4389
4628
|
return str(e)
|
|
4390
4629
|
except OSError as e:
|
|
4391
|
-
return f"Error listing '{
|
|
4630
|
+
return f"Error listing '{path}': {e.strerror}"
|
|
4392
4631
|
|
|
4393
4632
|
tools.extend([file_read, file_write, list_files])
|
|
4394
4633
|
{{/if}}
|
|
4395
4634
|
|
|
4396
4635
|
INSTRUCTIONS = """
|
|
4397
4636
|
You are a helpful assistant. Use tools when appropriate.
|
|
4398
|
-
{{#if
|
|
4399
|
-
You have
|
|
4400
|
-
{{
|
|
4637
|
+
{{#if needsOs}}
|
|
4638
|
+
You have access to the following mounted filesystems. Use file_read, file_write, and list_files with full absolute paths:
|
|
4639
|
+
{{#if sessionStorageMountPath}}- {{sessionStorageMountPath}}: ephemeral session storage (lost when session ends)
|
|
4640
|
+
{{/if}}{{#each efsMounts}}- {{mountPath}}: EFS persistent storage (persists across sessions and agent restarts)
|
|
4641
|
+
{{/each}}{{#each s3Mounts}}- {{mountPath}}: S3 Files persistent storage (durable, backed by S3)
|
|
4642
|
+
{{/each}}{{/if}}
|
|
4401
4643
|
"""
|
|
4402
4644
|
|
|
4403
4645
|
# Define the agent execution
|
|
@@ -4732,7 +4974,7 @@ from mcp_client.client import get_streamable_http_mcp_client
|
|
|
4732
4974
|
{{#if hasMemory}}
|
|
4733
4975
|
from memory.session import get_memory_session_manager
|
|
4734
4976
|
{{/if}}
|
|
4735
|
-
{{#if
|
|
4977
|
+
{{#if needsOs}}
|
|
4736
4978
|
import os
|
|
4737
4979
|
{{/if}}
|
|
4738
4980
|
|
|
@@ -4748,9 +4990,12 @@ mcp_clients = [get_streamable_http_mcp_client()]
|
|
|
4748
4990
|
|
|
4749
4991
|
DEFAULT_SYSTEM_PROMPT = """
|
|
4750
4992
|
You are a helpful assistant. Use tools when appropriate.
|
|
4751
|
-
{{#if
|
|
4752
|
-
You have
|
|
4753
|
-
{{
|
|
4993
|
+
{{#if needsOs}}
|
|
4994
|
+
You have access to the following mounted filesystems. Use file_read, file_write, and list_files with full absolute paths:
|
|
4995
|
+
{{#if sessionStorageMountPath}}- {{sessionStorageMountPath}}: ephemeral session storage (lost when session ends)
|
|
4996
|
+
{{/if}}{{#each efsMounts}}- {{mountPath}}: EFS persistent storage (persists across sessions and agent restarts)
|
|
4997
|
+
{{/each}}{{#each s3Mounts}}- {{mountPath}}: S3 Files persistent storage (durable, backed by S3)
|
|
4998
|
+
{{/each}}{{/if}}
|
|
4754
4999
|
"""
|
|
4755
5000
|
|
|
4756
5001
|
{{#if hasConfigBundle}}
|
|
@@ -4771,19 +5016,22 @@ def add_numbers(a: int, b: int) -> int:
|
|
|
4771
5016
|
return a+b
|
|
4772
5017
|
tools.append(add_numbers)
|
|
4773
5018
|
|
|
4774
|
-
{{#if
|
|
4775
|
-
|
|
5019
|
+
{{#if needsOs}}
|
|
5020
|
+
_MOUNT_PATHS = [
|
|
5021
|
+
{{#if sessionStorageMountPath}}"{{sessionStorageMountPath}}",{{/if}}
|
|
5022
|
+
{{#each efsMounts}}"{{mountPath}}",{{/each}}
|
|
5023
|
+
{{#each s3Mounts}}"{{mountPath}}",{{/each}}
|
|
5024
|
+
]
|
|
4776
5025
|
|
|
4777
5026
|
def _safe_resolve(path: str) -> str:
|
|
4778
|
-
|
|
4779
|
-
resolved
|
|
4780
|
-
|
|
4781
|
-
raise ValueError(f"Path '{path}' is outside the storage boundary")
|
|
5027
|
+
resolved = os.path.realpath(path)
|
|
5028
|
+
if not any(resolved == os.path.realpath(m) or resolved.startswith(os.path.realpath(m) + os.sep) for m in _MOUNT_PATHS):
|
|
5029
|
+
raise ValueError(f"Path '{path}' is not within any configured mount ({', '.join(_MOUNT_PATHS)})")
|
|
4782
5030
|
return resolved
|
|
4783
5031
|
|
|
4784
5032
|
@tool
|
|
4785
5033
|
def file_read(path: str) -> str:
|
|
4786
|
-
"""Read a file from
|
|
5034
|
+
"""Read a file from a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
4787
5035
|
try:
|
|
4788
5036
|
full_path = _safe_resolve(path)
|
|
4789
5037
|
with open(full_path) as f:
|
|
@@ -4795,7 +5043,7 @@ def file_read(path: str) -> str:
|
|
|
4795
5043
|
|
|
4796
5044
|
@tool
|
|
4797
5045
|
def file_write(path: str, content: str) -> str:
|
|
4798
|
-
"""Write
|
|
5046
|
+
"""Write a file to a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
4799
5047
|
try:
|
|
4800
5048
|
full_path = _safe_resolve(path)
|
|
4801
5049
|
parent = os.path.dirname(full_path)
|
|
@@ -4810,16 +5058,16 @@ def file_write(path: str, content: str) -> str:
|
|
|
4810
5058
|
return f"Error writing '{path}': {e.strerror}"
|
|
4811
5059
|
|
|
4812
5060
|
@tool
|
|
4813
|
-
def list_files(
|
|
4814
|
-
"""List files in
|
|
5061
|
+
def list_files(path: str) -> str:
|
|
5062
|
+
"""List files in a mounted filesystem directory. Use the absolute path (e.g. /mnt/tools)."""
|
|
4815
5063
|
try:
|
|
4816
|
-
|
|
4817
|
-
entries = os.listdir(
|
|
5064
|
+
full_path = _safe_resolve(path)
|
|
5065
|
+
entries = os.listdir(full_path)
|
|
4818
5066
|
return "\\n".join(entries) if entries else "(empty directory)"
|
|
4819
5067
|
except ValueError as e:
|
|
4820
5068
|
return str(e)
|
|
4821
5069
|
except OSError as e:
|
|
4822
|
-
return f"Error listing '{
|
|
5070
|
+
return f"Error listing '{path}': {e.strerror}"
|
|
4823
5071
|
|
|
4824
5072
|
tools.extend([file_read, file_write, list_files])
|
|
4825
5073
|
{{/if}}
|
|
@@ -5317,10 +5565,68 @@ Thumbs.db
|
|
|
5317
5565
|
`;
|
|
5318
5566
|
|
|
5319
5567
|
exports[`Assets Directory Snapshots > Python framework assets > python/python/mcp/standalone/base/main.py should match snapshot 1`] = `
|
|
5320
|
-
"
|
|
5568
|
+
"{{#if needsOs}}
|
|
5569
|
+
import os
|
|
5570
|
+
{{/if}}
|
|
5571
|
+
from mcp.server.fastmcp import FastMCP
|
|
5321
5572
|
|
|
5322
5573
|
mcp = FastMCP("{{ name }}", host="0.0.0.0", stateless_http=True)
|
|
5323
5574
|
|
|
5575
|
+
{{#if needsOs}}
|
|
5576
|
+
_MOUNT_PATHS = [
|
|
5577
|
+
{{#if sessionStorageMountPath}}"{{sessionStorageMountPath}}",{{/if}}
|
|
5578
|
+
{{#each efsMounts}}"{{mountPath}}",{{/each}}
|
|
5579
|
+
{{#each s3Mounts}}"{{mountPath}}",{{/each}}
|
|
5580
|
+
]
|
|
5581
|
+
|
|
5582
|
+
def _safe_resolve(path: str) -> str:
|
|
5583
|
+
resolved = os.path.realpath(path)
|
|
5584
|
+
if not any(resolved == os.path.realpath(m) or resolved.startswith(os.path.realpath(m) + os.sep) for m in _MOUNT_PATHS):
|
|
5585
|
+
raise ValueError(f"Path '{path}' is not within any configured mount ({', '.join(_MOUNT_PATHS)})")
|
|
5586
|
+
return resolved
|
|
5587
|
+
|
|
5588
|
+
@mcp.tool()
|
|
5589
|
+
def file_read(path: str) -> str:
|
|
5590
|
+
"""Read a file from a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
5591
|
+
try:
|
|
5592
|
+
full_path = _safe_resolve(path)
|
|
5593
|
+
with open(full_path) as f:
|
|
5594
|
+
return f.read()
|
|
5595
|
+
except ValueError as e:
|
|
5596
|
+
return str(e)
|
|
5597
|
+
except OSError as e:
|
|
5598
|
+
return f"Error reading '{path}': {e.strerror}"
|
|
5599
|
+
|
|
5600
|
+
@mcp.tool()
|
|
5601
|
+
def file_write(path: str, content: str) -> str:
|
|
5602
|
+
"""Write a file to a mounted filesystem. Use the absolute path (e.g. /mnt/tools/data.txt)."""
|
|
5603
|
+
try:
|
|
5604
|
+
full_path = _safe_resolve(path)
|
|
5605
|
+
parent = os.path.dirname(full_path)
|
|
5606
|
+
if parent:
|
|
5607
|
+
os.makedirs(parent, exist_ok=True)
|
|
5608
|
+
with open(full_path, "w") as f:
|
|
5609
|
+
f.write(content)
|
|
5610
|
+
return f"Written to {path}"
|
|
5611
|
+
except ValueError as e:
|
|
5612
|
+
return str(e)
|
|
5613
|
+
except OSError as e:
|
|
5614
|
+
return f"Error writing '{path}': {e.strerror}"
|
|
5615
|
+
|
|
5616
|
+
@mcp.tool()
|
|
5617
|
+
def list_files(path: str) -> str:
|
|
5618
|
+
"""List files in a mounted filesystem directory. Use the absolute path (e.g. /mnt/tools)."""
|
|
5619
|
+
try:
|
|
5620
|
+
full_path = _safe_resolve(path)
|
|
5621
|
+
entries = os.listdir(full_path)
|
|
5622
|
+
return "\\n".join(entries) if entries else "(empty directory)"
|
|
5623
|
+
except ValueError as e:
|
|
5624
|
+
return str(e)
|
|
5625
|
+
except OSError as e:
|
|
5626
|
+
return f"Error listing '{path}': {e.strerror}"
|
|
5627
|
+
|
|
5628
|
+
{{/if}}
|
|
5629
|
+
|
|
5324
5630
|
|
|
5325
5631
|
@mcp.tool()
|
|
5326
5632
|
def add_numbers(a: int, b: int) -> int:
|