agent-claw: automated task changes

This commit is contained in:
daniel
2026-05-06 18:55:16 -05:00
parent 38905bb1e9
commit 732b00fb66
8494 changed files with 2018127 additions and 4 deletions

View File

@@ -0,0 +1,21 @@
import type { OnEventResponse } from '../types';
export declare const CREATE_FAILED_PHYSICAL_ID_MARKER = "AWSCDK::CustomResourceProviderFramework::CREATE_FAILED";
export declare const MISSING_PHYSICAL_ID_MARKER = "AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID";
export interface CloudFormationResponseOptions {
readonly reason?: string;
readonly noEcho?: boolean;
}
export interface CloudFormationEventContext {
StackId: string;
RequestId: string;
PhysicalResourceId?: string;
LogicalResourceId: string;
ResponseURL: string;
Data?: any;
}
export declare function submitResponse(status: 'SUCCESS' | 'FAILED', event: CloudFormationEventContext, options?: CloudFormationResponseOptions): Promise<void>;
export declare let includeStackTraces: boolean;
export declare function safeHandler(block: (event: any) => Promise<void>): (event: any) => Promise<void>;
export declare function redactDataFromPayload(payload: OnEventResponse): OnEventResponse;
export declare class Retry extends Error {
}

View File

@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.Retry=exports.includeStackTraces=exports.MISSING_PHYSICAL_ID_MARKER=exports.CREATE_FAILED_PHYSICAL_ID_MARKER=void 0,exports.submitResponse=submitResponse,exports.safeHandler=safeHandler,exports.redactDataFromPayload=redactDataFromPayload;const url=require("url"),outbound_1=require("./outbound"),util_1=require("./util");exports.CREATE_FAILED_PHYSICAL_ID_MARKER="AWSCDK::CustomResourceProviderFramework::CREATE_FAILED",exports.MISSING_PHYSICAL_ID_MARKER="AWSCDK::CustomResourceProviderFramework::MISSING_PHYSICAL_ID";async function submitResponse(status,event,options={}){const json={Status:status,Reason:options.reason||status,StackId:event.StackId,RequestId:event.RequestId,PhysicalResourceId:event.PhysicalResourceId||exports.MISSING_PHYSICAL_ID_MARKER,LogicalResourceId:event.LogicalResourceId,NoEcho:options.noEcho,Data:event.Data},responseBody=JSON.stringify(json),parsedUrl=url.parse(event.ResponseURL),loggingSafeUrl=`${parsedUrl.protocol}//${parsedUrl.hostname}/${parsedUrl.pathname}?***`;options?.noEcho?(0,util_1.log)("submit redacted response to cloudformation",loggingSafeUrl,redactDataFromPayload(json)):(0,util_1.log)("submit response to cloudformation",loggingSafeUrl,json);const retryOptions={attempts:5,sleep:1e3};await(0,util_1.withRetries)(retryOptions,outbound_1.httpRequest)({hostname:parsedUrl.hostname,path:parsedUrl.path,method:"PUT",headers:{"content-type":"","content-length":Buffer.byteLength(responseBody,"utf8")}},responseBody)}exports.includeStackTraces=!0;function safeHandler(block){return async event=>{if(event.RequestType==="Delete"&&event.PhysicalResourceId===exports.CREATE_FAILED_PHYSICAL_ID_MARKER){(0,util_1.log)("ignoring DELETE event caused by a failed CREATE event"),await submitResponse("SUCCESS",event);return}try{await block(event)}catch(e){if(e instanceof Retry)throw(0,util_1.log)("retry requested by handler"),e;event.PhysicalResourceId||(event.RequestType==="Create"?((0,util_1.log)("CREATE failed, responding with a marker physical resource id so that the subsequent DELETE will be ignored"),event.PhysicalResourceId=exports.CREATE_FAILED_PHYSICAL_ID_MARKER):(0,util_1.log)(`ERROR: Malformed event. "PhysicalResourceId" is required: ${JSON.stringify({...event,ResponseURL:"..."})}`)),await submitResponse("FAILED",event,{reason:exports.includeStackTraces?e.stack:e.message})}}}function redactDataFromPayload(payload){const redactedPayload=JSON.parse(JSON.stringify(payload));if(redactedPayload.Data){const keys=Object.keys(redactedPayload.Data);for(const key of keys)redactedPayload.Data[key]="*****"}return redactedPayload}class Retry extends Error{}exports.Retry=Retry;

