@automagik/omni 2.260908.11 → 2.260908.12

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.
@@ -0,0 +1,46 @@
1
+ -- Durable named event consumers (#989, RFC #925 G7 — the durable half of the
2
+ -- event-consumer surface; the one-shot half, `omni events wait`, shipped in
3
+ -- PR #972).
4
+ --
5
+ -- omni_events.journal_seq: a monotonic journal position assigned by a
6
+ -- sequence at insert. The durable-consumer cursor is "last acked journal_seq"
7
+ -- and delivery resumes strictly after it. receivedAt cannot anchor an
8
+ -- at-least-once cursor — it carries the PUBLISHER's clock and lands out of
9
+ -- order under consumer retries. BIGSERIAL backfills existing rows (physical
10
+ -- order; they predate every consumer, so the order among them is moot).
11
+ --
12
+ -- durable_consumers: the registry — name (globally unique), event-type filter
13
+ -- (trailing-* prefix glob, the #966 contract), optional payload conditions
14
+ -- (same matcher as `events wait --filter` / automation triggers), and the
15
+ -- cursor. NOT consumer_offsets: that table is owned by the NATS subscription
16
+ -- layer (gap detection over NATS stream sequences); this registry has an
17
+ -- API-managed lifecycle and a different sequence space (the journal IS the
18
+ -- replay source, NATS is transport).
19
+ --
20
+ -- TENANCY: global — no tenant_id column, following the event_schemas
21
+ -- precedent (0056): the RLS coverage gate requires every tenant_id-bearing
22
+ -- table to be in the frozen G0 manifest, the G1 tenant plane, or the
23
+ -- runtime-denied exclusions. Event reads stay tenant-policed through
24
+ -- omni_events' own RLS; per-tenant consumer ownership joins additively in
25
+ -- the G6+ ownership pass.
26
+ --
27
+ -- Hand-written following the 0043/0044/0052 precedent (additive, idempotent).
28
+ --
29
+ -- NOTE: no explicit BEGIN/COMMIT — the boot migrator executes this file on a
30
+ -- pooled postgres-js connection, which rejects raw transaction control.
31
+
32
+ ALTER TABLE "omni_events" ADD COLUMN IF NOT EXISTS "journal_seq" bigserial;
33
+ --> statement-breakpoint
34
+ CREATE UNIQUE INDEX IF NOT EXISTS "omni_events_journal_seq_uq" ON "omni_events" ("journal_seq");
35
+ --> statement-breakpoint
36
+ CREATE TABLE IF NOT EXISTS "durable_consumers" (
37
+ "id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
38
+ "name" varchar(100) NOT NULL,
39
+ "event_type" varchar(255) NOT NULL,
40
+ "filters" jsonb,
41
+ "cursor" bigint DEFAULT 0 NOT NULL,
42
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
43
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
44
+ );
45
+ --> statement-breakpoint
46
+ CREATE UNIQUE INDEX IF NOT EXISTS "durable_consumers_name_uq" ON "durable_consumers" ("name");
@@ -449,6 +449,13 @@
449
449
  "when": 1786300000000,
450
450
  "tag": "0063_automation_manifest_provenance",
451
451
  "breakpoints": true
452
+ },
453
+ {
454
+ "idx": 64,
455
+ "version": "7",
456
+ "when": 1786400000000,
457
+ "tag": "0064_durable_consumers",
458
+ "breakpoints": true
452
459
  }
453
460
  ]
454
461
  }
