Closes #290

/claim #290

Adds an AWS Comprehend wrapper to @arakoodev/edgechains.js/ai so prompts can be PII-scrubbed before being sent to an Endpoint (OpenAI, GeminiAI, LlamaAI, RetellAI).

The issue asks for “new classes that can be chained with existing Endpoint classes (as observables)”. I exposed two surfaces over the same underlying logic so people can pick whichever matches their code:

  • AWSComprehend - promise API (detectPii, containsPii, redact, redactBatch, chain)
  • redact$, redactPii, redactPiiText, redactPiiBatch - RxJS Observable / operator API that drops into a pipe()

Files

JS/edgechains/arakoodev/src/ai/src/

  • lib/aws-comprehend/comprehend.ts - the class
  • lib/aws-comprehend/observables.ts - rxjs operators
  • lib/aws-comprehend/index.ts - barrel
  • tests/awsComprehend.test.ts - 17 vitest tests, AWS SDK mocked
  • index.ts - re-export the new symbols

JS/edgechains/examples/pii-redactor/

  • runnable example with both promise + observable demos against the existing OpenAI Endpoint

New deps in arakoodev/package.json

"@aws-sdk/client-comprehend": "^3.600.0",
"rxjs": "^7.8.1"

Usage

Promise:

import { AWSComprehend, OpenAI } from "@arakoodev/edgechains.js/ai";

const comprehend = new AWSComprehend({ region: "us-east-1" });
const openai     = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

const reply = await comprehend.chain(
    userPrompt,
    safe => openai.chat({ prompt: safe }),
    { strategy: "type" }   // -> "[EMAIL]", "[PHONE]", "[SSN]" ...
);

Observable:

import { from } from "rxjs";
import { mergeMap } from "rxjs/operators";
import { AWSComprehend, redactPii, OpenAI } from "@arakoodev/edgechains.js/ai";

const comprehend = new AWSComprehend();
const openai     = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

userPrompts$
  .pipe(
    redactPii(comprehend, { strategy: "type" }),
    mergeMap(r => openai.chat({ prompt: r.redactedText }))
  )
  .subscribe(reply => sendBack(reply));

redact() options: languageCode, piiEntityTypes (filter to specific types), minConfidence (default 0.5), redactionChar, strategy ("char" | "type" | "fixed").

Credentials resolved from constructor -> env (AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN) -> default AWS credential chain. Inputs above 100 KB are rejected before the network call (Comprehend’s hard limit).

Tests

cd JS/edgechains/arakoodev
pnpm install
pnpm test -- awsComprehend
Test Files  1 passed (1)
     Tests  17 passed (17)

Tests mock @aws-sdk/client-comprehend so they run with no AWS account. They cover detection, redaction (all three strategies + entity-type filter + confidence filter), batching, the promise chain() helper, and every observable operator including the from -> redactPii -> mergeMap(endpoint) composition that the issue asks for.

Demo

cd JS/edgechains/examples/pii-redactor
cp .env.example .env   # add AWS_* + OPENAI_API_KEY
pnpm install
pnpm start             # promise demo
pnpm run stream        # rxjs demo
ORIGINAL : Hi, I'm Sarah Chen (sarah.chen@acme.io). My phone is 415-555-0142 ...
REDACTED : Hi, I'm [NAME] ([EMAIL]). My phone is [PHONE] ...
LLM REPLY: Sure, here's a polite extension request you can send ...

IAM

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": ["comprehend:DetectPiiEntities", "comprehend:ContainsPiiEntities"],
    "Resource": "*"
  }]
}

Let me know if you’d like a different naming scheme for the operators or a different default for concurrency / minConfidence.

Claim

Total prize pool $75
Total paid $0
Status Pending
Submitted April 23, 2026
Last updated April 23, 2026

Contributors

PE

Pelumi Idowu

@Pearltechie

100%

Sponsors

AR

Arakoo.ai

@arakoodev

$25
GI

gittare

@gittare

$50