Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions chatwoot-adapter/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ All notable changes to the Chatwoot Adapter plugin are documented here. The form

### Fixed

- **An empty chat list no longer retires bulk backfill permanently.** The engine returns an empty list
while it is still warming up, and the completion marker is durable — so a sweep that ran at the wrong
moment disabled bulk backfill for that session forever. The marker is left unset so a later enable
tries again.
- **Chatwoot request errors no longer carry the customer's phone number.** These errors surface in
`healthCheck`, which the dashboard renders, and the contact-search URL carries the number in its query
string. The query is dropped and the response body is no longer appended; the path still says which
Expand Down
7 changes: 7 additions & 0 deletions chatwoot-adapter/backfill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ export async function backfillAllChats(deps: InboundDeps, sessionId: string): Pr
try {
if (await deps.store.isBulkBackfilled(sessionId)) return;
const chats = (await deps.engine.getChats(sessionId)) as ChatSummary[];
// An empty list is what the engine returns while it is still warming up, and marking the sweep done
// on it retires bulk backfill permanently for this session — the marker is durable. Leave it unset
// so the next enable tries again.
if (!Array.isArray(chats) || chats.length === 0) {
deps.log('chatwoot-adapter: no chats returned; leaving bulk backfill unmarked for a later attempt');
return;
}
for (const chat of chats) {
if (chat.isGroup && !deps.relayGroups) continue;
await deps.lock.run(`${sessionId}:${chat.id}`, async () => {
Expand Down
7 changes: 7 additions & 0 deletions typebot-connector/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ All notable changes to the Typebot Connector plugin are documented here. The for

## [Unreleased]

### Fixed

- **A malformed upstream response no longer throws out of the hook.** `messages` and `clientSideActions`
were only checked for null, so a Typebot server returning either as an object or a string raised a
TypeError inside the message handler. They are array-checked now and degrade to no bubbles.


## [0.2.2] — 2026-08-12

### Changed
Expand Down
6 changes: 4 additions & 2 deletions typebot-connector/typebot-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@ export class TypebotClient {

// ── normalization ─────────────────────────────────────────────────────────────────────
function normalize(raw: any): NormalizedResponse {
const bubbles = (raw?.messages ?? []).map(normalizeBubble).filter((b: Bubble | null): b is Bubble => b !== null);
// Array-check, not just nullish: the upstream is a third-party server and `messages` arriving as an
// object or a string would otherwise throw TypeError out of a hook rather than degrade to no bubbles.
const bubbles = (Array.isArray(raw?.messages) ? raw.messages : []).map(normalizeBubble).filter((b: Bubble | null): b is Bubble => b !== null);
const input = raw?.input ? normalizeInput(raw.input) : undefined;
const redirect = (raw?.clientSideActions ?? []).find((a: any) => a?.redirect)?.redirect;
const redirect = (Array.isArray(raw?.clientSideActions) ? raw.clientSideActions : []).find((a: any) => a?.redirect)?.redirect;
return { sessionId: raw?.sessionId, bubbles, input, redirectUrl: redirect?.url };
}

Expand Down
Loading