@axiom-lattice/pg-stores 3.2.2 → 3.3.0

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @axiom-lattice/pg-stores@3.2.2 build /home/runner/work/agentic/agentic/packages/pg-stores
2
+ > @axiom-lattice/pg-stores@3.3.0 build /home/runner/work/agentic/agentic/packages/pg-stores
3
3
  > tsup src/index.ts --format cjs,esm --dts --sourcemap
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -8,13 +8,13 @@
8
8
  CLI Target: es2020
9
9
  CJS Build start
10
10
  ESM Build start
11
- CJS dist/index.js 421.08 KB
12
- CJS dist/index.js.map 767.96 KB
13
- CJS ⚡️ Build success in 925ms
14
- ESM dist/index.mjs 412.72 KB
15
- ESM dist/index.mjs.map 767.62 KB
16
- ESM ⚡️ Build success in 1051ms
11
+ CJS dist/index.js 433.50 KB
12
+ CJS dist/index.js.map 790.48 KB
13
+ CJS ⚡️ Build success in 806ms
14
+ ESM dist/index.mjs 425.03 KB
15
+ ESM dist/index.mjs.map 790.15 KB
16
+ ESM ⚡️ Build success in 866ms
17
17
  DTS Build start
18
- DTS ⚡️ Build success in 13948ms
19
- DTS dist/index.d.ts 86.96 KB
20
- DTS dist/index.d.mts 86.96 KB
18
+ DTS ⚡️ Build success in 13743ms
19
+ DTS dist/index.d.ts 91.36 KB
20
+ DTS dist/index.d.mts 91.36 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,79 @@
1
1
  # @axiom-lattice/pg-stores
2
2
 
3
+ ## 3.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - eafaac8: Multi-gateway (PostgreSQL-only) coordination primitives — Plans 1 & 2.
8
+
9
+ **Plan 1 — replica identity + distributed leases**
10
+
11
+ - `getReplicaId()` stable per-process replica identity (`AXIOM_REPLICA_ID` or `hostname:pid`).
12
+ - `LeaseStore` / `LeaseRecord` protocol, `InMemoryLeaseStore` (registered as the default `"lease"` store), and `PostgreSQLLeaseStore` (migration v185 `lattice_leases`; atomic self-expiring upsert).
13
+ - `withLease(store, key, ownerLabel, fn)` — distributed critical-section helper with a unique per-invocation holder, bounded acquisition, heartbeat, and release-in-finally.
14
+
15
+ **Plan 2 — atomic thread-message-queue claim + lease**
16
+
17
+ - `ClaimMessagesOptions` and `IMessageQueueStore.claimPendingMessages` / `reclaimExpiredProcessing`.
18
+ - PostgreSQL migration v186 adds `locked_by` / `locked_at` / `lease_expires_at`; claim is an atomic `UPDATE … WHERE id IN (SELECT … FOR UPDATE SKIP LOCKED)` so concurrent Gateway replicas receive disjoint sets.
19
+ - In-memory and local SQLite implementations match the same semantics.
20
+
21
+ No existing behavior changes: the legacy `markProcessing` path is untouched; `Agent` is not yet rewired to the new claim (that is a follow-up plan).
22
+
23
+ - 396ad50: Multi-gateway (PostgreSQL-only) Plan 9 — durable outbox + cross-replica task notifications.
24
+
25
+ - `OutboxStore` / `OutboxEvent`: append-only durable event log (`append` / `listAfter` / `latestId`), InMemory + PostgreSQL (`lattice_outbox`, migration v187).
26
+ - `TaskLifecycleNotifier` / `ProjectTaskAdmissionNotifier`: `publish` keeps its existing local delivery and best-effort appends to the outbox (`originReplicaId`); new `setOutbox` + `deliverFromOutbox`.
27
+ - `OutboxPoller`: per-replica cursor poller that delivers only **foreign** outbox rows to local listeners (skips its own origin), so a peer's task lifecycle/admission events reach every replica.
28
+ - Gateway startup installs the outbox on both notifiers and starts the poller.
29
+ - e2e scenario 7: replica A publishes a lifecycle event; replica B receives it via the outbox; A receives its own exactly once (no double delivery). `pnpm e2e:multi-replica` now 7/7.
30
+
31
+ Deferred: scheduler startup restore/gating, Project Room realtime backplane, thread→replica streaming affinity.
32
+
33
+ - 6080389: Scheduler exactly-once across replicas (claim-before-execute).
34
+
35
+ - `ScheduleStorage.claimScheduledRun(taskId)` atomically transitions `pending -> running` (Memory/Local/PostgreSQL implementations).
36
+ - `DefaultScheduleClient.executeTask` claims before running the handler, so a fire armed on multiple replicas executes only once (losers skip). Retry/CRON-rearm paths re-set `PENDING`, so later fires are claimable. See ADR-158.
37
+
38
+ - 7ecbd01: Recover scheduled tasks stuck `running` after a crash.
39
+
40
+ - `ScheduleStorage.requeueStaleRunning(olderThanMs)` requeues `running` tasks older than a threshold back to `pending` (Memory/Local/PostgreSQL).
41
+ - `DefaultScheduleClient.restore()` requeues stale `running` schedules (30-minute heuristic) before re-arming, so a CRON schedule is no longer permanently stalled by a crash that left an unsettled claim. See ADR-158.
42
+
43
+ ### Patch Changes
44
+
45
+ - 360f9e9: Age-based retention/pruning for the durable outbox.
46
+
47
+ - `OutboxStore.pruneOlderThan(olderThanMs)` (InMemory + PostgreSQL).
48
+ - Gateway `OutboxRetentionJob` prunes `lattice_outbox` rows older than `AXIOM_OUTBOX_RETENTION_HOURS` (default 24h; `0`/invalid disables), after startup and every 6h. Safe because pollers read only new rows and history is not replayed. See ADR-161.
49
+
50
+ - b8c4c92: Multi-gateway (PostgreSQL-only) Plan 3 — thread-run ownership lease + JSONB fix.
51
+
52
+ - `threadRunLeaseKey` / `tryAcquireThreadRun` (non-blocking, heartbeat, idempotent holder-scoped release): a per-thread run ownership lease keyed `thread-run:<tenant>:<assistant>:<thread>`.
53
+ - `Agent` now gates its queue processor and `resumeTask()` behind that lease, so at most one Gateway replica processes a given thread at a time. Single-process behavior is unchanged (the default in-memory lease always acquires); multi-replica deployments require the PostgreSQL lease store.
54
+ - Fix: `ThreadMessageQueueStore.rowToMessage` no longer `JSON.parse`es the already-deserialized JSONB `message_content`, which previously threw for bare-string content.
55
+
56
+ Out of scope / follow-ups: cross-replica wakeup (Plan 5) and `ProjectTaskExecutionService.recover()` honoring `resumeTask`'s `settled:false` on lease contention (Plan 4).
57
+
58
+ - Updated dependencies [6addbbf]
59
+ - Updated dependencies [66e6080]
60
+ - Updated dependencies [360f9e9]
61
+ - Updated dependencies [eafaac8]
62
+ - Updated dependencies [b8c4c92]
63
+ - Updated dependencies [4c99955]
64
+ - Updated dependencies [167620b]
65
+ - Updated dependencies [d3cd2d5]
66
+ - Updated dependencies [396ad50]
67
+ - Updated dependencies [eec9db7]
68
+ - Updated dependencies [d4429f1]
69
+ - Updated dependencies [6080389]
70
+ - Updated dependencies [7ecbd01]
71
+ - Updated dependencies [e5e7b0f]
72
+ - Updated dependencies [00b179d]
73
+ - Updated dependencies [5f3d14b]
74
+ - @axiom-lattice/core@6.3.0
75
+ - @axiom-lattice/protocols@4.7.0
76
+
3
77
  ## 3.2.2
