Phase 3: proactive heartbeat — EventBridge 30min rule, heartbeat-runner Lambda, HEARTBEAT_OK suppression
This commit is contained in:
@@ -49,7 +49,7 @@ def _get_base_prompt(actor_id: str = '') -> str:
|
|||||||
else:
|
else:
|
||||||
print(f'[prompt_builder] Failed to load {memory_key}: {e}')
|
print(f'[prompt_builder] Failed to load {memory_key}: {e}')
|
||||||
|
|
||||||
for fname in ['SOUL.md', 'AGENTS.md', 'IDENTITY.md', 'TOOLS.md']:
|
for fname in ['SOUL.md', 'AGENTS.md', 'IDENTITY.md', 'TOOLS.md', 'HEARTBEAT.md']:
|
||||||
try:
|
try:
|
||||||
obj = s3.get_object(Bucket=bucket, Key=fname)
|
obj = s3.get_object(Bucket=bucket, Key=fname)
|
||||||
content = obj['Body'].read().decode('utf-8')
|
content = obj['Body'].read().decode('utf-8')
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -16,16 +16,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"49f9e3ee598c0259165125872304200dbdffee263d76fca541a8630534d8f5c5": {
|
"4f645198a38249aec43db7c3d289ab4896fad437f79e8cfe1ff77fc2e788167c": {
|
||||||
"displayName": "AgentRunner/Code",
|
"displayName": "AgentRunner/Code",
|
||||||
"source": {
|
"source": {
|
||||||
"path": "asset.49f9e3ee598c0259165125872304200dbdffee263d76fca541a8630534d8f5c5",
|
"path": "asset.4f645198a38249aec43db7c3d289ab4896fad437f79e8cfe1ff77fc2e788167c",
|
||||||
"packaging": "zip"
|
"packaging": "zip"
|
||||||
},
|
},
|
||||||
"destinations": {
|
"destinations": {
|
||||||
"495395224548-us-east-1-06bebbe8": {
|
"495395224548-us-east-1-2618668f": {
|
||||||
"bucketName": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
"bucketName": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
||||||
"objectKey": "49f9e3ee598c0259165125872304200dbdffee263d76fca541a8630534d8f5c5.zip",
|
"objectKey": "4f645198a38249aec43db7c3d289ab4896fad437f79e8cfe1ff77fc2e788167c.zip",
|
||||||
"region": "us-east-1",
|
"region": "us-east-1",
|
||||||
"assumeRoleArn": "arn:${AWS::Partition}:iam::495395224548:role/cdk-hnb659fds-file-publishing-role-495395224548-us-east-1"
|
"assumeRoleArn": "arn:${AWS::Partition}:iam::495395224548:role/cdk-hnb659fds-file-publishing-role-495395224548-us-east-1"
|
||||||
}
|
}
|
||||||
@@ -46,6 +46,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"724b3c95c6cd487c828621ad670d23696cd81da614d7df21b846c2d97ef058bf": {
|
||||||
|
"displayName": "HeartbeatRunner/Code",
|
||||||
|
"source": {
|
||||||
|
"path": "asset.724b3c95c6cd487c828621ad670d23696cd81da614d7df21b846c2d97ef058bf",
|
||||||
|
"packaging": "zip"
|
||||||
|
},
|
||||||
|
"destinations": {
|
||||||
|
"495395224548-us-east-1-5e11d898": {
|
||||||
|
"bucketName": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
||||||
|
"objectKey": "724b3c95c6cd487c828621ad670d23696cd81da614d7df21b846c2d97ef058bf.zip",
|
||||||
|
"region": "us-east-1",
|
||||||
|
"assumeRoleArn": "arn:${AWS::Partition}:iam::495395224548:role/cdk-hnb659fds-file-publishing-role-495395224548-us-east-1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"8e7324457a5952eb51f04a34fbc5ba853252e7157d8d8958ac5fda92e72edb1f": {
|
"8e7324457a5952eb51f04a34fbc5ba853252e7157d8d8958ac5fda92e72edb1f": {
|
||||||
"displayName": "Scheduler/Code",
|
"displayName": "Scheduler/Code",
|
||||||
"source": {
|
"source": {
|
||||||
@@ -61,16 +76,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"91a55dffd35b78473e5145ec4ffe46cfbab25239665de853966d1a1d64a186ec": {
|
"f5e50400defa8e717f9f7ae32453df078f55bafc76973f390e22e14616b1eea0": {
|
||||||
"displayName": "AgentClawStack Template",
|
"displayName": "AgentClawStack Template",
|
||||||
"source": {
|
"source": {
|
||||||
"path": "AgentClawStack.template.json",
|
"path": "AgentClawStack.template.json",
|
||||||
"packaging": "file"
|
"packaging": "file"
|
||||||
},
|
},
|
||||||
"destinations": {
|
"destinations": {
|
||||||
"495395224548-us-east-1-27a7d4e2": {
|
"495395224548-us-east-1-c8fd47dc": {
|
||||||
"bucketName": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
"bucketName": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
||||||
"objectKey": "91a55dffd35b78473e5145ec4ffe46cfbab25239665de853966d1a1d64a186ec.json",
|
"objectKey": "f5e50400defa8e717f9f7ae32453df078f55bafc76973f390e22e14616b1eea0.json",
|
||||||
"region": "us-east-1",
|
"region": "us-east-1",
|
||||||
"assumeRoleArn": "arn:${AWS::Partition}:iam::495395224548:role/cdk-hnb659fds-file-publishing-role-495395224548-us-east-1"
|
"assumeRoleArn": "arn:${AWS::Partition}:iam::495395224548:role/cdk-hnb659fds-file-publishing-role-495395224548-us-east-1"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:348:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:373:5)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:352:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:377:5)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:356:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:381:5)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:361:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:386:5)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:366:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:391:5)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:371:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:396:5)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -116,7 +116,7 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:376:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:401:5)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -130,7 +130,7 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:381:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:406:5)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:386:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:411:5)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
{
|
{
|
||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:391:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:416:5)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -199,7 +199,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new Table2 in aws-cdk-lib...",
|
"...new Table2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:60:26)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:62:26)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -214,7 +214,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new Table2 in aws-cdk-lib...",
|
"...new Table2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:69:24)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:71:24)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -229,7 +229,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new Queue2 in aws-cdk-lib...",
|
"...new Queue2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:77:26)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:79:26)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -244,7 +244,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new Function2 in aws-cdk-lib...",
|
"...new Function2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:86:24)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:88:24)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -259,7 +259,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new Function2 in aws-cdk-lib...",
|
"...new Function2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:103:27)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:105:27)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -274,7 +274,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new HttpApi2 in aws-cdk-lib...",
|
"...new HttpApi2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:141:21)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:143:21)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -289,7 +289,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new Role2 in aws-cdk-lib...",
|
"...new Role2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:159:26)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:161:26)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -304,7 +304,52 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new Function2 in aws-cdk-lib...",
|
"...new Function2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:236:28)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:238:28)",
|
||||||
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"/AgentClawStack/HeartbeatRunner/Resource": [
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:logicalId",
|
||||||
|
"data": "HeartbeatRunnerEA31B930"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:creationStack",
|
||||||
|
"data": [
|
||||||
|
"...new Function2 in aws-cdk-lib...",
|
||||||
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:309:31)",
|
||||||
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"/AgentClawStack/HeartbeatRule/Resource": [
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:logicalId",
|
||||||
|
"data": "HeartbeatRuleDCC8D7FB"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:creationStack",
|
||||||
|
"data": [
|
||||||
|
"...new Rule2 in aws-cdk-lib...",
|
||||||
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:325:27)",
|
||||||
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"/AgentClawStack/HeartbeatRule/AllowEventRuleAgentClawStackHeartbeatRunner11988F5B": [
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:logicalId",
|
||||||
|
"data": "HeartbeatRuleAllowEventRuleAgentClawStackHeartbeatRunner11988F5BB95BE86F"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:creationStack",
|
||||||
|
"data": [
|
||||||
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:329:19)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -319,7 +364,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new Function2 in aws-cdk-lib...",
|
"...new Function2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:307:25)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:332:25)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -334,7 +379,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...WrappedClass.addPermission in aws-cdk-lib...",
|
"...WrappedClass.addPermission in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:320:17)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:345:17)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -362,7 +407,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new Function2 in aws-cdk-lib...",
|
"...new Function2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:86:24)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:88:24)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -377,7 +422,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new Function2 in aws-cdk-lib...",
|
"...new Function2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:103:27)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:105:27)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -392,7 +437,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...WrappedClass.addEventSource in aws-cdk-lib...",
|
"...WrappedClass.addEventSource in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:135:19)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:137:19)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -407,7 +452,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new HttpApi2 in aws-cdk-lib...",
|
"...new HttpApi2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:141:21)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:143:21)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -424,7 +469,7 @@
|
|||||||
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
"Array.map (:)",
|
"Array.map (:)",
|
||||||
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:145:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:147:13)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -441,7 +486,7 @@
|
|||||||
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
"Array.map (:)",
|
"Array.map (:)",
|
||||||
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:145:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:147:13)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -458,7 +503,7 @@
|
|||||||
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
"Array.map (:)",
|
"Array.map (:)",
|
||||||
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:272:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:274:13)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -475,7 +520,7 @@
|
|||||||
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
"Array.map (:)",
|
"Array.map (:)",
|
||||||
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:272:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:274:13)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -492,7 +537,7 @@
|
|||||||
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
"Array.map (:)",
|
"Array.map (:)",
|
||||||
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:279:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:281:13)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -509,7 +554,7 @@
|
|||||||
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
"Array.map (:)",
|
"Array.map (:)",
|
||||||
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:279:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:281:13)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -526,7 +571,7 @@
|
|||||||
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
"Array.map (:)",
|
"Array.map (:)",
|
||||||
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:288:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:290:13)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -543,7 +588,7 @@
|
|||||||
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
"Array.map (:)",
|
"Array.map (:)",
|
||||||
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:288:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:290:13)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -558,7 +603,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:163:18)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:165:18)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -573,7 +618,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...environmentFromArn.grantRead in aws-cdk-lib...",
|
"...environmentFromArn.grantRead in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:199:29)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:201:29)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -588,7 +633,22 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new Function2 in aws-cdk-lib...",
|
"...new Function2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:236:28)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:238:28)",
|
||||||
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"/AgentClawStack/HeartbeatRunner/ServiceRole/Resource": [
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:logicalId",
|
||||||
|
"data": "HeartbeatRunnerServiceRole07B33F7E"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:creationStack",
|
||||||
|
"data": [
|
||||||
|
"...new Function2 in aws-cdk-lib...",
|
||||||
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:309:31)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -603,7 +663,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...new Function2 in aws-cdk-lib...",
|
"...new Function2 in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:307:25)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:332:25)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -618,7 +678,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...WrappedClass.grantSendMessages in aws-cdk-lib...",
|
"...WrappedClass.grantSendMessages in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:99:18)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:101:18)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -633,7 +693,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...WrappedClass.grantReadWriteData in aws-cdk-lib...",
|
"...WrappedClass.grantReadWriteData in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:120:18)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:122:18)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -650,7 +710,7 @@
|
|||||||
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
"Array.map (:)",
|
"Array.map (:)",
|
||||||
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:145:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:147:13)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -667,7 +727,7 @@
|
|||||||
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
"Array.map (:)",
|
"Array.map (:)",
|
||||||
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:272:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:274:13)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -684,7 +744,7 @@
|
|||||||
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
"Array.map (:)",
|
"Array.map (:)",
|
||||||
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:279:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:281:13)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -701,7 +761,7 @@
|
|||||||
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
"Array.map (:)",
|
"Array.map (:)",
|
||||||
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:288:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:290:13)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -716,7 +776,22 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...environmentFromArn.grantRead in aws-cdk-lib...",
|
"...environmentFromArn.grantRead in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:251:29)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:253:29)",
|
||||||
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"/AgentClawStack/HeartbeatRunner/ServiceRole/DefaultPolicy/Resource": [
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:logicalId",
|
||||||
|
"data": "HeartbeatRunnerServiceRoleDefaultPolicy08E364EE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:creationStack",
|
||||||
|
"data": [
|
||||||
|
"...WrappedClass.grantSendMessages in aws-cdk-lib...",
|
||||||
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:321:18)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
@@ -731,7 +806,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...environmentFromArn.grantRead in aws-cdk-lib...",
|
"...environmentFromArn.grantRead in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:318:20)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:343:20)",
|
||||||
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
"...node internals, ts-node, ts-node, ts-node..."
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -387,7 +387,7 @@
|
|||||||
"Properties": {
|
"Properties": {
|
||||||
"Code": {
|
"Code": {
|
||||||
"S3Bucket": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
"S3Bucket": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
||||||
"S3Key": "49f9e3ee598c0259165125872304200dbdffee263d76fca541a8630534d8f5c5.zip"
|
"S3Key": "4f645198a38249aec43db7c3d289ab4896fad437f79e8cfe1ff77fc2e788167c.zip"
|
||||||
},
|
},
|
||||||
"Environment": {
|
"Environment": {
|
||||||
"Variables": {
|
"Variables": {
|
||||||
@@ -423,7 +423,7 @@
|
|||||||
],
|
],
|
||||||
"Metadata": {
|
"Metadata": {
|
||||||
"aws:cdk:path": "AgentClawStack/AgentRunner/Resource",
|
"aws:cdk:path": "AgentClawStack/AgentRunner/Resource",
|
||||||
"aws:asset:path": "asset.49f9e3ee598c0259165125872304200dbdffee263d76fca541a8630534d8f5c5",
|
"aws:asset:path": "asset.4f645198a38249aec43db7c3d289ab4896fad437f79e8cfe1ff77fc2e788167c",
|
||||||
"aws:asset:is-bundled": false,
|
"aws:asset:is-bundled": false,
|
||||||
"aws:asset:property": "Code"
|
"aws:asset:property": "Code"
|
||||||
}
|
}
|
||||||
@@ -1199,6 +1199,191 @@
|
|||||||
"aws:asset:property": "Code"
|
"aws:asset:property": "Code"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"HeartbeatRunnerServiceRole07B33F7E": {
|
||||||
|
"Type": "AWS::IAM::Role",
|
||||||
|
"Properties": {
|
||||||
|
"AssumeRolePolicyDocument": {
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Action": "sts:AssumeRole",
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Principal": {
|
||||||
|
"Service": "lambda.amazonaws.com"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Version": "2012-10-17"
|
||||||
|
},
|
||||||
|
"ManagedPolicyArns": [
|
||||||
|
{
|
||||||
|
"Fn::Join": [
|
||||||
|
"",
|
||||||
|
[
|
||||||
|
"arn:",
|
||||||
|
{
|
||||||
|
"Ref": "AWS::Partition"
|
||||||
|
},
|
||||||
|
":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Metadata": {
|
||||||
|
"aws:cdk:path": "AgentClawStack/HeartbeatRunner/ServiceRole/Resource"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"HeartbeatRunnerServiceRoleDefaultPolicy08E364EE": {
|
||||||
|
"Type": "AWS::IAM::Policy",
|
||||||
|
"Properties": {
|
||||||
|
"PolicyDocument": {
|
||||||
|
"Statement": [
|
||||||
|
{
|
||||||
|
"Action": [
|
||||||
|
"sqs:SendMessage",
|
||||||
|
"sqs:GetQueueAttributes",
|
||||||
|
"sqs:GetQueueUrl"
|
||||||
|
],
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Resource": {
|
||||||
|
"Fn::GetAtt": [
|
||||||
|
"MessageQueue7A3BF959",
|
||||||
|
"Arn"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Action": [
|
||||||
|
"dynamodb:BatchGetItem",
|
||||||
|
"dynamodb:Query",
|
||||||
|
"dynamodb:GetItem",
|
||||||
|
"dynamodb:Scan",
|
||||||
|
"dynamodb:ConditionCheckItem",
|
||||||
|
"dynamodb:DescribeTable"
|
||||||
|
],
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Resource": [
|
||||||
|
{
|
||||||
|
"Fn::GetAtt": [
|
||||||
|
"UsersTable9725E9C8",
|
||||||
|
"Arn"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Action": [
|
||||||
|
"dynamodb:GetRecords",
|
||||||
|
"dynamodb:GetShardIterator"
|
||||||
|
],
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Resource": [
|
||||||
|
{
|
||||||
|
"Fn::GetAtt": [
|
||||||
|
"UsersTable9725E9C8",
|
||||||
|
"Arn"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Version": "2012-10-17"
|
||||||
|
},
|
||||||
|
"PolicyName": "HeartbeatRunnerServiceRoleDefaultPolicy08E364EE",
|
||||||
|
"Roles": [
|
||||||
|
{
|
||||||
|
"Ref": "HeartbeatRunnerServiceRole07B33F7E"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Metadata": {
|
||||||
|
"aws:cdk:path": "AgentClawStack/HeartbeatRunner/ServiceRole/DefaultPolicy/Resource"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"HeartbeatRunnerEA31B930": {
|
||||||
|
"Type": "AWS::Lambda::Function",
|
||||||
|
"Properties": {
|
||||||
|
"Code": {
|
||||||
|
"S3Bucket": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
||||||
|
"S3Key": "724b3c95c6cd487c828621ad670d23696cd81da614d7df21b846c2d97ef058bf.zip"
|
||||||
|
},
|
||||||
|
"Environment": {
|
||||||
|
"Variables": {
|
||||||
|
"MESSAGE_QUEUE_URL": {
|
||||||
|
"Ref": "MessageQueue7A3BF959"
|
||||||
|
},
|
||||||
|
"USERS_TABLE_NAME": {
|
||||||
|
"Ref": "UsersTable9725E9C8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"FunctionName": "agent-claw-heartbeat-runner",
|
||||||
|
"Handler": "handler.handler",
|
||||||
|
"MemorySize": 128,
|
||||||
|
"Role": {
|
||||||
|
"Fn::GetAtt": [
|
||||||
|
"HeartbeatRunnerServiceRole07B33F7E",
|
||||||
|
"Arn"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Runtime": "python3.12",
|
||||||
|
"Timeout": 60
|
||||||
|
},
|
||||||
|
"DependsOn": [
|
||||||
|
"HeartbeatRunnerServiceRoleDefaultPolicy08E364EE",
|
||||||
|
"HeartbeatRunnerServiceRole07B33F7E"
|
||||||
|
],
|
||||||
|
"Metadata": {
|
||||||
|
"aws:cdk:path": "AgentClawStack/HeartbeatRunner/Resource",
|
||||||
|
"aws:asset:path": "asset.724b3c95c6cd487c828621ad670d23696cd81da614d7df21b846c2d97ef058bf",
|
||||||
|
"aws:asset:is-bundled": false,
|
||||||
|
"aws:asset:property": "Code"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"HeartbeatRuleDCC8D7FB": {
|
||||||
|
"Type": "AWS::Events::Rule",
|
||||||
|
"Properties": {
|
||||||
|
"Name": "agent-claw-heartbeat",
|
||||||
|
"ScheduleExpression": "rate(30 minutes)",
|
||||||
|
"State": "ENABLED",
|
||||||
|
"Targets": [
|
||||||
|
{
|
||||||
|
"Arn": {
|
||||||
|
"Fn::GetAtt": [
|
||||||
|
"HeartbeatRunnerEA31B930",
|
||||||
|
"Arn"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Id": "Target0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Metadata": {
|
||||||
|
"aws:cdk:path": "AgentClawStack/HeartbeatRule/Resource"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"HeartbeatRuleAllowEventRuleAgentClawStackHeartbeatRunner11988F5BB95BE86F": {
|
||||||
|
"Type": "AWS::Lambda::Permission",
|
||||||
|
"Properties": {
|
||||||
|
"Action": "lambda:InvokeFunction",
|
||||||
|
"FunctionName": {
|
||||||
|
"Fn::GetAtt": [
|
||||||
|
"HeartbeatRunnerEA31B930",
|
||||||
|
"Arn"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Principal": "events.amazonaws.com",
|
||||||
|
"SourceArn": {
|
||||||
|
"Fn::GetAtt": [
|
||||||
|
"HeartbeatRuleDCC8D7FB",
|
||||||
|
"Arn"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Metadata": {
|
||||||
|
"aws:cdk:path": "AgentClawStack/HeartbeatRule/AllowEventRuleAgentClawStackHeartbeatRunner11988F5B"
|
||||||
|
}
|
||||||
|
},
|
||||||
"SchedulerServiceRole62CDA70C": {
|
"SchedulerServiceRole62CDA70C": {
|
||||||
"Type": "AWS::IAM::Role",
|
"Type": "AWS::IAM::Role",
|
||||||
"Properties": {
|
"Properties": {
|
||||||
@@ -1323,7 +1508,7 @@
|
|||||||
"CDKMetadata": {
|
"CDKMetadata": {
|
||||||
"Type": "AWS::CDK::Metadata",
|
"Type": "AWS::CDK::Metadata",
|
||||||
"Properties": {
|
"Properties": {
|
||||||
"Analytics": "v2:deflate64:H4sIAAAAAAAA/22PwU7DMAyGn2X31IxuPMCGQHBAjI775KZela1NSu1sqqK8O0rKOCBO/+ff+WO7hPKhhOUCr1zo5lx0poawF9RnVRE7P2pSeOVD4BVsvT6TbJFJNZPF3jU1hE+sO1KPR5shKv5iCB+efDYzRNVhXzcI4dlbLcbZ1PrlpwtZ2edRbzgMxrap/b+7o7E3zCl2y6d9ojLYQ6jcvErWneuMnnIoU1S8OiAzCcMmicLBtCh0xelSQngRGTaDSYEkqdwLtvnDGZJVOS8zvVqhdsTbOX/K/C5GlSel+M8B714GL1FZ1xCc+O5SruF+DcvFiY0pRm/F9ATVrN8RDS1cnQEAAA=="
|
"Analytics": "v2:deflate64:H4sIAAAAAAAA/21Py07DMBD8lt6dpaTlA1oEggOiJNyrTbJEbhM7ZNeNIsv/juy0HBCnmX3M7kwO+UMO6xVOnNXNOet0Bb4UrM+qILZurEnhxEfPG9i7+kyyRybVzAZ721TgP7HqSD1+mUSC4m8G/+HIpWYiQXXYVw2Cf3amFm1NHP3ypwsZKdOrNxwGbdo4/r97oLHXzFF200c/QWnswRd2sZLwYDtdz0mUWFC8OSIzCcMugsJBtyg04XzJwb+IDLtBR0GEWJaCbTq4kNgqrJOFvRqhdsRbnD9l2guKYgoGX7irM9dRCCr9j0evsd6dDE6CMrYhOPHdJd/C/RbWqxNrnY3OiO4JigV/AIxrt6WzAQAA"
|
||||||
},
|
},
|
||||||
"Metadata": {
|
"Metadata": {
|
||||||
"aws:cdk:path": "AgentClawStack/CDKMetadata/Default"
|
"aws:cdk:path": "AgentClawStack/CDKMetadata/Default"
|
||||||
|
|||||||
@@ -0,0 +1,272 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import uuid
|
||||||
|
import boto3
|
||||||
|
import urllib.request
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
# AWS clients
|
||||||
|
_ddb = None
|
||||||
|
_agentcore = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_ddb():
|
||||||
|
global _ddb
|
||||||
|
if _ddb is None:
|
||||||
|
_ddb = boto3.resource('dynamodb')
|
||||||
|
return _ddb
|
||||||
|
|
||||||
|
|
||||||
|
def get_agentcore():
|
||||||
|
global _agentcore
|
||||||
|
if _agentcore is None:
|
||||||
|
from botocore.config import Config
|
||||||
|
_agentcore = boto3.client(
|
||||||
|
'bedrock-agentcore',
|
||||||
|
region_name='us-east-1',
|
||||||
|
config=Config(read_timeout=600, connect_timeout=10)
|
||||||
|
)
|
||||||
|
return _agentcore
|
||||||
|
|
||||||
|
|
||||||
|
def get_or_create_user(actor_id: str, from_info: dict) -> dict:
|
||||||
|
"""Look up user in registry, auto-registering on first contact."""
|
||||||
|
table_name = os.environ.get('USERS_TABLE_NAME', '')
|
||||||
|
if not table_name:
|
||||||
|
return {'actor_id': actor_id, 'display_name': from_info.get('from_name', actor_id)}
|
||||||
|
table = get_ddb().Table(table_name)
|
||||||
|
response = table.get_item(Key={'actor_id': actor_id})
|
||||||
|
item = response.get('Item')
|
||||||
|
if item:
|
||||||
|
return item
|
||||||
|
now = int(time.time())
|
||||||
|
item = {
|
||||||
|
'actor_id': actor_id,
|
||||||
|
'display_name': from_info.get('from_name') or actor_id,
|
||||||
|
'telegram_username': from_info.get('from_username', ''),
|
||||||
|
'created_at': str(now),
|
||||||
|
'status': 'pending',
|
||||||
|
'services': {},
|
||||||
|
}
|
||||||
|
table.put_item(Item=item)
|
||||||
|
print(f'[agent-runner] Registered new user (pending): {actor_id}')
|
||||||
|
return item
|
||||||
|
|
||||||
|
|
||||||
|
def update_user_status(actor_id: str, name: str, status: str) -> None:
|
||||||
|
table_name = os.environ.get('USERS_TABLE_NAME', '')
|
||||||
|
if not table_name:
|
||||||
|
return
|
||||||
|
table = get_ddb().Table(table_name)
|
||||||
|
table.update_item(
|
||||||
|
Key={'actor_id': actor_id},
|
||||||
|
UpdateExpression='SET display_name = :n, #s = :s',
|
||||||
|
ExpressionAttributeNames={'#s': 'status'},
|
||||||
|
ExpressionAttributeValues={':n': name, ':s': status},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Per-invocation dedup: track sent message hashes to prevent AgentCore retry duplicates
|
||||||
|
_sent_hashes: set = set()
|
||||||
|
|
||||||
|
|
||||||
|
def send_telegram_direct(chat_id: str, token: str, text: str) -> None:
|
||||||
|
import hashlib
|
||||||
|
h = hashlib.md5(f'{chat_id}:{text}'.encode()).hexdigest()[:12]
|
||||||
|
if h in _sent_hashes:
|
||||||
|
print(f'[agent-runner] dedup: skipping duplicate message (hash={h})')
|
||||||
|
return
|
||||||
|
_sent_hashes.add(h)
|
||||||
|
url = f'https://api.telegram.org/bot{token}/sendMessage'
|
||||||
|
data = json.dumps({'chat_id': chat_id, 'text': text}).encode()
|
||||||
|
req = urllib.request.Request(url, data=data, headers={'Content-Type': 'application/json'})
|
||||||
|
try:
|
||||||
|
resp = urllib.request.urlopen(req, timeout=10)
|
||||||
|
resp_body = resp.read()
|
||||||
|
import re
|
||||||
|
msg_id = re.search(r'"message_id":(\d+)', resp_body.decode('utf-8', errors='replace'))
|
||||||
|
print(f'[agent-runner] Telegram sendMessage -> msg_id={msg_id.group(1) if msg_id else "?"} hash={h}')
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[agent-runner] Telegram sendMessage FAILED: {type(e).__name__}: {e} hash={h}')
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def get_or_create_session(actor_id: str) -> str:
|
||||||
|
"""Look up active session for actor, or create a new one."""
|
||||||
|
table = get_ddb().Table(os.environ['SESSION_TABLE_NAME'])
|
||||||
|
|
||||||
|
response = table.get_item(Key={'actor_id': actor_id})
|
||||||
|
item = response.get('Item')
|
||||||
|
|
||||||
|
now = int(time.time())
|
||||||
|
ttl_8hr = now + (8 * 3600)
|
||||||
|
|
||||||
|
if item and item.get('ttl', 0) > now:
|
||||||
|
# Active session exists — extend TTL
|
||||||
|
table.update_item(
|
||||||
|
Key={'actor_id': actor_id},
|
||||||
|
UpdateExpression='SET #ttl = :ttl',
|
||||||
|
ExpressionAttributeNames={'#ttl': 'ttl'},
|
||||||
|
ExpressionAttributeValues={':ttl': ttl_8hr},
|
||||||
|
)
|
||||||
|
return item['session_id']
|
||||||
|
|
||||||
|
# Create new session
|
||||||
|
session_id = str(uuid.uuid4())
|
||||||
|
table.put_item(Item={
|
||||||
|
'actor_id': actor_id,
|
||||||
|
'session_id': session_id,
|
||||||
|
'created_at': str(now),
|
||||||
|
'ttl': ttl_8hr,
|
||||||
|
})
|
||||||
|
return session_id
|
||||||
|
|
||||||
|
|
||||||
|
def handler(event, context):
|
||||||
|
# ── Parse SQS records (FIFO — all from same actor) ───────────────────
|
||||||
|
records = []
|
||||||
|
for record in event.get('Records', []):
|
||||||
|
try:
|
||||||
|
records.append(json.loads(record['body']))
|
||||||
|
except (json.JSONDecodeError, KeyError):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not records:
|
||||||
|
return
|
||||||
|
|
||||||
|
first = records[0]
|
||||||
|
channel = first.get('channel', 'telegram')
|
||||||
|
chat_id = first.get('chat_id', '')
|
||||||
|
actor_id = f"{channel}:{chat_id}"
|
||||||
|
|
||||||
|
# ── User registry ─────────────────────────────────────────────────────
|
||||||
|
from_info = first.get('messages', [{}])[0]
|
||||||
|
user_profile = get_or_create_user(actor_id, from_info)
|
||||||
|
|
||||||
|
# ── Onboarding gate ─────────────────────────────────────────────────────
|
||||||
|
table_name = os.environ.get('USERS_TABLE_NAME', '')
|
||||||
|
if table_name and user_profile.get('status', 'active') == 'pending':
|
||||||
|
raw_prompt = records[0]['messages'][0]['text'] if records else ''
|
||||||
|
is_name_msg = bool(raw_prompt and len(raw_prompt.strip()) < 50 and '?' not in raw_prompt)
|
||||||
|
if is_name_msg:
|
||||||
|
name = raw_prompt.strip()
|
||||||
|
update_user_status(actor_id, name=name, status='active')
|
||||||
|
user_profile['display_name'] = name
|
||||||
|
user_profile['status'] = 'active'
|
||||||
|
prompt = f"[System: User just registered with name '{name}'. Welcome them warmly and ask how you can help.]"
|
||||||
|
else:
|
||||||
|
bot_token_secret_arn = os.environ.get('TELEGRAM_BOT_TOKEN_SECRET_ARN', '')
|
||||||
|
bot_token = ''
|
||||||
|
if bot_token_secret_arn:
|
||||||
|
sm = boto3.client('secretsmanager', region_name='us-east-1')
|
||||||
|
bot_token = sm.get_secret_value(SecretId=bot_token_secret_arn)['SecretString']
|
||||||
|
send_telegram_direct(chat_id, bot_token, "Hi! I don't recognize you yet. What's your name?")
|
||||||
|
return
|
||||||
|
# ── Get or create AgentCore session ──────────────────────────────────
|
||||||
|
session_id = get_or_create_session(actor_id)
|
||||||
|
print(f"[agent-runner] actor={actor_id} session={session_id} user={user_profile.get('display_name', '')}")
|
||||||
|
|
||||||
|
# ── Bundle messages ───────────────────────────────────────────────────
|
||||||
|
if len(records) == 1:
|
||||||
|
prompt = records[0]['messages'][0]['text']
|
||||||
|
else:
|
||||||
|
lines = [
|
||||||
|
f"[{i+1}] {r['messages'][0]['text']}"
|
||||||
|
for i, r in enumerate(records)
|
||||||
|
]
|
||||||
|
prompt = f"You have {len(records)} queued messages:\n" + "\n".join(lines)
|
||||||
|
|
||||||
|
# ── Build payload for AgentCore Runtime 1 ────────────────────────────
|
||||||
|
payload: dict[str, Any] = {
|
||||||
|
'prompt': prompt,
|
||||||
|
'actor_id': actor_id,
|
||||||
|
'session_id': session_id,
|
||||||
|
'user_profile': {
|
||||||
|
'display_name': user_profile.get('display_name', actor_id),
|
||||||
|
'telegram_username': user_profile.get('telegram_username', ''),
|
||||||
|
'google_email': user_profile.get('google_email', ''),
|
||||||
|
'allowed': user_profile.get('allowed', True),
|
||||||
|
'services': user_profile.get('enrolled_services', user_profile.get('services', {})),
|
||||||
|
},
|
||||||
|
'channel_adapter': {
|
||||||
|
'type': channel,
|
||||||
|
'target_id': str(chat_id),
|
||||||
|
'bot_token_secret_arn': os.environ.get('TELEGRAM_BOT_TOKEN_SECRET_ARN', ''),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Invoke AgentCore Runtime 1 ────────────────────────────────────────
|
||||||
|
runtime_arn = os.environ.get('RUNTIME_1_ARN', '')
|
||||||
|
if not runtime_arn or runtime_arn == 'PLACEHOLDER_SET_AFTER_RUNTIME_DEPLOY':
|
||||||
|
print(f"[agent-runner] RUNTIME_1_ARN not set — skipping AgentCore invoke")
|
||||||
|
print(f"[agent-runner] Would have sent: {json.dumps(payload)[:200]}")
|
||||||
|
return
|
||||||
|
|
||||||
|
client = get_agentcore()
|
||||||
|
response = client.invoke_agent_runtime(
|
||||||
|
agentRuntimeArn=runtime_arn,
|
||||||
|
runtimeSessionId=session_id,
|
||||||
|
payload=json.dumps(payload).encode(),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Process streaming response: buffer text chunks and send to Telegram as paragraphs arrive
|
||||||
|
bot_token = ''
|
||||||
|
bot_token_secret_arn = os.environ.get('TELEGRAM_BOT_TOKEN_SECRET_ARN', '')
|
||||||
|
if bot_token_secret_arn:
|
||||||
|
sm = boto3.client('secretsmanager', region_name='us-east-1')
|
||||||
|
try:
|
||||||
|
bot_token = sm.get_secret_value(SecretId=bot_token_secret_arn)['SecretString']
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[agent-runner] Failed to get bot token: {e}')
|
||||||
|
|
||||||
|
body = response.get('response')
|
||||||
|
text_buffer = ''
|
||||||
|
leftover = ''
|
||||||
|
if body is not None:
|
||||||
|
for raw_chunk in body.iter_chunks():
|
||||||
|
if not raw_chunk:
|
||||||
|
continue
|
||||||
|
# AgentCore streams SSE format: "data: {...}\n\n"
|
||||||
|
text = leftover + raw_chunk.decode('utf-8', errors='replace')
|
||||||
|
parts = text.split('\n\n')
|
||||||
|
leftover = parts[-1]
|
||||||
|
for part in parts[:-1]:
|
||||||
|
for line in part.splitlines():
|
||||||
|
if not line.startswith('data: '):
|
||||||
|
continue
|
||||||
|
data = line[6:].strip()
|
||||||
|
if not data or data == '[DONE]':
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
event = json.loads(data)
|
||||||
|
except (json.JSONDecodeError, ValueError):
|
||||||
|
continue
|
||||||
|
if not isinstance(event, dict):
|
||||||
|
continue
|
||||||
|
# Extract text delta from contentBlockDelta ONLY
|
||||||
|
# Do NOT use event.get('data') — that's the full formatted summary,
|
||||||
|
# causing duplicate delivery alongside the token stream.
|
||||||
|
delta = event.get('event', {}).get('contentBlockDelta', {}).get('delta', {})
|
||||||
|
if not isinstance(delta, dict):
|
||||||
|
continue
|
||||||
|
token = delta.get('text', '')
|
||||||
|
if token:
|
||||||
|
text_buffer += token
|
||||||
|
# Only flush if buffer is very large — prevents splitting multi-turn responses
|
||||||
|
if len(text_buffer) > 1200:
|
||||||
|
print(f'[agent-runner] send chunk {len(text_buffer)}c to {chat_id}')
|
||||||
|
send_telegram_direct(str(chat_id), bot_token, text_buffer.strip())
|
||||||
|
text_buffer = ''
|
||||||
|
|
||||||
|
# Flush any remaining text
|
||||||
|
print(f'[agent-runner] stream done buffer={len(text_buffer)} bot_token_set={bool(bot_token)}')
|
||||||
|
if text_buffer.strip() and bot_token:
|
||||||
|
# Suppress heartbeat OK responses
|
||||||
|
if text_buffer.strip().upper().startswith('HEARTBEAT_OK'):
|
||||||
|
print(f'[agent-runner] heartbeat suppressed for {actor_id}')
|
||||||
|
return
|
||||||
|
print(f'[agent-runner] flushing {len(text_buffer)}c to {chat_id}')
|
||||||
|
send_telegram_direct(str(chat_id), bot_token, text_buffer.strip())
|
||||||
|
|
||||||
|
print(f"[agent-runner] Completed session={session_id} actor={actor_id}")
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
boto3>=1.34.0
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
_ddb = None
|
||||||
|
_sqs = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_ddb():
|
||||||
|
global _ddb
|
||||||
|
if _ddb is None:
|
||||||
|
_ddb = boto3.resource('dynamodb')
|
||||||
|
return _ddb
|
||||||
|
|
||||||
|
|
||||||
|
def get_sqs():
|
||||||
|
global _sqs
|
||||||
|
if _sqs is None:
|
||||||
|
_sqs = boto3.client('sqs')
|
||||||
|
return _sqs
|
||||||
|
|
||||||
|
|
||||||
|
def handler(event, context):
|
||||||
|
table_name = os.environ['USERS_TABLE_NAME']
|
||||||
|
queue_url = os.environ['MESSAGE_QUEUE_URL']
|
||||||
|
|
||||||
|
# Scan for active users
|
||||||
|
table = get_ddb().Table(table_name)
|
||||||
|
response = table.scan(
|
||||||
|
FilterExpression='#s = :active',
|
||||||
|
ExpressionAttributeNames={'#s': 'status'},
|
||||||
|
ExpressionAttributeValues={':active': 'active'},
|
||||||
|
)
|
||||||
|
users = response.get('Items', [])
|
||||||
|
|
||||||
|
# 30-min bucket for deduplication
|
||||||
|
bucket_ts = str(int(time.time()) // 1800)
|
||||||
|
sqs = get_sqs()
|
||||||
|
|
||||||
|
sent = 0
|
||||||
|
for user in users:
|
||||||
|
actor_id = user['actor_id']
|
||||||
|
# Extract chat_id from actor_id (format: "telegram:<chat_id>")
|
||||||
|
if not actor_id.startswith('telegram:'):
|
||||||
|
continue
|
||||||
|
chat_id = actor_id.split(':', 1)[1]
|
||||||
|
|
||||||
|
msg = {
|
||||||
|
'chat_id': chat_id,
|
||||||
|
'channel': 'telegram',
|
||||||
|
'messages': [{
|
||||||
|
'text': '[HEARTBEAT]',
|
||||||
|
'from_name': user.get('display_name', ''),
|
||||||
|
'from_username': user.get('telegram_username', ''),
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
|
||||||
|
sqs.send_message(
|
||||||
|
QueueUrl=queue_url,
|
||||||
|
MessageBody=json.dumps(msg),
|
||||||
|
MessageGroupId=actor_id,
|
||||||
|
MessageDeduplicationId=f'heartbeat-{actor_id}-{bucket_ts}',
|
||||||
|
)
|
||||||
|
sent += 1
|
||||||
|
|
||||||
|
print(f'[heartbeat-runner] Sent {sent} heartbeat messages')
|
||||||
|
return {'statusCode': 200, 'sent': sent}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
boto3>=1.34.0
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
"validateOnSynth": false,
|
"validateOnSynth": false,
|
||||||
"assumeRoleArn": "arn:${AWS::Partition}:iam::495395224548:role/cdk-hnb659fds-deploy-role-495395224548-us-east-1",
|
"assumeRoleArn": "arn:${AWS::Partition}:iam::495395224548:role/cdk-hnb659fds-deploy-role-495395224548-us-east-1",
|
||||||
"cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::495395224548:role/cdk-hnb659fds-cfn-exec-role-495395224548-us-east-1",
|
"cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::495395224548:role/cdk-hnb659fds-cfn-exec-role-495395224548-us-east-1",
|
||||||
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-495395224548-us-east-1/91a55dffd35b78473e5145ec4ffe46cfbab25239665de853966d1a1d64a186ec.json",
|
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-495395224548-us-east-1/f5e50400defa8e717f9f7ae32453df078f55bafc76973f390e22e14616b1eea0.json",
|
||||||
"requiresBootstrapStackVersion": 6,
|
"requiresBootstrapStackVersion": 6,
|
||||||
"bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version",
|
"bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version",
|
||||||
"additionalDependencies": [
|
"additionalDependencies": [
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -8,6 +8,8 @@ import * as apigatewayv2 from 'aws-cdk-lib/aws-apigatewayv2';
|
|||||||
import * as apigatewayv2integrations from 'aws-cdk-lib/aws-apigatewayv2-integrations';
|
import * as apigatewayv2integrations from 'aws-cdk-lib/aws-apigatewayv2-integrations';
|
||||||
import * as iam from 'aws-cdk-lib/aws-iam';
|
import * as iam from 'aws-cdk-lib/aws-iam';
|
||||||
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
|
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
|
||||||
|
import * as events from 'aws-cdk-lib/aws-events';
|
||||||
|
import * as eventsTargets from 'aws-cdk-lib/aws-events-targets';
|
||||||
import { SqsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';
|
import { SqsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';
|
||||||
import { Construct } from 'constructs';
|
import { Construct } from 'constructs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
@@ -303,6 +305,29 @@ export class AgentClawStack extends cdk.Stack {
|
|||||||
// Output the URL so it can be manually set in agentcore.json OAUTH_START_URL.
|
// Output the URL so it can be manually set in agentcore.json OAUTH_START_URL.
|
||||||
|
|
||||||
|
|
||||||
|
// ── Lambda: heartbeat-runner ──────────────────────────────────────────
|
||||||
|
const heartbeatRunnerFn = new lambda.Function(this, 'HeartbeatRunner', {
|
||||||
|
functionName: 'agent-claw-heartbeat-runner',
|
||||||
|
runtime: lambda.Runtime.PYTHON_3_12,
|
||||||
|
handler: 'handler.handler',
|
||||||
|
code: lambda.Code.fromAsset(path.join(__dirname, '../../src/lambdas/heartbeat-runner')),
|
||||||
|
timeout: cdk.Duration.seconds(60),
|
||||||
|
memorySize: 128,
|
||||||
|
environment: {
|
||||||
|
MESSAGE_QUEUE_URL: messageQueue.queueUrl,
|
||||||
|
USERS_TABLE_NAME: usersTable.tableName,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
messageQueue.grantSendMessages(heartbeatRunnerFn);
|
||||||
|
usersTable.grantReadData(heartbeatRunnerFn);
|
||||||
|
|
||||||
|
// EventBridge rule: every 30 minutes
|
||||||
|
const heartbeatRule = new events.Rule(this, 'HeartbeatRule', {
|
||||||
|
ruleName: 'agent-claw-heartbeat',
|
||||||
|
schedule: events.Schedule.rate(cdk.Duration.minutes(30)),
|
||||||
|
});
|
||||||
|
heartbeatRule.addTarget(new eventsTargets.LambdaFunction(heartbeatRunnerFn));
|
||||||
|
|
||||||
// ── Lambda: scheduler ─────────────────────────────────────────────────
|
// ── Lambda: scheduler ─────────────────────────────────────────────────
|
||||||
const schedulerFn = new lambda.Function(this, 'Scheduler', {
|
const schedulerFn = new lambda.Function(this, 'Scheduler', {
|
||||||
functionName: 'agent-claw-scheduler',
|
functionName: 'agent-claw-scheduler',
|
||||||
|
|||||||
@@ -262,6 +262,10 @@ def handler(event, context):
|
|||||||
# Flush any remaining text
|
# Flush any remaining text
|
||||||
print(f'[agent-runner] stream done buffer={len(text_buffer)} bot_token_set={bool(bot_token)}')
|
print(f'[agent-runner] stream done buffer={len(text_buffer)} bot_token_set={bool(bot_token)}')
|
||||||
if text_buffer.strip() and bot_token:
|
if text_buffer.strip() and bot_token:
|
||||||
|
# Suppress heartbeat OK responses
|
||||||
|
if text_buffer.strip().upper().startswith('HEARTBEAT_OK'):
|
||||||
|
print(f'[agent-runner] heartbeat suppressed for {actor_id}')
|
||||||
|
return
|
||||||
print(f'[agent-runner] flushing {len(text_buffer)}c to {chat_id}')
|
print(f'[agent-runner] flushing {len(text_buffer)}c to {chat_id}')
|
||||||
send_telegram_direct(str(chat_id), bot_token, text_buffer.strip())
|
send_telegram_direct(str(chat_id), bot_token, text_buffer.strip())
|
||||||
|
|
||||||
|
|||||||
68
src/lambdas/heartbeat-runner/handler.py
Normal file
68
src/lambdas/heartbeat-runner/handler.py
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
_ddb = None
|
||||||
|
_sqs = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_ddb():
|
||||||
|
global _ddb
|
||||||
|
if _ddb is None:
|
||||||
|
_ddb = boto3.resource('dynamodb')
|
||||||
|
return _ddb
|
||||||
|
|
||||||
|
|
||||||
|
def get_sqs():
|
||||||
|
global _sqs
|
||||||
|
if _sqs is None:
|
||||||
|
_sqs = boto3.client('sqs')
|
||||||
|
return _sqs
|
||||||
|
|
||||||
|
|
||||||
|
def handler(event, context):
|
||||||
|
table_name = os.environ['USERS_TABLE_NAME']
|
||||||
|
queue_url = os.environ['MESSAGE_QUEUE_URL']
|
||||||
|
|
||||||
|
# Scan for active users
|
||||||
|
table = get_ddb().Table(table_name)
|
||||||
|
response = table.scan(
|
||||||
|
FilterExpression='#s = :active',
|
||||||
|
ExpressionAttributeNames={'#s': 'status'},
|
||||||
|
ExpressionAttributeValues={':active': 'active'},
|
||||||
|
)
|
||||||
|
users = response.get('Items', [])
|
||||||
|
|
||||||
|
# 30-min bucket for deduplication
|
||||||
|
bucket_ts = str(int(time.time()) // 1800)
|
||||||
|
sqs = get_sqs()
|
||||||
|
|
||||||
|
sent = 0
|
||||||
|
for user in users:
|
||||||
|
actor_id = user['actor_id']
|
||||||
|
# Extract chat_id from actor_id (format: "telegram:<chat_id>")
|
||||||
|
if not actor_id.startswith('telegram:'):
|
||||||
|
continue
|
||||||
|
chat_id = actor_id.split(':', 1)[1]
|
||||||
|
|
||||||
|
msg = {
|
||||||
|
'chat_id': chat_id,
|
||||||
|
'channel': 'telegram',
|
||||||
|
'messages': [{
|
||||||
|
'text': '[HEARTBEAT]',
|
||||||
|
'from_name': user.get('display_name', ''),
|
||||||
|
'from_username': user.get('telegram_username', ''),
|
||||||
|
}],
|
||||||
|
}
|
||||||
|
|
||||||
|
sqs.send_message(
|
||||||
|
QueueUrl=queue_url,
|
||||||
|
MessageBody=json.dumps(msg),
|
||||||
|
MessageGroupId=actor_id,
|
||||||
|
MessageDeduplicationId=f'heartbeat-{actor_id}-{bucket_ts}',
|
||||||
|
)
|
||||||
|
sent += 1
|
||||||
|
|
||||||
|
print(f'[heartbeat-runner] Sent {sent} heartbeat messages')
|
||||||
|
return {'statusCode': 200, 'sent': sent}
|
||||||
1
src/lambdas/heartbeat-runner/requirements.txt
Normal file
1
src/lambdas/heartbeat-runner/requirements.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
boto3>=1.34.0
|
||||||
Reference in New Issue
Block a user