@automagik/omni 2.260804.3 → 2.260830.2

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
@@ -32212,6 +32212,8 @@ var init_instance = __esm(() => {
32212
32212
  sessionIdPrefix: exports_external.string().max(50).nullable(),
32213
32213
  discordBotToken: exports_external.string().nullable(),
32214
32214
  slackBotToken: exports_external.string().nullable(),
32215
+ slackUserToken: exports_external.string().nullable(),
32216
+ slackAuthMode: exports_external.string().nullable(),
32215
32217
  slackAppToken: exports_external.string().nullable(),
32216
32218
  slackSigningSecret: exports_external.string().nullable(),
32217
32219
  telegramBotToken: exports_external.string().nullable(),
@@ -73107,6 +73109,9 @@ __export(exports_schema, {
73107
73109
  settingValueTypes: () => settingValueTypes,
73108
73110
  settingChangeHistoryRelations: () => settingChangeHistoryRelations,
73109
73111
  settingChangeHistory: () => settingChangeHistory,
73112
+ scheduledMessages: () => scheduledMessages,
73113
+ scheduledMessageStatuses: () => scheduledMessageStatuses,
73114
+ scheduledMessageDeliveryModes: () => scheduledMessageDeliveryModes,
73110
73115
  ruleTypes: () => ruleTypes,
73111
73116
  replyFilterMode: () => replyFilterMode,
73112
73117
  providerSchemas: () => providerSchemas,
@@ -73207,7 +73212,7 @@ __export(exports_schema, {
73207
73212
  accessRules: () => accessRules,
73208
73213
  accessModes: () => accessModes
73209
73214
  });
73210
- var channelTypes, agentTypes, agentSystems, agentEntityTypes, debounceMode, splitDelayMode, supersedeMode, replyFilterMode, agentSessionStrategies, ruleTypes, accessModes, settingValueTypes, apiKeyStatuses, apiKeyProfiles, eventTypes, contentTypes, chatTypes, messageSources, messageTypes, messageStatuses, deliveryStatuses, jobStatuses, providerSchemas, agentProviders, agents, agentRoutes, agentSessions, apiKeys, apiKeyAuditLogs, apiKeysRelations, apiKeyAuditLogsRelations, instances, whatsappTemplates, whatsappFlowKeys, persons, platformIdentities, conversations, chats, chatParticipants, omniGroups, messages2, omniEvents, handoffLogs, closeContactOutcomes, closeContactLogs, accessRules, globalSettings, settingChangeHistory, batchJobs, syncJobTypes, syncJobs, mediaContent, chatIdMappings, pluginStorage, agentProvidersRelations, agentsRelations, instancesRelations, syncJobsRelations, personsRelations, platformIdentitiesRelations, conversationsRelations, chatsRelations, chatParticipantsRelations, messagesRelations, omniEventsRelations, accessRulesRelations, globalSettingsRelations, settingChangeHistoryRelations, batchJobsRelations, mediaContentRelations, chatIdMappingsRelations, deadLetterStatuses, deadLetterEvents, payloadStorageConfig, payloadStages, eventPayloads, webhookSources, conditionOperators, actionTypes, automationDebounceModes, automations2, automationLogStatuses, automationLogs, consumerOffsets, automationsRelations, automationLogsRelations, triggerLogs, triggerLogsRelations, agentRoutesRelations, agentTaskStatuses, agentTasks, agentTasksRelations, turnStatuses, turnActions, turns, turnsRelations, followUpDisarmReasons, chatFollowUpState, chatFollowUpStateRelations, processedEvents, genieHosts, tenantStatuses, principalTypes, principalStatuses, tenantRoles, membershipStatuses, credentialClasses, authCredentialStatuses, platformApiKeyStatuses, tenants, principals, tenantMemberships, tenantRolePolicies, platformApiKeys, tenantKeyLineage, authCredentials, tenantAuditLogs, platformAuditLogs, platformProviderCatalog, tenantProviderConfig, platformSettings, tenantSettings, platformSettingChangeHistory, tenantSettingChangeHistory, platformPluginStorage, tenantPluginStorage, platformPayloadStorageConfig, tenantPayloadStorageOverrides, tenantMigrationLedger, tenantMigrationLedgerHistory;
73215
+ var channelTypes, agentTypes, agentSystems, agentEntityTypes, debounceMode, splitDelayMode, supersedeMode, replyFilterMode, agentSessionStrategies, ruleTypes, accessModes, settingValueTypes, apiKeyStatuses, apiKeyProfiles, eventTypes, contentTypes, chatTypes, messageSources, messageTypes, messageStatuses, deliveryStatuses, scheduledMessageDeliveryModes, scheduledMessageStatuses, jobStatuses, providerSchemas, agentProviders, agents, agentRoutes, agentSessions, apiKeys, apiKeyAuditLogs, apiKeysRelations, apiKeyAuditLogsRelations, instances, whatsappTemplates, whatsappFlowKeys, scheduledMessages, persons, platformIdentities, conversations, chats, chatParticipants, omniGroups, messages2, omniEvents, handoffLogs, closeContactOutcomes, closeContactLogs, accessRules, globalSettings, settingChangeHistory, batchJobs, syncJobTypes, syncJobs, mediaContent, chatIdMappings, pluginStorage, agentProvidersRelations, agentsRelations, instancesRelations, syncJobsRelations, personsRelations, platformIdentitiesRelations, conversationsRelations, chatsRelations, chatParticipantsRelations, messagesRelations, omniEventsRelations, accessRulesRelations, globalSettingsRelations, settingChangeHistoryRelations, batchJobsRelations, mediaContentRelations, chatIdMappingsRelations, deadLetterStatuses, deadLetterEvents, payloadStorageConfig, payloadStages, eventPayloads, webhookSources, conditionOperators, actionTypes, automationDebounceModes, automations2, automationLogStatuses, automationLogs, consumerOffsets, automationsRelations, automationLogsRelations, triggerLogs, triggerLogsRelations, agentRoutesRelations, agentTaskStatuses, agentTasks, agentTasksRelations, turnStatuses, turnActions, turns, turnsRelations, followUpDisarmReasons, chatFollowUpState, chatFollowUpStateRelations, processedEvents, genieHosts, tenantStatuses, principalTypes, principalStatuses, tenantRoles, membershipStatuses, credentialClasses, authCredentialStatuses, platformApiKeyStatuses, tenants, principals, tenantMemberships, tenantRolePolicies, platformApiKeys, tenantKeyLineage, authCredentials, tenantAuditLogs, platformAuditLogs, platformProviderCatalog, tenantProviderConfig, platformSettings, tenantSettings, platformSettingChangeHistory, tenantSettingChangeHistory, platformPluginStorage, tenantPluginStorage, platformPayloadStorageConfig, tenantPayloadStorageOverrides, tenantMigrationLedger, tenantMigrationLedgerHistory;
73211
73216
  var init_schema2 = __esm(() => {
73212
73217
  init_events();
73213
73218
  init_types5();
@@ -73282,6 +73287,8 @@ var init_schema2 = __esm(() => {
73282
73287
  ];
73283
73288
  messageStatuses = ["active", "edited", "deleted", "expired"];
73284
73289
  deliveryStatuses = ["pending", "sent", "delivered", "read", "failed"];
73290
+ scheduledMessageDeliveryModes = ["platform", "local"];
73291
+ scheduledMessageStatuses = ["pending", "sending", "sent", "canceled", "failed"];
73285
73292
  jobStatuses = ["pending", "running", "completed", "failed", "cancelled"];
73286
73293
  providerSchemas = [
73287
73294
  "agno",
@@ -73484,6 +73491,8 @@ var init_schema2 = __esm(() => {
73484
73491
  guildConfigOverrides: jsonb("guild_config_overrides").$type(),
73485
73492
  discordPresence: jsonb("discord_presence").$type(),
73486
73493
  slackBotToken: text("slack_bot_token"),
73494
+ slackUserToken: text("slack_user_token"),
73495
+ slackAuthMode: varchar("slack_auth_mode", { length: 10 }),
73487
73496
  slackAppToken: text("slack_app_token"),
73488
73497
  slackSigningSecret: text("slack_signing_secret"),
73489
73498
  telegramBotToken: text("telegram_bot_token"),
@@ -73628,6 +73637,31 @@ var init_schema2 = __esm(() => {
73628
73637
  }, (t) => ({
73629
73638
  instanceUnique: uniqueIndex("idx_wa_flow_keys_instance").on(t.instanceId)
73630
73639
  }));
73640
+ scheduledMessages = pgTable("scheduled_messages", {
73641
+ id: uuid("id").primaryKey().defaultRandom(),
73642
+ instanceId: uuid("instance_id").notNull().references(() => instances.id, { onDelete: "cascade" }),
73643
+ chatExternalId: varchar("chat_external_id", { length: 255 }).notNull(),
73644
+ threadExternalId: varchar("thread_external_id", { length: 255 }),
73645
+ isThreadBroadcast: boolean("is_thread_broadcast").notNull().default(false),
73646
+ content: jsonb("content").$type().notNull(),
73647
+ sendAt: timestamp("send_at", { withTimezone: true }).notNull(),
73648
+ deliveryMode: varchar("delivery_mode", { length: 20 }).notNull().$type(),
73649
+ status: varchar("status", { length: 20 }).notNull().default("pending").$type(),
73650
+ externalScheduledId: varchar("external_scheduled_id", { length: 255 }),
73651
+ sentExternalId: varchar("sent_external_id", { length: 255 }),
73652
+ sentAt: timestamp("sent_at", { withTimezone: true }),
73653
+ canceledAt: timestamp("canceled_at", { withTimezone: true }),
73654
+ failedAt: timestamp("failed_at", { withTimezone: true }),
73655
+ lastError: text("last_error"),
73656
+ attemptCount: integer("attempt_count").notNull().default(0),
73657
+ createdByAgentId: uuid("created_by_agent_id"),
73658
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
73659
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
73660
+ }, (t) => ({
73661
+ dueIdx: index("scheduled_messages_due_idx").on(t.status, t.sendAt),
73662
+ instanceIdx: index("scheduled_messages_instance_idx").on(t.instanceId, t.status),
73663
+ chatIdx: index("scheduled_messages_chat_idx").on(t.instanceId, t.chatExternalId)
73664
+ }));
73631
73665
  persons = pgTable("persons", {
73632
73666
  id: uuid("id").primaryKey().defaultRandom(),
73633
73667
  displayName: varchar("display_name", { length: 255 }),
@@ -73812,6 +73846,15 @@ var init_schema2 = __esm(() => {
73812
73846
  replyToExternalId: varchar("reply_to_external_id", { length: 255 }),
73813
73847
  quotedText: text("quoted_text"),
73814
73848
  quotedSenderName: varchar("quoted_sender_name", { length: 255 }),
73849
+ threadExternalId: varchar("thread_external_id", { length: 255 }),
73850
+ threadRootMessageId: uuid("thread_root_message_id"),
73851
+ isThreadBroadcast: boolean("is_thread_broadcast").notNull().default(false),
73852
+ replyCount: integer("reply_count").notNull().default(0),
73853
+ latestReplyAt: timestamp("latest_reply_at", { withTimezone: true }),
73854
+ permalink: text("permalink"),
73855
+ pinnedAt: timestamp("pinned_at", { withTimezone: true }),
73856
+ pinnedBy: varchar("pinned_by", { length: 255 }),
73857
+ starredAt: timestamp("starred_at", { withTimezone: true }),
73815
73858
  forwardedFromMessageId: uuid("forwarded_from_message_id"),
73816
73859
  forwardedFromExternalId: varchar("forwarded_from_external_id", { length: 255 }),
73817
73860
  forwardCount: integer("forward_count").notNull().default(0),
@@ -73849,6 +73892,8 @@ var init_schema2 = __esm(() => {
73849
73892
  platformTimestampIdx: index("messages_platform_timestamp_idx").on(table3.platformTimestamp),
73850
73893
  replyToIdx: index("messages_reply_to_idx").on(table3.replyToMessageId),
73851
73894
  replyToExternalIdx: index("messages_reply_to_external_idx").on(table3.chatId, table3.replyToExternalId, table3.isFromMe),
73895
+ threadExternalIdx: index("messages_thread_external_idx").on(table3.chatId, table3.threadExternalId, table3.platformTimestamp),
73896
+ threadRootIdx: index("messages_thread_root_idx").on(table3.threadRootMessageId),
73852
73897
  hasMediaIdx: index("messages_has_media_idx").on(table3.hasMedia),
73853
73898
  originalEventIdx: index("messages_original_event_idx").on(table3.originalEventId)
73854
73899
  }));
@@ -126388,6 +126433,31 @@ function createOmniClient(config) {
126388
126433
  throwIfError(response, error);
126389
126434
  return data?.data ?? { code: "", phoneNumber: "", message: "", expiresIn: 0 };
126390
126435
  },
126436
+ async passkey(id) {
126437
+ const response = await apiFetch(`${baseUrl}/api/v2/instances/${id}/passkey`, {});
126438
+ const json = await response.json();
126439
+ if (!response.ok)
126440
+ throw OmniApiError.from(json, response.status);
126441
+ return json.data ?? null;
126442
+ },
126443
+ async submitPasskey(id, credential) {
126444
+ const response = await apiFetch(`${baseUrl}/api/v2/instances/${id}/passkey/response`, {
126445
+ method: "POST",
126446
+ headers: { "Content-Type": "application/json" },
126447
+ body: JSON.stringify(credential)
126448
+ });
126449
+ const json = await response.json();
126450
+ if (!response.ok)
126451
+ throw OmniApiError.from(json, response.status);
126452
+ },
126453
+ async confirmPasskey(id) {
126454
+ const response = await apiFetch(`${baseUrl}/api/v2/instances/${id}/passkey/confirm`, {
126455
+ method: "POST"
126456
+ });
126457
+ const json = await response.json();
126458
+ if (!response.ok)
126459
+ throw OmniApiError.from(json, response.status);
126460
+ },
126391
126461
  async syncProfile(id) {
126392
126462
  const resp = await apiFetch(`${baseUrl}/api/v2/instances/${id}/sync/profile`, {
126393
126463
  method: "POST"
@@ -127931,6 +128001,68 @@ function createOmniClient(config) {
127931
128001
  throwIfError(response, error);
127932
128002
  }
127933
128003
  },
128004
+ scheduledMessages: {
128005
+ async schedule(input) {
128006
+ const resp = await apiFetch(`${baseUrl}/api/v2/scheduled-messages`, {
128007
+ method: "POST",
128008
+ headers: { "Content-Type": "application/json" },
128009
+ body: JSON.stringify(input)
128010
+ });
128011
+ const json = await resp.json();
128012
+ if (!resp.ok)
128013
+ throw OmniApiError.from(json, resp.status);
128014
+ return json?.data ?? {};
128015
+ },
128016
+ async listPending(instanceId, limit) {
128017
+ const query = new URLSearchParams({ instanceId });
128018
+ if (limit !== undefined)
128019
+ query.set("limit", String(limit));
128020
+ const resp = await apiFetch(`${baseUrl}/api/v2/scheduled-messages?${query}`);
128021
+ const json = await resp.json();
128022
+ if (!resp.ok)
128023
+ throw OmniApiError.from(json, resp.status);
128024
+ return json?.data ?? [];
128025
+ },
128026
+ async get(id) {
128027
+ const resp = await apiFetch(`${baseUrl}/api/v2/scheduled-messages/${id}`);
128028
+ const json = await resp.json();
128029
+ if (!resp.ok)
128030
+ throw OmniApiError.from(json, resp.status);
128031
+ return json?.data ?? null;
128032
+ },
128033
+ async cancel(id) {
128034
+ const resp = await apiFetch(`${baseUrl}/api/v2/scheduled-messages/${id}`, { method: "DELETE" });
128035
+ const json = await resp.json();
128036
+ if (!resp.ok)
128037
+ throw OmniApiError.from(json, resp.status);
128038
+ return json?.data ?? {};
128039
+ }
128040
+ },
128041
+ slack: {
128042
+ async openDm(instanceId, userId) {
128043
+ const resp = await apiFetch(`${baseUrl}/api/v2/slack/dm/open`, {
128044
+ method: "POST",
128045
+ headers: { "Content-Type": "application/json" },
128046
+ body: JSON.stringify({ instanceId, userId })
128047
+ });
128048
+ const json = await resp.json();
128049
+ if (!resp.ok)
128050
+ throw OmniApiError.from(json, resp.status);
128051
+ return json?.data ?? { userId, channelId: "" };
128052
+ },
128053
+ async search(instanceId, query, options) {
128054
+ const params = new URLSearchParams({ instanceId, query });
128055
+ if (options?.count !== undefined)
128056
+ params.set("count", String(options.count));
128057
+ if (options?.page !== undefined)
128058
+ params.set("page", String(options.page));
128059
+ const resp = await apiFetch(`${baseUrl}/api/v2/slack/search?${params}`);
128060
+ const json = await resp.json();
128061
+ if (!resp.ok)
128062
+ throw OmniApiError.from(json, resp.status);
128063
+ return json?.data ?? [];
128064
+ }
128065
+ },
127934
128066
  followUp: {
127935
128067
  async getAgent(id) {
127936
128068
  const resp = await apiFetch(`${baseUrl}/api/v2/follow-up/agents/${id}`);
@@ -128149,7 +128281,7 @@ import { fileURLToPath } from "url";
128149
128281
  // package.json
128150
128282
  var package_default = {
128151
128283
  name: "@automagik/omni",
128152
- version: "2.260804.3",
128284
+ version: "2.260830.2",
128153
128285
  description: "LLM-optimized CLI for Omni",
128154
128286
  type: "module",
128155
128287
  bin: {
@@ -131905,19 +132037,33 @@ function createConfigCommand() {
131905
132037
  // src/commands/connect.ts
131906
132038
  import { execFileSync as execFileSync2 } from "child_process";
131907
132039
  init_output();
131908
- async function findOrCreateProvider(client, agentName, agentEntry, natsUrl) {
132040
+
132041
+ // src/commands/_setup-helpers.ts
132042
+ init_output();
132043
+ function schemaToAgentProvider(schema) {
132044
+ switch (schema) {
132045
+ case "agno":
132046
+ return "agno";
132047
+ case "claude-code":
132048
+ return "claude";
132049
+ default:
132050
+ return "custom";
132051
+ }
132052
+ }
132053
+ async function findOrCreateProvider(client, args) {
131909
132054
  try {
131910
132055
  const provider = await client.providers.create({
131911
- name: `nats-genie-${agentName}`,
131912
- schema: "nats-genie",
131913
- baseUrl: `nats://${natsUrl}`,
131914
- schemaConfig: { agentName: agentEntry.name, agentDir: agentEntry.dir, natsUrl }
132056
+ name: args.name,
132057
+ schema: args.schema,
132058
+ baseUrl: args.baseUrl,
132059
+ apiKey: args.apiKey,
132060
+ schemaConfig: args.schemaConfig
131915
132061
  });
131916
132062
  return provider.id;
131917
132063
  } catch {
131918
132064
  try {
131919
132065
  const providers = await client.providers.list();
131920
- const existing = providers.find((p) => p.name === `nats-genie-${agentName}` && p.schema === "nats-genie");
132066
+ const existing = providers.find((p) => p.name === args.name && p.schema === args.schema);
131921
132067
  if (existing) {
131922
132068
  info(`Using existing provider: ${existing.id}`);
131923
132069
  return existing.id;
@@ -131927,22 +132073,23 @@ async function findOrCreateProvider(client, agentName, agentEntry, natsUrl) {
131927
132073
  return null;
131928
132074
  }
131929
132075
  }
131930
- async function findOrCreateAgent(client, agentName, providerId) {
132076
+ async function findOrCreateAgent(client, args) {
131931
132077
  try {
131932
132078
  const agent = await client.agents.create({
131933
- name: agentName,
131934
- agentProviderId: providerId,
131935
- agentType: "assistant",
131936
- provider: "custom",
131937
- capabilities: [],
131938
- isInternal: false,
131939
- isActive: true
132079
+ name: args.name,
132080
+ agentProviderId: args.providerId,
132081
+ agentType: args.agentType ?? "assistant",
132082
+ provider: args.agentProvider,
132083
+ model: args.model,
132084
+ capabilities: args.capabilities ?? [],
132085
+ isInternal: args.isInternal ?? false,
132086
+ isActive: args.isActive ?? true
131940
132087
  });
131941
132088
  return agent.id;
131942
132089
  } catch {
131943
132090
  try {
131944
132091
  const { items } = await client.agents.list();
131945
- const existing = items.find((a) => a.name === agentName && a.agentProviderId === providerId);
132092
+ const existing = items.find((a) => a.name === args.name && a.agentProviderId === args.providerId);
131946
132093
  if (existing) {
131947
132094
  info(`Using existing agent: ${existing.id}`);
131948
132095
  return existing.id;
@@ -131952,6 +132099,8 @@ async function findOrCreateAgent(client, agentName, providerId) {
131952
132099
  return null;
131953
132100
  }
131954
132101
  }
132102
+
132103
+ // src/commands/connect.ts
131955
132104
  function createConnectCommand() {
131956
132105
  return new Command("connect").description("Connect an Omni instance to a Genie agent via NATS").argument("<instance-id>", "Omni instance ID").argument("<agent-name>", "Genie agent name (from genie directory)").option("--nats-url <url>", "NATS server URL", "localhost:4222").option("--mode <mode>", "Trigger mode: turn-based (round-trip) or fire-and-forget", "turn-based").option("--reply-filter <filter>", "Reply filter: all (reply to everything) or filtered", "all").action(async (instanceId, agentName, options) => {
131957
132106
  const client = getClient();
@@ -131978,11 +132127,20 @@ Make sure genie is installed and the agent is registered:
131978
132127
  return;
131979
132128
  }
131980
132129
  info("Creating NATS Genie provider...");
131981
- const providerId = await findOrCreateProvider(client, agentName, agentEntry, options.natsUrl);
132130
+ const providerId = await findOrCreateProvider(client, {
132131
+ name: `nats-genie-${agentName}`,
132132
+ schema: "nats-genie",
132133
+ baseUrl: `nats://${options.natsUrl}`,
132134
+ schemaConfig: { agentName: agentEntry.name, agentDir: agentEntry.dir, natsUrl: options.natsUrl }
132135
+ });
131982
132136
  if (!providerId)
131983
132137
  return;
131984
132138
  info("Creating agent record...");
131985
- const agentId = await findOrCreateAgent(client, agentName, providerId);
132139
+ const agentId = await findOrCreateAgent(client, {
132140
+ name: agentName,
132141
+ providerId,
132142
+ agentProvider: "custom"
132143
+ });
131986
132144
  if (!agentId)
131987
132145
  return;
131988
132146
  const triggerMode = options.mode === "turn-based" ? "round-trip" : "fire-and-forget";
@@ -134821,8 +134979,9 @@ async function streamEvents(client, options) {
134821
134979
  const shutdown = () => {
134822
134980
  stopped = true;
134823
134981
  };
134824
- process.on("SIGINT", shutdown);
134825
- process.on("SIGTERM", shutdown);
134982
+ const processEvents = process;
134983
+ processEvents.on("SIGINT", shutdown);
134984
+ processEvents.on("SIGTERM", shutdown);
134826
134985
  if (!ndjson)
134827
134986
  dim(`Streaming events (poll=${pollMs}ms). Ctrl+C to stop.`);
134828
134987
  try {
@@ -134834,8 +134993,8 @@ async function streamEvents(client, options) {
134834
134993
  await new Promise((resolve2) => setTimeout(resolve2, pollMs));
134835
134994
  }
134836
134995
  } finally {
134837
- process.off("SIGINT", shutdown);
134838
- process.off("SIGTERM", shutdown);
134996
+ processEvents.off("SIGINT", shutdown);
134997
+ processEvents.off("SIGTERM", shutdown);
134839
134998
  await flushStdout();
134840
134999
  }
134841
135000
  }
@@ -136045,6 +136204,39 @@ function createInstancesCommand() {
136045
136204
  error(`Failed to request pairing code: ${message}`);
136046
136205
  }
136047
136206
  });
136207
+ instances.command("passkey <id>").description("Get the pending WhatsApp passkey ceremony").action(async (rawId) => {
136208
+ const client = getClient();
136209
+ try {
136210
+ const id = await resolveInstanceId(rawId);
136211
+ data(await client.instances.passkey(id));
136212
+ } catch (err) {
136213
+ const message = err instanceof Error ? err.message : "Unknown error";
136214
+ error(`Failed to get passkey state: ${message}`);
136215
+ }
136216
+ });
136217
+ instances.command("passkey-submit <id>").description("Submit a WebAuthn assertion for WhatsApp pairing").requiredOption("--response-file <path>", "JSON file containing the one-time WebAuthn assertion").action(async (rawId, options) => {
136218
+ const client = getClient();
136219
+ try {
136220
+ const id = await resolveInstanceId(rawId);
136221
+ const credential = await Bun.file(options.responseFile).json();
136222
+ await client.instances.submitPasskey(id, credential);
136223
+ success("Passkey response submitted");
136224
+ } catch (err) {
136225
+ const message = err instanceof Error ? err.message : "Unknown error";
136226
+ error(`Failed to submit passkey response: ${message}`);
136227
+ }
136228
+ });
136229
+ instances.command("passkey-confirm <id>").description("Confirm a pending WhatsApp passkey pairing").action(async (rawId) => {
136230
+ const client = getClient();
136231
+ try {
136232
+ const id = await resolveInstanceId(rawId);
136233
+ await client.instances.confirmPasskey(id);
136234
+ success("Passkey pairing confirmed");
136235
+ } catch (err) {
136236
+ const message = err instanceof Error ? err.message : "Unknown error";
136237
+ error(`Failed to confirm passkey pairing: ${message}`);
136238
+ }
136239
+ });
136048
136240
  instances.command("connect <id>").description("Connect an instance").option("--force-new-qr", "Force generation of new QR code").option("--token <token>", "Discord bot token (for Discord instances)").option("--twilio-account-sid <sid>", "Twilio Account SID").option("--twilio-auth-token <token>", "Twilio Auth Token").option("--twilio-from <address>", "Twilio WhatsApp sender address (whatsapp:+E164)").option("--twilio-messaging-service-sid <sid>", "Twilio Messaging Service SID").option("--twilio-status-callback-url <url>", "Twilio outbound status callback URL").option("--twilio-webhook-url <url>", "Public Twilio webhook URL for signature validation").option("--twilio-validate-signature", "Validate X-Twilio-Signature on webhooks").option("--no-twilio-validate-signature", "Disable X-Twilio-Signature validation").option("--access-token <token>", "WhatsApp Cloud (Meta) access token \u2014 pair with --phone-number-id + --waba-id").option("--phone-number-id <id>", "WhatsApp Cloud phone_number_id (Graph API id, not E.164)").option("--waba-id <id>", "WhatsApp Business Account id (WABA id)").option("--meta-app-id <id>", "Optional override for META_APP_ID (when the tenant owns its own Meta App)").option("--meta-business-id <id>", "Optional Meta Business Manager id").action(async (rawId, options) => {
136049
136241
  const client = getClient();
136050
136242
  try {
@@ -139703,6 +139895,84 @@ function createSayCommand() {
139703
139895
  });
139704
139896
  }
139705
139897
 
139898
+ // src/commands/schedule.ts
139899
+ init_output();
139900
+ function parseSendAt(raw2, now = new Date) {
139901
+ const relative = /^(\d+)\s*(m|h|d)$/i.exec(raw2.trim());
139902
+ if (relative) {
139903
+ const amount = Number(relative[1]);
139904
+ const unit = (relative[2] ?? "").toLowerCase();
139905
+ const ms = unit === "m" ? 60000 : unit === "h" ? 3600000 : 86400000;
139906
+ return new Date(now.getTime() + amount * ms);
139907
+ }
139908
+ const parsed = new Date(raw2);
139909
+ if (Number.isNaN(parsed.getTime())) {
139910
+ throw new Error(`Could not read "${raw2}" as a time. Use an ISO-8601 instant or a relative offset (30m, 2h, 3d).`);
139911
+ }
139912
+ return parsed;
139913
+ }
139914
+ function createScheduleCommand() {
139915
+ const cmd = new Command("schedule").description("Schedule messages for later delivery (#889)");
139916
+ cmd.command("send <instance> <chat> <text>").description("Schedule a text message. <chat> is the PLATFORM id (Slack C\u2026/D\u2026).").requiredOption("--at <when>", "ISO-8601 instant, or a relative offset: 30m, 2h, 3d").option("--thread <ts>", "Post into this thread (Slack thread_ts)").option("--broadcast", "Also surface it in the channel (Slack reply_broadcast)").action(async (instance3, chat, text3, opts) => {
139917
+ try {
139918
+ const sendAt = parseSendAt(opts.at);
139919
+ const instanceId = await resolveInstanceId(instance3);
139920
+ const row = await getClient().scheduledMessages.schedule({
139921
+ instanceId,
139922
+ chatId: chat,
139923
+ content: { type: "text", text: text3 },
139924
+ sendAt: sendAt.toISOString(),
139925
+ threadId: opts.thread,
139926
+ isThreadBroadcast: opts.broadcast === true
139927
+ });
139928
+ success(`Scheduled for ${sendAt.toISOString()} (${row.deliveryMode} mode) \u2014 id ${row.id}`);
139929
+ } catch (err2) {
139930
+ error(`Failed to schedule: ${err2 instanceof Error ? err2.message : "Unknown error"}`, undefined, 3);
139931
+ }
139932
+ });
139933
+ cmd.command("list <instance>").description("List pending messages scheduled through omni.").option("--limit <n>", "Max rows", "100").action(async (instance3, opts) => {
139934
+ try {
139935
+ const instanceId = await resolveInstanceId(instance3);
139936
+ const rows = await getClient().scheduledMessages.listPending(instanceId, Number(opts.limit));
139937
+ if (rows.length === 0) {
139938
+ info("No pending scheduled messages.");
139939
+ info("(Only messages scheduled through omni are listed.)");
139940
+ return;
139941
+ }
139942
+ list(rows.map((r6) => ({
139943
+ id: String(r6.id ?? ""),
139944
+ sendAt: String(r6.sendAt ?? ""),
139945
+ chat: String(r6.chatExternalId ?? ""),
139946
+ mode: String(r6.deliveryMode ?? ""),
139947
+ status: String(r6.status ?? "")
139948
+ })));
139949
+ } catch (err2) {
139950
+ error(`Failed to list: ${err2 instanceof Error ? err2.message : "Unknown error"}`, undefined, 3);
139951
+ }
139952
+ });
139953
+ cmd.command("get <id>").description("Show one scheduled message.").action(async (id) => {
139954
+ try {
139955
+ const row = await getClient().scheduledMessages.get(id);
139956
+ if (!row) {
139957
+ error(`Scheduled message ${id} not found.`, undefined, 4);
139958
+ return;
139959
+ }
139960
+ data(row);
139961
+ } catch (err2) {
139962
+ error(`Failed to read: ${err2 instanceof Error ? err2.message : "Unknown error"}`, undefined, 3);
139963
+ }
139964
+ });
139965
+ cmd.command("cancel <id>").description("Cancel a pending scheduled message.").action(async (id) => {
139966
+ try {
139967
+ const row = await getClient().scheduledMessages.cancel(id);
139968
+ success(`Scheduled message ${id} is now ${row.status}.`);
139969
+ } catch (err2) {
139970
+ error(`Failed to cancel: ${err2 instanceof Error ? err2.message : "Unknown error"}`, undefined, 3);
139971
+ }
139972
+ });
139973
+ return cmd;
139974
+ }
139975
+
139706
139976
  // src/commands/see.ts
139707
139977
  import { existsSync as existsSync16, readFileSync as readFileSync13, statSync as statSync5 } from "fs";
139708
139978
  import { extname as extname4 } from "path";
@@ -140459,6 +140729,226 @@ function createSettingsCommand() {
140459
140729
  return settings;
140460
140730
  }
140461
140731
 
140732
+ // src/commands/setup.ts
140733
+ init_src2();
140734
+ init_output();
140735
+ function buildAgnoConfig(opts) {
140736
+ if (!opts.baseUrl)
140737
+ return { error: "agno provider requires --base-url (Agno API URL)." };
140738
+ const schemaConfig = {};
140739
+ if (opts.defaultAgentId)
140740
+ schemaConfig.defaultAgentId = opts.defaultAgentId;
140741
+ return {
140742
+ baseUrl: opts.baseUrl,
140743
+ apiKey: opts.apiKey,
140744
+ schemaConfig: Object.keys(schemaConfig).length > 0 ? schemaConfig : undefined
140745
+ };
140746
+ }
140747
+ function buildWebhookConfig(opts) {
140748
+ const url = opts.webhookUrl ?? opts.baseUrl;
140749
+ if (!url)
140750
+ return { error: "webhook provider requires --webhook-url (or --base-url)." };
140751
+ return { baseUrl: url, apiKey: opts.apiKey };
140752
+ }
140753
+ function buildOpenClawConfig2(opts) {
140754
+ if (!opts.baseUrl)
140755
+ return { error: "openclaw provider requires --base-url (ws:// or wss://)." };
140756
+ if (!opts.baseUrl.startsWith("ws://") && !opts.baseUrl.startsWith("wss://")) {
140757
+ return { error: `openclaw requires ws:// or wss:// URL. Got: ${opts.baseUrl}` };
140758
+ }
140759
+ if (!opts.defaultAgentId) {
140760
+ return { error: "openclaw provider requires --default-agent-id." };
140761
+ }
140762
+ return {
140763
+ baseUrl: opts.baseUrl,
140764
+ apiKey: opts.apiKey,
140765
+ schemaConfig: { defaultAgentId: opts.defaultAgentId }
140766
+ };
140767
+ }
140768
+ function buildAgUiConfig(opts) {
140769
+ if (!opts.baseUrl)
140770
+ return { error: "ag-ui provider requires --base-url." };
140771
+ return { baseUrl: opts.baseUrl, apiKey: opts.apiKey };
140772
+ }
140773
+ function buildClaudeCodeConfig2(opts) {
140774
+ if (!opts.baseUrl)
140775
+ return { error: "claude-code provider requires --base-url." };
140776
+ if (!opts.projectPath)
140777
+ return { error: "claude-code provider requires --project-path." };
140778
+ const schemaConfig = { projectPath: opts.projectPath };
140779
+ if (opts.maxTurns)
140780
+ schemaConfig.maxTurns = opts.maxTurns;
140781
+ if (opts.permissionMode)
140782
+ schemaConfig.permissionMode = opts.permissionMode;
140783
+ if (opts.model)
140784
+ schemaConfig.model = opts.model;
140785
+ if (opts.systemPrompt)
140786
+ schemaConfig.systemPrompt = opts.systemPrompt;
140787
+ return { baseUrl: opts.baseUrl, apiKey: opts.apiKey, schemaConfig };
140788
+ }
140789
+ function buildA2aConfig(opts) {
140790
+ if (!opts.baseUrl)
140791
+ return { error: "a2a provider requires --base-url." };
140792
+ return { baseUrl: opts.baseUrl, apiKey: opts.apiKey };
140793
+ }
140794
+ function buildNatsGenieConfig2(opts) {
140795
+ const natsUrl = opts.natsUrl ?? "localhost:4222";
140796
+ const schemaConfig = { natsUrl };
140797
+ if (opts.agentName)
140798
+ schemaConfig.agentName = opts.agentName;
140799
+ if (opts.targetAgent)
140800
+ schemaConfig.targetAgent = opts.targetAgent;
140801
+ if (opts.teamName)
140802
+ schemaConfig.teamName = opts.teamName;
140803
+ return {
140804
+ baseUrl: opts.baseUrl ?? `nats://${natsUrl}`,
140805
+ apiKey: opts.apiKey,
140806
+ schemaConfig
140807
+ };
140808
+ }
140809
+ function buildProviderConfig(opts) {
140810
+ switch (opts.schema) {
140811
+ case "agno":
140812
+ return buildAgnoConfig(opts);
140813
+ case "webhook":
140814
+ return buildWebhookConfig(opts);
140815
+ case "openclaw":
140816
+ return buildOpenClawConfig2(opts);
140817
+ case "ag-ui":
140818
+ return buildAgUiConfig(opts);
140819
+ case "claude-code":
140820
+ return buildClaudeCodeConfig2(opts);
140821
+ case "a2a":
140822
+ return buildA2aConfig(opts);
140823
+ case "nats-genie":
140824
+ return buildNatsGenieConfig2(opts);
140825
+ default:
140826
+ return { error: `Unsupported --schema "${opts.schema}". Valid: ${[...PROVIDER_SCHEMAS].join(", ")}` };
140827
+ }
140828
+ }
140829
+ function createTopLevelSetupCommand() {
140830
+ const setup = new Command("setup").description("Compound setup wizards for Omni resources");
140831
+ setup.command("agent").description("Wire an agent to an instance in one step (provider + agent + binding + health check)").requiredOption("--instance <name-or-uuid>", "Omni instance (name or UUID)").requiredOption("--schema <schema>", `Provider schema (${[...PROVIDER_SCHEMAS].join(", ")})`).requiredOption("--name <name>", "Agent name (also used as default provider name)").option("--provider-name <name>", "Provider name override (default: <schema>-<name>)").option("--base-url <url>", "Provider base URL (required for most schemas)").option("--api-key <key>", "API key for the provider").option("--mode <mode>", "Trigger mode: turn-based (round-trip) or fire-and-forget", "turn-based").option("--reply-filter <filter>", "Reply filter: all | filtered", "all").option("--default-agent-id <id>", "Default agent ID (agno, openclaw)").option("--project-path <path>", "Project directory (claude-code)").option("--max-turns <n>", "Max conversation turns (claude-code)", Number.parseInt).option("--permission-mode <mode>", "Permission mode (claude-code)").option("--model <model>", "Model override").option("--system-prompt <prompt>", "System prompt (claude-code)").option("--agent-name <name>", "Agent identity (nats-genie)").option("--target-agent <name>", "Target agent inbox (nats-genie)").option("--team-name <template>", "Team name template (nats-genie)").option("--nats-url <url>", "NATS server URL (nats-genie, default: localhost:4222)").option("--webhook-url <url>", "Webhook endpoint (webhook)").action(async (options3) => {
140832
+ await runSetupAgent(options3);
140833
+ });
140834
+ return setup;
140835
+ }
140836
+ async function runSetupAgent(options3) {
140837
+ if (!PROVIDER_SCHEMAS.includes(options3.schema)) {
140838
+ error(`Invalid --schema "${options3.schema}". Valid: ${[...PROVIDER_SCHEMAS].join(", ")}`);
140839
+ return;
140840
+ }
140841
+ const client = getClient();
140842
+ const instanceId = await resolveInstanceId(options3.instance);
140843
+ const built = buildProviderConfig(options3);
140844
+ if ("error" in built) {
140845
+ error(built.error);
140846
+ return;
140847
+ }
140848
+ const providerName = options3.providerName ?? `${options3.schema}-${options3.name}`;
140849
+ info(`Creating ${options3.schema} provider "${providerName}"...`);
140850
+ const providerId = await findOrCreateProvider(client, {
140851
+ name: providerName,
140852
+ schema: options3.schema,
140853
+ baseUrl: built.baseUrl,
140854
+ apiKey: built.apiKey,
140855
+ schemaConfig: built.schemaConfig
140856
+ });
140857
+ if (!providerId)
140858
+ return;
140859
+ info(`Creating agent record "${options3.name}"...`);
140860
+ const agentId = await findOrCreateAgent(client, {
140861
+ name: options3.name,
140862
+ providerId,
140863
+ agentProvider: schemaToAgentProvider(options3.schema),
140864
+ model: options3.model
140865
+ });
140866
+ if (!agentId)
140867
+ return;
140868
+ const triggerMode = options3.mode === "turn-based" ? "round-trip" : "fire-and-forget";
140869
+ const agentReplyFilter = {
140870
+ mode: options3.replyFilter,
140871
+ conditions: { onDm: true, onMention: true, onReply: true, onNameMatch: false }
140872
+ };
140873
+ info("Updating instance agent assignment...");
140874
+ try {
140875
+ await client.instances.update(instanceId, {
140876
+ agentId,
140877
+ agentProviderId: providerId,
140878
+ agentReplyFilter,
140879
+ triggerMode
140880
+ });
140881
+ } catch (err2) {
140882
+ const message2 = err2 instanceof Error ? err2.message : "Unknown error";
140883
+ warn(`Could not update instance agent assignment: ${message2}`);
140884
+ info(`Set manually: omni instances update ${instanceId} --agent-id ${agentId} --agent-provider-id ${providerId}`);
140885
+ return;
140886
+ }
140887
+ info("Testing provider connectivity...");
140888
+ let healthSummary;
140889
+ try {
140890
+ const health = await client.providers.checkHealth(providerId);
140891
+ healthSummary = health.healthy ? `healthy (latency: ${health.latency}ms)` : `unhealthy \u2014 ${health.error ?? "unknown error"}`;
140892
+ if (health.healthy) {
140893
+ success(`Provider is healthy (latency: ${health.latency}ms)`);
140894
+ } else {
140895
+ warn(`Provider created but health check failed: ${health.error ?? "unknown error"}`);
140896
+ }
140897
+ } catch (err2) {
140898
+ const message2 = err2 instanceof Error ? err2.message : "Unknown error";
140899
+ healthSummary = `error \u2014 ${message2}`;
140900
+ warn(`Health check errored: ${message2}`);
140901
+ }
140902
+ success(`Connected instance "${options3.instance}" to agent "${options3.name}".`);
140903
+ header("Configuration Summary");
140904
+ keyValue("Instance ID", instanceId);
140905
+ keyValue("Schema", options3.schema);
140906
+ keyValue("Provider ID", providerId);
140907
+ keyValue("Agent ID", agentId);
140908
+ keyValue("Reply Filter", options3.replyFilter);
140909
+ keyValue("Trigger Mode", `${triggerMode} (--mode ${options3.mode})`);
140910
+ keyValue("Health", healthSummary);
140911
+ }
140912
+
140913
+ // src/commands/slack.ts
140914
+ init_output();
140915
+ function createSlackCommand() {
140916
+ const cmd = new Command("slack").description("Slack-only operations: open a DM, search messages (#889)");
140917
+ cmd.command("dm <instance> <userId>").description("Resolve the DM channel id for a Slack user (U\u2026). Idempotent.").action(async (instance3, userId) => {
140918
+ try {
140919
+ const instanceId = await resolveInstanceId(instance3);
140920
+ const { channelId } = await getClient().slack.openDm(instanceId, userId);
140921
+ success(`DM channel with ${userId}: ${channelId}`);
140922
+ info(`Send with: omni send text ${instance3} ${channelId} "..."`);
140923
+ } catch (err2) {
140924
+ error(`Failed to open DM: ${err2 instanceof Error ? err2.message : "Unknown error"}`, undefined, 3);
140925
+ }
140926
+ });
140927
+ cmd.command("search <instance> <query>").description("Search messages. Needs an instance in 'user' auth mode \u2014 a bot token cannot search.").option("--count <n>", "Results per page", "20").option("--page <n>", "Page number", "1").action(async (instance3, query, opts) => {
140928
+ try {
140929
+ const instanceId = await resolveInstanceId(instance3);
140930
+ const matches = await getClient().slack.search(instanceId, query, {
140931
+ count: Number(opts.count),
140932
+ page: Number(opts.page)
140933
+ });
140934
+ if (matches.length === 0) {
140935
+ info("No matches.");
140936
+ return;
140937
+ }
140938
+ list(matches.map((m10) => ({
140939
+ channel: String(m10.channelId ?? ""),
140940
+ ts: String(m10.ts ?? ""),
140941
+ from: String(m10.username ?? ""),
140942
+ text: String(m10.text ?? "").slice(0, 80)
140943
+ })));
140944
+ info(`${matches.length} result(s), from the authorizing user's perspective.`);
140945
+ } catch (err2) {
140946
+ error(`Search failed: ${err2 instanceof Error ? err2.message : "Unknown error"}`, undefined, 3);
140947
+ }
140948
+ });
140949
+ return cmd;
140950
+ }
140951
+
140462
140952
  // src/commands/speak.ts
140463
140953
  import { writeFile as writeFile2 } from "fs/promises";
140464
140954
  init_output();
@@ -142627,6 +143117,18 @@ var COMMANDS = [
142627
143117
  helpGroup: "Management",
142628
143118
  helpDescription: "Idle-chat follow-up config (agents/instances/chats)"
142629
143119
  },
143120
+ {
143121
+ create: createScheduleCommand,
143122
+ category: "core",
143123
+ helpGroup: "Core",
143124
+ helpDescription: "Schedule messages for later delivery"
143125
+ },
143126
+ {
143127
+ create: createSlackCommand,
143128
+ category: "advanced",
143129
+ helpGroup: "Management",
143130
+ helpDescription: "Slack-only: open a DM by user id, search messages"
143131
+ },
142630
143132
  {
142631
143133
  create: createAgentsCommand,
142632
143134
  category: "core",
@@ -142645,6 +143147,12 @@ var COMMANDS = [
142645
143147
  helpGroup: "Management",
142646
143148
  helpDescription: "Connect instance to genie agent via NATS"
142647
143149
  },
143150
+ {
143151
+ create: createTopLevelSetupCommand,
143152
+ category: "core",
143153
+ helpGroup: "Management",
143154
+ helpDescription: "Compound setup (agent \u2192 provider \u2192 instance, any schema)"
143155
+ },
142648
143156
  {
142649
143157
  create: createRoutesCommand,
142650
143158
  category: "standard",