4
78
 
5
79
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Pool, PoolConfig, PoolClient } from 'pg';
2
2
  export { Pool, PoolConfig } from 'pg';
3
- import { ThreadStore, Thread, CreateThreadRequest, AssistantStore, Assistant, CreateAssistantRequest, DatabaseConfigStore, DatabaseConfigEntry, CreateDatabaseConfigRequest, UpdateDatabaseConfigRequest, ConnectionStore, ConnectionEntry, MetricsServerConfigStore, MetricsServerConfigEntry, CreateMetricsServerConfigRequest, UpdateMetricsServerConfigRequest, McpServerConfigStore, McpServerConfigEntry, CreateMcpServerConfigRequest, UpdateMcpServerConfigRequest, WorkspaceStore, Workspace, CreateWorkspaceRequest, UpdateWorkspaceRequest, ProjectStore, ProjectFilter, Project, CreateProjectRequest, UpdateProjectRequest, UpdateProjectCapabilityBundlesResult, UserStore, User, CreateUserRequest, UpdateUserRequest, TenantStore, Tenant, CreateTenantRequest, UpdateTenantRequest, UserTenantLinkStore, UserTenantLink, CreateUserTenantLinkRequest, UpdateUserTenantLinkRequest, WorkflowTrackingStore, CreateWorkflowRunRequest, WorkflowRun, UpdateWorkflowRunRequest, QueryWorkflowRunsOptions, QueryWorkflowRunsResult, CreateRunStepRequest, RunStep, UpdateRunStepRequest, StepType, EvalStore, EvalProject, CreateEvalProjectRequest, EvalSuite, CreateEvalSuiteRequest, EvalCase, CreateEvalCaseRequest, EvalRun, CreateEvalRunRequest, EvalRunResult, EvalProjectReport, BindingRegistry, Binding, CreateBindingInput, BindingMutablePatch, BindingListParams, ChannelInstallationStore, ChannelInstallation, ChannelInstallationType, CreateChannelInstallationInput, UpdateChannelInstallationRequest, A2AApiKeyStore, A2AApiKeyRecord, CreateA2AApiKeyInput, UpdateA2AApiKeyInput, A2AApiKeyEntry, OpenAuditStore, OpenAuditQuery, OpenAuditRecord, OpenAuditAppendInput, AgentWebAppStore, AgentWebApp, CreateAgentWebAppInput, AgentWebAppStorePatch, AgentWebAppUpdateOptions, ScheduleStorage, ScheduledTaskDefinition, ScheduledTaskStatus, ScheduleExecutionType, TaskStore, CreateTaskRequest, TaskItem, TaskListFilter, TaskDependentListQuery, UpdateTaskRequest, TaskMutationSnapshot, TaskWorkItemStore, CreateWorkItemRequest, TaskWorkItem, CreateWorkItemIfAbsentRequest, TaskWorkItemListFilter, ProjectLifecycleEventQuery, MenuRegistry, MenuItem, CreateMenuItemInput, UpdateMenuItemInput, SharedResourceStore, ShareRecord, CollectionStore, Collection, CreateCollectionRequest, UpdateCollectionRequest, VectorStoreProvider, VectorStoreCreateParams, CapabilityBundleStore, CapabilityBundle, InternalCreateCapabilityBundleInput, InternalUpdateCapabilityBundleInput, CapabilityBundleDeleteResult, ProjectRoomStore, ProjectRoom, ProjectMembershipStore, ProjectMembership, ProjectHumanRole, ProjectMembershipMutationResult, ProjectBotMembershipStore, ProjectBotMembership, ProjectRoomMessageStore, ProjectRoomMessage, ProjectRoomReadStateStore, ProjectRoomReadState, UserPushSubscriptionStore, UserPushSubscription, ModelProviderStore, ModelProviderEntry, CreateModelProviderRequest, UpdateModelProviderRequest, ModelProviderStatus, ModelProviderModelEntry, ProviderModelInput, SkillStore, Skill, CreateSkillRequest } from '@axiom-lattice/protocols';
3
+ import { ThreadStore, Thread, CreateThreadRequest, AssistantStore, Assistant, CreateAssistantRequest, DatabaseConfigStore, DatabaseConfigEntry, CreateDatabaseConfigRequest, UpdateDatabaseConfigRequest, ConnectionStore, ConnectionEntry, MetricsServerConfigStore, MetricsServerConfigEntry, CreateMetricsServerConfigRequest, UpdateMetricsServerConfigRequest, McpServerConfigStore, McpServerConfigEntry, CreateMcpServerConfigRequest, UpdateMcpServerConfigRequest, WorkspaceStore, Workspace, CreateWorkspaceRequest, UpdateWorkspaceRequest, ProjectStore, ProjectFilter, Project, CreateProjectRequest, UpdateProjectRequest, UpdateProjectCapabilityBundlesResult, UserStore, User, CreateUserRequest, UpdateUserRequest, TenantStore, Tenant, CreateTenantRequest, UpdateTenantRequest, UserTenantLinkStore, UserTenantLink, CreateUserTenantLinkRequest, UpdateUserTenantLinkRequest, WorkflowTrackingStore, CreateWorkflowRunRequest, WorkflowRun, UpdateWorkflowRunRequest, QueryWorkflowRunsOptions, QueryWorkflowRunsResult, CreateRunStepRequest, RunStep, UpdateRunStepRequest, StepType, EvalStore, EvalProject, CreateEvalProjectRequest, EvalSuite, CreateEvalSuiteRequest, EvalCase, CreateEvalCaseRequest, EvalRun, CreateEvalRunRequest, EvalRunResult, EvalProjectReport, BindingRegistry, Binding, CreateBindingInput, BindingMutablePatch, BindingListParams, ChannelInstallationStore, ChannelInstallation, ChannelInstallationType, CreateChannelInstallationInput, UpdateChannelInstallationRequest, A2AApiKeyStore, A2AApiKeyRecord, CreateA2AApiKeyInput, UpdateA2AApiKeyInput, A2AApiKeyEntry, OpenAuditStore, OpenAuditQuery, OpenAuditRecord, OpenAuditAppendInput, AgentWebAppStore, AgentWebApp, CreateAgentWebAppInput, AgentWebAppStorePatch, AgentWebAppUpdateOptions, ScheduleStorage, ScheduledTaskDefinition, ScheduledTaskStatus, ScheduleExecutionType, TaskStore, CreateTaskRequest, TaskItem, TaskListFilter, TaskDependentListQuery, UpdateTaskRequest, TaskMutationSnapshot, TaskWorkItemStore, CreateWorkItemRequest, TaskWorkItem, CreateWorkItemIfAbsentRequest, TaskWorkItemListFilter, ProjectLifecycleEventQuery, MenuRegistry, MenuItem, CreateMenuItemInput, UpdateMenuItemInput, SharedResourceStore, ShareRecord, CollectionStore, Collection, CreateCollectionRequest, UpdateCollectionRequest, VectorStoreProvider, VectorStoreCreateParams, CapabilityBundleStore, CapabilityBundle, InternalCreateCapabilityBundleInput, InternalUpdateCapabilityBundleInput, CapabilityBundleDeleteResult, ProjectRoomStore, ProjectRoom, ProjectMembershipStore, ProjectMembership, ProjectHumanRole, ProjectMembershipMutationResult, ProjectBotMembershipStore, ProjectBotMembership, ProjectRoomMessageStore, ProjectRoomMessage, ProjectRoomReadStateStore, ProjectRoomReadState, UserPushSubscriptionStore, UserPushSubscription, ModelProviderStore, ModelProviderEntry, CreateModelProviderRequest, UpdateModelProviderRequest, ModelProviderStatus, ModelProviderModelEntry, ProviderModelInput, LeaseStore, LeaseRecord, OutboxStore, OutboxEvent, SkillStore, Skill, CreateSkillRequest } from '@axiom-lattice/protocols';
4
4
  export { AgentWebApp, AgentWebAppAppearance, AgentWebAppFeatures, AgentWebAppScope, AgentWebAppStatus, AgentWebAppStore, Assistant, AssistantStore, Binding, BindingRegistry, CapabilityBundle, CapabilityBundleStore, ChannelInstallation, ChannelInstallationStore, ConnectionEntry, ConnectionStore, CreateAgentWebAppInput, CreateAssistantRequest, CreateBindingInput, CreateCapabilityBundleInput, CreateChannelInstallationInput, CreateChannelInstallationRequest, CreateDatabaseConfigRequest, CreateEvalCaseRequest, CreateEvalProjectRequest, CreateEvalRunRequest, CreateEvalSuiteRequest, CreateMcpServerConfigRequest, CreateMenuItemInput, CreateMetricsServerConfigRequest, CreateProjectRequest, CreateRunStepRequest, CreateShareRequest, CreateSkillRequest, CreateTenantRequest, CreateThreadRequest, CreateUserRequest, CreateUserTenantLinkRequest, CreateWorkflowRunRequest, CreateWorkspaceRequest, DatabaseConfig, DatabaseConfigEntry, DatabaseConfigStore, DatabaseType, EvalCase, EvalProject, EvalProjectReport, EvalRun, EvalRunResult, EvalStore, EvalSuite, LarkChannelInstallationConfig, McpServerConfigEntry, McpServerConfigStore, MenuItem, MenuRegistry, MetricsServerConfig, MetricsServerConfigEntry, MetricsServerConfigStore, Project, ProjectStore, ResourceAddress, RunStep, ScheduleExecutionType, ScheduleStorage, ScheduledTaskDefinition, ScheduledTaskStatus, ShareRecord, ShareResult, ShareVisibility, SharedResourceStore, Skill, SkillStore, StorageType, Tenant, TenantStatus, TenantStore, Thread, ThreadStore, UpdateAgentWebAppInput, UpdateCapabilityBundleInput, UpdateChannelInstallationRequest, UpdateDatabaseConfigRequest, UpdateMcpServerConfigRequest, UpdateMetricsServerConfigRequest, UpdateProjectRequest, UpdateRunStepRequest, UpdateTenantRequest, UpdateUserRequest, UpdateUserTenantLinkRequest, UpdateWorkflowRunRequest, UpdateWorkspaceRequest, User, UserStore, UserTenantLink, UserTenantLinkStore, UserTenantRole, WorkflowRun, WorkflowTrackingStore, Workspace, WorkspaceStore } from '@axiom-lattice/protocols';
