refactor: normalize delivery context
Co-authored-by: adam91holt <adam91holt@users.noreply.github.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import { callGateway } from "../gateway/call.js";
|
|||||||
import { defaultRuntime } from "../runtime.js";
|
import { defaultRuntime } from "../runtime.js";
|
||||||
import {
|
import {
|
||||||
type DeliveryContext,
|
type DeliveryContext,
|
||||||
|
deliveryContextFromSession,
|
||||||
deliveryContextKey,
|
deliveryContextKey,
|
||||||
mergeDeliveryContext,
|
mergeDeliveryContext,
|
||||||
normalizeDeliveryContext,
|
normalizeDeliveryContext,
|
||||||
@@ -96,6 +97,7 @@ type AnnounceQueueItem = {
|
|||||||
enqueuedAt: number;
|
enqueuedAt: number;
|
||||||
sessionKey: string;
|
sessionKey: string;
|
||||||
origin?: DeliveryContext;
|
origin?: DeliveryContext;
|
||||||
|
originKey?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type AnnounceQueueState = {
|
type AnnounceQueueState = {
|
||||||
@@ -180,7 +182,9 @@ function enqueueAnnounce(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
queue.items.push(item);
|
const origin = normalizeDeliveryContext(item.origin);
|
||||||
|
const originKey = deliveryContextKey(origin);
|
||||||
|
queue.items.push({ ...item, origin, originKey });
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,17 +233,14 @@ function hasCrossChannelItems(items: AnnounceQueueItem[]): boolean {
|
|||||||
const keys = new Set<string>();
|
const keys = new Set<string>();
|
||||||
let hasUnkeyed = false;
|
let hasUnkeyed = false;
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const origin = normalizeDeliveryContext(item.origin);
|
if (!item.origin) {
|
||||||
if (!origin) {
|
|
||||||
hasUnkeyed = true;
|
hasUnkeyed = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!origin.channel || !origin.to) {
|
if (!item.originKey) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const key = deliveryContextKey(origin);
|
keys.add(item.originKey);
|
||||||
if (!key) return true;
|
|
||||||
keys.add(key);
|
|
||||||
}
|
}
|
||||||
if (keys.size === 0) return false;
|
if (keys.size === 0) return false;
|
||||||
if (hasUnkeyed) return true;
|
if (hasUnkeyed) return true;
|
||||||
@@ -382,14 +383,7 @@ async function maybeQueueSubagentAnnounce(params: {
|
|||||||
queueSettings.mode === "steer-backlog" ||
|
queueSettings.mode === "steer-backlog" ||
|
||||||
queueSettings.mode === "interrupt";
|
queueSettings.mode === "interrupt";
|
||||||
if (isActive && (shouldFollowup || queueSettings.mode === "steer")) {
|
if (isActive && (shouldFollowup || queueSettings.mode === "steer")) {
|
||||||
const origin = mergeDeliveryContext(
|
const origin = mergeDeliveryContext(deliveryContextFromSession(entry), params.requesterOrigin);
|
||||||
{
|
|
||||||
channel: entry?.lastChannel,
|
|
||||||
to: entry?.lastTo,
|
|
||||||
accountId: entry?.lastAccountId,
|
|
||||||
},
|
|
||||||
params.requesterOrigin,
|
|
||||||
);
|
|
||||||
enqueueAnnounce(
|
enqueueAnnounce(
|
||||||
canonicalKey,
|
canonicalKey,
|
||||||
{
|
{
|
||||||
@@ -633,11 +627,7 @@ export async function runSubagentAnnounceFlow(params: {
|
|||||||
let directOrigin = requesterOrigin;
|
let directOrigin = requesterOrigin;
|
||||||
if (!directOrigin) {
|
if (!directOrigin) {
|
||||||
const { entry } = loadRequesterSessionEntry(params.requesterSessionKey);
|
const { entry } = loadRequesterSessionEntry(params.requesterSessionKey);
|
||||||
directOrigin = normalizeDeliveryContext({
|
directOrigin = deliveryContextFromSession(entry);
|
||||||
channel: entry?.lastChannel ?? entry?.channel,
|
|
||||||
to: entry?.lastTo,
|
|
||||||
accountId: entry?.lastAccountId,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
await callGateway({
|
await callGateway({
|
||||||
method: "agent",
|
method: "agent",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import {
|
|||||||
resolveGatewayMessageChannel,
|
resolveGatewayMessageChannel,
|
||||||
} from "../../utils/message-channel.js";
|
} from "../../utils/message-channel.js";
|
||||||
import { normalizeAccountId } from "../../utils/account-id.js";
|
import { normalizeAccountId } from "../../utils/account-id.js";
|
||||||
|
import { deliveryContextFromSession } from "../../utils/delivery-context.js";
|
||||||
import type { AgentCommandOpts } from "./types.js";
|
import type { AgentCommandOpts } from "./types.js";
|
||||||
|
|
||||||
type RunResult = Awaited<
|
type RunResult = Awaited<
|
||||||
@@ -31,10 +32,11 @@ function resolveDeliveryAccountId(params: {
|
|||||||
sessionEntry?: SessionEntry;
|
sessionEntry?: SessionEntry;
|
||||||
targetMode: ChannelOutboundTargetMode;
|
targetMode: ChannelOutboundTargetMode;
|
||||||
}) {
|
}) {
|
||||||
|
const sessionOrigin = deliveryContextFromSession(params.sessionEntry);
|
||||||
return (
|
return (
|
||||||
normalizeAccountId(params.opts.accountId) ??
|
normalizeAccountId(params.opts.accountId) ??
|
||||||
(params.targetMode === "implicit"
|
(params.targetMode === "implicit"
|
||||||
? normalizeAccountId(params.sessionEntry?.lastAccountId)
|
? normalizeAccountId(sessionOrigin?.accountId)
|
||||||
: undefined)
|
: undefined)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest";
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
deliveryContextKey,
|
deliveryContextKey,
|
||||||
|
deliveryContextFromSession,
|
||||||
mergeDeliveryContext,
|
mergeDeliveryContext,
|
||||||
normalizeDeliveryContext,
|
normalizeDeliveryContext,
|
||||||
} from "./delivery-context.js";
|
} from "./delivery-context.js";
|
||||||
@@ -42,4 +43,19 @@ describe("delivery context helpers", () => {
|
|||||||
);
|
);
|
||||||
expect(deliveryContextKey({ channel: "whatsapp" })).toBeUndefined();
|
expect(deliveryContextKey({ channel: "whatsapp" })).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("derives delivery context from a session entry", () => {
|
||||||
|
expect(
|
||||||
|
deliveryContextFromSession({
|
||||||
|
channel: "webchat",
|
||||||
|
lastChannel: " whatsapp ",
|
||||||
|
lastTo: " +1777 ",
|
||||||
|
lastAccountId: " acct-9 ",
|
||||||
|
}),
|
||||||
|
).toEqual({
|
||||||
|
channel: "whatsapp",
|
||||||
|
to: "+1777",
|
||||||
|
accountId: "acct-9",
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,13 @@ export type DeliveryContext = {
|
|||||||
accountId?: string;
|
accountId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type DeliveryContextSessionSource = {
|
||||||
|
channel?: string;
|
||||||
|
lastChannel?: string;
|
||||||
|
lastTo?: string;
|
||||||
|
lastAccountId?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export function normalizeDeliveryContext(context?: DeliveryContext): DeliveryContext | undefined {
|
export function normalizeDeliveryContext(context?: DeliveryContext): DeliveryContext | undefined {
|
||||||
if (!context) return undefined;
|
if (!context) return undefined;
|
||||||
const channel = typeof context.channel === "string" ? context.channel.trim() : undefined;
|
const channel = typeof context.channel === "string" ? context.channel.trim() : undefined;
|
||||||
@@ -19,6 +26,17 @@ export function normalizeDeliveryContext(context?: DeliveryContext): DeliveryCon
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function deliveryContextFromSession(
|
||||||
|
entry?: DeliveryContextSessionSource,
|
||||||
|
): DeliveryContext | undefined {
|
||||||
|
if (!entry) return undefined;
|
||||||
|
return normalizeDeliveryContext({
|
||||||
|
channel: entry.lastChannel ?? entry.channel,
|
||||||
|
to: entry.lastTo,
|
||||||
|
accountId: entry.lastAccountId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function mergeDeliveryContext(
|
export function mergeDeliveryContext(
|
||||||
primary?: DeliveryContext,
|
primary?: DeliveryContext,
|
||||||
fallback?: DeliveryContext,
|
fallback?: DeliveryContext,
|
||||||
|
|||||||
Reference in New Issue
Block a user