OAuth callback: send Telegram confirmation message after Google auth
This commit is contained in:
Binary file not shown.
@@ -31,16 +31,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"5be87975e51a6859dfad098b3d998a0bcd09a4f9a437bbf38923338fb559eb9e": {
|
"a6d7ca10ce41a486503b8ea9f109a54841bb31af9548c618fdca79ac13b34c6a": {
|
||||||
"displayName": "OAuthHandler/Code",
|
"displayName": "OAuthHandler/Code",
|
||||||
"source": {
|
"source": {
|
||||||
"path": "asset.5be87975e51a6859dfad098b3d998a0bcd09a4f9a437bbf38923338fb559eb9e",
|
"path": "asset.a6d7ca10ce41a486503b8ea9f109a54841bb31af9548c618fdca79ac13b34c6a",
|
||||||
"packaging": "zip"
|
"packaging": "zip"
|
||||||
},
|
},
|
||||||
"destinations": {
|
"destinations": {
|
||||||
"495395224548-us-east-1-23c3d77a": {
|
"495395224548-us-east-1-77bd44d3": {
|
||||||
"bucketName": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
"bucketName": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
||||||
"objectKey": "5be87975e51a6859dfad098b3d998a0bcd09a4f9a437bbf38923338fb559eb9e.zip",
|
"objectKey": "a6d7ca10ce41a486503b8ea9f109a54841bb31af9548c618fdca79ac13b34c6a.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"
|
||||||
}
|
}
|
||||||
@@ -61,16 +61,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"c6cd323425a93776b45e2e0806064efbc5c84a3d6d78532282df6dd62cc14bda": {
|
"6c96ac78834e047807c02e9e41e5a6f43de9b760bc3954d97cb2c3df560d71e7": {
|
||||||
"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-51c91ff7": {
|
"495395224548-us-east-1-014f016d": {
|
||||||
"bucketName": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
"bucketName": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
||||||
"objectKey": "c6cd323425a93776b45e2e0806064efbc5c84a3d6d78532282df6dd62cc14bda.json",
|
"objectKey": "6c96ac78834e047807c02e9e41e5a6f43de9b760bc3954d97cb2c3df560d71e7.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:331:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:342: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:335:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:346: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:339:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:350: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:344:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:355: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:349:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:360: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:354:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:365: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:359:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:370: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:364:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:375: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:369:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:380: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:374:5)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:385: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..."
|
||||||
]
|
]
|
||||||
@@ -319,7 +319,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:290:25)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:301: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 +334,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:303:17)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:314: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..."
|
||||||
]
|
]
|
||||||
@@ -458,7 +458,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:264:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:266: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 +475,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:264:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:266: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 +492,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:271:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:273: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 +509,41 @@
|
|||||||
".../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:271:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:273:13)",
|
||||||
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"/AgentClawStack/WebhookApi/ANY--workspace--{proxy+}/WorkspaceMcpIntegration-Permission": [
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:logicalId",
|
||||||
|
"data": "WebhookApiANYworkspaceproxyWorkspaceMcpIntegrationPermission97613ADF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:creationStack",
|
||||||
|
"data": [
|
||||||
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
|
"Array.map (:)",
|
||||||
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:282:13)",
|
||||||
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"/AgentClawStack/WebhookApi/ANY--workspace--{proxy+}/Resource": [
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:logicalId",
|
||||||
|
"data": "WebhookApiANYworkspaceproxy4455BE19"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:creationStack",
|
||||||
|
"data": [
|
||||||
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
|
"Array.map (:)",
|
||||||
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:282: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..."
|
||||||
]
|
]
|
||||||
@@ -569,7 +603,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:290:25)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:301: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..."
|
||||||
]
|
]
|
||||||
@@ -633,7 +667,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:264:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:266: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..."
|
||||||
]
|
]
|
||||||
@@ -650,7 +684,24 @@
|
|||||||
".../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:271:13)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:273:13)",
|
||||||
|
"<anonymous> (/Users/daniel/agent-claw/cdk/bin/agent-claw.ts:8:1)",
|
||||||
|
"...node internals, ts-node, ts-node, ts-node..."
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"/AgentClawStack/WebhookApi/ANY--workspace--{proxy+}/WorkspaceMcpIntegration/Resource": [
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:logicalId",
|
||||||
|
"data": "WebhookApiANYworkspaceproxyWorkspaceMcpIntegration7377EE13"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "aws:cdk:creationStack",
|
||||||
|
"data": [
|
||||||
|
".../Users/daniel/agent-claw/cdk/node_modules/aws-cdk-lib/aws-apigatewayv2/lib/http/api.js:1:96 in aws-cdk-lib...",
|
||||||
|
"Array.map (:)",
|
||||||
|
"...WrappedClass.<anonymous> in aws-cdk-lib...",
|
||||||
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:282: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..."
|
||||||
]
|
]
|
||||||
@@ -665,7 +716,7 @@
|
|||||||
"type": "aws:cdk:creationStack",
|
"type": "aws:cdk:creationStack",
|
||||||
"data": [
|
"data": [
|
||||||
"...SecretBase.grantRead in aws-cdk-lib...",
|
"...SecretBase.grantRead in aws-cdk-lib...",
|
||||||
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:250:29)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:251: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..."
|
||||||
]
|
]
|
||||||
@@ -680,7 +731,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:301:20)",
|
"new AgentClawStack (/Users/daniel/agent-claw/cdk/lib/agent-claw-stack.ts:312: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..."
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -695,6 +695,93 @@
|
|||||||
"aws:cdk:path": "AgentClawStack/WebhookApi/GET--oauth--callback/Resource"
|
"aws:cdk:path": "AgentClawStack/WebhookApi/GET--oauth--callback/Resource"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"WebhookApiANYworkspaceproxyWorkspaceMcpIntegration7377EE13": {
|
||||||
|
"Type": "AWS::ApiGatewayV2::Integration",
|
||||||
|
"Properties": {
|
||||||
|
"ApiId": {
|
||||||
|
"Ref": "WebhookApi28122C53"
|
||||||
|
},
|
||||||
|
"IntegrationType": "AWS_PROXY",
|
||||||
|
"IntegrationUri": {
|
||||||
|
"Fn::Join": [
|
||||||
|
"",
|
||||||
|
[
|
||||||
|
"arn:",
|
||||||
|
{
|
||||||
|
"Ref": "AWS::Partition"
|
||||||
|
},
|
||||||
|
":lambda:us-east-1:495395224548:function:agent-claw-workspace-mcp"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"PayloadFormatVersion": "2.0"
|
||||||
|
},
|
||||||
|
"Metadata": {
|
||||||
|
"aws:cdk:path": "AgentClawStack/WebhookApi/ANY--workspace--{proxy+}/WorkspaceMcpIntegration/Resource"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"WebhookApiANYworkspaceproxyWorkspaceMcpIntegrationPermission97613ADF": {
|
||||||
|
"Type": "AWS::Lambda::Permission",
|
||||||
|
"Properties": {
|
||||||
|
"Action": "lambda:InvokeFunction",
|
||||||
|
"FunctionName": {
|
||||||
|
"Fn::Join": [
|
||||||
|
"",
|
||||||
|
[
|
||||||
|
"arn:",
|
||||||
|
{
|
||||||
|
"Ref": "AWS::Partition"
|
||||||
|
},
|
||||||
|
":lambda:us-east-1:495395224548:function:agent-claw-workspace-mcp"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Principal": "apigateway.amazonaws.com",
|
||||||
|
"SourceArn": {
|
||||||
|
"Fn::Join": [
|
||||||
|
"",
|
||||||
|
[
|
||||||
|
"arn:",
|
||||||
|
{
|
||||||
|
"Ref": "AWS::Partition"
|
||||||
|
},
|
||||||
|
":execute-api:us-east-1:495395224548:",
|
||||||
|
{
|
||||||
|
"Ref": "WebhookApi28122C53"
|
||||||
|
},
|
||||||
|
"/*/*/workspace/{proxy+}"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Metadata": {
|
||||||
|
"aws:cdk:path": "AgentClawStack/WebhookApi/ANY--workspace--{proxy+}/WorkspaceMcpIntegration-Permission"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"WebhookApiANYworkspaceproxy4455BE19": {
|
||||||
|
"Type": "AWS::ApiGatewayV2::Route",
|
||||||
|
"Properties": {
|
||||||
|
"ApiId": {
|
||||||
|
"Ref": "WebhookApi28122C53"
|
||||||
|
},
|
||||||
|
"AuthorizationType": "NONE",
|
||||||
|
"RouteKey": "ANY /workspace/{proxy+}",
|
||||||
|
"Target": {
|
||||||
|
"Fn::Join": [
|
||||||
|
"",
|
||||||
|
[
|
||||||
|
"integrations/",
|
||||||
|
{
|
||||||
|
"Ref": "WebhookApiANYworkspaceproxyWorkspaceMcpIntegration7377EE13"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Metadata": {
|
||||||
|
"aws:cdk:path": "AgentClawStack/WebhookApi/ANY--workspace--{proxy+}/Resource"
|
||||||
|
}
|
||||||
|
},
|
||||||
"Runtime1RoleA7A82078": {
|
"Runtime1RoleA7A82078": {
|
||||||
"Type": "AWS::IAM::Role",
|
"Type": "AWS::IAM::Role",
|
||||||
"Properties": {
|
"Properties": {
|
||||||
@@ -1014,6 +1101,14 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"Action": [
|
||||||
|
"secretsmanager:GetSecretValue",
|
||||||
|
"secretsmanager:DescribeSecret"
|
||||||
|
],
|
||||||
|
"Effect": "Allow",
|
||||||
|
"Resource": "arn:aws:secretsmanager:us-east-1:495395224548:secret:agent-claw/telegram-bot-token-Oq3in3"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Action": [
|
"Action": [
|
||||||
"dynamodb:BatchGetItem",
|
"dynamodb:BatchGetItem",
|
||||||
@@ -1081,7 +1176,7 @@
|
|||||||
"Properties": {
|
"Properties": {
|
||||||
"Code": {
|
"Code": {
|
||||||
"S3Bucket": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
"S3Bucket": "cdk-hnb659fds-assets-495395224548-us-east-1",
|
||||||
"S3Key": "5be87975e51a6859dfad098b3d998a0bcd09a4f9a437bbf38923338fb559eb9e.zip"
|
"S3Key": "a6d7ca10ce41a486503b8ea9f109a54841bb31af9548c618fdca79ac13b34c6a.zip"
|
||||||
},
|
},
|
||||||
"Environment": {
|
"Environment": {
|
||||||
"Variables": {
|
"Variables": {
|
||||||
@@ -1100,6 +1195,7 @@
|
|||||||
"USERS_TABLE_NAME": {
|
"USERS_TABLE_NAME": {
|
||||||
"Ref": "UsersTable9725E9C8"
|
"Ref": "UsersTable9725E9C8"
|
||||||
},
|
},
|
||||||
|
"TELEGRAM_BOT_TOKEN_SECRET_ARN": "arn:aws:secretsmanager:us-east-1:495395224548:secret:agent-claw/telegram-bot-token-Oq3in3",
|
||||||
"OAUTH_REDIRECT_URI": {
|
"OAUTH_REDIRECT_URI": {
|
||||||
"Fn::Join": [
|
"Fn::Join": [
|
||||||
"",
|
"",
|
||||||
@@ -1136,7 +1232,7 @@
|
|||||||
],
|
],
|
||||||
"Metadata": {
|
"Metadata": {
|
||||||
"aws:cdk:path": "AgentClawStack/OAuthHandler/Resource",
|
"aws:cdk:path": "AgentClawStack/OAuthHandler/Resource",
|
||||||
"aws:asset:path": "asset.5be87975e51a6859dfad098b3d998a0bcd09a4f9a437bbf38923338fb559eb9e",
|
"aws:asset:path": "asset.a6d7ca10ce41a486503b8ea9f109a54841bb31af9548c618fdca79ac13b34c6a",
|
||||||
"aws:asset:is-bundled": false,
|
"aws:asset:is-bundled": false,
|
||||||
"aws:asset:property": "Code"
|
"aws:asset:property": "Code"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,232 @@
|
|||||||
|
"""
|
||||||
|
Google OAuth handler Lambda.
|
||||||
|
|
||||||
|
Routes:
|
||||||
|
GET /oauth/start?actor_id=telegram:123 → redirect to Google OAuth consent
|
||||||
|
GET /oauth/callback?code=...&state=... → exchange code, store tokens, update DynamoDB
|
||||||
|
"""
|
||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
|
import hmac
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import urllib.parse
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
import boto3
|
||||||
|
|
||||||
|
_sm = None
|
||||||
|
_ddb = None
|
||||||
|
|
||||||
|
SCOPES = ' '.join([
|
||||||
|
'https://www.googleapis.com/auth/gmail.modify',
|
||||||
|
'https://www.googleapis.com/auth/calendar',
|
||||||
|
'https://www.googleapis.com/auth/drive',
|
||||||
|
'https://www.googleapis.com/auth/spreadsheets',
|
||||||
|
'https://www.googleapis.com/auth/documents',
|
||||||
|
'openid',
|
||||||
|
'email',
|
||||||
|
'profile',
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def get_sm():
|
||||||
|
global _sm
|
||||||
|
if _sm is None:
|
||||||
|
_sm = boto3.client('secretsmanager', region_name=os.environ.get('AWS_REGION', 'us-east-1'))
|
||||||
|
return _sm
|
||||||
|
|
||||||
|
|
||||||
|
def get_ddb():
|
||||||
|
global _ddb
|
||||||
|
if _ddb is None:
|
||||||
|
_ddb = boto3.resource('dynamodb')
|
||||||
|
return _ddb
|
||||||
|
|
||||||
|
|
||||||
|
def get_oauth_client() -> tuple[str, str]:
|
||||||
|
"""Return (client_id, client_secret) from Secrets Manager."""
|
||||||
|
arn = os.environ['GOOGLE_OAUTH_CLIENT_SECRET_ARN']
|
||||||
|
secret = json.loads(get_sm().get_secret_value(SecretId=arn)['SecretString'])
|
||||||
|
return secret['client_id'], secret['client_secret']
|
||||||
|
|
||||||
|
|
||||||
|
def actor_id_to_secret_name(actor_id: str) -> str:
|
||||||
|
safe = actor_id.replace(':', '-').replace('/', '-')
|
||||||
|
return f'agent-claw/google-credentials/{safe}'
|
||||||
|
|
||||||
|
|
||||||
|
def _redirect(url: str) -> dict:
|
||||||
|
return {'statusCode': 302, 'headers': {'Location': url}, 'body': ''}
|
||||||
|
|
||||||
|
|
||||||
|
def _html(body: str, status: int = 200) -> dict:
|
||||||
|
return {'statusCode': status, 'headers': {'Content-Type': 'text/html'}, 'body': body}
|
||||||
|
|
||||||
|
|
||||||
|
def handler(event, context):
|
||||||
|
path = event.get('rawPath') or event.get('path', '')
|
||||||
|
params = event.get('queryStringParameters') or {}
|
||||||
|
|
||||||
|
if path.endswith('/oauth/start'):
|
||||||
|
return handle_start(params)
|
||||||
|
elif path.endswith('/oauth/callback'):
|
||||||
|
return handle_callback(params)
|
||||||
|
else:
|
||||||
|
return {'statusCode': 404, 'body': 'Not found'}
|
||||||
|
|
||||||
|
|
||||||
|
def handle_start(params: dict) -> dict:
|
||||||
|
actor_id = params.get('actor_id', '')
|
||||||
|
if not actor_id:
|
||||||
|
return _html('<h1>Missing actor_id</h1>', 400)
|
||||||
|
|
||||||
|
client_id, _ = get_oauth_client()
|
||||||
|
redirect_uri = os.environ['OAUTH_REDIRECT_URI']
|
||||||
|
|
||||||
|
# Encode actor_id in state (base64 to keep URL-safe)
|
||||||
|
state = base64.urlsafe_b64encode(actor_id.encode()).decode().rstrip('=')
|
||||||
|
|
||||||
|
auth_url = (
|
||||||
|
'https://accounts.google.com/o/oauth2/v2/auth?'
|
||||||
|
+ urllib.parse.urlencode({
|
||||||
|
'client_id': client_id,
|
||||||
|
'redirect_uri': redirect_uri,
|
||||||
|
'response_type': 'code',
|
||||||
|
'scope': SCOPES,
|
||||||
|
'access_type': 'offline',
|
||||||
|
'prompt': 'consent',
|
||||||
|
'state': state,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
return _redirect(auth_url)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_callback(params: dict) -> dict:
|
||||||
|
code = params.get('code', '')
|
||||||
|
state = params.get('state', '')
|
||||||
|
error = params.get('error', '')
|
||||||
|
|
||||||
|
if error:
|
||||||
|
return _html(f'<h1>OAuth error: {error}</h1>', 400)
|
||||||
|
if not code or not state:
|
||||||
|
return _html('<h1>Missing code or state</h1>', 400)
|
||||||
|
|
||||||
|
# Decode actor_id from state
|
||||||
|
try:
|
||||||
|
padding = 4 - len(state) % 4
|
||||||
|
actor_id = base64.urlsafe_b64decode(state + '=' * padding).decode()
|
||||||
|
except Exception:
|
||||||
|
return _html('<h1>Invalid state</h1>', 400)
|
||||||
|
|
||||||
|
client_id, client_secret = get_oauth_client()
|
||||||
|
redirect_uri = os.environ['OAUTH_REDIRECT_URI']
|
||||||
|
|
||||||
|
# Exchange code for tokens
|
||||||
|
token_data = urllib.parse.urlencode({
|
||||||
|
'code': code,
|
||||||
|
'client_id': client_id,
|
||||||
|
'client_secret': client_secret,
|
||||||
|
'redirect_uri': redirect_uri,
|
||||||
|
'grant_type': 'authorization_code',
|
||||||
|
}).encode()
|
||||||
|
|
||||||
|
req = urllib.request.Request(
|
||||||
|
'https://oauth2.googleapis.com/token',
|
||||||
|
data=token_data,
|
||||||
|
headers={'Content-Type': 'application/x-www-form-urlencoded'},
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(req, timeout=15) as resp:
|
||||||
|
tokens = json.loads(resp.read())
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[oauth] Token exchange failed: {e}')
|
||||||
|
return _html(f'<h1>Token exchange failed: {e}</h1>', 500)
|
||||||
|
|
||||||
|
# Fetch user email from Google
|
||||||
|
user_email = ''
|
||||||
|
try:
|
||||||
|
id_token_payload = tokens.get('id_token', '').split('.')[1]
|
||||||
|
padding = 4 - len(id_token_payload) % 4
|
||||||
|
claims = json.loads(base64.urlsafe_b64decode(id_token_payload + '=' * padding))
|
||||||
|
user_email = claims.get('email', '')
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if not user_email:
|
||||||
|
# Fallback: call userinfo endpoint
|
||||||
|
try:
|
||||||
|
access_token = tokens.get('access_token', '')
|
||||||
|
req2 = urllib.request.Request(
|
||||||
|
'https://www.googleapis.com/oauth2/v3/userinfo',
|
||||||
|
headers={'Authorization': f'Bearer {access_token}'},
|
||||||
|
)
|
||||||
|
with urllib.request.urlopen(req2, timeout=10) as resp2:
|
||||||
|
user_email = json.loads(resp2.read()).get('email', '')
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[oauth] userinfo fetch failed: {e}')
|
||||||
|
|
||||||
|
# Build credentials dict (google-auth format)
|
||||||
|
creds = {
|
||||||
|
'token': tokens.get('access_token'),
|
||||||
|
'refresh_token': tokens.get('refresh_token'),
|
||||||
|
'token_uri': 'https://oauth2.googleapis.com/token',
|
||||||
|
'client_id': client_id,
|
||||||
|
'client_secret': client_secret,
|
||||||
|
'scopes': SCOPES.split(),
|
||||||
|
'email': user_email,
|
||||||
|
'user_email': user_email,
|
||||||
|
}
|
||||||
|
if tokens.get('expires_in'):
|
||||||
|
creds['expiry'] = time.strftime(
|
||||||
|
'%Y-%m-%dT%H:%M:%SZ',
|
||||||
|
time.gmtime(time.time() + int(tokens['expires_in']))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Store in Secrets Manager
|
||||||
|
secret_name = actor_id_to_secret_name(actor_id)
|
||||||
|
sm = get_sm()
|
||||||
|
try:
|
||||||
|
sm.create_secret(Name=secret_name, SecretString=json.dumps(creds))
|
||||||
|
except sm.exceptions.ResourceExistsException:
|
||||||
|
sm.put_secret_value(SecretId=secret_name, SecretString=json.dumps(creds))
|
||||||
|
print(f'[oauth] Stored credentials for actor={actor_id} email={user_email}')
|
||||||
|
|
||||||
|
# Update DynamoDB users table with google_email
|
||||||
|
table_name = os.environ.get('USERS_TABLE_NAME', '')
|
||||||
|
if table_name and actor_id:
|
||||||
|
try:
|
||||||
|
get_ddb().Table(table_name).update_item(
|
||||||
|
Key={'actor_id': actor_id},
|
||||||
|
UpdateExpression='SET google_email = :e',
|
||||||
|
ExpressionAttributeValues={':e': user_email},
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[oauth] DynamoDB update failed: {e}')
|
||||||
|
|
||||||
|
# Best-effort Telegram confirmation
|
||||||
|
try:
|
||||||
|
bot_token_arn = os.environ.get('TELEGRAM_BOT_TOKEN_SECRET_ARN', '')
|
||||||
|
if bot_token_arn and actor_id.startswith('telegram:'):
|
||||||
|
chat_id = actor_id.split(':', 1)[1]
|
||||||
|
bot_token = get_sm().get_secret_value(SecretId=bot_token_arn)['SecretString']
|
||||||
|
tg_text = (
|
||||||
|
f'✅ Google account connected!\n\n'
|
||||||
|
f'{user_email} is now linked. You can now ask me about your Gmail, Calendar, and Drive.'
|
||||||
|
)
|
||||||
|
tg_payload = json.dumps({'chat_id': chat_id, 'text': tg_text}).encode()
|
||||||
|
tg_req = urllib.request.Request(
|
||||||
|
f'https://api.telegram.org/bot{bot_token}/sendMessage',
|
||||||
|
data=tg_payload,
|
||||||
|
headers={'Content-Type': 'application/json'},
|
||||||
|
)
|
||||||
|
urllib.request.urlopen(tg_req, timeout=5)
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[oauth] Telegram notification failed: {e}')
|
||||||
|
|
||||||
|
return _html(
|
||||||
|
f'<h1>✅ Google account connected!</h1>'
|
||||||
|
f'<p>Connected <b>{user_email}</b> to your agent account.</p>'
|
||||||
|
f'<p>You can close this window and return to Telegram.</p>'
|
||||||
|
)
|
||||||
@@ -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/c6cd323425a93776b45e2e0806064efbc5c84a3d6d78532282df6dd62cc14bda.json",
|
"stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-495395224548-us-east-1/6c96ac78834e047807c02e9e41e5a6f43de9b760bc3954d97cb2c3df560d71e7.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
@@ -243,11 +243,13 @@ export class AgentClawStack extends cdk.Stack {
|
|||||||
environment: {
|
environment: {
|
||||||
GOOGLE_OAUTH_CLIENT_SECRET_ARN: googleOAuthClientSecret.secretArn,
|
GOOGLE_OAUTH_CLIENT_SECRET_ARN: googleOAuthClientSecret.secretArn,
|
||||||
USERS_TABLE_NAME: usersTable.tableName,
|
USERS_TABLE_NAME: usersTable.tableName,
|
||||||
|
TELEGRAM_BOT_TOKEN_SECRET_ARN: telegramBotTokenSecretArn,
|
||||||
// OAUTH_REDIRECT_URI set after API GW URL is known — injected via addEnvironment below
|
// OAUTH_REDIRECT_URI set after API GW URL is known — injected via addEnvironment below
|
||||||
OAUTH_REDIRECT_URI: 'PLACEHOLDER',
|
OAUTH_REDIRECT_URI: 'PLACEHOLDER',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
googleOAuthClientSecret.grantRead(oauthHandlerFn);
|
googleOAuthClientSecret.grantRead(oauthHandlerFn);
|
||||||
|
botTokenSecret.grantRead(oauthHandlerFn);
|
||||||
usersTable.grantReadWriteData(oauthHandlerFn);
|
usersTable.grantReadWriteData(oauthHandlerFn);
|
||||||
// Grant OAuth handler write access to per-user credential secrets
|
// Grant OAuth handler write access to per-user credential secrets
|
||||||
oauthHandlerFn.addToRolePolicy(new iam.PolicyStatement({
|
oauthHandlerFn.addToRolePolicy(new iam.PolicyStatement({
|
||||||
|
|||||||
@@ -205,6 +205,26 @@ def handle_callback(params: dict) -> dict:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'[oauth] DynamoDB update failed: {e}')
|
print(f'[oauth] DynamoDB update failed: {e}')
|
||||||
|
|
||||||
|
# Best-effort Telegram confirmation
|
||||||
|
try:
|
||||||
|
bot_token_arn = os.environ.get('TELEGRAM_BOT_TOKEN_SECRET_ARN', '')
|
||||||
|
if bot_token_arn and actor_id.startswith('telegram:'):
|
||||||
|
chat_id = actor_id.split(':', 1)[1]
|
||||||
|
bot_token = get_sm().get_secret_value(SecretId=bot_token_arn)['SecretString']
|
||||||
|
tg_text = (
|
||||||
|
f'✅ Google account connected!\n\n'
|
||||||
|
f'{user_email} is now linked. You can now ask me about your Gmail, Calendar, and Drive.'
|
||||||
|
)
|
||||||
|
tg_payload = json.dumps({'chat_id': chat_id, 'text': tg_text}).encode()
|
||||||
|
tg_req = urllib.request.Request(
|
||||||
|
f'https://api.telegram.org/bot{bot_token}/sendMessage',
|
||||||
|
data=tg_payload,
|
||||||
|
headers={'Content-Type': 'application/json'},
|
||||||
|
)
|
||||||
|
urllib.request.urlopen(tg_req, timeout=5)
|
||||||
|
except Exception as e:
|
||||||
|
print(f'[oauth] Telegram notification failed: {e}')
|
||||||
|
|
||||||
return _html(
|
return _html(
|
||||||
f'<h1>✅ Google account connected!</h1>'
|
f'<h1>✅ Google account connected!</h1>'
|
||||||
f'<p>Connected <b>{user_email}</b> to your agent account.</p>'
|
f'<p>Connected <b>{user_email}</b> to your agent account.</p>'
|
||||||
|
|||||||
Reference in New Issue
Block a user