@automagik/omni 2.260603.1 → 2.260603.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -36303,9 +36303,13 @@ class AgnoClient {
36303
36303
  async deleteSession(sessionId) {
36304
36304
  const url = `${this.baseUrl}/sessions/${encodeURIComponent(sessionId)}`;
36305
36305
  const response = await this.fetchWithTimeout(url, { method: "DELETE", headers: this.getHeaders() }, this.defaultTimeoutMs);
36306
+ if (response.status === 404) {
36307
+ return { ok: true, status: response.status, sessionId, existed: false };
36308
+ }
36306
36309
  if (!response.ok) {
36307
36310
  this.handleErrorResponse(response, `deleting session ${sessionId}`);
36308
36311
  }
36312
+ return { ok: true, status: response.status, sessionId, existed: true };
36309
36313
  }
36310
36314
  }
36311
36315
  function createAgnoClient(config2) {
@@ -124967,7 +124971,7 @@ import { fileURLToPath } from "url";
124967
124971
  // package.json
124968
124972
  var package_default = {
124969
124973
  name: "@automagik/omni",
124970
- version: "2.260603.1",
124974
+ version: "2.260603.3",
124971
124975
  description: "LLM-optimized CLI for Omni",
124972
124976
  type: "module",
124973
124977
  bin: {
@@ -29981,9 +29981,13 @@ class AgnoClient {
29981
29981
  async deleteSession(sessionId) {
29982
29982
  const url = `${this.baseUrl}/sessions/${encodeURIComponent(sessionId)}`;
29983
29983
  const response = await this.fetchWithTimeout(url, { method: "DELETE", headers: this.getHeaders() }, this.defaultTimeoutMs);
29984
+ if (response.status === 404) {
29985
+ return { ok: true, status: response.status, sessionId, existed: false };
29986
+ }
29984
29987
  if (!response.ok) {
29985
29988
  this.handleErrorResponse(response, `deleting session ${sessionId}`);
29986
29989
  }
29990
+ return { ok: true, status: response.status, sessionId, existed: true };
29987
29991
  }
29988
29992
  }
29989
29993
  function createAgnoClient(config2) {
@@ -225241,7 +225245,7 @@ var init_sentry_scrub = __esm(() => {
225241
225245
  var require_package7 = __commonJS((exports, module) => {
225242
225246
  module.exports = {
225243
225247
  name: "@omni/api",
225244
- version: "2.260603.1",
225248
+ version: "2.260603.3",
225245
225249
  type: "module",
225246
225250
  exports: {
225247
225251
  ".": {
@@ -336612,6 +336616,117 @@ var init_idempotency = __esm(() => {
336612
336616
  log93 = createLogger("idempotency");
336613
336617
  });
336614
336618
 
336619
+ // ../api/src/services/agent-session-identity.ts
336620
+ function computeLegacySessionId(strategy, userId, chatId, threadId2) {
336621
+ switch (strategy) {
336622
+ case "per_user":
336623
+ return userId;
336624
+ case "per_chat":
336625
+ return chatId;
336626
+ case "per_thread":
336627
+ return `thread:${chatId}:${threadId2 ?? chatId}`;
336628
+ default:
336629
+ return `${userId}:${chatId}`;
336630
+ }
336631
+ }
336632
+ function readHeader(headers, name) {
336633
+ if (!headers || typeof headers !== "object")
336634
+ return;
336635
+ const headerMap = headers;
336636
+ const lowerName = name.toLowerCase();
336637
+ for (const [key, value] of Object.entries(headerMap)) {
336638
+ if (key.toLowerCase() === lowerName && typeof value === "string" && value.trim())
336639
+ return value.trim();
336640
+ }
336641
+ return;
336642
+ }
336643
+ function readStringField(source, names) {
336644
+ if (!source)
336645
+ return;
336646
+ for (const name of names) {
336647
+ const value = source[name];
336648
+ if (typeof value === "string" && value.trim())
336649
+ return value.trim();
336650
+ }
336651
+ return;
336652
+ }
336653
+ function extractKhalSessionIdFromRawPayload(rawPayload) {
336654
+ const direct = readStringField(rawPayload, ["khalSessionId", "khal_session_id", "session_id"]);
336655
+ if (direct)
336656
+ return direct;
336657
+ return readHeader(rawPayload?.headers, "x-khal-session-id");
336658
+ }
336659
+ function resolveKhalEnvironment(rawPayload, explicitEnvironment) {
336660
+ const explicit = explicitEnvironment?.trim();
336661
+ if (explicit)
336662
+ return explicit;
336663
+ const fromPayload = readStringField(rawPayload, ["khalEnv", "khalEnvironment", "environment", "env"]);
336664
+ if (fromPayload)
336665
+ return fromPayload;
336666
+ return readHeader(rawPayload?.headers, "x-khal-env") ?? readHeader(rawPayload?.headers, "x-khal-environment") ?? process.env.KHAL_SESSION_ENV?.trim() ?? process.env.KHAL_ENV?.trim() ?? process.env.OMNI_ENV?.trim();
336667
+ }
336668
+ function channelToKhalSessionSegment(channel5) {
336669
+ if (!channel5)
336670
+ return;
336671
+ if (channel5 === "whatsapp-gupshup")
336672
+ return "gupshup";
336673
+ if (channel5 === "whatsapp-cloud")
336674
+ return "whatsapp";
336675
+ if (channel5 === "whatsapp-baileys")
336676
+ return "whatsapp";
336677
+ return String(channel5).replace(/^channel-/, "");
336678
+ }
336679
+ function buildCanonicalKhalSessionId(input) {
336680
+ return `khal:${input.environment}:omni:${input.instanceId}:${input.channelSegment}:${input.personId}`;
336681
+ }
336682
+ function resolveKhalSessionId(input) {
336683
+ const sessionStrategy = input.sessionStrategy ?? "per_chat";
336684
+ const legacySessionId = computeLegacySessionId(sessionStrategy, input.from, input.chatId, input.threadId);
336685
+ const explicitKhalSessionId = extractKhalSessionIdFromRawPayload(input.rawPayload);
336686
+ if (explicitKhalSessionId) {
336687
+ return {
336688
+ sessionId: explicitKhalSessionId,
336689
+ legacySessionId,
336690
+ sessionStrategy,
336691
+ canonicalSessionId: explicitKhalSessionId,
336692
+ personId: input.personId ?? undefined,
336693
+ environment: resolveKhalEnvironment(input.rawPayload, input.environment),
336694
+ channelSegment: channelToKhalSessionSegment(input.channel),
336695
+ source: "explicit-khal"
336696
+ };
336697
+ }
336698
+ const environment = resolveKhalEnvironment(input.rawPayload, input.environment);
336699
+ const channelSegment = channelToKhalSessionSegment(input.channel);
336700
+ const personId = input.personId?.trim();
336701
+ if (input.providerSchema === "agno" && environment && channelSegment && personId) {
336702
+ const canonicalSessionId = buildCanonicalKhalSessionId({
336703
+ environment,
336704
+ instanceId: input.instanceId,
336705
+ channelSegment,
336706
+ personId
336707
+ });
336708
+ return {
336709
+ sessionId: canonicalSessionId,
336710
+ legacySessionId,
336711
+ sessionStrategy,
336712
+ canonicalSessionId,
336713
+ personId,
336714
+ environment,
336715
+ channelSegment,
336716
+ source: "canonical-khal"
336717
+ };
336718
+ }
336719
+ return {
336720
+ sessionId: legacySessionId,
336721
+ legacySessionId,
336722
+ sessionStrategy,
336723
+ personId: personId ?? undefined,
336724
+ environment,
336725
+ channelSegment,
336726
+ source: "legacy"
336727
+ };
336728
+ }
336729
+
336615
336730
  // ../api/src/services/message-context.ts
336616
336731
  function extractPhoneFromJid(jid) {
336617
336732
  return jid.replace(/:.*$/, "").replace(/@.*$/, "").replace(/^@/, "");
@@ -338794,9 +338909,20 @@ async function dispatchViaStreamingProvider(services, instance4, messages4, trig
338794
338909
  if (!messageTexts.length && mediaFiles.length)
338795
338910
  messageTexts.push("[Media message]");
338796
338911
  const rawThreadId = extractThreadId(messages4);
338797
- const explicitKhalSessionId = extractKhalSessionId(messages4);
338798
- const sessionId = explicitKhalSessionId ?? computeSessionId(instance4.agentSessionStrategy ?? "per_chat", senderId, chatId, rawThreadId);
338799
338912
  const rawPl = messages4[0]?.payload.rawPayload ?? {};
338913
+ const sessionIdentity = resolveKhalSessionId({
338914
+ providerSchema: resolved.provider.schema,
338915
+ sessionStrategy: instance4.agentSessionStrategy ?? "per_chat",
338916
+ from: senderId,
338917
+ chatId,
338918
+ channel: channel5,
338919
+ instanceId: instance4.id,
338920
+ personId,
338921
+ rawPayload: rawPl,
338922
+ threadId: rawThreadId
338923
+ });
338924
+ const sessionId = sessionIdentity.sessionId;
338925
+ const explicitKhalSessionId = sessionIdentity.canonicalSessionId;
338800
338926
  const replyToId = messages4[0]?.payload.replyToId ?? messages4[0]?.payload.externalId;
338801
338927
  const currentMessageIds = messages4.map((msg) => msg.payload.externalId).filter((id) => !!id);
338802
338928
  const dbContextMessages = await buildContextMessages(services, instance4, chatId, currentMessageIds);
@@ -339030,8 +339156,20 @@ async function dispatchViaProvider(services, instance4, messages4, triggerType,
339030
339156
  messageTexts.push("[Media message]");
339031
339157
  }
339032
339158
  const rawThreadId = extractThreadId(messages4);
339033
- const explicitKhalSessionId = extractKhalSessionId(messages4);
339034
- const sessionId = explicitKhalSessionId ?? computeSessionId(instance4.agentSessionStrategy ?? "per_chat", senderId, chatId, rawThreadId);
339159
+ const rawPl = messages4[0]?.payload.rawPayload ?? {};
339160
+ const sessionIdentity = resolveKhalSessionId({
339161
+ providerSchema: provider.schema,
339162
+ sessionStrategy: instance4.agentSessionStrategy ?? "per_chat",
339163
+ from: senderId,
339164
+ chatId,
339165
+ channel: channel5,
339166
+ instanceId: instance4.id,
339167
+ personId,
339168
+ rawPayload: rawPl,
339169
+ threadId: rawThreadId
339170
+ });
339171
+ const sessionId = sessionIdentity.sessionId;
339172
+ const explicitKhalSessionId = sessionIdentity.canonicalSessionId;
339035
339173
  const currentMessageIds = messages4.map((msg) => msg.payload.externalId).filter((id) => !!id);
339036
339174
  const dbContextMessages = await buildContextMessages(services, instance4, chatId, currentMessageIds);
339037
339175
  const allContextMessages = mergeContextMessages(extraContextMessages, dbContextMessages);
@@ -339970,7 +340108,16 @@ async function processReactionTrigger(services, baseInstance, payload, metadata,
339970
340108
  if (provider) {
339971
340109
  const effectivePersonId = reactionPersonId ?? metadata.personId;
339972
340110
  const senderName2 = await services.agentRunner.getSenderName(effectivePersonId, undefined);
339973
- const sessionId = computeSessionId(instance4.agentSessionStrategy ?? "per_chat", payload.from, externalChatId);
340111
+ const sessionId = resolveKhalSessionId({
340112
+ providerSchema: provider.schema,
340113
+ sessionStrategy: instance4.agentSessionStrategy ?? "per_chat",
340114
+ from: payload.from,
340115
+ chatId: externalChatId,
340116
+ channel: channel5,
340117
+ instanceId: instance4.id,
340118
+ personId: effectivePersonId,
340119
+ rawPayload: payload.rawPayload
340120
+ }).sessionId;
339974
340121
  const customerContext = await resolveCustomerContext(services, effectivePersonId);
339975
340122
  const trigger = {
339976
340123
  traceId: metadata.traceId,
@@ -349830,7 +349977,16 @@ async function sendMessage(services, instanceId, chatId, text3) {
349830
349977
  });
349831
349978
  }
349832
349979
  }
349833
- async function clearAgentSession(services, db2, instanceId, from, chatId) {
349980
+ async function resolveCleanupPersonId(services, db2, instanceId, chatId, from, metadataPersonId) {
349981
+ if (metadataPersonId?.trim())
349982
+ return metadataPersonId.trim();
349983
+ const dbChat = await services.chats.findByExternalIdSmart(instanceId, chatId);
349984
+ if (!dbChat?.id)
349985
+ return;
349986
+ const [participant] = await db2.select({ personId: chatParticipants.personId }).from(chatParticipants).where(and2(eq(chatParticipants.chatId, dbChat.id), eq(chatParticipants.platformUserId, from))).limit(1);
349987
+ return participant?.personId ?? undefined;
349988
+ }
349989
+ async function clearAgentSession(services, db2, instanceId, from, chatId, options = {}) {
349834
349990
  const instance4 = await services.agentRunner.getInstanceWithProvider(instanceId);
349835
349991
  if (!instance4?.agentId) {
349836
349992
  throw new Error("No agent configured for instance");
@@ -349840,14 +349996,31 @@ async function clearAgentSession(services, db2, instanceId, from, chatId) {
349840
349996
  throw new Error("Agent has no provider configured");
349841
349997
  }
349842
349998
  const providerRecord = await services.providers.getById(agentRow.agentProviderId);
349843
- const sessionStrategy = instance4.agentSessionStrategy ?? "per_chat";
349844
- const sessionId = computeSessionId(sessionStrategy, from, chatId);
349999
+ const personId = await resolveCleanupPersonId(services, db2, instanceId, chatId, from, options.personId);
350000
+ const identity = resolveKhalSessionId({
350001
+ providerSchema: providerRecord.schema,
350002
+ sessionStrategy: instance4.agentSessionStrategy ?? "per_chat",
350003
+ from,
350004
+ chatId,
350005
+ channel: instance4.channel,
350006
+ instanceId,
350007
+ personId,
350008
+ rawPayload: options.rawPayload
350009
+ });
350010
+ const { sessionId, legacySessionId } = identity;
350011
+ const hasKhalContext = !!identity.canonicalSessionId || !!identity.environment || !!options.rawPayload?.khalSessionId;
350012
+ if (providerRecord.schema === "agno" && hasKhalContext && identity.source === "legacy") {
350013
+ throw new Error("Canonical KHAL session resolution failed; refusing blind legacy Agno reset");
350014
+ }
349845
350015
  const dispatchInstance = { ...instance4, agentProviderId: agentRow.agentProviderId };
349846
350016
  await applyAgentFkOverrides(db2, instance4.agentId, dispatchInstance);
349847
350017
  const agentProvider = resolveProvider(providerRecord, dispatchInstance, db2);
349848
350018
  if (agentProvider?.resetSession) {
349849
350019
  await agentProvider.resetSession(sessionId, chatId, instanceId);
349850
- return { sessionId, sessionStrategy };
350020
+ if (legacySessionId !== sessionId) {
350021
+ await agentProvider.resetSession(legacySessionId, chatId, instanceId);
350022
+ }
350023
+ return identity;
349851
350024
  }
349852
350025
  if (providerRecord.schema !== "agno") {
349853
350026
  throw new Error(`Session clearing not supported for ${providerRecord.schema} providers`);
@@ -349857,18 +350030,28 @@ async function clearAgentSession(services, db2, instanceId, from, chatId) {
349857
350030
  apiKey: providerRecord.apiKey ?? "",
349858
350031
  defaultTimeoutMs: (providerRecord.defaultTimeout ?? 60) * 1000
349859
350032
  });
349860
- await client.deleteSession?.(sessionId);
349861
- return { sessionId, sessionStrategy };
350033
+ const primaryDelete = await client.deleteSession?.(sessionId);
350034
+ const legacyDelete = legacySessionId !== sessionId ? await client.deleteSession?.(legacySessionId) : undefined;
350035
+ log105.info("Agno session delete verified", {
350036
+ instanceId,
350037
+ sessionId,
350038
+ legacySessionId,
350039
+ primaryStatus: primaryDelete?.status,
350040
+ primaryExisted: primaryDelete?.existed,
350041
+ legacyStatus: legacyDelete?.status,
350042
+ legacyExisted: legacyDelete?.existed
350043
+ });
350044
+ return identity;
349862
350045
  }
349863
350046
  async function handleTrashEmojiMessage(services, db2, event) {
349864
- const { content, chatId, from } = event.payload;
350047
+ const { content, chatId } = event.payload;
349865
350048
  const { instanceId } = event.metadata;
349866
350049
  if (!instanceId || !content?.text)
349867
350050
  return;
349868
350051
  if (!isTrashEmojiOnly2(content.text))
349869
350052
  return;
349870
350053
  const result = await withIdempotency(db2, event.id, "session-cleaner", async () => {
349871
- await runTrashEmojiCleanup(services, db2, instanceId, chatId, from);
350054
+ await runTrashEmojiCleanup(services, db2, event);
349872
350055
  });
349873
350056
  if (!result.executed) {
349874
350057
  log105.debug("Trash emoji event already processed (NATS redelivery skipped)", {
@@ -349878,11 +350061,26 @@ async function handleTrashEmojiMessage(services, db2, event) {
349878
350061
  });
349879
350062
  }
349880
350063
  }
349881
- async function runTrashEmojiCleanup(services, db2, instanceId, chatId, from) {
349882
- log105.info("Trash emoji detected, clearing session", { instanceId, chatId, from });
350064
+ async function runTrashEmojiCleanup(services, db2, event) {
350065
+ const { chatId, from, rawPayload } = event.payload;
350066
+ const { instanceId, personId } = event.metadata;
350067
+ if (!instanceId)
350068
+ return;
350069
+ log105.info("Trash emoji detected, clearing session", { instanceId, chatId, from, personId });
349883
350070
  try {
349884
- const { sessionId, sessionStrategy } = await clearAgentSession(services, db2, instanceId, from, chatId);
349885
- log105.info("Session cleared successfully", { instanceId, sessionId, sessionStrategy });
350071
+ const identity = await clearAgentSession(services, db2, instanceId, from, chatId, { personId, rawPayload });
350072
+ const { sessionId, legacySessionId, sessionStrategy, source, canonicalSessionId, environment, channelSegment } = identity;
350073
+ log105.info("Session cleared successfully", {
350074
+ instanceId,
350075
+ sessionId,
350076
+ legacySessionId,
350077
+ sessionStrategy,
350078
+ source,
350079
+ canonicalSessionId,
350080
+ personId: identity.personId,
350081
+ environment,
350082
+ channelSegment
350083
+ });
349886
350084
  try {
349887
350085
  const dbChat = await services.chats.findByExternalIdSmart(instanceId, chatId);
349888
350086
  if (dbChat?.id) {
@@ -349954,7 +350152,6 @@ var init_session_cleaner = __esm(() => {
349954
350152
  init_src5();
349955
350153
  init_drizzle_orm();
349956
350154
  init_idempotency();
349957
- init_agent_runner();
349958
350155
  init_agent_dispatcher();
349959
350156
  init_loader2();
349960
350157
  log105 = createLogger("session-cleaner");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automagik/omni",
3
- "version": "2.260603.1",
3
+ "version": "2.260603.3",
4
4
  "description": "LLM-optimized CLI for Omni",
5
5
  "type": "module",
6
6
  "bin": {