From 8dc3472797446589a38961fcda7cccb988a21244 Mon Sep 17 00:00:00 2001 From: Matthew Davidian <84351798+matthewdavidian@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:07:05 -0800 Subject: [PATCH 1/5] Add DocuPipe async document pipeline interface --- AppSrc/cDocuPipeClient.pkg | 179 +++++++++++++++++++++ AppSrc/cDocuPipeDocumentService.pkg | 65 ++++++++ AppSrc/cDocuPipeJobService.pkg | 37 +++++ AppSrc/cDocuPipeStandardizationService.pkg | 74 +++++++++ AppSrc/docupipeai.h | 52 ++++++ AppSrc/docupipeai.pkg | 63 ++++++++ README.md | 55 +++++++ 7 files changed, 525 insertions(+) create mode 100644 AppSrc/cDocuPipeClient.pkg create mode 100644 AppSrc/cDocuPipeDocumentService.pkg create mode 100644 AppSrc/cDocuPipeJobService.pkg create mode 100644 AppSrc/cDocuPipeStandardizationService.pkg create mode 100644 AppSrc/docupipeai.h create mode 100644 AppSrc/docupipeai.pkg diff --git a/AppSrc/cDocuPipeClient.pkg b/AppSrc/cDocuPipeClient.pkg new file mode 100644 index 0000000..d073cd6 --- /dev/null +++ b/AppSrc/cDocuPipeClient.pkg @@ -0,0 +1,179 @@ +Use cdtJsonHttpTransfer.pkg +Use cBase64Attachment_mixin.pkg +Use cJsonObject.pkg +Use docupipeai.h + +Class cDocuPipeClient is a cdtJsonHttpTransfer + Import_Class_Protocol cBase64Attachment_mixin + + Procedure Construct_Object + Forward Send Construct_Object + + Send Define_cBase64Attachment_mixin + + Property String psApiKey "" + Property String psBaseUrl "https://app.docupipe.ai" + Property Integer piTimeoutSeconds 90 + Property Integer piRetryCount 1 + Property Boolean pbLogRawJson False + Property String psLastError "" + + Set peTransferFlags to ifSecure + Set piRemotePort to rpHttpSSL + End_Procedure + + Procedure Configure tDocuPipeConfig cfg + If (cfg.sApiKey<>'') Set psApiKey to cfg.sApiKey + If (cfg.sBaseUrl<>'') Set psBaseUrl to cfg.sBaseUrl + If (cfg.iTimeoutSeconds>0) Set piTimeoutSeconds to cfg.iTimeoutSeconds + If (cfg.iRetryCount>=0) Set piRetryCount to cfg.iRetryCount + Set pbLogRawJson to cfg.bLogRawJson + Send SetTimeout (piTimeoutSeconds(Self)) + End_Procedure + + Function HostFromBaseUrl Returns String + String sBase sHost + + Get psBaseUrl to sBase + Move (Replace("https://",sBase,"")) to sHost + Move (Replace("http://",sHost,"")) to sHost + If (Right(sHost,1)='/') Move (Left(sHost,Length(sHost)-1)) to sHost + + Function_Return sHost + End_Function + + Function NormalizePath String sPath Returns String + String sRet + Move sPath to sRet + While (Left(sRet,1)='/') + Move (Right(sRet,Length(sRet)-1)) to sRet + Loop + Function_Return sRet + End_Function + + Procedure AddStandardHeaders Boolean bJsonBody + Integer iRetVal + + Set pbClearHeaders to False + Send ClearHeaders + + Get AddHeader "Accept" "application/json" to iRetVal + Get AddHeader "X-API-Key" (psApiKey(Self)) to iRetVal + If (bJsonBody) Get AddHeader "Content-Type" "application/json" to iRetVal + End_Procedure + + Function ShouldRetry Boolean bTransferOk Integer iStatus Returns Boolean + Boolean bRetry + + Move False to bRetry + If (not(bTransferOk)) Move True to bRetry + Else If (iStatus=429) Move True to bRetry + Else If (iStatus>=500 and iStatus<=599) Move True to bRetry + + Function_Return bRetry + End_Function + + Function ExecuteJsonRequest String sVerb String sPath Handle hoRequest Returns tDocuPipeResult + tDocuPipeResult Result + Handle hoResponse + String sHost sRawJson sPathOnly + Boolean bTransferOk bJsonBody bRetry + Integer iAttempt iAttempts iStatus + + Move (Trim(sVerb)) to sVerb + Move (Uppercase(sVerb)) to sVerb + Move (NormalizePath(Self,sPath)) to sPathOnly + Move (HostFromBaseUrl(Self)) to sHost + Move (piRetryCount(Self)+1) to iAttempts + Move (hoRequest<>0) to bJsonBody + + If (psApiKey(Self)="") Begin + Move "DocuPipe API key is not configured." to Result.sError + Function_Return Result + End + + For iAttempt from 1 to iAttempts + Send AddStandardHeaders bJsonBody + + Move False to bTransferOk + If (sVerb="GET") Begin + Get HttpGetJson sHost sPathOnly (&bTransferOk) to hoResponse + End + Else Begin + Get HttpVerbJson sHost sPathOnly hoRequest sVerb (&bTransferOk) to hoResponse + End + + Get ResponseStatusCode to iStatus + Move iStatus to Result.iHttpStatus + + If (hoResponse) Begin + Move (Stringify(hoResponse)) to sRawJson + Send Destroy of hoResponse + Move 0 to hoResponse + End + Else Begin + Get DataReceived to sRawJson + End + + Move sRawJson to Result.sRawJson + Move (bTransferOk and iStatus>=200 and iStatus<300) to Result.bOk + + If (Result.bOk) Function_Return Result + + Move (ShouldRetry(Self,bTransferOk,iStatus)) to bRetry + If (not(bRetry) or iAttempt=iAttempts) Begin + If (sRawJson<>'') Move sRawJson to Result.sError + Else If (not(bTransferOk)) Move (TransferErrorDescription(Self)) to Result.sError + Else Move ('HTTP error '+String(iStatus)) to Result.sError + Function_Return Result + End + Loop + + Move "DocuPipe request failed after retries." to Result.sError + Function_Return Result + End_Function + + + Function ExtractJsonStringValue String sJson String sKey Returns String + Integer iKey iColon iStart iStop + String sNeedle sTail sValue + + Move ('"'+sKey+'"') to sNeedle + Move (Pos(sNeedle,sJson)) to iKey + If (iKey=0) Function_Return "" + + Move (Mid(sJson,Length(sJson)-iKey+1,iKey)) to sTail + Move (Pos(':',sTail)) to iColon + If (iColon=0) Function_Return "" + + Move (Mid(sTail,Length(sTail)-iColon+1,iColon)) to sTail + Move (Pos('"',sTail)) to iStart + If (iStart=0) Function_Return "" + + Move (Mid(sTail,Length(sTail)-iStart,iStart+1)) to sTail + Move (Pos('"',sTail)) to iStop + If (iStop=0) Function_Return "" + + Move (Left(sTail,iStop-1)) to sValue + Function_Return sValue + End_Function + + Function BuildDocumentFileRequest String sFilePath String sDataset String sWorkflowId Returns Handle + Handle hoReq + tAIAttachment Attachment + + Get Create (RefClass(cJsonObject)) to hoReq + Send InitializeJsonType of hoReq jsonTypeObject + + Get CreateAttachment sFilePath to Attachment + + Send SetMemberValue of hoReq "contentBase64" jsonTypeString (UCharArrayToString(Attachment.uBase64File)) + Send SetMemberValue of hoReq "mimeType" jsonTypeString Attachment.sMimeType + Send SetMemberValue of hoReq "filename" jsonTypeString sFilePath + + If (sDataset<>'') Send SetMemberValue of hoReq "dataset" jsonTypeString sDataset + If (sWorkflowId<>'') Send SetMemberValue of hoReq "workflowId" jsonTypeString sWorkflowId + + Function_Return hoReq + End_Function +End_Class diff --git a/AppSrc/cDocuPipeDocumentService.pkg b/AppSrc/cDocuPipeDocumentService.pkg new file mode 100644 index 0000000..cd9f0fd --- /dev/null +++ b/AppSrc/cDocuPipeDocumentService.pkg @@ -0,0 +1,65 @@ +Use cJsonObject.pkg +Use docupipeai.h +Use cDocuPipeClient.pkg + +Class cDocuPipeDocumentService is a cObject + + Function SubmitDocumentFromFile Handle hoClient String sFilePath String sDataset String sWorkflowId Returns tDocuPipeDocumentSubmitResponse + tDocuPipeDocumentSubmitResponse Response + tDocuPipeResult Result + Handle hoReq + + Get BuildDocumentFileRequest of hoClient sFilePath sDataset sWorkflowId to hoReq + Get ExecuteJsonRequest of hoClient "POST" "/document" hoReq to Result + Send Destroy of hoReq + + Move Result.bOk to Response.bOk + Move Result.iHttpStatus to Response.iHttpStatus + Move Result.sError to Response.sError + Move Result.sRawJson to Response.sRawJson + + If (Result.sRawJson<>'') Begin + Get ExtractJsonStringValue of hoClient Result.sRawJson "documentId" to Response.sDocumentId + If (Response.sDocumentId='') Get ExtractJsonStringValue of hoClient Result.sRawJson "document_id" to Response.sDocumentId + If (Response.sDocumentId='') Get ExtractJsonStringValue of hoClient Result.sRawJson "id" to Response.sDocumentId + End + + Function_Return Response + End_Function + + Function SubmitDocumentFromUrl Handle hoClient String sUrl String sDataset String sWorkflowId Returns tDocuPipeDocumentSubmitResponse + tDocuPipeDocumentSubmitResponse Response + tDocuPipeResult Result + Handle hoReq + + Get Create (RefClass(cJsonObject)) to hoReq + Send InitializeJsonType of hoReq jsonTypeObject + Send SetMemberValue of hoReq "url" jsonTypeString sUrl + If (sDataset<>'') Send SetMemberValue of hoReq "dataset" jsonTypeString sDataset + If (sWorkflowId<>'') Send SetMemberValue of hoReq "workflowId" jsonTypeString sWorkflowId + + Get ExecuteJsonRequest of hoClient "POST" "/document" hoReq to Result + Send Destroy of hoReq + + Move Result.bOk to Response.bOk + Move Result.iHttpStatus to Response.iHttpStatus + Move Result.sError to Response.sError + Move Result.sRawJson to Response.sRawJson + + If (Result.sRawJson<>'') Begin + Get ExtractJsonStringValue of hoClient Result.sRawJson "documentId" to Response.sDocumentId + If (Response.sDocumentId='') Get ExtractJsonStringValue of hoClient Result.sRawJson "document_id" to Response.sDocumentId + If (Response.sDocumentId='') Get ExtractJsonStringValue of hoClient Result.sRawJson "id" to Response.sDocumentId + End + + Function_Return Response + End_Function + + Function GetDocument Handle hoClient String sDocumentId Returns tDocuPipeResult + tDocuPipeResult Result + + Get ExecuteJsonRequest of hoClient "GET" ("/document/"+sDocumentId) 0 to Result + Function_Return Result + End_Function + +End_Class diff --git a/AppSrc/cDocuPipeJobService.pkg b/AppSrc/cDocuPipeJobService.pkg new file mode 100644 index 0000000..ba2adcc --- /dev/null +++ b/AppSrc/cDocuPipeJobService.pkg @@ -0,0 +1,37 @@ +Use docupipeai.h +Use cDocuPipeClient.pkg + +Class cDocuPipeJobService is a cObject + + Function GetJob Handle hoClient String sJobId Returns tDocuPipeJobResponse + tDocuPipeJobResponse Response + tDocuPipeResult Result + + Get ExecuteJsonRequest of hoClient "GET" ("/job/"+sJobId) 0 to Result + + Move Result.bOk to Response.bOk + Move Result.iHttpStatus to Response.iHttpStatus + Move Result.sError to Response.sError + Move Result.sRawJson to Response.sRawJson + Move sJobId to Response.sJobId + + If (Result.sRawJson<>'') Begin + Get ExtractJsonStringValue of hoClient Result.sRawJson "jobId" to Response.sJobId + If (Response.sJobId='') Get ExtractJsonStringValue of hoClient Result.sRawJson "job_id" to Response.sJobId + + Get ExtractJsonStringValue of hoClient Result.sRawJson "status" to Response.sStatus + Get ExtractJsonStringValue of hoClient Result.sRawJson "standardizationId" to Response.sStandardizationId + If (Response.sStandardizationId='') Get ExtractJsonStringValue of hoClient Result.sRawJson "standardization_id" to Response.sStandardizationId + End + + Function_Return Response + End_Function + + Function IsTerminalJobStatus String sStatus Returns Boolean + String sCompare + + Move (Lowercase(Trim(sStatus))) to sCompare + Function_Return (sCompare="completed" or sCompare="complete" or sCompare="failed" or sCompare="error" or sCompare="cancelled" or sCompare="canceled") + End_Function + +End_Class diff --git a/AppSrc/cDocuPipeStandardizationService.pkg b/AppSrc/cDocuPipeStandardizationService.pkg new file mode 100644 index 0000000..310761c --- /dev/null +++ b/AppSrc/cDocuPipeStandardizationService.pkg @@ -0,0 +1,74 @@ +Use cJsonObject.pkg +Use docupipeai.h +Use cDocuPipeClient.pkg + +Class cDocuPipeStandardizationService is a cObject + + Function Standardize Handle hoClient String[] aDocumentIds String sSchemaId String sGuidelines String sDisplayMode String sSplitMode String sEffortLevel Returns tDocuPipeStandardizeResponse + tDocuPipeStandardizeResponse Response + tDocuPipeResult Result + Handle hoReq hoIds hoId + Integer i iCount + + Get Create (RefClass(cJsonObject)) to hoReq + Send InitializeJsonType of hoReq jsonTypeObject + + Get Create (RefClass(cJsonObject)) to hoIds + Send InitializeJsonType of hoIds jsonTypeArray + + Move (SizeOfArray(aDocumentIds)) to iCount + For i from 0 to (iCount-1) + Get Create (RefClass(cJsonObject)) to hoId + Send InitializeJsonType of hoId jsonTypeString + Send SetStringValue of hoId aDocumentIds[i] + Send AddMember of hoIds hoId + Send Destroy of hoId + Loop + + Send SetMember of hoReq "documentIds" hoIds + Send Destroy of hoIds + + If (sSchemaId<>'') Send SetMemberValue of hoReq "schemaId" jsonTypeString sSchemaId + If (sGuidelines<>'') Send SetMemberValue of hoReq "guidelines" jsonTypeString sGuidelines + If (sDisplayMode<>'') Send SetMemberValue of hoReq "displayMode" jsonTypeString sDisplayMode + If (sSplitMode<>'') Send SetMemberValue of hoReq "splitMode" jsonTypeString sSplitMode + If (sEffortLevel<>'') Send SetMemberValue of hoReq "effortLevel" jsonTypeString sEffortLevel + + Get ExecuteJsonRequest of hoClient "POST" "/v2/standardize/batch" hoReq to Result + Send Destroy of hoReq + + Move Result.bOk to Response.bOk + Move Result.iHttpStatus to Response.iHttpStatus + Move Result.sError to Response.sError + Move Result.sRawJson to Response.sRawJson + + If (Result.sRawJson<>'') Begin + Get ExtractJsonStringValue of hoClient Result.sRawJson "jobId" to Response.sJobId + If (Response.sJobId='') Get ExtractJsonStringValue of hoClient Result.sRawJson "job_id" to Response.sJobId + If (Response.sJobId='') Get ExtractJsonStringValue of hoClient Result.sRawJson "id" to Response.sJobId + End + + Function_Return Response + End_Function + + Function GetStandardization Handle hoClient String sStandardizationId Returns tDocuPipeStandardizationGetResponse + tDocuPipeStandardizationGetResponse Response + tDocuPipeResult Result + + Get ExecuteJsonRequest of hoClient "GET" ("/standardization/"+sStandardizationId) 0 to Result + + Move Result.bOk to Response.bOk + Move Result.iHttpStatus to Response.iHttpStatus + Move Result.sError to Response.sError + Move Result.sRawJson to Response.sRawJson + Move sStandardizationId to Response.sStandardizationId + + If (Result.sRawJson<>'') Begin + Get ExtractJsonStringValue of hoClient Result.sRawJson "standardizationId" to Response.sStandardizationId + If (Response.sStandardizationId='') Get ExtractJsonStringValue of hoClient Result.sRawJson "standardization_id" to Response.sStandardizationId + Move Result.sRawJson to Response.sDataJson + End + + Function_Return Response + End_Function +End_Class diff --git a/AppSrc/docupipeai.h b/AppSrc/docupipeai.h new file mode 100644 index 0000000..4fe3f24 --- /dev/null +++ b/AppSrc/docupipeai.h @@ -0,0 +1,52 @@ +Use Windows.pkg + +Struct tDocuPipeConfig + String sApiKey + String sBaseUrl + Integer iTimeoutSeconds + Integer iRetryCount + Boolean bLogRawJson +End_Struct + +Struct tDocuPipeResult + Boolean bOk + Integer iHttpStatus + String sError + String sRawJson + String sRequestId +End_Struct + +Struct tDocuPipeDocumentSubmitResponse + Boolean bOk + Integer iHttpStatus + String sError + String sDocumentId + String sRawJson +End_Struct + +Struct tDocuPipeStandardizeResponse + Boolean bOk + Integer iHttpStatus + String sError + String sJobId + String sRawJson +End_Struct + +Struct tDocuPipeJobResponse + Boolean bOk + Integer iHttpStatus + String sError + String sJobId + String sStatus + String sStandardizationId + String sRawJson +End_Struct + +Struct tDocuPipeStandardizationGetResponse + Boolean bOk + Integer iHttpStatus + String sError + String sStandardizationId + String sRawJson + String sDataJson +End_Struct diff --git a/AppSrc/docupipeai.pkg b/AppSrc/docupipeai.pkg new file mode 100644 index 0000000..59688db --- /dev/null +++ b/AppSrc/docupipeai.pkg @@ -0,0 +1,63 @@ +Use docupipeai.h +Use cDocuPipeClient.pkg +Use cDocuPipeDocumentService.pkg +Use cDocuPipeStandardizationService.pkg +Use cDocuPipeJobService.pkg + +Class cDocuPipeInterface is a cObject + + Procedure Construct_Object + Forward Send Construct_Object + + Object oDocuPipeClient is a cDocuPipeClient + End_Object + + Object oDocuPipeDocumentService is a cDocuPipeDocumentService + End_Object + + Object oDocuPipeStandardizationService is a cDocuPipeStandardizationService + End_Object + + Object oDocuPipeJobService is a cDocuPipeJobService + End_Object + End_Procedure + + Procedure Configure tDocuPipeConfig cfg + Send Configure of (oDocuPipeClient(Self)) cfg + End_Procedure + + Function SubmitDocumentFromFile String sFilePath String sDataset String sWorkflowId Returns tDocuPipeDocumentSubmitResponse + Function_Return (SubmitDocumentFromFile(oDocuPipeDocumentService(Self),oDocuPipeClient(Self),sFilePath,sDataset,sWorkflowId)) + End_Function + + Function SubmitDocumentFromUrl String sUrl String sDataset String sWorkflowId Returns tDocuPipeDocumentSubmitResponse + Function_Return (SubmitDocumentFromUrl(oDocuPipeDocumentService(Self),oDocuPipeClient(Self),sUrl,sDataset,sWorkflowId)) + End_Function + + Function GetDocument String sDocumentId Returns tDocuPipeResult + Function_Return (GetDocument(oDocuPipeDocumentService(Self),oDocuPipeClient(Self),sDocumentId)) + End_Function + + Function Standardize String[] aDocumentIds String sSchemaId String sGuidelines String sDisplayMode String sSplitMode String sEffortLevel Returns tDocuPipeStandardizeResponse + Function_Return (Standardize(oDocuPipeStandardizationService(Self),oDocuPipeClient(Self),aDocumentIds,sSchemaId,sGuidelines,sDisplayMode,sSplitMode,sEffortLevel)) + End_Function + + Function GetJob String sJobId Returns tDocuPipeJobResponse + Function_Return (GetJob(oDocuPipeJobService(Self),oDocuPipeClient(Self),sJobId)) + End_Function + + Function GetStandardization String sStandardizationId Returns tDocuPipeStandardizationGetResponse + Function_Return (GetStandardization(oDocuPipeStandardizationService(Self),oDocuPipeClient(Self),sStandardizationId)) + End_Function + + Function IsTerminalJobStatus String sStatus Returns Boolean + Function_Return (IsTerminalJobStatus(oDocuPipeJobService(Self),sStatus)) + End_Function + +End_Class + +Global_Variable Handle ghoDocuPipe + +Object oDocuPipe is a cDocuPipeInterface + Move Self to ghoDocuPipe +End_Object diff --git a/README.md b/README.md index 6f38239..8f6f808 100644 --- a/README.md +++ b/README.md @@ -157,3 +157,58 @@ There are two views, one that allows you to submit a request to any of the four [ ] On the Request side, support other parameters besides the max tokens, model id (e.g. Temperature, number of completions, top_p, etc) [ ] REplace backup of database with a script to create tables/etc. Matt Davidian August 2025 + + +# DOCUPIPE PIPELINE INTERFACE +DocuPipe support is implemented as a parallel **document pipeline** interface (not part of `cAiInterface`). + +Primary entry point: +- `Use docupipeai.pkg` +- Global object handle: `ghoDocuPipe` + +Main async-first calls: +- `Configure tDocuPipeConfig cfg` +- `SubmitDocumentFromFile ...` / `SubmitDocumentFromUrl ...` +- `Standardize ...` +- `GetJob ...` +- `GetStandardization ...` +- `GetDocument ...` + +Example polling flow: + +```dataflex +Use docupipeai.pkg + +Procedure RunDocuPipeExample + tDocuPipeConfig cfg + tDocuPipeDocumentSubmitResponse submitResp + tDocuPipeStandardizeResponse standardizeResp + tDocuPipeJobResponse jobResp + tDocuPipeStandardizationGetResponse stdResp + String[] aDocumentIds + + Move (EnvironmentVariable(ghoEnvironment,"docupipe-api-key")) to cfg.sApiKey + Move "https://app.docupipe.ai" to cfg.sBaseUrl + Move 90 to cfg.iTimeoutSeconds + Move 1 to cfg.iRetryCount + Send Configure of ghoDocuPipe cfg + + Get SubmitDocumentFromUrl of ghoDocuPipe "https://example.com/invoice.pdf" "" "" to submitResp + If (not(submitResp.bOk)) Procedure_Return + + Move submitResp.sDocumentId to aDocumentIds[0] + + Get Standardize of ghoDocuPipe aDocumentIds "" "" "" "" "" to standardizeResp + If (not(standardizeResp.bOk)) Procedure_Return + + Repeat + Get GetJob of ghoDocuPipe standardizeResp.sJobId to jobResp + If (IsTerminalJobStatus(ghoDocuPipe,jobResp.sStatus)) Break + Sleep 2 + Until False + + If (Lowercase(jobResp.sStatus)="completed") Begin + Get GetStandardization of ghoDocuPipe jobResp.sStandardizationId to stdResp + End +End_Procedure +``` From 76b0abbb3cfc0099fdd58a750a4a66d832cd086d Mon Sep 17 00:00:00 2001 From: matthewdavidian Date: Tue, 28 Jul 2026 14:41:38 -0700 Subject: [PATCH 2/5] added sDescripton to tAttachment added sDescripton member to tAttachment struct --- AppSrc/ai.h | 1 + 1 file changed, 1 insertion(+) diff --git a/AppSrc/ai.h b/AppSrc/ai.h index b218ebf..81e1bff 100644 --- a/AppSrc/ai.h +++ b/AppSrc/ai.h @@ -12,6 +12,7 @@ Struct tAIAttachment UChar[] uBase64File String sMimeType String sFileID + String sDescription // for reference/UI only, not passed to AI at the moment End_Struct // unified structure for all AI model details From b679a423992d2c6ec05d6542beaeae3749cfe9db Mon Sep 17 00:00:00 2001 From: matthewdavidian Date: Tue, 28 Jul 2026 14:42:09 -0700 Subject: [PATCH 3/5] handle JSON attachments added mime type application/json --- AppSrc/cClaudeRequest.pkg | 1 + 1 file changed, 1 insertion(+) diff --git a/AppSrc/cClaudeRequest.pkg b/AppSrc/cClaudeRequest.pkg index 78d93aa..cc111c9 100644 --- a/AppSrc/cClaudeRequest.pkg +++ b/AppSrc/cClaudeRequest.pkg @@ -79,6 +79,7 @@ Class cClaudeRequest is a cJsonObject Send AddMember of hoContent hoDocument If (Attachments[iDoc].sMimeType='application/pdf') Send SetMemberValue of hoDocument "type" jsonTypeString "document" + else If (Attachments[iDoc].sMimeType='application/json') Send SetMemberValue of hoDocument "type" jsonTypeString "text" Else If (Left(Attachments[iDoc].sMimeType,5)='image') Send SetMemberValue of hoDocument "type" jsonTypeString "image" Else If (Left(Attachments[iDoc].sMimeType,4)='text') Send SetMemberValue of hoDocument "type" jsonTypeString "text" Else Error DFERR_PROGRAM ("Unknown attachment type:"*Attachments[iDoc].sMimeType) From 319d6581a8fc13656a601210c505938dc653178c Mon Sep 17 00:00:00 2001 From: matthewdavidian Date: Tue, 28 Jul 2026 14:42:59 -0700 Subject: [PATCH 4/5] refactored SetTimeout New code from forums, link in comment --- AppSrc/cdtJsonHttpTransfer.pkg | 56 ++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/AppSrc/cdtJsonHttpTransfer.pkg b/AppSrc/cdtJsonHttpTransfer.pkg index d27711e..4d73f39 100644 --- a/AppSrc/cdtJsonHttpTransfer.pkg +++ b/AppSrc/cdtJsonHttpTransfer.pkg @@ -3,6 +3,20 @@ Use cJSON_Mixin.pkg External_Function InternetSetOption "InternetSetOptionA" wininet.dll Handle hInet DWord dwOption Pointer buf DWord bufLen Returns Boolean External_Function InternetQueryOption "InternetQueryOptionA" wininet.dll Handle hInet DWord dwOption Pointer buf DWord bufLen Returns Boolean +Define INTERNET_OPTION_CALLBACK for 1 +Define INTERNET_OPTION_CONNECT_TIMEOUT for 2 +Define INTERNET_OPTION_CONNECT_RETRIES for 3 +Define INTERNET_OPTION_CONNECT_BACKOFF for 4 +Define INTERNET_OPTION_SEND_TIMEOUT for 5 +Define INTERNET_OPTION_CONTROL_SEND_TIMEOUT for INTERNET_OPTION_SEND_TIMEOUT +Define INTERNET_OPTION_RECEIVE_TIMEOUT for 6 +Define INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT for INTERNET_OPTION_RECEIVE_TIMEOUT +Define INTERNET_OPTION_DATA_SEND_TIMEOUT for 7 +Define INTERNET_OPTION_DATA_RECEIVE_TIMEOUT for 8 +Define INTERNET_OPTION_HANDLE_TYPE for 9 +Define INTERNET_OPTION_LISTEN_TIMEOUT for 11 +Define INTERNET_OPTION_READ_BUFFER_SIZE for 12 +Define INTERNET_OPTION_WRITE_BUFFER_SIZE for 13 Class cdtJsonHttpTransfer is a cJsonHttpTransfer @@ -94,27 +108,31 @@ Class cdtJsonHttpTransfer is a cJsonHttpTransfer End_Procedure // added because Grok is SLOOOOWWW - // https://support.dataaccess.com/Forums/showthread.php?53291-cHttpTransfer-and-TimeOuts&highlight=cHttpTransfer+timeout + // https://support.dataaccess.com/Forums/entry.php?95-How-to-change-the-internet-connection-timeout Procedure SetTimeout Integer iSeconds - Handle hInet - Integer iSize val retval - Pointer valPtr - String tmp - // - // Following code set the timeout values + String sText + DWord dwBufferLength + Boolean bQueryOptionSucceeded + Integer iCurrentReceiveTimeOut iNewReceiveTimeOut eTransferStatus - Move "XXXXX" to tmp // Make room for the response in memmory. - Move 0 to val // Make room for the response in memmory. - Move (AddressOf(val)) to valptr // Set up the pointer in memory for the response - - Get RootHandle to hInet // What Http/ftp transfer object are we using - SELF - Move ( SizeOfType(Integer)) to iSize - Move (iSeconds*1000) to val // 30 second timeout - Move (AddressOf(val)) to valptr // Identify pointer to the value - - Move (InternetSetOption( Addressof(hInet), 2, valptr, Addressof(iSize) )) to tmp // data receive timeout ?? - Move (InternetSetOption( Addressof(hInet), 5, valptr, Addressof(iSize ))) to tmp // data send timeout ?? - Move (InternetSetOption( Addressof(hInet), 6, valptr, Addressof(iSize) )) to tmp // connect time out ?? + Move (SizeOfType (Integer)) to dwBufferLength + Move 0 to iCurrentReceiveTimeOut + + Move (WinAPI_InternetQueryOption (0, INTERNET_OPTION_RECEIVE_TIMEOUT, AddressOf (iCurrentReceiveTimeOut), AddressOf (dwBufferLength))) to bQueryOptionSucceeded + Move (iSeconds*1000) to iNewReceiveTimeOut + Move (WinAPI_InternetSetOption (0, INTERNET_OPTION_RECEIVE_TIMEOUT, AddressOf (iNewReceiveTimeOut), dwBufferLength)) to bQueryOptionSucceeded + +// Get wsSayHello of oWSTestService "Vincent" to sText +// Get peTransferStatus of oWSTestService to eTransferStatus +// +// Move (WinAPI_InternetSetOption (0, INTERNET_OPTION_RECEIVE_TIMEOUT, AddressOf (iCurrentReceiveTimeOut), dwBufferLength)) to bQueryOptionSucceeded +// +// If (eTransferStatus = wssOK) Begin +// Send Info_Box sText "TestService Results" +// End +// Else Begin +// Send Stop_Box eTransferStatus "Transfer Status" +// End End_Procedure End_Class From 50d993ebdbd8fa8101c50a60bf1ab39bb3393528 Mon Sep 17 00:00:00 2001 From: matthewdavidian Date: Wed, 29 Jul 2026 16:09:01 -0700 Subject: [PATCH 5/5] Create DIAI 2025.sws initial commit --- DTAi 2025.sws | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 DTAi 2025.sws diff --git a/DTAi 2025.sws b/DTAi 2025.sws new file mode 100644 index 0000000..481bb5b --- /dev/null +++ b/DTAi 2025.sws @@ -0,0 +1,12 @@ +[Properties] +Version=25.0 +[WorkspacePaths] +ConfigFile=.\Programs\Config.ws +[Preferences] +DefaultFormHeight=12 +[Conditionals] +Is$WebApp=False +Is$Win64=False +[Projects] +Project0=ai.src +Project1=box.src