View File

@@ -0,0 +1,6 @@
export declare const USER_ON_EVENT_FUNCTION_ARN_ENV = "USER_ON_EVENT_FUNCTION_ARN";
export declare const USER_IS_COMPLETE_FUNCTION_ARN_ENV = "USER_IS_COMPLETE_FUNCTION_ARN";
export declare const WAITER_STATE_MACHINE_ARN_ENV = "WAITER_STATE_MACHINE_ARN";
export declare const FRAMEWORK_ON_EVENT_HANDLER_NAME = "onEvent";
export declare const FRAMEWORK_IS_COMPLETE_HANDLER_NAME = "isComplete";
export declare const FRAMEWORK_ON_TIMEOUT_HANDLER_NAME = "onTimeout";

View File

@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.FRAMEWORK_ON_TIMEOUT_HANDLER_NAME=exports.FRAMEWORK_IS_COMPLETE_HANDLER_NAME=exports.FRAMEWORK_ON_EVENT_HANDLER_NAME=exports.WAITER_STATE_MACHINE_ARN_ENV=exports.USER_IS_COMPLETE_FUNCTION_ARN_ENV=exports.USER_ON_EVENT_FUNCTION_ARN_ENV=void 0,exports.USER_ON_EVENT_FUNCTION_ARN_ENV="USER_ON_EVENT_FUNCTION_ARN",exports.USER_IS_COMPLETE_FUNCTION_ARN_ENV="USER_IS_COMPLETE_FUNCTION_ARN",exports.WAITER_STATE_MACHINE_ARN_ENV="WAITER_STATE_MACHINE_ARN",exports.FRAMEWORK_ON_EVENT_HANDLER_NAME="onEvent",exports.FRAMEWORK_IS_COMPLETE_HANDLER_NAME="isComplete",exports.FRAMEWORK_ON_TIMEOUT_HANDLER_NAME="onTimeout";

View File

@@ -0,0 +1,7 @@
declare const _default: {
onEvent: (event: any) => Promise<void>;
isComplete: (event: any) => Promise<void>;
onTimeout: typeof onTimeout;
};
export = _default;
declare function onTimeout(timeoutEvent: any): Promise<void>;

View File

