feat: persist session origin metadata across connectors
This commit is contained in:
@@ -38,6 +38,7 @@ Docs: https://docs.clawd.bot
|
|||||||
### Changes
|
### Changes
|
||||||
- Memory: add OpenAI Batch API indexing for embeddings when configured.
|
- Memory: add OpenAI Batch API indexing for embeddings when configured.
|
||||||
- Memory: enable OpenAI batch indexing by default for OpenAI embeddings.
|
- Memory: enable OpenAI batch indexing by default for OpenAI embeddings.
|
||||||
|
- Sessions: persist origin metadata across connectors for generic session explainers.
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- Memory: retry transient 5xx errors (Cloudflare) during embedding indexing.
|
- Memory: retry transient 5xx errors (Cloudflare) during embedding indexing.
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ All session state is **owned by the gateway** (the “master” Clawdbot). UI cl
|
|||||||
- Transcripts: `~/.clawdbot/agents/<agentId>/sessions/<SessionId>.jsonl` (Telegram topic sessions use `.../<SessionId>-topic-<threadId>.jsonl`).
|
- Transcripts: `~/.clawdbot/agents/<agentId>/sessions/<SessionId>.jsonl` (Telegram topic sessions use `.../<SessionId>-topic-<threadId>.jsonl`).
|
||||||
- The store is a map `sessionKey -> { sessionId, updatedAt, ... }`. Deleting entries is safe; they are recreated on demand.
|
- The store is a map `sessionKey -> { sessionId, updatedAt, ... }`. Deleting entries is safe; they are recreated on demand.
|
||||||
- Group entries may include `displayName`, `channel`, `subject`, `room`, and `space` to label sessions in UIs.
|
- Group entries may include `displayName`, `channel`, `subject`, `room`, and `space` to label sessions in UIs.
|
||||||
|
- Session entries include `origin` metadata (label + routing hints) so UIs can explain where a session came from.
|
||||||
- Clawdbot does **not** read legacy Pi/Tau session folders.
|
- Clawdbot does **not** read legacy Pi/Tau session folders.
|
||||||
|
|
||||||
## Session pruning
|
## Session pruning
|
||||||
@@ -113,3 +114,11 @@ Send these as standalone messages so they register.
|
|||||||
## Tips
|
## Tips
|
||||||
- Keep the primary key dedicated to 1:1 traffic; let groups keep their own keys.
|
- Keep the primary key dedicated to 1:1 traffic; let groups keep their own keys.
|
||||||
- When automating cleanup, delete individual keys instead of the whole store to preserve context elsewhere.
|
- When automating cleanup, delete individual keys instead of the whole store to preserve context elsewhere.
|
||||||
|
|
||||||
|
## Session origin metadata
|
||||||
|
Each session entry records where it came from (best-effort) in `origin`:
|
||||||
|
- `label`: human label (resolved from conversation label + group subject/channel)
|
||||||
|
- `provider`: normalized channel id (including extensions)
|
||||||
|
- `from`/`to`: raw routing ids from the inbound envelope
|
||||||
|
- `accountId`: provider account id (when multi-account)
|
||||||
|
- `threadId`: thread/topic id when the channel supports it
|
||||||
|
|||||||
@@ -18,7 +18,11 @@ import type { ReplyPayload } from "../../../../../src/auto-reply/types.js";
|
|||||||
import { resolveCommandAuthorizedFromAuthorizers } from "../../../../../src/channels/command-gating.js";
|
import { resolveCommandAuthorizedFromAuthorizers } from "../../../../../src/channels/command-gating.js";
|
||||||
import { formatAllowlistMatchMeta } from "../../../../../src/channels/plugins/allowlist-match.js";
|
import { formatAllowlistMatchMeta } from "../../../../../src/channels/plugins/allowlist-match.js";
|
||||||
import { loadConfig } from "../../../../../src/config/config.js";
|
import { loadConfig } from "../../../../../src/config/config.js";
|
||||||
import { resolveStorePath, updateLastRoute } from "../../../../../src/config/sessions.js";
|
import {
|
||||||
|
recordSessionMetaFromInbound,
|
||||||
|
resolveStorePath,
|
||||||
|
updateLastRoute,
|
||||||
|
} from "../../../../../src/config/sessions.js";
|
||||||
import { danger, logVerbose, shouldLogVerbose } from "../../../../../src/globals.js";
|
import { danger, logVerbose, shouldLogVerbose } from "../../../../../src/globals.js";
|
||||||
import { enqueueSystemEvent } from "../../../../../src/infra/system-events.js";
|
import { enqueueSystemEvent } from "../../../../../src/infra/system-events.js";
|
||||||
import { getChildLogger } from "../../../../../src/logging.js";
|
import { getChildLogger } from "../../../../../src/logging.js";
|
||||||
@@ -494,7 +498,7 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
|
|||||||
});
|
});
|
||||||
|
|
||||||
const groupSystemPrompt = roomConfigInfo.config?.systemPrompt?.trim() || undefined;
|
const groupSystemPrompt = roomConfigInfo.config?.systemPrompt?.trim() || undefined;
|
||||||
const ctxPayload = finalizeInboundContext({
|
const ctxPayload = finalizeInboundContext({
|
||||||
Body: body,
|
Body: body,
|
||||||
RawBody: bodyText,
|
RawBody: bodyText,
|
||||||
CommandBody: bodyText,
|
CommandBody: bodyText,
|
||||||
@@ -526,10 +530,21 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
|
|||||||
OriginatingTo: `room:${roomId}`,
|
OriginatingTo: `room:${roomId}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const storePath = resolveStorePath(cfg.session?.store, {
|
||||||
|
agentId: route.agentId,
|
||||||
|
});
|
||||||
|
void recordSessionMetaFromInbound({
|
||||||
|
storePath,
|
||||||
|
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
||||||
|
ctx: ctxPayload,
|
||||||
|
}).catch((err) => {
|
||||||
|
logger.warn(
|
||||||
|
{ error: String(err), storePath, sessionKey: ctxPayload.SessionKey ?? route.sessionKey },
|
||||||
|
"failed updating session meta",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
if (isDirectMessage) {
|
if (isDirectMessage) {
|
||||||
const storePath = resolveStorePath(cfg.session?.store, {
|
|
||||||
agentId: route.agentId,
|
|
||||||
});
|
|
||||||
await updateLastRoute({
|
await updateLastRoute({
|
||||||
storePath,
|
storePath,
|
||||||
sessionKey: route.mainSessionKey,
|
sessionKey: route.mainSessionKey,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { resolveCommandAuthorizedFromAuthorizers } from "../../../../src/channel
|
|||||||
import { formatAllowlistMatchMeta } from "../../../../src/channels/plugins/allowlist-match.js";
|
import { formatAllowlistMatchMeta } from "../../../../src/channels/plugins/allowlist-match.js";
|
||||||
import { danger, logVerbose, shouldLogVerbose } from "../../../../src/globals.js";
|
import { danger, logVerbose, shouldLogVerbose } from "../../../../src/globals.js";
|
||||||
import { enqueueSystemEvent } from "../../../../src/infra/system-events.js";
|
import { enqueueSystemEvent } from "../../../../src/infra/system-events.js";
|
||||||
|
import { recordSessionMetaFromInbound, resolveStorePath } from "../../../../src/config/sessions.js";
|
||||||
import {
|
import {
|
||||||
readChannelAllowFromStore,
|
readChannelAllowFromStore,
|
||||||
upsertChannelPairingRequest,
|
upsertChannelPairingRequest,
|
||||||
@@ -459,6 +460,17 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
|
|||||||
...mediaPayload,
|
...mediaPayload,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const storePath = resolveStorePath(cfg.session?.store, {
|
||||||
|
agentId: route.agentId,
|
||||||
|
});
|
||||||
|
void recordSessionMetaFromInbound({
|
||||||
|
storePath,
|
||||||
|
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
||||||
|
ctx: ctxPayload,
|
||||||
|
}).catch((err) => {
|
||||||
|
logVerbose(`msteams: failed updating session meta: ${String(err)}`);
|
||||||
|
});
|
||||||
|
|
||||||
if (shouldLogVerbose()) {
|
if (shouldLogVerbose()) {
|
||||||
logVerbose(`msteams inbound: from=${ctxPayload.From} preview="${preview}"`);
|
logVerbose(`msteams inbound: from=${ctxPayload.From} preview="${preview}"`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
} from "../../../src/auto-reply/command-detection.js";
|
} from "../../../src/auto-reply/command-detection.js";
|
||||||
import { finalizeInboundContext } from "../../../src/auto-reply/reply/inbound-context.js";
|
import { finalizeInboundContext } from "../../../src/auto-reply/reply/inbound-context.js";
|
||||||
import { resolveCommandAuthorizedFromAuthorizers } from "../../../src/channels/command-gating.js";
|
import { resolveCommandAuthorizedFromAuthorizers } from "../../../src/channels/command-gating.js";
|
||||||
|
import { recordSessionMetaFromInbound, resolveStorePath } from "../../../src/config/sessions.js";
|
||||||
import {
|
import {
|
||||||
ZaloApiError,
|
ZaloApiError,
|
||||||
deleteWebhook,
|
deleteWebhook,
|
||||||
@@ -552,6 +553,17 @@ async function processMessageWithPipeline(params: {
|
|||||||
OriginatingTo: `zalo:${chatId}`,
|
OriginatingTo: `zalo:${chatId}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const storePath = resolveStorePath(config.session?.store, {
|
||||||
|
agentId: route.agentId,
|
||||||
|
});
|
||||||
|
void recordSessionMetaFromInbound({
|
||||||
|
storePath,
|
||||||
|
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
||||||
|
ctx: ctxPayload,
|
||||||
|
}).catch((err) => {
|
||||||
|
runtime.error?.(`zalo: failed updating session meta: ${String(err)}`);
|
||||||
|
});
|
||||||
|
|
||||||
await deps.dispatchReplyWithBufferedBlockDispatcher({
|
await deps.dispatchReplyWithBufferedBlockDispatcher({
|
||||||
ctx: ctxPayload,
|
ctx: ctxPayload,
|
||||||
cfg: config,
|
cfg: config,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
import { mergeAllowlist, summarizeMapping } from "../../../src/channels/allowlists/resolve-utils.js";
|
import { mergeAllowlist, summarizeMapping } from "../../../src/channels/allowlists/resolve-utils.js";
|
||||||
import { finalizeInboundContext } from "../../../src/auto-reply/reply/inbound-context.js";
|
import { finalizeInboundContext } from "../../../src/auto-reply/reply/inbound-context.js";
|
||||||
import { resolveCommandAuthorizedFromAuthorizers } from "../../../src/channels/command-gating.js";
|
import { resolveCommandAuthorizedFromAuthorizers } from "../../../src/channels/command-gating.js";
|
||||||
|
import { recordSessionMetaFromInbound, resolveStorePath } from "../../../src/config/sessions.js";
|
||||||
import { loadCoreChannelDeps, type CoreChannelDeps } from "./core-bridge.js";
|
import { loadCoreChannelDeps, type CoreChannelDeps } from "./core-bridge.js";
|
||||||
import { sendMessageZalouser } from "./send.js";
|
import { sendMessageZalouser } from "./send.js";
|
||||||
import type {
|
import type {
|
||||||
@@ -299,6 +300,17 @@ async function processMessage(
|
|||||||
OriginatingTo: `zalouser:${chatId}`,
|
OriginatingTo: `zalouser:${chatId}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const storePath = resolveStorePath(config.session?.store, {
|
||||||
|
agentId: route.agentId,
|
||||||
|
});
|
||||||
|
void recordSessionMetaFromInbound({
|
||||||
|
storePath,
|
||||||
|
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
||||||
|
ctx: ctxPayload,
|
||||||
|
}).catch((err) => {
|
||||||
|
runtime.error?.(`zalouser: failed updating session meta: ${String(err)}`);
|
||||||
|
});
|
||||||
|
|
||||||
await deps.dispatchReplyWithBufferedBlockDispatcher({
|
await deps.dispatchReplyWithBufferedBlockDispatcher({
|
||||||
ctx: ctxPayload,
|
ctx: ctxPayload,
|
||||||
cfg: config,
|
cfg: config,
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ vi.mock("../config/sessions.js", () => ({
|
|||||||
resolveAgentIdFromSessionKey: () => "main",
|
resolveAgentIdFromSessionKey: () => "main",
|
||||||
resolveStorePath: () => "/tmp/sessions.json",
|
resolveStorePath: () => "/tmp/sessions.json",
|
||||||
resolveMainSessionKey: () => "agent:main:main",
|
resolveMainSessionKey: () => "agent:main:main",
|
||||||
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("./pi-embedded.js", () => embeddedRunMock);
|
vi.mock("./pi-embedded.js", () => embeddedRunMock);
|
||||||
|
|||||||
@@ -4,13 +4,11 @@ import path from "node:path";
|
|||||||
|
|
||||||
import { CURRENT_SESSION_VERSION, SessionManager } from "@mariozechner/pi-coding-agent";
|
import { CURRENT_SESSION_VERSION, SessionManager } from "@mariozechner/pi-coding-agent";
|
||||||
import { resolveSessionAgentId } from "../../agents/agent-scope.js";
|
import { resolveSessionAgentId } from "../../agents/agent-scope.js";
|
||||||
import { getChannelDock } from "../../channels/dock.js";
|
|
||||||
import { normalizeChannelId } from "../../channels/plugins/index.js";
|
|
||||||
import type { ClawdbotConfig } from "../../config/config.js";
|
import type { ClawdbotConfig } from "../../config/config.js";
|
||||||
import {
|
import {
|
||||||
buildGroupDisplayName,
|
|
||||||
DEFAULT_IDLE_MINUTES,
|
DEFAULT_IDLE_MINUTES,
|
||||||
DEFAULT_RESET_TRIGGERS,
|
DEFAULT_RESET_TRIGGERS,
|
||||||
|
deriveSessionMetaPatch,
|
||||||
type GroupKeyResolution,
|
type GroupKeyResolution,
|
||||||
loadSessionStore,
|
loadSessionStore,
|
||||||
resolveGroupSessionKey,
|
resolveGroupSessionKey,
|
||||||
@@ -237,39 +235,16 @@ export async function initSessionState(params: {
|
|||||||
lastTo,
|
lastTo,
|
||||||
lastAccountId,
|
lastAccountId,
|
||||||
};
|
};
|
||||||
if (groupResolution?.channel) {
|
const metaPatch = deriveSessionMetaPatch({
|
||||||
const channel = groupResolution.channel;
|
ctx: sessionCtxForState,
|
||||||
const subject = ctx.GroupSubject?.trim();
|
sessionKey,
|
||||||
const space = ctx.GroupSpace?.trim();
|
existing: sessionEntry,
|
||||||
const explicitChannel = ctx.GroupChannel?.trim();
|
groupResolution,
|
||||||
const normalizedChannel = normalizeChannelId(channel);
|
});
|
||||||
const isChannelProvider = Boolean(
|
if (metaPatch) {
|
||||||
normalizedChannel &&
|
sessionEntry = { ...sessionEntry, ...metaPatch };
|
||||||
getChannelDock(normalizedChannel)?.capabilities.chatTypes.includes("channel"),
|
}
|
||||||
);
|
if (!sessionEntry.chatType) {
|
||||||
const nextGroupChannel =
|
|
||||||
explicitChannel ??
|
|
||||||
((groupResolution.chatType === "channel" || isChannelProvider) &&
|
|
||||||
subject &&
|
|
||||||
subject.startsWith("#")
|
|
||||||
? subject
|
|
||||||
: undefined);
|
|
||||||
const nextSubject = nextGroupChannel ? undefined : subject;
|
|
||||||
sessionEntry.chatType = groupResolution.chatType ?? "group";
|
|
||||||
sessionEntry.channel = channel;
|
|
||||||
sessionEntry.groupId = groupResolution.id;
|
|
||||||
if (nextSubject) sessionEntry.subject = nextSubject;
|
|
||||||
if (nextGroupChannel) sessionEntry.groupChannel = nextGroupChannel;
|
|
||||||
if (space) sessionEntry.space = space;
|
|
||||||
sessionEntry.displayName = buildGroupDisplayName({
|
|
||||||
provider: sessionEntry.channel,
|
|
||||||
subject: sessionEntry.subject,
|
|
||||||
groupChannel: sessionEntry.groupChannel,
|
|
||||||
space: sessionEntry.space,
|
|
||||||
id: groupResolution.id,
|
|
||||||
key: sessionKey,
|
|
||||||
});
|
|
||||||
} else if (!sessionEntry.chatType) {
|
|
||||||
sessionEntry.chatType = "direct";
|
sessionEntry.chatType = "direct";
|
||||||
}
|
}
|
||||||
const threadLabel = ctx.ThreadLabel?.trim();
|
const threadLabel = ctx.ThreadLabel?.trim();
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
|||||||
vi.mock("../config/sessions.js", () => ({
|
vi.mock("../config/sessions.js", () => ({
|
||||||
resolveStorePath: () => "/tmp/sessions.json",
|
resolveStorePath: () => "/tmp/sessions.json",
|
||||||
loadSessionStore: () => testStore,
|
loadSessionStore: () => testStore,
|
||||||
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("../web/auth-store.js", () => ({
|
vi.mock("../web/auth-store.js", () => ({
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ vi.mock("../config/sessions.js", () => ({
|
|||||||
loadSessionStore: mocks.loadSessionStore,
|
loadSessionStore: mocks.loadSessionStore,
|
||||||
resolveMainSessionKey: mocks.resolveMainSessionKey,
|
resolveMainSessionKey: mocks.resolveMainSessionKey,
|
||||||
resolveStorePath: mocks.resolveStorePath,
|
resolveStorePath: mocks.resolveStorePath,
|
||||||
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
vi.mock("../channels/plugins/index.js", () => ({
|
vi.mock("../channels/plugins/index.js", () => ({
|
||||||
listChannelPlugins: () =>
|
listChannelPlugins: () =>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from "./sessions/group.js";
|
export * from "./sessions/group.js";
|
||||||
|
export * from "./sessions/metadata.js";
|
||||||
export * from "./sessions/main-session.js";
|
export * from "./sessions/main-session.js";
|
||||||
export * from "./sessions/paths.js";
|
export * from "./sessions/paths.js";
|
||||||
export * from "./sessions/session-key.js";
|
export * from "./sessions/session-key.js";
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import {
|
|||||||
normalizeSessionDeliveryFields,
|
normalizeSessionDeliveryFields,
|
||||||
type DeliveryContext,
|
type DeliveryContext,
|
||||||
} from "../../utils/delivery-context.js";
|
} from "../../utils/delivery-context.js";
|
||||||
|
import type { MsgContext } from "../../auto-reply/templating.js";
|
||||||
|
import { deriveSessionMetaPatch } from "./metadata.js";
|
||||||
import { mergeSessionEntry, type SessionEntry } from "./types.js";
|
import { mergeSessionEntry, type SessionEntry } from "./types.js";
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -334,6 +336,31 @@ export async function updateSessionStoreEntry(params: {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function recordSessionMetaFromInbound(params: {
|
||||||
|
storePath: string;
|
||||||
|
sessionKey: string;
|
||||||
|
ctx: MsgContext;
|
||||||
|
groupResolution?: import("./types.js").GroupKeyResolution | null;
|
||||||
|
createIfMissing?: boolean;
|
||||||
|
}): Promise<SessionEntry | null> {
|
||||||
|
const { storePath, sessionKey, ctx } = params;
|
||||||
|
const createIfMissing = params.createIfMissing ?? true;
|
||||||
|
return await updateSessionStore(storePath, (store) => {
|
||||||
|
const existing = store[sessionKey];
|
||||||
|
const patch = deriveSessionMetaPatch({
|
||||||
|
ctx,
|
||||||
|
sessionKey,
|
||||||
|
existing,
|
||||||
|
groupResolution: params.groupResolution,
|
||||||
|
});
|
||||||
|
if (!patch) return existing ?? null;
|
||||||
|
if (!existing && !createIfMissing) return null;
|
||||||
|
const next = mergeSessionEntry(existing, patch);
|
||||||
|
store[sessionKey] = next;
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export async function updateLastRoute(params: {
|
export async function updateLastRoute(params: {
|
||||||
storePath: string;
|
storePath: string;
|
||||||
sessionKey: string;
|
sessionKey: string;
|
||||||
|
|||||||
@@ -11,6 +11,17 @@ export type SessionChannelId = ChannelId | "webchat";
|
|||||||
|
|
||||||
export type SessionChatType = NormalizedChatType;
|
export type SessionChatType = NormalizedChatType;
|
||||||
|
|
||||||
|
export type SessionOrigin = {
|
||||||
|
label?: string;
|
||||||
|
provider?: string;
|
||||||
|
surface?: string;
|
||||||
|
chatType?: SessionChatType;
|
||||||
|
from?: string;
|
||||||
|
to?: string;
|
||||||
|
accountId?: string;
|
||||||
|
threadId?: string | number;
|
||||||
|
};
|
||||||
|
|
||||||
export type SessionEntry = {
|
export type SessionEntry = {
|
||||||
/**
|
/**
|
||||||
* Last delivered heartbeat payload (used to suppress duplicate heartbeat notifications).
|
* Last delivered heartbeat payload (used to suppress duplicate heartbeat notifications).
|
||||||
@@ -69,6 +80,7 @@ export type SessionEntry = {
|
|||||||
subject?: string;
|
subject?: string;
|
||||||
groupChannel?: string;
|
groupChannel?: string;
|
||||||
space?: string;
|
space?: string;
|
||||||
|
origin?: SessionOrigin;
|
||||||
deliveryContext?: DeliveryContext;
|
deliveryContext?: DeliveryContext;
|
||||||
lastChannel?: SessionChannelId;
|
lastChannel?: SessionChannelId;
|
||||||
lastTo?: string;
|
lastTo?: string;
|
||||||
|
|||||||
@@ -17,7 +17,11 @@ import {
|
|||||||
import { finalizeInboundContext } from "../../auto-reply/reply/inbound-context.js";
|
import { finalizeInboundContext } from "../../auto-reply/reply/inbound-context.js";
|
||||||
import { createReplyDispatcherWithTyping } from "../../auto-reply/reply/reply-dispatcher.js";
|
import { createReplyDispatcherWithTyping } from "../../auto-reply/reply/reply-dispatcher.js";
|
||||||
import type { ReplyPayload } from "../../auto-reply/types.js";
|
import type { ReplyPayload } from "../../auto-reply/types.js";
|
||||||
import { resolveStorePath, updateLastRoute } from "../../config/sessions.js";
|
import {
|
||||||
|
recordSessionMetaFromInbound,
|
||||||
|
resolveStorePath,
|
||||||
|
updateLastRoute,
|
||||||
|
} from "../../config/sessions.js";
|
||||||
import { danger, logVerbose, shouldLogVerbose } from "../../globals.js";
|
import { danger, logVerbose, shouldLogVerbose } from "../../globals.js";
|
||||||
import { buildAgentSessionKey } from "../../routing/resolve-route.js";
|
import { buildAgentSessionKey } from "../../routing/resolve-route.js";
|
||||||
import { resolveThreadSessionKeys } from "../../routing/session-key.js";
|
import { resolveThreadSessionKeys } from "../../routing/session-key.js";
|
||||||
@@ -264,11 +268,18 @@ export async function processDiscordMessage(ctx: DiscordMessagePreflightContext)
|
|||||||
OriginatingTo: autoThreadContext?.OriginatingTo ?? replyTarget,
|
OriginatingTo: autoThreadContext?.OriginatingTo ?? replyTarget,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const storePath = resolveStorePath(cfg.session?.store, {
|
||||||
|
agentId: route.agentId,
|
||||||
|
});
|
||||||
|
void recordSessionMetaFromInbound({
|
||||||
|
storePath,
|
||||||
|
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
||||||
|
ctx: ctxPayload,
|
||||||
|
}).catch((err) => {
|
||||||
|
logVerbose(`discord: failed updating session meta: ${String(err)}`);
|
||||||
|
});
|
||||||
|
|
||||||
if (isDirectMessage) {
|
if (isDirectMessage) {
|
||||||
const sessionCfg = cfg.session;
|
|
||||||
const storePath = resolveStorePath(sessionCfg?.store, {
|
|
||||||
agentId: route.agentId,
|
|
||||||
});
|
|
||||||
await updateLastRoute({
|
await updateLastRoute({
|
||||||
storePath,
|
storePath,
|
||||||
sessionKey: route.mainSessionKey,
|
sessionKey: route.mainSessionKey,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
import { loadConfig } from "../config/config.js";
|
import { loadConfig } from "../config/config.js";
|
||||||
import {
|
import {
|
||||||
resolveMainSessionKeyFromConfig,
|
resolveMainSessionKeyFromConfig,
|
||||||
|
snapshotSessionOrigin,
|
||||||
type SessionEntry,
|
type SessionEntry,
|
||||||
updateSessionStore,
|
updateSessionStore,
|
||||||
} from "../config/sessions.js";
|
} from "../config/sessions.js";
|
||||||
@@ -205,6 +206,7 @@ export const handleSessionsBridgeMethods: BridgeMethodHandler = async (
|
|||||||
contextTokens: entry?.contextTokens,
|
contextTokens: entry?.contextTokens,
|
||||||
sendPolicy: entry?.sendPolicy,
|
sendPolicy: entry?.sendPolicy,
|
||||||
label: entry?.label,
|
label: entry?.label,
|
||||||
|
origin: snapshotSessionOrigin(entry),
|
||||||
displayName: entry?.displayName,
|
displayName: entry?.displayName,
|
||||||
chatType: entry?.chatType,
|
chatType: entry?.chatType,
|
||||||
channel: entry?.channel,
|
channel: entry?.channel,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { stopSubagentsForRequester } from "../../auto-reply/reply/abort.js";
|
|||||||
import { clearSessionQueues } from "../../auto-reply/reply/queue.js";
|
import { clearSessionQueues } from "../../auto-reply/reply/queue.js";
|
||||||
import { loadConfig } from "../../config/config.js";
|
import { loadConfig } from "../../config/config.js";
|
||||||
import {
|
import {
|
||||||
|
snapshotSessionOrigin,
|
||||||
resolveMainSessionKey,
|
resolveMainSessionKey,
|
||||||
type SessionEntry,
|
type SessionEntry,
|
||||||
updateSessionStore,
|
updateSessionStore,
|
||||||
@@ -173,6 +174,7 @@ export const sessionsHandlers: GatewayRequestHandlers = {
|
|||||||
contextTokens: entry?.contextTokens,
|
contextTokens: entry?.contextTokens,
|
||||||
sendPolicy: entry?.sendPolicy,
|
sendPolicy: entry?.sendPolicy,
|
||||||
label: entry?.label,
|
label: entry?.label,
|
||||||
|
origin: snapshotSessionOrigin(entry),
|
||||||
lastChannel: entry?.lastChannel,
|
lastChannel: entry?.lastChannel,
|
||||||
lastTo: entry?.lastTo,
|
lastTo: entry?.lastTo,
|
||||||
skillsSnapshot: entry?.skillsSnapshot,
|
skillsSnapshot: entry?.skillsSnapshot,
|
||||||
|
|||||||
@@ -381,6 +381,8 @@ export function listSessionsFromStore(params: {
|
|||||||
const groupChannel = entry?.groupChannel;
|
const groupChannel = entry?.groupChannel;
|
||||||
const space = entry?.space;
|
const space = entry?.space;
|
||||||
const id = parsed?.id;
|
const id = parsed?.id;
|
||||||
|
const origin = entry?.origin;
|
||||||
|
const originLabel = origin?.label;
|
||||||
const displayName =
|
const displayName =
|
||||||
entry?.displayName ??
|
entry?.displayName ??
|
||||||
(channel
|
(channel
|
||||||
@@ -393,7 +395,8 @@ export function listSessionsFromStore(params: {
|
|||||||
key,
|
key,
|
||||||
})
|
})
|
||||||
: undefined) ??
|
: undefined) ??
|
||||||
entry?.label;
|
entry?.label ??
|
||||||
|
originLabel;
|
||||||
const deliveryFields = normalizeSessionDeliveryFields(entry);
|
const deliveryFields = normalizeSessionDeliveryFields(entry);
|
||||||
return {
|
return {
|
||||||
key,
|
key,
|
||||||
@@ -405,6 +408,7 @@ export function listSessionsFromStore(params: {
|
|||||||
groupChannel,
|
groupChannel,
|
||||||
space,
|
space,
|
||||||
chatType: entry?.chatType,
|
chatType: entry?.chatType,
|
||||||
|
origin,
|
||||||
updatedAt,
|
updatedAt,
|
||||||
sessionId: entry?.sessionId,
|
sessionId: entry?.sessionId,
|
||||||
systemSent: entry?.systemSent,
|
systemSent: entry?.systemSent,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export type GatewaySessionRow = {
|
|||||||
groupChannel?: string;
|
groupChannel?: string;
|
||||||
space?: string;
|
space?: string;
|
||||||
chatType?: NormalizedChatType;
|
chatType?: NormalizedChatType;
|
||||||
|
origin?: SessionEntry["origin"];
|
||||||
updatedAt: number | null;
|
updatedAt: number | null;
|
||||||
sessionId?: string;
|
sessionId?: string;
|
||||||
systemSent?: boolean;
|
systemSent?: boolean;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ vi.mock("../pairing/pairing-store.js", () => ({
|
|||||||
vi.mock("../config/sessions.js", () => ({
|
vi.mock("../config/sessions.js", () => ({
|
||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("./client.js", () => ({
|
vi.mock("./client.js", () => ({
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ vi.mock("../pairing/pairing-store.js", () => ({
|
|||||||
vi.mock("../config/sessions.js", () => ({
|
vi.mock("../config/sessions.js", () => ({
|
||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("./client.js", () => ({
|
vi.mock("./client.js", () => ({
|
||||||
|
|||||||
@@ -32,7 +32,11 @@ import {
|
|||||||
resolveChannelGroupPolicy,
|
resolveChannelGroupPolicy,
|
||||||
resolveChannelGroupRequireMention,
|
resolveChannelGroupRequireMention,
|
||||||
} from "../../config/group-policy.js";
|
} from "../../config/group-policy.js";
|
||||||
import { resolveStorePath, updateLastRoute } from "../../config/sessions.js";
|
import {
|
||||||
|
recordSessionMetaFromInbound,
|
||||||
|
resolveStorePath,
|
||||||
|
updateLastRoute,
|
||||||
|
} from "../../config/sessions.js";
|
||||||
import { danger, logVerbose, shouldLogVerbose } from "../../globals.js";
|
import { danger, logVerbose, shouldLogVerbose } from "../../globals.js";
|
||||||
import { waitForTransportReady } from "../../infra/transport-ready.js";
|
import { waitForTransportReady } from "../../infra/transport-ready.js";
|
||||||
import { mediaKindFromMime } from "../../media/constants.js";
|
import { mediaKindFromMime } from "../../media/constants.js";
|
||||||
@@ -449,11 +453,18 @@ export async function monitorIMessageProvider(opts: MonitorIMessageOpts = {}): P
|
|||||||
OriginatingTo: imessageTo,
|
OriginatingTo: imessageTo,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const storePath = resolveStorePath(cfg.session?.store, {
|
||||||
|
agentId: route.agentId,
|
||||||
|
});
|
||||||
|
void recordSessionMetaFromInbound({
|
||||||
|
storePath,
|
||||||
|
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
||||||
|
ctx: ctxPayload,
|
||||||
|
}).catch((err) => {
|
||||||
|
logVerbose(`imessage: failed updating session meta: ${String(err)}`);
|
||||||
|
});
|
||||||
|
|
||||||
if (!isGroup) {
|
if (!isGroup) {
|
||||||
const sessionCfg = cfg.session;
|
|
||||||
const storePath = resolveStorePath(sessionCfg?.store, {
|
|
||||||
agentId: route.agentId,
|
|
||||||
});
|
|
||||||
const to = (isGroup ? chatTarget : undefined) || sender;
|
const to = (isGroup ? chatTarget : undefined) || sender;
|
||||||
if (to) {
|
if (to) {
|
||||||
await updateLastRoute({
|
await updateLastRoute({
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ vi.mock("../pairing/pairing-store.js", () => ({
|
|||||||
vi.mock("../config/sessions.js", () => ({
|
vi.mock("../config/sessions.js", () => ({
|
||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const streamMock = vi.fn();
|
const streamMock = vi.fn();
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ vi.mock("../pairing/pairing-store.js", () => ({
|
|||||||
vi.mock("../config/sessions.js", () => ({
|
vi.mock("../config/sessions.js", () => ({
|
||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const streamMock = vi.fn();
|
const streamMock = vi.fn();
|
||||||
|
|||||||
@@ -20,7 +20,11 @@ import {
|
|||||||
} from "../../auto-reply/reply/history.js";
|
} from "../../auto-reply/reply/history.js";
|
||||||
import { finalizeInboundContext } from "../../auto-reply/reply/inbound-context.js";
|
import { finalizeInboundContext } from "../../auto-reply/reply/inbound-context.js";
|
||||||
import { createReplyDispatcher } from "../../auto-reply/reply/reply-dispatcher.js";
|
import { createReplyDispatcher } from "../../auto-reply/reply/reply-dispatcher.js";
|
||||||
import { resolveStorePath, updateLastRoute } from "../../config/sessions.js";
|
import {
|
||||||
|
recordSessionMetaFromInbound,
|
||||||
|
resolveStorePath,
|
||||||
|
updateLastRoute,
|
||||||
|
} from "../../config/sessions.js";
|
||||||
import { danger, logVerbose, shouldLogVerbose } from "../../globals.js";
|
import { danger, logVerbose, shouldLogVerbose } from "../../globals.js";
|
||||||
import { enqueueSystemEvent } from "../../infra/system-events.js";
|
import { enqueueSystemEvent } from "../../infra/system-events.js";
|
||||||
import { mediaKindFromMime } from "../../media/constants.js";
|
import { mediaKindFromMime } from "../../media/constants.js";
|
||||||
@@ -140,11 +144,18 @@ export function createSignalEventHandler(deps: SignalEventHandlerDeps) {
|
|||||||
OriginatingTo: signalTo,
|
OriginatingTo: signalTo,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const storePath = resolveStorePath(deps.cfg.session?.store, {
|
||||||
|
agentId: route.agentId,
|
||||||
|
});
|
||||||
|
void recordSessionMetaFromInbound({
|
||||||
|
storePath,
|
||||||
|
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
||||||
|
ctx: ctxPayload,
|
||||||
|
}).catch((err) => {
|
||||||
|
logVerbose(`signal: failed updating session meta: ${String(err)}`);
|
||||||
|
});
|
||||||
|
|
||||||
if (!entry.isGroup) {
|
if (!entry.isGroup) {
|
||||||
const sessionCfg = deps.cfg.session;
|
|
||||||
const storePath = resolveStorePath(sessionCfg?.store, {
|
|
||||||
agentId: route.agentId,
|
|
||||||
});
|
|
||||||
await updateLastRoute({
|
await updateLastRoute({
|
||||||
storePath,
|
storePath,
|
||||||
sessionKey: route.mainSessionKey,
|
sessionKey: route.mainSessionKey,
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ vi.mock("../config/sessions.js", () => ({
|
|||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
resolveSessionKey: vi.fn(),
|
resolveSessionKey: vi.fn(),
|
||||||
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("@slack/bolt", () => {
|
vi.mock("@slack/bolt", () => {
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ vi.mock("../config/sessions.js", () => ({
|
|||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
resolveSessionKey: vi.fn(),
|
resolveSessionKey: vi.fn(),
|
||||||
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("@slack/bolt", () => {
|
vi.mock("@slack/bolt", () => {
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ vi.mock("../config/sessions.js", () => ({
|
|||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
resolveSessionKey: vi.fn(),
|
resolveSessionKey: vi.fn(),
|
||||||
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("@slack/bolt", () => {
|
vi.mock("@slack/bolt", () => {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { resolveThreadSessionKeys } from "../../../routing/session-key.js";
|
|||||||
import { resolveMentionGatingWithBypass } from "../../../channels/mention-gating.js";
|
import { resolveMentionGatingWithBypass } from "../../../channels/mention-gating.js";
|
||||||
import { resolveConversationLabel } from "../../../channels/conversation-label.js";
|
import { resolveConversationLabel } from "../../../channels/conversation-label.js";
|
||||||
import { resolveControlCommandGate } from "../../../channels/command-gating.js";
|
import { resolveControlCommandGate } from "../../../channels/command-gating.js";
|
||||||
|
import { recordSessionMetaFromInbound, resolveStorePath } from "../../../config/sessions.js";
|
||||||
|
|
||||||
import type { ResolvedSlackAccount } from "../../accounts.js";
|
import type { ResolvedSlackAccount } from "../../accounts.js";
|
||||||
import { reactSlackMessage } from "../../actions.js";
|
import { reactSlackMessage } from "../../actions.js";
|
||||||
@@ -471,6 +472,24 @@ export async function prepareSlackMessage(params: {
|
|||||||
OriginatingTo: slackTo,
|
OriginatingTo: slackTo,
|
||||||
}) satisfies FinalizedMsgContext;
|
}) satisfies FinalizedMsgContext;
|
||||||
|
|
||||||
|
const storePath = resolveStorePath(ctx.cfg.session?.store, {
|
||||||
|
agentId: route.agentId,
|
||||||
|
});
|
||||||
|
void recordSessionMetaFromInbound({
|
||||||
|
storePath,
|
||||||
|
sessionKey: sessionKey,
|
||||||
|
ctx: ctxPayload,
|
||||||
|
}).catch((err) => {
|
||||||
|
ctx.logger.warn(
|
||||||
|
{
|
||||||
|
error: String(err),
|
||||||
|
storePath,
|
||||||
|
sessionKey,
|
||||||
|
},
|
||||||
|
"failed updating session meta",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const replyTarget = ctxPayload.To ?? undefined;
|
const replyTarget = ctxPayload.To ?? undefined;
|
||||||
if (!replyTarget) return null;
|
if (!replyTarget) return null;
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ import {
|
|||||||
import { finalizeInboundContext } from "../auto-reply/reply/inbound-context.js";
|
import { finalizeInboundContext } from "../auto-reply/reply/inbound-context.js";
|
||||||
import { buildMentionRegexes, matchesMentionPatterns } from "../auto-reply/reply/mentions.js";
|
import { buildMentionRegexes, matchesMentionPatterns } from "../auto-reply/reply/mentions.js";
|
||||||
import { formatLocationText, toLocationContext } from "../channels/location.js";
|
import { formatLocationText, toLocationContext } from "../channels/location.js";
|
||||||
import { resolveStorePath, updateLastRoute } from "../config/sessions.js";
|
import {
|
||||||
|
recordSessionMetaFromInbound,
|
||||||
|
resolveStorePath,
|
||||||
|
updateLastRoute,
|
||||||
|
} from "../config/sessions.js";
|
||||||
import type { ClawdbotConfig } from "../config/config.js";
|
import type { ClawdbotConfig } from "../config/config.js";
|
||||||
import type { DmPolicy, TelegramGroupConfig, TelegramTopicConfig } from "../config/types.js";
|
import type { DmPolicy, TelegramGroupConfig, TelegramTopicConfig } from "../config/types.js";
|
||||||
import { logVerbose, shouldLogVerbose } from "../globals.js";
|
import { logVerbose, shouldLogVerbose } from "../globals.js";
|
||||||
@@ -500,6 +504,17 @@ export const buildTelegramMessageContext = async ({
|
|||||||
OriginatingTo: `telegram:${chatId}`,
|
OriginatingTo: `telegram:${chatId}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const storePath = resolveStorePath(cfg.session?.store, {
|
||||||
|
agentId: route.agentId,
|
||||||
|
});
|
||||||
|
void recordSessionMetaFromInbound({
|
||||||
|
storePath,
|
||||||
|
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
||||||
|
ctx: ctxPayload,
|
||||||
|
}).catch((err) => {
|
||||||
|
logVerbose(`telegram: failed updating session meta: ${String(err)}`);
|
||||||
|
});
|
||||||
|
|
||||||
if (replyTarget && shouldLogVerbose()) {
|
if (replyTarget && shouldLogVerbose()) {
|
||||||
const preview = replyTarget.body.replace(/\s+/g, " ").slice(0, 120);
|
const preview = replyTarget.body.replace(/\s+/g, " ").slice(0, 120);
|
||||||
logVerbose(
|
logVerbose(
|
||||||
@@ -514,10 +529,6 @@ export const buildTelegramMessageContext = async ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isGroup) {
|
if (!isGroup) {
|
||||||
const sessionCfg = cfg.session;
|
|
||||||
const storePath = resolveStorePath(sessionCfg?.store, {
|
|
||||||
agentId: route.agentId,
|
|
||||||
});
|
|
||||||
await updateLastRoute({
|
await updateLastRoute({
|
||||||
storePath,
|
storePath,
|
||||||
sessionKey: route.mainSessionKey,
|
sessionKey: route.mainSessionKey,
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { shouldComputeCommandAuthorized } from "../../../auto-reply/command-dete
|
|||||||
import { finalizeInboundContext } from "../../../auto-reply/reply/inbound-context.js";
|
import { finalizeInboundContext } from "../../../auto-reply/reply/inbound-context.js";
|
||||||
import { toLocationContext } from "../../../channels/location.js";
|
import { toLocationContext } from "../../../channels/location.js";
|
||||||
import type { loadConfig } from "../../../config/config.js";
|
import type { loadConfig } from "../../../config/config.js";
|
||||||
|
import { recordSessionMetaFromInbound, resolveStorePath } from "../../../config/sessions.js";
|
||||||
import { logVerbose, shouldLogVerbose } from "../../../globals.js";
|
import { logVerbose, shouldLogVerbose } from "../../../globals.js";
|
||||||
import type { getChildLogger } from "../../../logging.js";
|
import type { getChildLogger } from "../../../logging.js";
|
||||||
import { readChannelAllowFromStore } from "../../../pairing/pairing-store.js";
|
import { readChannelAllowFromStore } from "../../../pairing/pairing-store.js";
|
||||||
@@ -33,7 +34,7 @@ import type { WebInboundMsg } from "../types.js";
|
|||||||
import { elide } from "../util.js";
|
import { elide } from "../util.js";
|
||||||
import { maybeSendAckReaction } from "./ack-reaction.js";
|
import { maybeSendAckReaction } from "./ack-reaction.js";
|
||||||
import { formatGroupMembers } from "./group-members.js";
|
import { formatGroupMembers } from "./group-members.js";
|
||||||
import { updateLastRouteInBackground } from "./last-route.js";
|
import { trackBackgroundTask, updateLastRouteInBackground } from "./last-route.js";
|
||||||
import { buildInboundLine } from "./message-line.js";
|
import { buildInboundLine } from "./message-line.js";
|
||||||
|
|
||||||
export type GroupHistoryEntry = {
|
export type GroupHistoryEntry = {
|
||||||
@@ -249,8 +250,7 @@ export async function processMessage(params: {
|
|||||||
identityName: resolveIdentityName(params.cfg, params.route.agentId),
|
identityName: resolveIdentityName(params.cfg, params.route.agentId),
|
||||||
};
|
};
|
||||||
|
|
||||||
const { queuedFinal } = await dispatchReplyWithBufferedBlockDispatcher({
|
const ctxPayload = finalizeInboundContext({
|
||||||
ctx: finalizeInboundContext({
|
|
||||||
Body: combinedBody,
|
Body: combinedBody,
|
||||||
RawBody: params.msg.body,
|
RawBody: params.msg.body,
|
||||||
CommandBody: params.msg.body,
|
CommandBody: params.msg.body,
|
||||||
@@ -283,7 +283,29 @@ export async function processMessage(params: {
|
|||||||
Surface: "whatsapp",
|
Surface: "whatsapp",
|
||||||
OriginatingChannel: "whatsapp",
|
OriginatingChannel: "whatsapp",
|
||||||
OriginatingTo: params.msg.from,
|
OriginatingTo: params.msg.from,
|
||||||
}),
|
});
|
||||||
|
|
||||||
|
const storePath = resolveStorePath(params.cfg.session?.store, {
|
||||||
|
agentId: params.route.agentId,
|
||||||
|
});
|
||||||
|
const metaTask = recordSessionMetaFromInbound({
|
||||||
|
storePath,
|
||||||
|
sessionKey: params.route.sessionKey,
|
||||||
|
ctx: ctxPayload,
|
||||||
|
}).catch((err) => {
|
||||||
|
params.replyLogger.warn(
|
||||||
|
{
|
||||||
|
error: formatError(err),
|
||||||
|
storePath,
|
||||||
|
sessionKey: params.route.sessionKey,
|
||||||
|
},
|
||||||
|
"failed updating session meta",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
trackBackgroundTask(params.backgroundTasks, metaTask);
|
||||||
|
|
||||||
|
const { queuedFinal } = await dispatchReplyWithBufferedBlockDispatcher({
|
||||||
|
ctx: ctxPayload,
|
||||||
cfg: params.cfg,
|
cfg: params.cfg,
|
||||||
replyResolver: params.replyResolver,
|
replyResolver: params.replyResolver,
|
||||||
dispatcherOptions: {
|
dispatcherOptions: {
|
||||||
|
|||||||
Reference in New Issue
Block a user