fix: backwards compatibility for delivery context and reason detection
- isDeliveryContextExpired: contexts without timestamp are now valid (not expired) - mergeDeliveryContext: only add updatedAt if at least one input has it - resolveHeartbeatDeliveryTarget: fix allowFrom-fallback reason when explicit mode rejects - Update test for requireExplicitTarget default (now false)
This commit is contained in:
parent
e260f38a69
commit
db386bef7e
@ -408,26 +408,26 @@ describe("resolveHeartbeatDeliveryTarget", () => {
|
||||
).toThrow(/requireExplicitTarget is enabled but no explicit 'to' target was provided/);
|
||||
});
|
||||
|
||||
it("throws error when requireExplicitTarget defaults to true and no to is set", () => {
|
||||
it("allows implicit routing when requireExplicitTarget defaults to false", () => {
|
||||
const cfg: ClawdbotConfig = {
|
||||
agents: {
|
||||
defaults: {
|
||||
heartbeat: {
|
||||
target: "whatsapp",
|
||||
// requireExplicitTarget defaults to true now
|
||||
// no `to` set
|
||||
// requireExplicitTarget defaults to false (backwards compatible)
|
||||
// no `to` set - should use implicit routing
|
||||
},
|
||||
},
|
||||
},
|
||||
channels: { whatsapp: { allowFrom: ["+1555000001"] } },
|
||||
};
|
||||
// FIX-1.4: Default is now strict mode - throws if no explicit target
|
||||
expect(() =>
|
||||
resolveHeartbeatDeliveryTarget({
|
||||
cfg,
|
||||
entry: { sessionId: "test", updatedAt: 1, lastChannel: "whatsapp", lastTo: "+1555000001" },
|
||||
}),
|
||||
).toThrow(/requireExplicitTarget is enabled but no explicit 'to' target was provided/);
|
||||
// Default is backwards compatible - allows implicit routing
|
||||
const result = resolveHeartbeatDeliveryTarget({
|
||||
cfg,
|
||||
entry: { sessionId: "test", updatedAt: 1, lastChannel: "whatsapp", lastTo: "+1555000001" },
|
||||
});
|
||||
expect(result.channel).toBe("whatsapp");
|
||||
expect(result.to).toBe("+1555000001");
|
||||
});
|
||||
|
||||
it("allows heartbeat delivery when requireExplicitTarget is true and to is set", () => {
|
||||
|
||||
@ -257,7 +257,10 @@ export function resolveHeartbeatDeliveryTarget(params: {
|
||||
accountId: resolvedTarget.accountId,
|
||||
mode: "explicit",
|
||||
});
|
||||
if (explicit.ok && explicit.to !== resolved.to) {
|
||||
// Set reason to "allowFrom-fallback" if:
|
||||
// 1. Explicit mode failed (target not in allowlist) and heartbeat succeeded, OR
|
||||
// 2. Explicit mode succeeded but returned a different target than heartbeat mode
|
||||
if (!explicit.ok || (explicit.ok && explicit.to !== resolved.to)) {
|
||||
reason = "allowFrom-fallback";
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ export type DeliveryContextSessionSource = {
|
||||
* Check if a delivery context has expired based on its updatedAt timestamp.
|
||||
* @param context The delivery context to check
|
||||
* @param ttlMs TTL in milliseconds (default: 24 hours)
|
||||
* @returns true if the context has expired or has no timestamp
|
||||
* @returns true if the context has expired, false if valid or no timestamp (backwards compatible)
|
||||
*/
|
||||
export function isDeliveryContextExpired(
|
||||
context?: DeliveryContext,
|
||||
@ -72,7 +72,8 @@ export function isDeliveryContextExpired(
|
||||
): boolean {
|
||||
if (!context) return true;
|
||||
const updatedAt = context.updatedAt;
|
||||
if (typeof updatedAt !== "number" || !Number.isFinite(updatedAt)) return true;
|
||||
// Backwards compatibility: contexts without timestamps are considered valid (not expired)
|
||||
if (typeof updatedAt !== "number" || !Number.isFinite(updatedAt)) return false;
|
||||
const now = Date.now();
|
||||
return now - updatedAt > ttlMs;
|
||||
}
|
||||
@ -185,10 +186,13 @@ export function mergeDeliveryContext(
|
||||
const normalizedPrimary = normalizeDeliveryContext(primary);
|
||||
const normalizedFallback = normalizeDeliveryContext(fallback);
|
||||
if (!normalizedPrimary && !normalizedFallback) return undefined;
|
||||
// Use the most recent timestamp from either context
|
||||
const primaryUpdatedAt = normalizedPrimary?.updatedAt ?? 0;
|
||||
const fallbackUpdatedAt = normalizedFallback?.updatedAt ?? 0;
|
||||
const updatedAt = Math.max(primaryUpdatedAt, fallbackUpdatedAt) || Date.now();
|
||||
// Use the most recent timestamp from either context (only if at least one has it)
|
||||
const primaryUpdatedAt = normalizedPrimary?.updatedAt;
|
||||
const fallbackUpdatedAt = normalizedFallback?.updatedAt;
|
||||
const hasTimestamp = primaryUpdatedAt != null || fallbackUpdatedAt != null;
|
||||
const updatedAt = hasTimestamp
|
||||
? Math.max(primaryUpdatedAt ?? 0, fallbackUpdatedAt ?? 0)
|
||||
: undefined;
|
||||
return normalizeDeliveryContext({
|
||||
channel: normalizedPrimary?.channel ?? normalizedFallback?.channel,
|
||||
to: normalizedPrimary?.to ?? normalizedFallback?.to,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user