@@ -0,0 +1,3 @@
"use strict";const cfnResponse=require("./cfn-response"),consts=require("./consts"),outbound_1=require("./outbound"),util_1=require("./util");async function onEvent(cfnRequest){const sanitizedRequest={...cfnRequest,ResponseURL:"..."};(0,util_1.log)("onEventHandler",sanitizedRequest),cfnRequest.ResourceProperties=cfnRequest.ResourceProperties||{};const onEventResult=await invokeUserFunction(consts.USER_ON_EVENT_FUNCTION_ARN_ENV,sanitizedRequest,cfnRequest.ResponseURL);onEventResult?.NoEcho?(0,util_1.log)("redacted onEvent returned:",cfnResponse.redactDataFromPayload(onEventResult)):(0,util_1.log)("onEvent returned:",onEventResult);const resourceEvent=createResponseEvent(cfnRequest,onEventResult),sanitizedEvent={...resourceEvent,ResponseURL:"..."};if(onEventResult?.NoEcho?(0,util_1.log)("readacted event:",cfnResponse.redactDataFromPayload(sanitizedEvent)):(0,util_1.log)("event:",sanitizedEvent),!process.env[consts.USER_IS_COMPLETE_FUNCTION_ARN_ENV])return cfnResponse.submitResponse("SUCCESS",resourceEvent,{noEcho:resourceEvent.NoEcho});const waiter={stateMachineArn:(0,util_1.getEnv)(consts.WAITER_STATE_MACHINE_ARN_ENV),input:JSON.stringify(resourceEvent)};(0,util_1.log)("starting waiter",{stateMachineArn:(0,util_1.getEnv)(consts.WAITER_STATE_MACHINE_ARN_ENV)}),await(0,outbound_1.startExecution)(waiter)}async function isComplete(event){const sanitizedRequest={...event,ResponseURL:"..."};event?.NoEcho?(0,util_1.log)("redacted isComplete request",cfnResponse.redactDataFromPayload(sanitizedRequest)):(0,util_1.log)("isComplete",sanitizedRequest);const isCompleteResult=await invokeUserFunction(consts.USER_IS_COMPLETE_FUNCTION_ARN_ENV,sanitizedRequest,event.ResponseURL);if(event?.NoEcho?(0,util_1.log)("redacted user isComplete returned:",cfnResponse.redactDataFromPayload(isCompleteResult)):(0,util_1.log)("user isComplete returned:",isCompleteResult),!isCompleteResult.IsComplete)throw isCompleteResult.Data&&Object.keys(isCompleteResult.Data).length>0?new Error('"Data" is not allowed if "IsComplete" is "False"'):new cfnResponse.Retry(JSON.stringify(event));const response={...event,...isCompleteResult,Data:{...event.Data,...isCompleteResult.Data}};await cfnResponse.submitResponse("SUCCESS",response,{noEcho:event.NoEcho})}async function onTimeout(timeoutEvent){(0,util_1.log)("timeoutHandler",timeoutEvent);const isCompleteRequest=JSON.parse(JSON.parse(timeoutEvent.Cause).errorMessage);await cfnResponse.submitResponse("FAILED",isCompleteRequest,{reason:"Operation timed out"})}async function invokeUserFunction(functionArnEnv,sanitizedPayload,responseUrl){const functionArn=(0,util_1.getEnv)(functionArnEnv);(0,util_1.log)(`executing user function ${functionArn} with payload`,sanitizedPayload);const resp=await(0,outbound_1.invokeFunction)({FunctionName:functionArn,Payload:JSON.stringify({...sanitizedPayload,ResponseURL:responseUrl})});(0,util_1.log)("user function response:",resp,typeof resp);const jsonPayload=(0,util_1.parseJsonPayload)(resp.Payload);if(resp.FunctionError){(0,util_1.log)("user function threw an error:",resp.FunctionError);const errorMessage=jsonPayload.errorMessage||"error",arn=functionArn.split(":"),functionName=arn[arn.length-1],message=[errorMessage,"",`Logs: /aws/lambda/${functionName}`,""].join(`
`),e=new Error(message);throw jsonPayload.trace&&(e.stack=[message,...jsonPayload.trace.slice(1)].join(`
`)),e}return jsonPayload}function createResponseEvent(cfnRequest,onEventResult){onEventResult=onEventResult||{};const physicalResourceId=onEventResult.PhysicalResourceId||defaultPhysicalResourceId(cfnRequest);if(cfnRequest.RequestType==="Delete"&&physicalResourceId!==cfnRequest.PhysicalResourceId)throw new Error(`DELETE: cannot change the physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${onEventResult.PhysicalResourceId}" during deletion`);return cfnRequest.RequestType==="Update"&&physicalResourceId!==cfnRequest.PhysicalResourceId&&(0,util_1.log)(`UPDATE: changing physical resource ID from "${cfnRequest.PhysicalResourceId}" to "${onEventResult.PhysicalResourceId}"`),{...cfnRequest,...onEventResult,PhysicalResourceId:physicalResourceId}}function defaultPhysicalResourceId(req){switch(req.RequestType){case"Create":return req.RequestId;case"Update":case"Delete":return req.PhysicalResourceId;default:throw new Error(`Invalid "RequestType" in request "${JSON.stringify(req)}"`)}}module.exports={[consts.FRAMEWORK_ON_EVENT_HANDLER_NAME]:cfnResponse.safeHandler(onEvent),[consts.FRAMEWORK_IS_COMPLETE_HANDLER_NAME]:cfnResponse.safeHandler(isComplete),[consts.FRAMEWORK_ON_TIMEOUT_HANDLER_NAME]:onTimeout};

