@hotmeshio/hotmesh 0.21.1 → 0.22.1

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.
Files changed (32) hide show
  1. package/README.md +12 -129
  2. package/build/modules/utils.d.ts +2 -0
  3. package/build/modules/utils.js +9 -1
  4. package/build/package.json +8 -2
  5. package/build/services/activities/hook.d.ts +178 -58
  6. package/build/services/activities/hook.js +244 -58
  7. package/build/services/activities/trigger.js +5 -1
  8. package/build/services/durable/client.d.ts +273 -67
  9. package/build/services/durable/client.js +351 -126
  10. package/build/services/durable/index.d.ts +7 -3
  11. package/build/services/durable/index.js +6 -0
  12. package/build/services/durable/schemas/factory.js +40 -0
  13. package/build/services/durable/worker.js +5 -28
  14. package/build/services/durable/workflow/condition.d.ts +69 -37
  15. package/build/services/durable/workflow/condition.js +70 -39
  16. package/build/services/hotmesh/index.d.ts +31 -4
  17. package/build/services/hotmesh/index.js +31 -4
  18. package/build/services/store/index.d.ts +1 -1
  19. package/build/services/store/providers/postgres/kvsql.d.ts +1 -1
  20. package/build/services/store/providers/postgres/kvtables.js +83 -122
  21. package/build/services/store/providers/postgres/kvtypes/hash/basic.d.ts +1 -1
  22. package/build/services/store/providers/postgres/kvtypes/hash/basic.js +8 -8
  23. package/build/services/store/providers/postgres/kvtypes/hash/index.d.ts +1 -1
  24. package/build/services/store/providers/postgres/postgres.d.ts +51 -188
  25. package/build/services/store/providers/postgres/postgres.js +542 -285
  26. package/build/types/activity.d.ts +2 -0
  27. package/build/types/hmsh_escalations.d.ts +240 -0
  28. package/build/types/index.d.ts +1 -1
  29. package/build/types/provider.d.ts +2 -0
  30. package/package.json +9 -2
  31. package/build/types/signal.d.ts +0 -147
  32. /package/build/types/{signal.js → hmsh_escalations.js} +0 -0