5
- import { IMessageQueueStore, AddMessageParams, PendingMessage, QueueScope, ThreadInfo } from '@axiom-lattice/core';
5
+ import { IMessageQueueStore, AddMessageParams, PendingMessage, QueueScope, ClaimMessagesOptions, ThreadInfo } from '@axiom-lattice/core';
6
6
  export { AddMessageParams, PendingMessage, ThreadInfo } from '@axiom-lattice/core';
7
7
  import { PostgresSaver } from '@langchain/langgraph-checkpoint-postgres';
8
8
  import { DocumentInterface } from '@langchain/core/documents';
@@ -925,6 +925,14 @@ declare class ThreadMessageQueueStore implements IMessageQueueStore {
925
925
  * Get pending messages for thread
926
926
  */
927
927
  getPendingMessages(threadId: string, scope?: QueueScope): Promise<PendingMessage[]>;
928
+ /**
929
+ * Atomically claims pending messages for a replica, stamping a lease.
930
+ */
931
+ claimPendingMessages(threadId: string, scope: QueueScope | undefined, options: ClaimMessagesOptions): Promise<PendingMessage[]>;
932
+ /**
933
+ * Returns expired processing rows to pending and clears their lease.
934
+ */
935
+ reclaimExpiredProcessing(threadId: string, scope?: QueueScope): Promise<number>;
928
936
  /**
929
937
  * Get processing messages for a thread
930
938
  */
@@ -1159,6 +1167,25 @@ declare class PostgreSQLScheduleStorage implements ScheduleStorage {
1159
1167
  * Update task
1160
1168
  */
1161
1169
  update(taskId: string, updates: Partial<ScheduledTaskDefinition>): Promise<void>;
1170
+ /**
1171
+ * Atomically claims one due fire by transitioning the task `pending -> running`.
1172
+ *
1173
+ * Only one caller wins the `UPDATE ... WHERE status = 'pending'`; all others
1174
+ * observe zero affected rows and must skip execution.
1175
+ *
1176
+ * @param taskId Task to claim.
1177
+ * @returns True when this caller won the claim (task was `pending`); false if
1178
+ * another replica already claimed it or it is not pending.
1179
+ */
1180
+ claimScheduledRun(taskId: string): Promise<boolean>;
1181
+ /**
1182
+ * Requeues `running` tasks whose `updated_at` is older than `olderThanMs` back
1183
+ * to `pending` (recovery after a crash that left a claim unsettled).
1184
+ *
1185
+ * @param olderThanMs Age threshold in milliseconds.
1186
+ * @returns The number of tasks requeued.
1187
+ */
1188
+ requeueStaleRunning(olderThanMs: number): Promise<number>;
1162
1189
  /**
1163
1190
  * Delete task
1164
1191
  */
@@ -1811,6 +1838,84 @@ declare class PostgreSQLModelProviderStore implements ModelProviderStore {
1811
1838
  private mapRowToModel;
1812
1839
  }
1813
1840
 
1841
+ interface PostgreSQLLeaseStoreOptions {
1842
+ pool?: Pool;
1843
+ poolConfig?: string | PoolConfig;
1844
+ autoMigrate?: boolean;
1845
+ }
1846
+ /**
1847
+ * PostgreSQL {@link LeaseStore}: cross-replica exclusion with self-expiring rows.
1848
+ *
1849
+ * @remarks `tryAcquire` is a single atomic upsert guarded by `expires_at`; no
1850
+ * external lock manager is required. Uses the shared `lattice_leases` table.
1851
+ */
1852
+ declare class PostgreSQLLeaseStore implements LeaseStore {
1853
+ private pool;
1854
+ private ownsPool;
1855
+ private initialized;
1856
+ private initPromise;
1857
+ private migrationManager;
1858
+ /** @param options An externally managed pool, or a pool config/URL. */
1859
+ constructor(options: PostgreSQLLeaseStoreOptions);
1860
+ /** Runs pending migrations once. */
1861
+ initialize(): Promise<void>;
1862
+ /** Ends the pool when this store owns it. */
1863
+ dispose(): Promise<void>;
1864
+ /** Atomically acquires a free/expired key (or re-acquires the caller's own). */
1865
+ tryAcquire(key: string, holder: string, ttlMs: number): Promise<boolean>;
1866
+ /** Extends a lease only while `holder` still owns it. */
1867
+ renew(key: string, holder: string, ttlMs: number): Promise<boolean>;
1868
+ /** Deletes a lease only when `holder` owns it. */
1869
+ release(key: string, holder: string): Promise<boolean>;
1870
+ /** Returns the live lease, or `null` when free/expired/absent. */
1871
+ get(key: string): Promise<LeaseRecord | null>;
1872
+ }
1873
+
1874
+ interface PostgreSQLOutboxStoreOptions {
1875
+ pool?: Pool;
1876
+ poolConfig?: string | PoolConfig;
1877
+ autoMigrate?: boolean;
1878
+ }
1879
+ /**
1880
+ * PostgreSQL {@link OutboxStore}: an append-only, cross-replica notification log.
1881
+ *
1882
+ * @remarks Ids come from a `BIGSERIAL`, giving a total order across replicas.
1883
+ * Callers poll with a cursor (`listAfter`) and skip their own `originReplicaId`;
1884
+ * delivery is therefore at-least-once. Uses the shared `lattice_outbox` table.
1885
+ */
1886
+ declare class PostgreSQLOutboxStore implements OutboxStore {
1887
+ private pool;
1888
+ private ownsPool;
1889
+ private initialized;
1890
+ private initPromise;
1891
+ private migrationManager;
1892
+ /** @param options An externally managed pool, or a pool config/URL. */
1893
+ constructor(options: PostgreSQLOutboxStoreOptions);
1894
+ /** Runs pending migrations once. */
1895
+ initialize(): Promise<void>;
1896
+ /** Ends the pool when this store owns it. */
1897
+ dispose(): Promise<void>;
1898
+ /** Appends one event and returns it with its assigned id. */
1899
+ append(input: {
1900
+ topic: string;
1901
+ payload: unknown;
1902
+ originReplicaId: string;
1903
+ }): Promise<OutboxEvent>;
1904
+ /** Lists up to `limit` events with `id > cursor`, ascending. */
1905
+ listAfter(cursor: string | null, limit: number): Promise<OutboxEvent[]>;
1906
+ /** Returns the newest id, or `null` when the log is empty. */
1907
+ latestId(): Promise<string | null>;
1908
+ /**
1909
+ * Deletes events older than `olderThanMs` (evaluated against the database clock).
1910
+ *
1911
+ * @param olderThanMs Age threshold in milliseconds.
1912
+ * @returns The number of rows deleted.
1913
+ */
1914
+ pruneOlderThan(olderThanMs: number): Promise<number>;
1915
+ /** Maps a `lattice_outbox` row to an {@link OutboxEvent}. */
1916
+ private rowToEvent;
1917
+ }
1918
+
1814
1919
  declare function createPgStoreConfig(connectionString: string): Promise<{
1815
1920
  workspace: PostgreSQLWorkspaceStore;
1816
1921
  project: PostgreSQLProjectStore;
@@ -1845,6 +1950,8 @@ declare function createPgStoreConfig(connectionString: string): Promise<{
1845
1950
  projectRoomMessage: PostgreSQLProjectRoomMessageStore;
1846
1951
  projectRoomReadState: PostgreSQLProjectRoomReadStateStore;
1847
1952
  userPushSubscription: PostgreSQLUserPushSubscriptionStore;
1953
+ lease: PostgreSQLLeaseStore;
1954
+ outbox: PostgreSQLOutboxStore;
1848
1955
  vectorStoreProvider: PGVectorStoreProvider;
1849
1956
  checkpoint: PostgresSaver;
1850
1957
  }>;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Pool, PoolConfig, PoolClient } from 'pg';
2
2
  export { Pool, PoolConfig } from 'pg';
3
- import { ThreadStore, Thread, CreateThreadRequest, AssistantStore, Assistant, CreateAssistantRequest, DatabaseConfigStore, DatabaseConfigEntry, CreateDatabaseConfigRequest, UpdateDatabaseConfigRequest, ConnectionStore, ConnectionEntry, MetricsServerConfigStore, MetricsServerConfigEntry, CreateMetricsServerConfigRequest, UpdateMetricsServerConfigRequest, McpServerConfigStore, McpServerConfigEntry, CreateMcpServerConfigRequest, UpdateMcpServerConfigRequest, WorkspaceStore, Workspace, CreateWorkspaceRequest, UpdateWorkspaceRequest, ProjectStore, ProjectFilter, Project, CreateProjectRequest, UpdateProjectRequest, UpdateProjectCapabilityBundlesResult, UserStore, User, CreateUserRequest, UpdateUserRequest, TenantStore, Tenant, CreateTenantRequest, UpdateTenantRequest, UserTenantLinkStore, UserTenantLink, CreateUserTenantLinkRequest, UpdateUserTenantLinkRequest, WorkflowTrackingStore, CreateWorkflowRunRequest, WorkflowRun, UpdateWorkflowRunRequest, QueryWorkflowRunsOptions, QueryWorkflowRunsResult, CreateRunStepRequest, RunStep, UpdateRunStepRequest, StepType, EvalStore, EvalProject, CreateEvalProjectRequest, EvalSuite, CreateEvalSuiteRequest, EvalCase, CreateEvalCaseRequest, EvalRun, CreateEvalRunRequest, EvalRunResult, EvalProjectReport, BindingRegistry, Binding, CreateBindingInput, BindingMutablePatch, BindingListParams, ChannelInstallationStore, ChannelInstallation, ChannelInstallationType, CreateChannelInstallationInput, UpdateChannelInstallationRequest, A2AApiKeyStore, A2AApiKeyRecord, CreateA2AApiKeyInput, UpdateA2AApiKeyInput, A2AApiKeyEntry, OpenAuditStore, OpenAuditQuery, OpenAuditRecord, OpenAuditAppendInput, AgentWebAppStore, AgentWebApp, CreateAgentWebAppInput, AgentWebAppStorePatch, AgentWebAppUpdateOptions, ScheduleStorage, ScheduledTaskDefinition, ScheduledTaskStatus, ScheduleExecutionType, TaskStore, CreateTaskRequest, TaskItem, TaskListFilter, TaskDependentListQuery, UpdateTaskRequest, TaskMutationSnapshot, TaskWorkItemStore, CreateWorkItemRequest, TaskWorkItem, CreateWorkItemIfAbsentRequest, TaskWorkItemListFilter, ProjectLifecycleEventQuery, MenuRegistry, MenuItem, CreateMenuItemInput, UpdateMenuItemInput, SharedResourceStore, ShareRecord, CollectionStore, Collection, CreateCollectionRequest, UpdateCollectionRequest, VectorStoreProvider, VectorStoreCreateParams, CapabilityBundleStore, CapabilityBundle, InternalCreateCapabilityBundleInput, InternalUpdateCapabilityBundleInput, CapabilityBundleDeleteResult, ProjectRoomStore, ProjectRoom, ProjectMembershipStore, ProjectMembership, ProjectHumanRole, ProjectMembershipMutationResult, ProjectBotMembershipStore, ProjectBotMembership, ProjectRoomMessageStore, ProjectRoomMessage, ProjectRoomReadStateStore, ProjectRoomReadState, UserPushSubscriptionStore, UserPushSubscription, ModelProviderStore, ModelProviderEntry, CreateModelProviderRequest, UpdateModelProviderRequest, ModelProviderStatus, ModelProviderModelEntry, ProviderModelInput, SkillStore, Skill, CreateSkillRequest } from '@axiom-lattice/protocols';
3
+ import { ThreadStore, Thread, CreateThreadRequest, AssistantStore, Assistant, CreateAssistantRequest, DatabaseConfigStore, DatabaseConfigEntry, CreateDatabaseConfigRequest, UpdateDatabaseConfigRequest, ConnectionStore, ConnectionEntry, MetricsServerConfigStore, MetricsServerConfigEntry, CreateMetricsServerConfigRequest, UpdateMetricsServerConfigRequest, McpServerConfigStore, McpServerConfigEntry, CreateMcpServerConfigRequest, UpdateMcpServerConfigRequest, WorkspaceStore, Workspace, CreateWorkspaceRequest, UpdateWorkspaceRequest, ProjectStore, ProjectFilter, Project, CreateProjectRequest, UpdateProjectRequest, UpdateProjectCapabilityBundlesResult, UserStore, User, CreateUserRequest, UpdateUserRequest, TenantStore, Tenant, CreateTenantRequest, UpdateTenantRequest, UserTenantLinkStore, UserTenantLink, CreateUserTenantLinkRequest, UpdateUserTenantLinkRequest, WorkflowTrackingStore, CreateWorkflowRunRequest, WorkflowRun, UpdateWorkflowRunRequest, QueryWorkflowRunsOptions, QueryWorkflowRunsResult, CreateRunStepRequest, RunStep, UpdateRunStepRequest, StepType, EvalStore, EvalProject, CreateEvalProjectRequest, EvalSuite, CreateEvalSuiteRequest, EvalCase, CreateEvalCaseRequest, EvalRun, CreateEvalRunRequest, EvalRunResult, EvalProjectReport, BindingRegistry, Binding, CreateBindingInput, BindingMutablePatch, BindingListParams, ChannelInstallationStore, ChannelInstallation, ChannelInstallationType, CreateChannelInstallationInput, UpdateChannelInstallationRequest, A2AApiKeyStore, A2AApiKeyRecord, CreateA2AApiKeyInput, UpdateA2AApiKeyInput, A2AApiKeyEntry, OpenAuditStore, OpenAuditQuery, OpenAuditRecord, OpenAuditAppendInput, AgentWebAppStore, AgentWebApp, CreateAgentWebAppInput, AgentWebAppStorePatch, AgentWebAppUpdateOptions, ScheduleStorage, ScheduledTaskDefinition, ScheduledTaskStatus, ScheduleExecutionType, TaskStore, CreateTaskRequest, TaskItem, TaskListFilter, TaskDependentListQuery, UpdateTaskRequest, TaskMutationSnapshot, TaskWorkItemStore, CreateWorkItemRequest, TaskWorkItem, CreateWorkItemIfAbsentRequest, TaskWorkItemListFilter, ProjectLifecycleEventQuery, MenuRegistry, MenuItem, CreateMenuItemInput, UpdateMenuItemInput, SharedResourceStore, ShareRecord, CollectionStore, Collection, CreateCollectionRequest, UpdateCollectionRequest, VectorStoreProvider, VectorStoreCreateParams, CapabilityBundleStore, CapabilityBundle, InternalCreateCapabilityBundleInput, InternalUpdateCapabilityBundleInput, CapabilityBundleDeleteResult, ProjectRoomStore, ProjectRoom, ProjectMembershipStore, ProjectMembership, ProjectHumanRole, ProjectMembershipMutationResult, ProjectBotMembershipStore, ProjectBotMembership, ProjectRoomMessageStore, ProjectRoomMessage, ProjectRoomReadStateStore, ProjectRoomReadState, UserPushSubscriptionStore, UserPushSubscription, ModelProviderStore, ModelProviderEntry, CreateModelProviderRequest, UpdateModelProviderRequest, ModelProviderStatus, ModelProviderModelEntry, ProviderModelInput, LeaseStore, LeaseRecord, OutboxStore, OutboxEvent, SkillStore, Skill, CreateSkillRequest } from '@axiom-lattice/protocols';
4
4
  export { AgentWebApp, AgentWebAppAppearance, AgentWebAppFeatures, AgentWebAppScope, AgentWebAppStatus, AgentWebAppStore, Assistant, AssistantStore, Binding, BindingRegistry, CapabilityBundle, CapabilityBundleStore, ChannelInstallation, ChannelInstallationStore, ConnectionEntry, ConnectionStore, CreateAgentWebAppInput, CreateAssistantRequest, CreateBindingInput, CreateCapabilityBundleInput, CreateChannelInstallationInput, CreateChannelInstallationRequest, CreateDatabaseConfigRequest, CreateEvalCaseRequest, CreateEvalProjectRequest, CreateEvalRunRequest, CreateEvalSuiteRequest, CreateMcpServerConfigRequest, CreateMenuItemInput, CreateMetricsServerConfigRequest, CreateProjectRequest, CreateRunStepRequest, CreateShareRequest, CreateSkillRequest, CreateTenantRequest, CreateThreadRequest, CreateUserRequest, CreateUserTenantLinkRequest, CreateWorkflowRunRequest, CreateWorkspaceRequest, DatabaseConfig, DatabaseConfigEntry, DatabaseConfigStore, DatabaseType, EvalCase, EvalProject, EvalProjectReport, EvalRun, EvalRunResult, EvalStore, EvalSuite, LarkChannelInstallationConfig, McpServerConfigEntry, McpServerConfigStore, MenuItem, MenuRegistry, MetricsServerConfig, MetricsServerConfigEntry, MetricsServerConfigStore, Project, ProjectStore, ResourceAddress, RunStep, ScheduleExecutionType, ScheduleStorage, ScheduledTaskDefinition, ScheduledTaskStatus, ShareRecord, ShareResult, ShareVisibility, SharedResourceStore, Skill, SkillStore, StorageType, Tenant, TenantStatus, TenantStore, Thread, ThreadStore, UpdateAgentWebAppInput, UpdateCapabilityBundleInput, UpdateChannelInstallationRequest, UpdateDatabaseConfigRequest, UpdateMcpServerConfigRequest, UpdateMetricsServerConfigRequest, UpdateProjectRequest, UpdateRunStepRequest, UpdateTenantRequest, UpdateUserRequest, UpdateUserTenantLinkRequest, UpdateWorkflowRunRequest, UpdateWorkspaceRequest, User, UserStore, UserTenantLink, UserTenantLinkStore, UserTenantRole, WorkflowRun, WorkflowTrackingStore, Workspace, WorkspaceStore } from '@axiom-lattice/protocols';
5
- import { IMessageQueueStore, AddMessageParams, PendingMessage, QueueScope, ThreadInfo } from '@axiom-lattice/core';
5
+ import { IMessageQueueStore, AddMessageParams, PendingMessage, QueueScope, ClaimMessagesOptions, ThreadInfo } from '@axiom-lattice/core';
6
6
  export { AddMessageParams, PendingMessage, ThreadInfo } from '@axiom-lattice/core';
7
7
  import { PostgresSaver } from '@langchain/langgraph-checkpoint-postgres';
8
8
  import { DocumentInterface } from '@langchain/core/documents';
@@ -925,6 +925,14 @@ declare class ThreadMessageQueueStore implements IMessageQueueStore {
925
925
  * Get pending messages for thread
926
926
  */
927
927
  getPendingMessages(threadId: string, scope?: QueueScope): Promise<PendingMessage[]>;
928
+ /**
929
+ * Atomically claims pending messages for a replica, stamping a lease.
930
+ */
931
+ claimPendingMessages(threadId: string, scope: QueueScope | undefined, options: ClaimMessagesOptions): Promise<PendingMessage[]>;
932
+ /**
933
+ * Returns expired processing rows to pending and clears their lease.
934
+ */
935
+ reclaimExpiredProcessing(threadId: string, scope?: QueueScope): Promise<number>;
928
936
  /**
929
937
  * Get processing messages for a thread
930
938
  */
@@ -1159,6 +1167,25 @@ declare class PostgreSQLScheduleStorage implements ScheduleStorage {
1159
1167
  * Update task
1160
1168
  */
1161
1169
  update(taskId: string, updates: Partial<ScheduledTaskDefinition>): Promise<void>;
1170
+ /**
1171
+ * Atomically claims one due fire by transitioning the task `pending -> running`.
1172
+ *
1173
+ * Only one caller wins the `UPDATE ... WHERE status = 'pending'`; all others
1174
+ * observe zero affected rows and must skip execution.
1175
+ *
1176
+ * @param taskId Task to claim.
1177
+ * @returns True when this caller won the claim (task was `pending`); false if
1178
+ * another replica already claimed it or it is not pending.
1179
+ */
1180
+ claimScheduledRun(taskId: string): Promise<boolean>;
1181
+ /**
1182
+ * Requeues `running` tasks whose `updated_at` is older than `olderThanMs` back
1183
+ * to `pending` (recovery after a crash that left a claim unsettled).
1184
+ *
1185
+ * @param olderThanMs Age threshold in milliseconds.
1186
+ * @returns The number of tasks requeued.
1187
+ */
1188
+ requeueStaleRunning(olderThanMs: number): Promise<number>;
1162
1189
  /**
1163
1190
  * Delete task
1164
1191
  */
@@ -1811,6 +1838,84 @@ declare class PostgreSQLModelProviderStore implements ModelProviderStore {
1811
1838
  private mapRowToModel;
1812
1839
  }
1813
1840
 
1841
+ interface PostgreSQLLeaseStoreOptions {
1842
+ pool?: Pool;
1843
+ poolConfig?: string | PoolConfig;
1844
+ autoMigrate?: boolean;
1845
+ }
1846
+ /**
1847
+ * PostgreSQL {@link LeaseStore}: cross-replica exclusion with self-expiring rows.
1848
+ *
1849
+ * @remarks `tryAcquire` is a single atomic upsert guarded by `expires_at`; no
1850
+ * external lock manager is required. Uses the shared `lattice_leases` table.
1851
+ */
1852
+ declare class PostgreSQLLeaseStore implements LeaseStore {
1853
+ private pool;
1854
+ private ownsPool;
1855
+ private initialized;
1856
+ private initPromise;
1857
+ private migrationManager;
1858
+ /** @param options An externally managed pool, or a pool config/URL. */
1859
+ constructor(options: PostgreSQLLeaseStoreOptions);
1860
+ /** Runs pending migrations once. */
1861
+ initialize(): Promise<void>;
1862
+ /** Ends the pool when this store owns it. */
1863
+ dispose(): Promise<void>;
1864
+ /** Atomically acquires a free/expired key (or re-acquires the caller's own). */
1865
+ tryAcquire(key: string, holder: string, ttlMs: number): Promise<boolean>;
1866
+ /** Extends a lease only while `holder` still owns it. */
1867
+ renew(key: string, holder: string, ttlMs: number): Promise<boolean>;
1868
+ /** Deletes a lease only when `holder` owns it. */
1869
+ release(key: string, holder: string): Promise<boolean>;
1870
+ /** Returns the live lease, or `null` when free/expired/absent. */
1871
+ get(key: string): Promise<LeaseRecord | null>;
1872
+ }
1873
+
1874
+ interface PostgreSQLOutboxStoreOptions {
1875
+ pool?: Pool;
1876
+ poolConfig?: string | PoolConfig;
1877
+ autoMigrate?: boolean;
1878
+ }
1879
+ /**
1880
+ * PostgreSQL {@link OutboxStore}: an append-only, cross-replica notification log.
1881
+ *
1882
+ * @remarks Ids come from a `BIGSERIAL`, giving a total order across replicas.
1883
+ * Callers poll with a cursor (`listAfter`) and skip their own `originReplicaId`;
1884
+ * delivery is therefore at-least-once. Uses the shared `lattice_outbox` table.
1885
+ */
1886
+ declare class PostgreSQLOutboxStore implements OutboxStore {
1887
+ private pool;
1888
+ private ownsPool;
1889
+ private initialized;
1890
+ private initPromise;
1891
+ private migrationManager;
1892
+ /** @param options An externally managed pool, or a pool config/URL. */
1893
+ constructor(options: PostgreSQLOutboxStoreOptions);
1894
+ /** Runs pending migrations once. */
1895
+ initialize(): Promise<void>;
1896
+ /** Ends the pool when this store owns it. */
1897
+ dispose(): Promise<void>;
1898
+ /** Appends one event and returns it with its assigned id. */
1899
+ append(input: {
1900
+ topic: string;
1901
+ payload: unknown;
1902
+ originReplicaId: string;
1903
+ }): Promise<OutboxEvent>;
1904
+ /** Lists up to `limit` events with `id > cursor`, ascending. */
1905
+ listAfter(cursor: string | null, limit: number): Promise<OutboxEvent[]>;
1906
+ /** Returns the newest id, or `null` when the log is empty. */
1907
+ latestId(): Promise<string | null>;
1908
+ /**
1909
+ * Deletes events older than `olderThanMs` (evaluated against the database clock).
1910
+ *
1911
+ * @param olderThanMs Age threshold in milliseconds.
1912
+ * @returns The number of rows deleted.
1913
+ */
1914
+ pruneOlderThan(olderThanMs: number): Promise<number>;
1915
+ /** Maps a `lattice_outbox` row to an {@link OutboxEvent}. */
1916
+ private rowToEvent;
1917
+ }
1918
+
1814
1919
  declare function createPgStoreConfig(connectionString: string): Promise<{
1815
1920
  workspace: PostgreSQLWorkspaceStore;
1816
1921
  project: PostgreSQLProjectStore;
@@ -1845,6 +1950,8 @@ declare function createPgStoreConfig(connectionString: string): Promise<{
1845
1950
  projectRoomMessage: PostgreSQLProjectRoomMessageStore;
1846
1951
  projectRoomReadState: PostgreSQLProjectRoomReadStateStore;
1847
1952
  userPushSubscription: PostgreSQLUserPushSubscriptionStore;
1953
+ lease: PostgreSQLLeaseStore;
1954
+ outbox: PostgreSQLOutboxStore;
1848
1955
  vectorStoreProvider: PGVectorStoreProvider;
1849
1956
  checkpoint: PostgresSaver;
1850
1957
  }>;