View File

@@ -0,0 +1,10 @@
import * as https from 'https';
import type { InvocationResponse, InvokeCommandInput } from '@aws-sdk/client-lambda';
import type { StartExecutionInput, StartExecutionOutput } from '@aws-sdk/client-sfn';
declare function defaultHttpRequest(options: https.RequestOptions, requestBody: string): Promise<void>;
declare function defaultStartExecution(req: StartExecutionInput): Promise<StartExecutionOutput>;
declare function defaultInvokeFunction(req: InvokeCommandInput): Promise<InvocationResponse>;
export declare let startExecution: typeof defaultStartExecution;
export declare let invokeFunction: typeof defaultInvokeFunction;
export declare let httpRequest: typeof defaultHttpRequest;
export {};

View File

@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.httpRequest=exports.invokeFunction=exports.startExecution=void 0;const https=require("https"),client_lambda_1=require("@aws-sdk/client-lambda"),client_sfn_1=require("@aws-sdk/client-sfn"),FRAMEWORK_HANDLER_TIMEOUT=9e5,awsSdkConfig={httpOptions:{timeout:FRAMEWORK_HANDLER_TIMEOUT}};async function defaultHttpRequest(options,requestBody){return new Promise((resolve,reject)=>{try{const request=https.request(options,response=>{response.resume(),!response.statusCode||response.statusCode>=400?reject(new Error(`Unsuccessful HTTP response: ${response.statusCode}`)):resolve()});request.on("error",reject),request.write(requestBody),request.end()}catch(e){reject(e)}})}let sfn,lambda;async function defaultStartExecution(req){return sfn||(sfn=new client_sfn_1.SFN(awsSdkConfig)),sfn.startExecution(req)}async function defaultInvokeFunction(req){lambda||(lambda=new client_lambda_1.Lambda(awsSdkConfig));try{return await lambda.invoke(req)}catch{return await(0,client_lambda_1.waitUntilFunctionActiveV2)({client:lambda,maxWaitTime:300},{FunctionName:req.FunctionName}),lambda.invoke(req)}}exports.startExecution=defaultStartExecution,exports.invokeFunction=defaultInvokeFunction,exports.httpRequest=defaultHttpRequest;

View File

@@ -0,0 +1,10 @@
export declare function getEnv(name: string): string;
export declare function log(title: any, ...args: any[]): void;
export interface RetryOptions {
/** How many retries (will at least try once) */
readonly attempts: number;
/** Sleep base, in ms */
readonly sleep: number;
}
export declare function withRetries<A extends Array<any>, B>(options: RetryOptions, fn: (...xs: A) => Promise<B>): (...xs: A) => Promise<B>;
export declare function parseJsonPayload(payload: string | Buffer | Uint8Array | undefined | null): any;

View File

@@ -0,0 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getEnv=getEnv,exports.log=log,exports.withRetries=withRetries,exports.parseJsonPayload=parseJsonPayload;function getEnv(name){const value=process.env[name];if(!value)throw new Error(`The environment variable "${name}" is not defined`);return value}function log(title,...args){console.log("[provider-framework]",title,...args.map(x=>typeof x=="object"?JSON.stringify(x,void 0,2):x))}function withRetries(options,fn){return async(...xs)=>{let attempts=options.attempts,ms=options.sleep;for(;;)try{return await fn(...xs)}catch(e){if(attempts--<=0)throw e;await sleep(Math.floor(Math.random()*ms)),ms*=2}}}async function sleep(ms){return new Promise(ok=>setTimeout(ok,ms))}function parseJsonPayload(payload){const text=new TextDecoder().decode(Buffer.from(payload??""));if(!text)return{};try{return JSON.parse(text)}catch{throw new Error(`return values from user-handlers must be JSON objects. got: "${text}"`)}}