@@ -166,65 +166,6 @@ const KVTables = (context) => ({
166
166
  ON ${jobsTable} (key) WHERE is_live;
167
167
  `);
168
168
  }
169
- // v0.21.0: signal queue table for first-class HITL escalation primitives
170
- const sigTable = `${schemaName}.hotmesh_signals`;
171
- const { rows: sigRows } = await client.query(`SELECT to_regclass('${sigTable}') AS tbl`);
172
- if (!sigRows[0].tbl) {
173
- await client.query(`
174
- CREATE TABLE IF NOT EXISTS ${sigTable} (
175
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
176
- namespace TEXT NOT NULL,
177
- app_id TEXT NOT NULL,
178
- signal_key TEXT NOT NULL,
179
- workflow_id TEXT NOT NULL,
180
- job_id TEXT,
181
- topic TEXT,
182
- status TEXT NOT NULL DEFAULT 'pending',
183
- role TEXT,
184
- type TEXT,
185
- subtype TEXT,
186
- priority INT NOT NULL DEFAULT 5,
187
- description TEXT,
188
- task_queue TEXT,
189
- workflow_type TEXT,
190
- assigned_to TEXT,
191
- claimed_at TIMESTAMPTZ,
192
- claim_expires_at TIMESTAMPTZ,
193
- resolved_at TIMESTAMPTZ,
194
- resolver_payload JSONB,
195
- envelope JSONB,
196
- metadata JSONB,
197
- expires_at TIMESTAMPTZ,
198
- created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
199
- updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
200
- UNIQUE(namespace, app_id, signal_key)
201
- );
202
- `);
203
- await client.query(`
204
- CREATE INDEX IF NOT EXISTS idx_hmsig_namespace_status
205
- ON ${sigTable}(namespace, app_id, status);
206
- `);
207
- await client.query(`
208
- CREATE INDEX IF NOT EXISTS idx_hmsig_signal_key
209
- ON ${sigTable}(namespace, app_id, signal_key);
210
- `);
211
- await client.query(`
212
- CREATE INDEX IF NOT EXISTS idx_hmsig_role_status
213
- ON ${sigTable}(namespace, app_id, role, status);
214
- `);
215
- await client.query(`
216
- CREATE INDEX IF NOT EXISTS idx_hmsig_task_queue
217
- ON ${sigTable}(namespace, app_id, task_queue, status);
218
- `);
219
- await client.query(`
220
- CREATE INDEX IF NOT EXISTS idx_hmsig_metadata_gin
221
- ON ${sigTable} USING GIN(metadata);
222
- `);
223
- await client.query(`
224
- CREATE INDEX IF NOT EXISTS idx_hmsig_claim_expiry
225
- ON ${sigTable}(claim_expires_at) WHERE status = 'claimed';
226
- `);
227
- }
228
169
  },
229
170
  async createTables(client, appName) {
230
171
  try {
@@ -259,6 +200,87 @@ const KVTables = (context) => ({
259
200
  deployed_at TIMESTAMPTZ DEFAULT NOW(),
260
201
  PRIMARY KEY (app_id, version)
261
202
  );
203
+ `);
204
+ await client.query(`
205
+ CREATE TABLE IF NOT EXISTS public.hmsh_escalations (
206
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
207
+ namespace TEXT NOT NULL,
208
+ app_id TEXT NOT NULL,
209
+ signal_key TEXT,
210
+ topic TEXT,
211
+ workflow_id TEXT,
212
+ task_queue TEXT,
213
+ workflow_type TEXT,
214
+ type TEXT,
215
+ subtype TEXT,
216
+ entity TEXT,
217
+ description TEXT,
218
+ role TEXT,
219
+ status TEXT NOT NULL DEFAULT 'pending',
220
+ priority INT NOT NULL DEFAULT 5,
221
+ assigned_to TEXT,
222
+ assigned_until TIMESTAMPTZ,
223
+ claimed_at TIMESTAMPTZ,
224
+ claim_expires_at TIMESTAMPTZ,
225
+ resolved_at TIMESTAMPTZ,
226
+ escalation_payload JSONB,
227
+ resolver_payload JSONB,
228
+ envelope JSONB,
229
+ metadata JSONB,
230
+ origin_id TEXT,
231
+ parent_id TEXT,
232
+ initiated_by TEXT,
233
+ created_by TEXT,
234
+ milestones JSONB NOT NULL DEFAULT '[]',
235
+ trace_id TEXT,
236
+ span_id TEXT,
237
+ expires_at TIMESTAMPTZ,
238
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
239
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
240
+ );
241
+ `);
242
+ await client.query(`
243
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_hmsh_esc_signal_key
244
+ ON public.hmsh_escalations(namespace, app_id, signal_key)
245
+ WHERE signal_key IS NOT NULL;
246
+ `);
247
+ await client.query(`
248
+ CREATE INDEX IF NOT EXISTS idx_hmsh_esc_available
249
+ ON public.hmsh_escalations(namespace, app_id, role, priority ASC, created_at ASC)
250
+ WHERE status = 'pending';
251
+ `);
252
+ await client.query(`
253
+ CREATE INDEX IF NOT EXISTS idx_hmsh_esc_available_expiry
254
+ ON public.hmsh_escalations(namespace, app_id, role, assigned_until, created_at DESC);
255
+ `);
256
+ await client.query(`
257
+ CREATE INDEX IF NOT EXISTS idx_hmsh_esc_assigned
258
+ ON public.hmsh_escalations(assigned_to, assigned_until, created_at DESC)
259
+ WHERE status = 'claimed' AND assigned_to IS NOT NULL;
260
+ `);
261
+ await client.query(`
262
+ CREATE INDEX IF NOT EXISTS idx_hmsh_esc_claim_expiry
263
+ ON public.hmsh_escalations(claim_expires_at)
264
+ WHERE status = 'claimed';
265
+ `);
266
+ await client.query(`
267
+ CREATE INDEX IF NOT EXISTS idx_hmsh_esc_entity
268
+ ON public.hmsh_escalations(namespace, app_id, entity, created_at DESC)
269
+ WHERE entity IS NOT NULL;
270
+ `);
271
+ await client.query(`
272
+ CREATE INDEX IF NOT EXISTS idx_hmsh_esc_workflow
273
+ ON public.hmsh_escalations(workflow_id)
274
+ WHERE workflow_id IS NOT NULL;
275
+ `);
276
+ await client.query(`
277
+ CREATE INDEX IF NOT EXISTS idx_hmsh_esc_origin
278
+ ON public.hmsh_escalations(origin_id)
279
+ WHERE origin_id IS NOT NULL;
280
+ `);
281
+ await client.query(`
282
+ CREATE INDEX IF NOT EXISTS idx_hmsh_esc_metadata
283
+ ON public.hmsh_escalations USING GIN(metadata jsonb_path_ops);
262
284
  `);
263
285
  break;
264
286
  case 'relational_connection':
@@ -320,6 +342,8 @@ const KVTables = (context) => ({
320
342
  id UUID DEFAULT gen_random_uuid(),
321
343
  key TEXT NOT NULL,
322
344
  entity TEXT,
345
+ origin_id TEXT,
346
+ parent_id TEXT,
323
347
  status INTEGER NOT NULL,
324
348
  context JSONB DEFAULT '{}',
325
349
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
@@ -535,64 +559,6 @@ const KVTables = (context) => ({
535
559
  ON ${fullTableName} (key, score, member);
536
560
  `);
537
561
  break;
538
- case 'signal_queue': {
539
- const tbl = fullTableName;
540
- await client.query(`
541
- CREATE TABLE IF NOT EXISTS ${tbl} (
542
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
543
- namespace TEXT NOT NULL,
544
- app_id TEXT NOT NULL,
545
- signal_key TEXT NOT NULL,
546
- workflow_id TEXT NOT NULL,
547
- job_id TEXT,
548
- topic TEXT,
549
- status TEXT NOT NULL DEFAULT 'pending',
550
- role TEXT,
551
- type TEXT,
552
- subtype TEXT,
553
- priority INT NOT NULL DEFAULT 5,
554
- description TEXT,
555
- task_queue TEXT,
556
- workflow_type TEXT,
557
- assigned_to TEXT,
558
- claimed_at TIMESTAMPTZ,
559
- claim_expires_at TIMESTAMPTZ,
560
- resolved_at TIMESTAMPTZ,
561
- resolver_payload JSONB,
562
- envelope JSONB,
563
- metadata JSONB,
564
- expires_at TIMESTAMPTZ,
565
- created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
566
- updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
567
- UNIQUE(namespace, app_id, signal_key)
568
- );
569
- `);
570
- await client.query(`
571
- CREATE INDEX IF NOT EXISTS idx_hmsig_namespace_status
572
- ON ${tbl}(namespace, app_id, status);
573
- `);
574
- await client.query(`
575
- CREATE INDEX IF NOT EXISTS idx_hmsig_signal_key
576
- ON ${tbl}(namespace, app_id, signal_key);
577
- `);
578
- await client.query(`
579
- CREATE INDEX IF NOT EXISTS idx_hmsig_role_status
580
- ON ${tbl}(namespace, app_id, role, status);
581
- `);
582
- await client.query(`
583
- CREATE INDEX IF NOT EXISTS idx_hmsig_task_queue
584
- ON ${tbl}(namespace, app_id, task_queue, status);
585
- `);
586
- await client.query(`
587
- CREATE INDEX IF NOT EXISTS idx_hmsig_metadata_gin
588
- ON ${tbl} USING GIN(metadata);
589
- `);
590
- await client.query(`
591
- CREATE INDEX IF NOT EXISTS idx_hmsig_claim_expiry
592
- ON ${tbl}(claim_expires_at) WHERE status = 'claimed';
593
- `);
594
- break;
595
- }
596
562
  default:
597
563
  context.logger.warn(`Unknown table type for ${tableDef.name}`);
598
564
  break;
@@ -710,11 +676,6 @@ const KVTables = (context) => ({
710
676
  name: 'signal_registry',
711
677
  type: 'string',
712
678
  },
713
- {
714
- schema: schemaName,
715
- name: 'hotmesh_signals',
716
- type: 'signal_queue',
717
- },
718
679
  ];
719
680
  return tableDefinitions;
720
681
  },
@@ -1,6 +1,6 @@
1
1
  import { HashContext, SqlResult, HSetOptions, ProviderTransaction } from './types';
2
2
  export declare function createBasicOperations(context: HashContext['context']): {
3
- hsetnx(key: string, field: string, value: string, multi?: ProviderTransaction, entity?: string): Promise<number>;
3
+ hsetnx(key: string, field: string, value: string, multi?: ProviderTransaction, entity?: string, originId?: string, parentId?: string): Promise<number>;
4
4
  hset(key: string, fields: Record<string, string>, options?: HSetOptions, multi?: ProviderTransaction): Promise<number | any>;
5
5
  hget(key: string, field: string, multi?: ProviderTransaction): Promise<string | null>;
6
6
  hdel(key: string, fields: string[], multi?: unknown): Promise<number>;
@@ -4,8 +4,8 @@ exports._setStatusAndCollateGuid = exports._collateLeg2Entry = exports._hincrbyf
4
4
  const utils_1 = require("./utils");
5
5
  function createBasicOperations(context) {
6
6
  return {
7
- async hsetnx(key, field, value, multi, entity) {
8
- const { sql, params } = _hset(context, key, { [field]: value }, { nx: true, entity });
7
+ async hsetnx(key, field, value, multi, entity, originId, parentId) {
8
+ const { sql, params } = _hset(context, key, { [field]: value }, { nx: true, entity, originId, parentId });
9
9
  if (multi) {
10
10
  multi.addCommand(sql, params, 'number');
11
11
  return Promise.resolve(0);
@@ -281,25 +281,25 @@ function _hset(context, key, fields, options) {
281
281
  if (options?.nx) {
282
282
  // Use WHERE NOT EXISTS to enforce nx
283
283
  sql = `
284
- INSERT INTO ${targetTable} (id, key, status, entity)
285
- SELECT gen_random_uuid(), $1, $2, $3
284
+ INSERT INTO ${targetTable} (id, key, status, entity, origin_id, parent_id)
285
+ SELECT gen_random_uuid(), $1, $2, $3, $4, $5
286
286
  WHERE NOT EXISTS (
287
287
  SELECT 1 FROM ${targetTable}
288
288
  WHERE key = $1 AND is_live
289
289
  )
290
290
  RETURNING 1 as count
291
291
  `;
292
- params.push(key, fields[':'], options?.entity ?? null);
292
+ params.push(key, fields[':'], options?.entity ?? null, options?.originId ?? null, options?.parentId ?? null);
293
293
  }
294
294
  else {
295
295
  // Update existing job or insert new one
296
296
  sql = `
297
- INSERT INTO ${targetTable} (id, key, status, entity)
298
- VALUES (gen_random_uuid(), $1, $2, $3)
297
+ INSERT INTO ${targetTable} (id, key, status, entity, origin_id, parent_id)
298
+ VALUES (gen_random_uuid(), $1, $2, $3, $4, $5)
299
299
  ON CONFLICT (key) WHERE is_live DO UPDATE SET status = EXCLUDED.status
300
300
  RETURNING 1 as count
301
301
  `;
302
- params.push(key, fields[':'], options?.entity ?? null);
302
+ params.push(key, fields[':'], options?.entity ?? null, options?.originId ?? null, options?.parentId ?? null);
303
303
  }
304
304
  }
305
305
  else if (isJobsTableResult) {
@@ -20,7 +20,7 @@ export declare const hashModule: (context: KVSQL) => {
20
20
  cursor: number;
21
21
  keys: string[];
22
22
  }>;
23
- hsetnx(key: string, field: string, value: string, multi?: import("./types").ProviderTransaction, entity?: string): Promise<number>;
23
+ hsetnx(key: string, field: string, value: string, multi?: import("./types").ProviderTransaction, entity?: string, originId?: string, parentId?: string): Promise<number>;
24
24
  hget(key: string, field: string, multi?: import("./types").ProviderTransaction): Promise<string>;
25
25
  hdel(key: string, fields: string[], multi?: unknown): Promise<number>;
26
26
  hmget(key: string, fields: string[], multi?: import("./types").ProviderTransaction): Promise<string[]>;
@@ -11,7 +11,6 @@ import { Transitions } from '../../../../types/transition';
11
11
  import { JobInterruptOptions } from '../../../../types/job';
12
12
  import { WorkListTaskType } from '../../../../types/task';
13
13
  import { ThrottleOptions } from '../../../../types/quorum';
14
- import { SignalQueueEntry } from '../../../../types/signal';
15
14
  import { StoreService } from '../..';
16
15
  import { PostgresClientType } from '../../../../types';
17
16
  import { KVSQL } from './kvsql';
@@ -105,7 +104,7 @@ declare class PostgresStoreService extends StoreService<ProviderClient, Provider
105
104
  * `purposeful re-entry`.
106
105
  */
107
106
  collateSynthetic(jobId: string, guid: string, amount: number, transaction?: ProviderTransaction): Promise<number>;
108
- setStateNX(jobId: string, appId: string, status?: number, entity?: string, transaction?: ProviderTransaction): Promise<boolean>;
107
+ setStateNX(jobId: string, appId: string, status?: number, entity?: string, transaction?: ProviderTransaction, originId?: string, parentId?: string): Promise<boolean>;
109
108
  getSchema(activityId: string, appVersion: AppVID): Promise<ActivityType>;
110
109
  getSchemas(appVersion: AppVID): Promise<Record<string, ActivityType>>;
111
110
  setSchemas(schemas: Record<string, ActivityType>, appVersion: AppVID): Promise<any>;
@@ -223,198 +222,62 @@ declare class PostgresStoreService extends StoreService<ProviderClient, Provider
223
222
  activity?: string;
224
223
  types?: string[];
225
224
  }): Promise<import('../../../../types/exporter').StreamHistoryEntry[]>;
226
- private signalQueueTable;
227
- private rowToSignalEntry;
228
- enqueueSignal(params: {
229
- namespace: string;
230
- appId: string;
231
- signalKey: string;
232
- workflowId: string;
233
- jobId?: string;
225
+ /**
226
+ * Parse a HotMesh-encoded value string.
227
+ * Values may be prefixed with `/s` (JSON), `/d` (number), `/t` or `/f` (boolean), `/n` (null).
228
+ */
229
+ private parseHmshValue;
230
+ private _escalationInsertSql;
231
+ private _escalationInsertParams;
232
+ createEscalation(params: import('../../../../types/hmsh_escalations').CreateEscalationParams): Promise<import('../../../../types/hmsh_escalations').EscalationEntry>;
233
+ /**
234
+ * Enqueues the escalation INSERT into an existing Leg1 transaction so the row
235
+ * is written atomically with the job state checkpoint. On conflict
236
+ * (ON CONFLICT DO NOTHING) the command is a no-op, making it safe for
237
+ * idempotent re-runs after a crash.
238
+ */
239
+ addEscalationToTransaction(params: import('../../../../types/hmsh_escalations').CreateEscalationParams, transaction: import('../../../../types/provider').ProviderTransaction): void;
240
+ /**
241
+ * Full-fidelity INSERT for data migration. Preserves the original `id` (UUID),
242
+ * lifecycle state, and timestamps from the source table. Uses
243
+ * `ON CONFLICT (id) DO NOTHING` so re-running a migration batch is safe —
244
+ * rows that already exist are skipped and `null` is returned for them.
245
+ */
246
+ createEscalationForMigration(params: import('../../../../types/hmsh_escalations').MigrateEscalationParams): Promise<import('../../../../types/hmsh_escalations').EscalationEntry | null>;
247
+ getEscalation(id: string, namespace?: string): Promise<import('../../../../types/hmsh_escalations').EscalationEntry | null>;
248
+ getEscalationBySignalKey(signalKey: string, namespace?: string): Promise<import('../../../../types/hmsh_escalations').EscalationEntry | null>;
249
+ listEscalations(params?: import('../../../../types/hmsh_escalations').ListEscalationsParams): Promise<import('../../../../types/hmsh_escalations').EscalationEntry[]>;
250
+ claimEscalation(params: import('../../../../types/hmsh_escalations').ClaimEscalationParams): Promise<import('../../../../types/hmsh_escalations').ClaimEscalationResult>;
251
+ claimEscalationByMetadata(params: import('../../../../types/hmsh_escalations').ClaimByMetadataParams): Promise<import('../../../../types/hmsh_escalations').ClaimByMetadataResult>;
252
+ releaseEscalation(params: import('../../../../types/hmsh_escalations').ReleaseEscalationParams): Promise<import('../../../../types/hmsh_escalations').ReleaseEscalationResult>;
253
+ resolveEscalation(params: import('../../../../types/hmsh_escalations').ResolveEscalationParams): Promise<import('../../../../types/hmsh_escalations').ResolveEscalationResult & {
254
+ signalKey?: string;
234
255
  topic?: string;
235
- role?: string;
236
- type?: string;
237
- subtype?: string;
238
- priority?: number;
239
- description?: string;
240
- taskQueue?: string;
241
- workflowType?: string;
242
- assignedTo?: string;
243
- metadata?: Record<string, unknown>;
244
- envelope?: Record<string, unknown>;
245
- expiresAt?: Date;
246
- }): Promise<{
247
- id: string;
248
- } | null>;
249
- claimSignal(params: {
250
- namespace: string;
251
- appId: string;
252
- id: string;
253
- assignee?: string;
254
- durationMinutes?: number;
255
- }): Promise<{
256
- ok: true;
257
- entry: SignalQueueEntry;
258
- } | {
259
- ok: false;
260
- reason: 'not-found' | 'conflict';
261
256
  }>;
262
- claimSignalByMetadata(params: {
263
- namespace: string;
264
- appId: string;
265
- key: string;
266
- value: unknown;
267
- assignee?: string;
268
- durationMinutes?: number;
269
- }): Promise<{
270
- ok: true;
271
- entry: SignalQueueEntry;
272
- } | {
273
- ok: false;
274
- reason: 'not-found' | 'conflict';
275
- }>;
276
- releaseSignal(params: {
277
- namespace: string;
278
- appId: string;
279
- id: string;
280
- }): Promise<{
281
- ok: true;
282
- } | {
283
- ok: false;
284
- reason: 'not-found' | 'wrong-status';
257
+ resolveEscalationByMetadata(params: import('../../../../types/hmsh_escalations').ResolveByMetadataParams): Promise<import('../../../../types/hmsh_escalations').ResolveEscalationResult & {
258
+ signalKey?: string;
259
+ topic?: string;
285
260
  }>;
286
- resolveSignal(params: {
287
- namespace: string;
288
- appId: string;
261
+ /**
262
+ * Queues the escalation UPDATE into an existing transaction without executing it.
263
+ * Used by client.ts resolve() to commit the status change atomically with signal delivery.
264
+ */
265
+ queueResolveEscalation(params: {
289
266
  id: string;
267
+ namespace?: string;
290
268
  resolverPayload?: Record<string, unknown>;
291
- }): Promise<{
292
- ok: true;
293
- signalKey: string;
294
- topic: string;
295
- } | {
296
- ok: false;
297
- reason: 'not-found' | 'already-resolved';
298
- }>;
299
- resolveSignalByMetadata(params: {
300
- namespace: string;
301
- appId: string;
302
- key: string;
303
- value: unknown;
304
- resolverPayload?: Record<string, unknown>;
305
- }): Promise<{
306
- ok: true;
307
- signalKey: string;
308
- topic: string;
309
- } | {
310
- ok: false;
311
- reason: 'not-found';
312
- }>;
313
- releaseExpiredSignals(params: {
314
- namespace: string;
315
- appId: string;
316
- }): Promise<number>;
317
- listSignals(params: {
318
- namespace: string;
319
- appId: string;
320
- status?: string;
321
- role?: string;
322
- taskQueue?: string;
323
- limit?: number;
324
- offset?: number;
325
- }): Promise<{
326
- id: string;
327
- namespace: string;
328
- appId: string;
329
- signalKey: string;
330
- workflowId: string;
331
- jobId: string;
332
- topic: string;
333
- status: "pending" | "claimed" | "resolved" | "expired" | "released";
334
- role: string;
335
- type: string;
336
- subtype: string;
337
- priority: number;
338
- description: string;
339
- taskQueue: string;
340
- workflowType: string;
341
- assignedTo: string;
342
- claimedAt: Date;
343
- claimExpiresAt: Date;
344
- resolvedAt: Date;
345
- resolverPayload: Record<string, unknown>;
346
- envelope: Record<string, unknown>;
347
- metadata: Record<string, unknown>;
348
- expiresAt: Date;
349
- createdAt: Date;
350
- updatedAt: Date;
351
- }[]>;
352
- getSignal(params: {
353
- namespace: string;
354
- appId: string;
355
- id: string;
356
- }): Promise<{
357
- id: string;
358
- namespace: string;
359
- appId: string;
360
- signalKey: string;
361
- workflowId: string;
362
- jobId: string;
363
- topic: string;
364
- status: "pending" | "claimed" | "resolved" | "expired" | "released";
365
- role: string;
366
- type: string;
367
- subtype: string;
368
- priority: number;
369
- description: string;
370
- taskQueue: string;
371
- workflowType: string;
372
- assignedTo: string;
373
- claimedAt: Date;
374
- claimExpiresAt: Date;
375
- resolvedAt: Date;
376
- resolverPayload: Record<string, unknown>;
377
- envelope: Record<string, unknown>;
378
- metadata: Record<string, unknown>;
379
- expiresAt: Date;
380
- createdAt: Date;
381
- updatedAt: Date;
382
- }>;
383
- getSignalBySignalKey(params: {
384
- namespace: string;
385
- appId: string;
386
- signalKey: string;
387
- }): Promise<{
388
- id: string;
389
- namespace: string;
390
- appId: string;
391
- signalKey: string;
392
- workflowId: string;
393
- jobId: string;
394
- topic: string;
395
- status: "pending" | "claimed" | "resolved" | "expired" | "released";
396
- role: string;
397
- type: string;
398
- subtype: string;
399
- priority: number;
400
- description: string;
401
- taskQueue: string;
402
- workflowType: string;
403
- assignedTo: string;
404
- claimedAt: Date;
405
- claimExpiresAt: Date;
406
- resolvedAt: Date;
407
- resolverPayload: Record<string, unknown>;
408
- envelope: Record<string, unknown>;
409
- metadata: Record<string, unknown>;
410
- expiresAt: Date;
411
- createdAt: Date;
412
- updatedAt: Date;
413
- }>;
269
+ }, transaction: {
270
+ addCommand: (sql: string, params: any[], returnType: string) => any;
271
+ }): void;
414
272
  /**
415
- * Parse a HotMesh-encoded value string.
416
- * Values may be prefixed with `/s` (JSON), `/d` (number), `/t` or `/f` (boolean), `/n` (null).
273
+ * Finds the highest-priority pending or claimed escalation matching the given metadata filter.
274
+ * Used by client.ts resolveByMetadata() to get routing info before building the atomic transaction.
417
275
  */
418
- private parseHmshValue;
276
+ findEscalationByMetadata(key: string, value: string, roles: string[] | null, namespace?: string): Promise<import('../../../../types/hmsh_escalations').EscalationEntry | null>;
277
+ cancelEscalation(id: string, namespace?: string): Promise<import('../../../../types/hmsh_escalations').CancelEscalationResult>;
278
+ escalateEscalationToRole(params: import('../../../../types/hmsh_escalations').EscalateToRoleParams): Promise<import('../../../../types/hmsh_escalations').EscalationEntry | null>;
279
+ updateEscalation(params: import('../../../../types/hmsh_escalations').UpdateEscalationParams): Promise<import('../../../../types/hmsh_escalations').EscalationEntry | null>;
280
+ appendEscalationMilestones(params: import('../../../../types/hmsh_escalations').AppendMilestonesParams): Promise<import('../../../../types/hmsh_escalations').EscalationEntry | null>;
281
+ releaseExpiredEscalations(namespace?: string): Promise<number>;
419
282
  }
420
283
  export { PostgresStoreService };