@@ -117,6 +117,53 @@ export declare function matchesWaitEvent(event: WaitEventRow, filters: StreamFil
117
117
  * accepted transport (the issue's non-goal keeps SSE/WS out of scope).
118
118
  */
119
119
  export declare function waitForEvent(client: OmniClient, params: WaitParams): Promise<WaitEventRow | null>;
120
+ /** A durable consumer as the API returns it (registration + live lag). */
121
+ interface ConsumerData {
122
+ id: string;
123
+ name: string;
124
+ eventType: string;
125
+ filters: AutomationCondition[] | null;
126
+ cursor: number;
127
+ head: number;
128
+ lag: number;
129
+ createdAt: string;
130
+ updatedAt: string;
131
+ }
132
+ /**
133
+ * Raw CLI→API call for the consumer endpoints — the generated SDK does not
134
+ * cover them yet (`schemaApiRequest` precedent; the CLI only ever talks to
135
+ * the API, never the database).
136
+ */
137
+ export declare function consumersApiRequest<T>(path: string, init?: {
138
+ method?: string;
139
+ body?: string;
140
+ }): Promise<T>;
141
+ export declare function summarizeConsumerRow(row: ConsumerData): Record<string, unknown>;
142
+ export interface FollowParams {
143
+ consumer: string;
144
+ /** Max rows scanned per pull page. */
145
+ limit: number;
146
+ /** Server-side long-poll window per pull when the journal is idle. */
147
+ waitMs: number;
148
+ /** Advance the cursor as pages are printed (default). false = peek one page, exit. */
149
+ ack: boolean;
150
+ /** Exit 0 once caught up (no new rows scanned) instead of tailing forever. */
151
+ untilIdle: boolean;
152
+ /** External stop signal (SIGINT). */
153
+ isStopped?: () => boolean;
154
+ /** Line sink — defaults to output.raw (stdout). Injected by tests. */
155
+ emit?: (line: string) => void;
156
+ }
157
+ /**
158
+ * The `omni events follow` loop: pull a page from the stored cursor, print
159
+ * each event as a JSON line, ack the SCANNED cursor (so filtered-out rows are
160
+ * skipped too), repeat. Resumes exactly-after-cursor across restarts because
161
+ * progress lives server-side.
162
+ *
163
+ * With `ack: false` the stored cursor never moves, so a loop would replay the
164
+ * same page forever — peek mode prints ONE page and returns.
165
+ */
166
+ export declare function followConsumer(params: FollowParams): Promise<void>;
120
167
  export declare function createEventsCommand(): Command;
121
168
  export {};
122
169
  //# sourceMappingURL=events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/commands/events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/commands/events.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -81405,6 +81405,7 @@ __export(exports_schema, {
81405
81405
  eventTypes: () => eventTypes,
81406
81406
  eventSchemas: () => eventSchemas,
81407
81407
  eventPayloads: () => eventPayloads,
81408
+ durableConsumers: () => durableConsumers,
81408
81409
  deliveryStatuses: () => deliveryStatuses,
81409
81410
  debounceMode: () => debounceMode,
81410
81411
  deadLetterStatuses: () => deadLetterStatuses,
@@ -81465,7 +81466,7 @@ __export(exports_schema, {
81465
81466
  accessRules: () => accessRules,
81466
81467
  accessModes: () => accessModes
81467
81468
  });
81468
- 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, webhookSignatureAlgorithms, connectorLivenessStatuses, connectorWindowSemanticsValues, connectorMutationPolicies, webhookSources, eventSchemas, 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;
81469
+ 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, webhookSignatureAlgorithms, connectorLivenessStatuses, connectorWindowSemanticsValues, connectorMutationPolicies, webhookSources, eventSchemas, conditionOperators, actionTypes, automationDebounceModes, automations2, automationLogStatuses, automationLogs, consumerOffsets, durableConsumers, 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;
81469
81470
  var init_schema2 = __esm(() => {
81470
81471
  init_events();
81471
81472
  init_types4();
@@ -82201,10 +82202,12 @@ var init_schema2 = __esm(() => {
82201
82202
  idempotencyKey: text("idempotency_key"),
82202
82203
  metadata: jsonb("metadata").$type(),
82203
82204
  causationId: uuid("causation_id"),
82205
+ journalSeq: bigserial("journal_seq", { mode: "number" }),
82204
82206
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
82205
82207
  tenantId: uuid("tenant_id").references(() => tenants.id, { onDelete: "restrict" })
82206
82208
  }, (table3) => ({
82207
82209
  causationIdx: index("omni_events_causation_idx").on(table3.causationId),
82210
+ journalSeqUq: uniqueIndex("omni_events_journal_seq_uq").on(table3.journalSeq),
82208
82211
  tenantIdx: index("omni_events_tenant_idx").on(table3.tenantId),
82209
82212
  tenantIdUq: uniqueIndex("omni_events_tenant_id_uq").on(table3.tenantId, table3.id),
82210
82213
  idempotencyKeyUq: uniqueIndex("omni_events_idempotency_key_uq").on(table3.idempotencyKey),
@@ -82799,6 +82802,17 @@ var init_schema2 = __esm(() => {
82799
82802
  lastEventId: uuid("last_event_id"),
82800
82803
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
82801
82804
  });
82805
+ durableConsumers = pgTable("durable_consumers", {
82806
+ id: uuid("id").primaryKey().defaultRandom(),
82807
+ name: varchar("name", { length: 100 }).notNull(),
82808
+ eventType: varchar("event_type", { length: 255 }).notNull(),
82809
+ filters: jsonb("filters").$type(),
82810
+ cursor: bigint2("cursor", { mode: "number" }).notNull().default(0),
82811
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
82812
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
82813
+ }, (table3) => ({
82814
+ nameUq: uniqueIndex("durable_consumers_name_uq").on(table3.name)
82815
+ }));
82802
82816
  automationsRelations = relations(automations2, ({ many }) => ({
82803
82817
  logs: many(automationLogs)
82804
82818
  }));
@@ -122930,12 +122944,12 @@ var require_instrumentation8 = __commonJS((exports) => {
122930
122944
  pendingMetrics.forEach((m10) => m10());
122931
122945
  return result;
122932
122946
  }).catch((reason) => {
122933
- let errorMessage2;
122947
+ let errorMessage3;
122934
122948
  let errorType = semantic_conventions_1.ERROR_TYPE_VALUE_OTHER;
122935
122949
  if (typeof reason === "string" || reason === undefined) {
122936
- errorMessage2 = reason;
122950
+ errorMessage3 = reason;
122937
122951
  } else if (typeof reason === "object" && Object.prototype.hasOwnProperty.call(reason, "message")) {
122938
- errorMessage2 = reason.message;
122952
+ errorMessage3 = reason.message;
122939
122953
  errorType = reason.constructor.name;
122940
122954
  }
122941
122955
  pendingMetrics.forEach((m10) => m10(errorType));
@@ -122943,7 +122957,7 @@ var require_instrumentation8 = __commonJS((exports) => {
122943
122957
  span.setAttribute(semantic_conventions_1.ATTR_ERROR_TYPE, errorType);
122944
122958
  span.setStatus({
122945
122959
  code: api_1.SpanStatusCode.ERROR,
122946
- message: errorMessage2
122960
+ message: errorMessage3
122947
122961
  });
122948
122962
  });
122949
122963
  throw reason;
@@ -136746,7 +136760,7 @@ import { fileURLToPath } from "url";
136746
136760
  // package.json
136747
136761
  var package_default = {
136748
136762
  name: "@automagik/omni",
136749
- version: "2.260908.11",
136763
+ version: "2.260908.12",
136750
136764
  repository: {
136751
136765
  type: "git",
136752
136766
  url: "git+https://github.com/automagik-dev/omni.git",
@@ -143824,9 +143838,119 @@ async function waitForEvent(client, params) {
143824
143838
  await new Promise((resolve2) => setTimeout(resolve2, Math.min(params.pollMs, remaining)));
143825
143839
  }
143826
143840
  }
143841
+ async function consumersApiRequest(path, init = {}) {
143842
+ const config2 = loadConfig();
143843
+ const baseUrl = config2.apiUrl ?? "http://localhost:8882";
143844
+ const resp = await fetch(`${baseUrl}/api/v2/events/consumers${path}`, {
143845
+ method: init.method ?? "GET",
143846
+ body: init.body,
143847
+ headers: { "content-type": "application/json", "x-api-key": config2.apiKey ?? "" }
143848
+ });
143849
+ if (!resp.ok) {
143850
+ throw new Error(`API returned ${resp.status}: ${await resp.text()}`);
143851
+ }
143852
+ return await resp.json();
143853
+ }
143854
+ function summarizeConsumerRow(row) {
143855
+ return {
143856
+ name: row.name,
143857
+ eventType: row.eventType,
143858
+ filters: row.filters?.length ? row.filters.map((f10) => `${f10.field} ${f10.operator} ${JSON.stringify(f10.value)}`).join(" AND ") : "-",
143859
+ cursor: row.cursor,
143860
+ lag: row.lag,
143861
+ updatedAt: row.updatedAt
143862
+ };
143863
+ }
143864
+ async function followConsumer(params) {
143865
+ const emit = params.emit ?? raw;
143866
+ let acked = -1;
143867
+ for (;; ) {
143868
+ if (params.isStopped?.())
143869
+ return;
143870
+ const page = await consumersApiRequest(`/${encodeURIComponent(params.consumer)}/pull?limit=${params.limit}&waitMs=${params.waitMs}`, { method: "POST" });
143871
+ for (const item of page.items) {
143872
+ emit(JSON.stringify(item));
143873
+ }
143874
+ if (!params.ack) {
143875
+ await flushStdout();
143876
+ return;
143877
+ }
143878
+ if (page.cursor > acked) {
143879
+ await consumersApiRequest(`/${encodeURIComponent(params.consumer)}/ack`, {
143880
+ method: "POST",
143881
+ body: JSON.stringify({ cursor: page.cursor })
143882
+ });
143883
+ }
143884
+ const progressed = page.items.length > 0 || page.hasMore || acked >= 0 && page.cursor > acked;
143885
+ acked = Math.max(acked, page.cursor);
143886
+ if (params.untilIdle && !progressed && !page.hasMore) {
143887
+ await flushStdout();
143888
+ return;
143889
+ }
143890
+ if (!progressed && params.waitMs < 1000) {
143891
+ await new Promise((resolve2) => setTimeout(resolve2, 1000));
143892
+ }
143893
+ }
143894
+ }
143895
+ function createConsumersCommand() {
143896
+ const consumers = new Command("consumers").description("Manage durable event consumers (named cursors over the event journal)");
143897
+ consumers.command("create <name>").description("Register a durable consumer").requiredOption("--type <type>", "Event type filter (trailing * = prefix glob, e.g. custom.github.*)").option("--filter <k=v>", "Payload condition, repeatable (dot paths + JSON values \u2014 same matcher as events wait)", (value, previous) => [...previous, value], []).option("--from-beginning", "Start the cursor at 0 (replay the full journal) instead of the current head").action(async (name, options) => {
143898
+ try {
143899
+ const filters = parseWaitFilters(WaitOptionsSchema.shape.filter.parse(options.filter));
143900
+ const result = await consumersApiRequest("", {
143901
+ method: "POST",
143902
+ body: JSON.stringify({
143903
+ name,
143904
+ eventType: options.type,
143905
+ filters: filters.length ? filters : undefined,
143906
+ startFrom: options.fromBeginning ? "beginning" : undefined
143907
+ })
143908
+ });
143909
+ success(`Consumer registered: ${result.data.name} (cursor ${result.data.cursor})`, {
143910
+ name: result.data.name,
143911
+ eventType: result.data.eventType,
143912
+ cursor: result.data.cursor,
143913
+ lag: result.data.lag
143914
+ });
143915
+ } catch (err2) {
143916
+ error(`Failed to create consumer: ${errorMessage(err2)}`);
143917
+ }
143918
+ });
143919
+ consumers.command("ls").description("List durable consumers with their cursor and lag").action(async () => {
143920
+ try {
143921
+ const result = await consumersApiRequest("");
143922
+ list(result.items.map(summarizeConsumerRow), { emptyMessage: "No durable consumers registered." });
143923
+ } catch (err2) {
143924
+ error(`Failed to list consumers: ${errorMessage(err2)}`);
143925
+ }
143926
+ });
143927
+ consumers.command("inspect <name>").description("Show one consumer: filter, cursor, journal head, lag").action(async (name) => {
143928
+ try {
143929
+ const result = await consumersApiRequest(`/${encodeURIComponent(name)}`);
143930
+ data(result.data);
143931
+ } catch (err2) {
143932
+ error(`Failed to inspect consumer: ${errorMessage(err2)}`);
143933
+ }
143934
+ });
143935
+ consumers.command("rm <name>").description("Delete a consumer registration (the journal itself is untouched)").action(async (name) => {
143936
+ try {
143937
+ await consumersApiRequest(`/${encodeURIComponent(name)}`, { method: "DELETE" });
143938
+ success(`Consumer removed: ${name}`);
143939
+ } catch (err2) {
143940
+ error(`Failed to remove consumer: ${errorMessage(err2)}`);
143941
+ }
143942
+ });
143943
+ return consumers;
143944
+ }
143945
+ function errorMessage(err2) {
143946
+ if (err2 instanceof exports_external.ZodError)
143947
+ return err2.issues.map((i6) => i6.message).join("; ");
143948
+ return err2 instanceof Error ? err2.message : "Unknown error";
143949
+ }
143827
143950
  function createEventsCommand() {
143828
143951
  const events2 = new Command("events").description("Query events");
143829
143952
  events2.addCommand(createSchemaCommand());
143953
+ events2.addCommand(createConsumersCommand());
143830
143954
  events2.command("list").description("List events").option("--instance <id>", "Filter by instance ID").option("--channel <type>", "Filter by channel type").option("--type <type>", "Filter by event type (trailing * = prefix glob, e.g. custom.*)").option("--chat-id <id>", "Filter by chat ID").option("--since <time>", "Events since (e.g., 24h, 7d, or ISO timestamp)").option("--until <time>", "Events until (ISO timestamp)").option("--limit <n>", "Limit results", (v4) => Number.parseInt(v4, 10), 50).action(async (options) => {
143831
143955
  const client = getClient();
143832
143956
  try {
@@ -143899,6 +144023,31 @@ function createEventsCommand() {
143899
144023
  error(`Failed to wait for event: ${message2}`);
143900
144024
  }
143901
144025
  });
144026
+ events2.command("follow").description("Tail the journal through a durable consumer: resumes from its stored cursor, prints JSON lines, acks as it goes.").requiredOption("--consumer <name>", "Durable consumer to follow (create with: omni events consumers create)").option("--limit <n>", "Max journal rows scanned per pull", (v4) => Number.parseInt(v4, 10), 100).option("--wait-ms <n>", "Server-side long-poll window per pull when idle (max 30000)", (v4) => Number.parseInt(v4, 10), 1e4).option("--no-ack", "Peek: print one page without advancing the cursor, then exit").option("--until-idle", "Exit 0 once caught up with the journal instead of tailing forever").action(async (options) => {
144027
+ let stopped = false;
144028
+ const shutdown = () => {
144029
+ stopped = true;
144030
+ };
144031
+ const processEvents = process;
144032
+ processEvents.on("SIGINT", shutdown);
144033
+ processEvents.on("SIGTERM", shutdown);
144034
+ try {
144035
+ await followConsumer({
144036
+ consumer: options.consumer,
144037
+ limit: Math.min(Math.max(options.limit, 1), 500),
144038
+ waitMs: Math.min(Math.max(options.waitMs, 0), 30000),
144039
+ ack: options.ack,
144040
+ untilIdle: options.untilIdle === true,
144041
+ isStopped: () => stopped
144042
+ });
144043
+ } catch (err2) {
144044
+ error(`Failed to follow consumer: ${errorMessage(err2)}`);
144045
+ } finally {
144046
+ processEvents.off("SIGINT", shutdown);
144047
+ processEvents.off("SIGTERM", shutdown);
144048
+ await flushStdout();
144049
+ }
144050
+ });
143902
144051
  events2.command("get <id>").description("Get full details for a single event by ID").action(async (id) => {
143903
144052
  const client = getClient();
143904
144053
  try {
@@ -151019,11 +151168,11 @@ function createNatsReplySidecarArtifact() {
151019
151168
  };
151020
151169
  }
151021
151170
  var REGISTRY = [createNatsReplySidecarArtifact()];
151022
- function errorMessage(error2) {
151171
+ function errorMessage2(error2) {
151023
151172
  return error2 instanceof Error ? error2.message : String(error2);
151024
151173
  }
151025
151174
  function erroredOutcome(name, phase, error2) {
151026
- const message2 = errorMessage(error2);
151175
+ const message2 = errorMessage2(error2);
151027
151176
  return {
151028
151177
  name,
151029
151178
  state: "errored",