@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.
- package/db/drizzle/0064_durable_consumers.sql +46 -0
- package/db/drizzle/meta/_journal.json +7 -0
- package/dist/commands/events.d.ts +47 -0
- package/dist/commands/events.d.ts.map +1 -1
- package/dist/index.js +157 -8
- package/dist/server/index.js +588 -240
- package/package.json +1 -1
|
@@ -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
|
|
122947
|
+
let errorMessage3;
|
|
122934
122948
|
let errorType = semantic_conventions_1.ERROR_TYPE_VALUE_OTHER;
|
|
122935
122949
|
if (typeof reason === "string" || reason === undefined) {
|
|
122936
|
-
|
|
122950
|
+
errorMessage3 = reason;
|
|
122937
122951
|
} else if (typeof reason === "object" && Object.prototype.hasOwnProperty.call(reason, "message")) {
|
|
122938
|
-
|
|
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:
|
|
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.
|
|
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
|
|
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 =
|
|
151175
|
+
const message2 = errorMessage2(error2);
|
|
151027
151176
|
return {
|
|
151028
151177
|
name,
|
|
151029
151178
|
state: "errored",
|