TypeScript Indexing and Search

This guide adds indexed history text and a proxied search endpoint.

New to indexing and search concepts? Read Indexing & Search first.

Prerequisites

Starting checkpoint: typescript/examples/vecelai/doc-checkpoints/03-with-history

Import Search Proxy Helpers

app.ts
  memoryServiceConfigFromEnv,
  withMemoryService,
  withProxy,
} from "@chirino/memory-service-vercelai";

const app = express();
app.use(express.text({ type: "*/*" }));

What changed: Checkpoint 07 adds memoryServiceConfigFromEnv(...), withProxy, and a shared memoryServiceConfig used by the search endpoint.

Why needed: The app can forward search requests to Memory Service while preserving user-scoped auth behavior.

Add Indexed Content to History Appends

app.ts
function indexedContent(text: string, _role: "USER" | "AI"): string {
  return text;
}

What changed: Adds the indexedContent(...) projection function.

Why needed: This is the redaction/transformation point before searchable index data is written.

app.ts

  const result = await withMemoryService(
    {
      ...memoryServiceConfig,
      conversationId,
      authorization,
      memoryContentType: "vercelai",
      userText: userMessage,
      indexer: (message) => indexedContent(message.text, message.role),

What changed: Wires indexer into withMemoryService(...).

Why needed: USER/AI history entries need an explicit searchable projection for conversation search.

Security warning indexedContent is stored as searchable index data and is not encrypted like message content. Redact or minimize sensitive values before writing it.

Expose Search Endpoint

app.ts
app.post("/v1/conversations/search", async (req, res) => {
  await withProxy(req, res, memoryServiceConfig, (proxy) =>
    proxy.searchConversations(req.body ?? {}),
  );
});

What changed: The app adds POST /v1/conversations/search and relays request body to Memory Service.

Why needed: Frontend clients can run semantic/fulltext search through the same app origin.

Make sure you define a shell function that can get the bearer token for the bob user:

function get-token() {
  curl -sSfX POST http://localhost:8081/realms/memory-service/protocol/openid-connect/token \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "client_id=memory-service-client" \
    -d "client_secret=change-me" \
    -d "grant_type=password" \
    -d "username=bob" \
    -d "password=bob" \
    | jq -r '.access_token'
}

Create searchable history:

curl -NsSfX POST http://localhost:9090/chat/f1a4d9c2-5b6e-4a7d-8c21-9b3e5d6f7555 \
  -H "Authorization: Bearer $(get-token)" \
  -H "Content-Type: text/plain" \
  -d "Give me a random number between 1 and 100."

Example output:

Sure, I can help with that.

Search conversations:

curl -sSfX POST http://localhost:9090/v1/conversations/search \
  -H "Authorization: Bearer $(get-token)" \
  -H "Content-Type: application/json" \
  -d '{"query": "random number", "searchType": "auto"}' | jq

Example output:

{
  "data": [
    {
      "conversationId": "f1a4d9c2-5b6e-4a7d-8c21-9b3e5d6f7555"
    }
  ],
  "afterCursor": null
}

Next Steps