@hasna/loops 0.4.28 → 0.4.29

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 (77) hide show
  1. package/CHANGELOG.md +84 -1
  2. package/README.md +226 -49
  3. package/dist/api/index.d.ts +20 -19
  4. package/dist/api/index.js +6846 -1087
  5. package/dist/cli/index.js +2471 -885
  6. package/dist/cli/safe-error-context.d.ts +1 -0
  7. package/dist/daemon/daemon.d.ts +1 -0
  8. package/dist/daemon/index.js +1786 -493
  9. package/dist/generated/storage-kit/index.d.ts +1 -1
  10. package/dist/generated/storage-kit/mode.d.ts +6 -12
  11. package/dist/index.d.ts +3 -3
  12. package/dist/index.js +4778 -1016
  13. package/dist/lib/advancement.d.ts +52 -0
  14. package/dist/lib/agent-adapter.d.ts +20 -2
  15. package/dist/lib/auth/route-policy.d.ts +14 -0
  16. package/dist/lib/auth/tenant-auth.d.ts +38 -0
  17. package/dist/lib/cloud/mode.d.ts +2 -8
  18. package/dist/lib/cloud/storage.d.ts +1 -2
  19. package/dist/lib/cloud/transport.d.ts +4 -18
  20. package/dist/lib/errors.d.ts +43 -1
  21. package/dist/lib/format.d.ts +2 -2
  22. package/dist/lib/goal/runner.d.ts +36 -3
  23. package/dist/lib/health.d.ts +1 -1
  24. package/dist/lib/labels.d.ts +4 -0
  25. package/dist/lib/loop-status.d.ts +4 -0
  26. package/dist/lib/migration.d.ts +4 -17
  27. package/dist/lib/mode.d.ts +2 -5
  28. package/dist/lib/mode.js +27 -36
  29. package/dist/lib/route/index.d.ts +2 -2
  30. package/dist/lib/route/throttle.d.ts +7 -0
  31. package/dist/lib/route/types.d.ts +3 -0
  32. package/dist/lib/run-completion.d.ts +18 -0
  33. package/dist/lib/scheduler.d.ts +5 -11
  34. package/dist/lib/storage/contract.d.ts +15 -1
  35. package/dist/lib/storage/index.d.ts +1 -1
  36. package/dist/lib/storage/index.js +3864 -457
  37. package/dist/lib/storage/pg-executor.d.ts +10 -5
  38. package/dist/lib/storage/postgres-loop-storage.d.ts +50 -24
  39. package/dist/lib/storage/postgres-schema.d.ts +8 -0
  40. package/dist/lib/storage/postgres-schema.js +1323 -1
  41. package/dist/lib/storage/postgres.d.ts +3 -1
  42. package/dist/lib/storage/postgres.js +1353 -27
  43. package/dist/lib/storage/provider-credentials.d.ts +84 -0
  44. package/dist/lib/storage/shared-database-transfer.d.ts +136 -0
  45. package/dist/lib/storage/sqlite.d.ts +15 -2
  46. package/dist/lib/storage/sqlite.js +1299 -217
  47. package/dist/lib/storage/tenant-backfill-s3.d.ts +53 -0
  48. package/dist/lib/storage/tenant-backfill.d.ts +40 -0
  49. package/dist/lib/store/index.d.ts +11 -8
  50. package/dist/lib/store.d.ts +52 -7
  51. package/dist/lib/store.js +1266 -217
  52. package/dist/lib/templates.d.ts +11 -0
  53. package/dist/lib/workflow-events.d.ts +6 -0
  54. package/dist/lib/workflow-provenance.d.ts +8 -0
  55. package/dist/lib/workflow-runner.d.ts +52 -4
  56. package/dist/mcp/index.js +1961 -651
  57. package/dist/runner/index.d.ts +20 -2
  58. package/dist/runner/index.js +2113 -177
  59. package/dist/sdk/http.d.ts +211 -3
  60. package/dist/sdk/http.js +301 -0
  61. package/dist/sdk/index.d.ts +7 -2
  62. package/dist/sdk/index.js +1959 -711
  63. package/dist/serve/index.d.ts +14 -0
  64. package/dist/serve/index.js +12323 -1743
  65. package/dist/types.d.ts +64 -3
  66. package/docs/AUTOMATION_RUNTIME_DESIGN.md +32 -32
  67. package/docs/CUTOVER-RUNBOOK.md +158 -31
  68. package/docs/DEPLOYMENT_MODES.md +78 -56
  69. package/docs/RUNTIME_BOUNDARY.md +26 -26
  70. package/docs/SHARED-DATABASE-TRANSFER.md +95 -0
  71. package/docs/SHARED_KIT_EXTRACTION_INVENTORY.md +631 -0
  72. package/docs/TRANSCRIPT_LOOP_PATTERNS.md +3 -3
  73. package/docs/UNIFIED_PRODUCT_CONTRACT.md +365 -0
  74. package/docs/USAGE.md +143 -52
  75. package/docs/workflows/transcript-feedback-to-loops.json +2 -2
  76. package/package.json +7 -3
  77. package/dist/lib/storage/pg-runner-claim.d.ts +0 -40
@@ -8,12 +8,11 @@ export interface PgExecutorOptions {
8
8
  idleTimeoutMillis?: number;
9
9
  }
10
10
  /**
11
- * `PostgresQueryExecutor` backed by a live `pg.Pool` via the vendored kit.
11
+ * `PostgresQueryExecutor` backed by a live `pg.Pool` via the generated kit.
12
12
  *
13
- * Transaction support is intentionally omitted: `PostgresStorage.migrate`
14
- * treats DDL as idempotent (`CREATE ... IF NOT EXISTS` + a checksum ledger), so
15
- * a pooled sequential apply is correct and avoids binding every inner
16
- * `execute` to a single dedicated client.
13
+ * Transactions bind every statement to one dedicated pool client. This is
14
+ * required both for atomic migration+ledger writes and request-scoped RLS
15
+ * settings established with `SET LOCAL`.
17
16
  */
18
17
  export declare class PgPoolExecutor implements PostgresQueryExecutor {
19
18
  private readonly client;
@@ -23,5 +22,11 @@ export declare class PgPoolExecutor implements PostgresQueryExecutor {
23
22
  get queryClient(): PoolQueryClient;
24
23
  query<T extends Record<string, unknown>>(sql: string, params?: readonly unknown[]): Promise<T[]>;
25
24
  execute(sql: string, params?: readonly unknown[]): Promise<void>;
25
+ transaction<T>(fn: (executor: PostgresQueryExecutor) => Promise<T>): Promise<T>;
26
+ withRequestContext<T>(context: {
27
+ tenantId: string;
28
+ principalId: string;
29
+ requestId: string;
30
+ }, fn: (client: PoolQueryClient) => Promise<T>): Promise<T>;
26
31
  close(): Promise<void>;
27
32
  }
@@ -1,23 +1,29 @@
1
- import type { RecoverExpiredRunLeasesResult } from "../store.js";
1
+ import type { RecoverExpiredRunLeasesResult, RecoveredLeaseRunPage } from "../store.js";
2
2
  import { Store } from "../store.js";
3
3
  import type { PoolQueryClient } from "../../generated/storage-kit/query.js";
4
4
  import type { LoopStorageContract, LoopStorageMethodName } from "./contract.js";
5
- /** Thrown by store methods that are not yet ported to the Postgres backend. */
6
- export declare class NotImplementedError extends Error {
7
- readonly code = "not_implemented";
8
- constructor(method: string);
9
- }
10
5
  type M<K extends LoopStorageMethodName> = Store[K] extends (...a: infer A) => infer R ? {
11
6
  args: A;
12
7
  result: R;
13
8
  } : never;
9
+ export interface TenantStorageContext {
10
+ tenantId: string;
11
+ principalId: string;
12
+ requestId: string;
13
+ }
14
14
  export declare class PostgresLoopStorage implements LoopStorageContract {
15
- private readonly client;
16
15
  readonly backend = "postgres";
17
16
  readonly supportsRemoteRunners = true;
18
- constructor(client: PoolQueryClient);
17
+ readonly tenantId: string;
18
+ readonly principalId: string;
19
+ readonly requestId: string;
20
+ private readonly client;
21
+ constructor(client: PoolQueryClient, context: TenantStorageContext, opts?: {
22
+ contextAlreadyBound?: boolean;
23
+ });
19
24
  close(): Promise<void>;
20
25
  private assertDaemonLeaseFence;
26
+ private lockWorkflowRun;
21
27
  private loadLoop;
22
28
  private loadRun;
23
29
  private loadRunBySlot;
@@ -25,18 +31,24 @@ export declare class PostgresLoopStorage implements LoopStorageContract {
25
31
  private setWorkItemsForLoop;
26
32
  private setWorkItemsForWorkflowRun;
27
33
  private cascadeWorkItemsForLoopRun;
34
+ private maybeArchiveGeneratedRouteWorkflow;
28
35
  createLoop(...args: M<"createLoop">["args"]): Promise<M<"createLoop">["result"]>;
29
36
  getLoop(...args: M<"getLoop">["args"]): Promise<M<"getLoop">["result"]>;
30
37
  findLoopByName(...args: M<"findLoopByName">["args"]): Promise<M<"findLoopByName">["result"]>;
31
38
  requireLoop(...args: M<"requireLoop">["args"]): Promise<M<"requireLoop">["result"]>;
39
+ requireUniqueLoop(...args: M<"requireUniqueLoop">["args"]): Promise<M<"requireUniqueLoop">["result"]>;
32
40
  listLoops(...args: M<"listLoops">["args"]): Promise<M<"listLoops">["result"]>;
33
41
  dueLoops(...args: M<"dueLoops">["args"]): Promise<M<"dueLoops">["result"]>;
34
42
  updateLoop(...args: M<"updateLoop">["args"]): Promise<M<"updateLoop">["result"]>;
43
+ advanceLoopIfCurrent(...args: M<"advanceLoopIfCurrent">["args"]): Promise<M<"advanceLoopIfCurrent">["result"]>;
44
+ tripCircuitBreakerIfCurrent(...args: M<"tripCircuitBreakerIfCurrent">["args"]): Promise<M<"tripCircuitBreakerIfCurrent">["result"]>;
35
45
  renameLoop(...args: M<"renameLoop">["args"]): Promise<M<"renameLoop">["result"]>;
36
46
  archiveLoop(...args: M<"archiveLoop">["args"]): Promise<M<"archiveLoop">["result"]>;
37
47
  unarchiveLoop(...args: M<"unarchiveLoop">["args"]): Promise<M<"unarchiveLoop">["result"]>;
38
48
  deleteLoop(...args: M<"deleteLoop">["args"]): Promise<M<"deleteLoop">["result"]>;
39
49
  private requireLoopIn;
50
+ private requireUniqueLoopIn;
51
+ private requireArchiveMutationLoopIn;
40
52
  countLoops(...args: M<"countLoops">["args"]): Promise<M<"countLoops">["result"]>;
41
53
  upsertMigrationWorkflow(...args: M<"upsertMigrationWorkflow">["args"]): Promise<M<"upsertMigrationWorkflow">["result"]>;
42
54
  upsertMigrationLoop(...args: M<"upsertMigrationLoop">["args"]): Promise<M<"upsertMigrationLoop">["result"]>;
@@ -44,6 +56,7 @@ export declare class PostgresLoopStorage implements LoopStorageContract {
44
56
  createSkippedRun(...args: M<"createSkippedRun">["args"]): Promise<M<"createSkippedRun">["result"]>;
45
57
  getRun(...args: M<"getRun">["args"]): Promise<M<"getRun">["result"]>;
46
58
  getRunBySlot(...args: M<"getRunBySlot">["args"]): Promise<M<"getRunBySlot">["result"]>;
59
+ nextRetryableRun(...args: M<"nextRetryableRun">["args"]): Promise<M<"nextRetryableRun">["result"]>;
47
60
  /**
48
61
  * Claim a specific loop slot for a runner.
49
62
  *
@@ -62,6 +75,7 @@ export declare class PostgresLoopStorage implements LoopStorageContract {
62
75
  heartbeatRunLease(...args: M<"heartbeatRunLease">["args"]): Promise<M<"heartbeatRunLease">["result"]>;
63
76
  recordRunProcess(...args: M<"recordRunProcess">["args"]): Promise<M<"recordRunProcess">["result"]>;
64
77
  listRuns(...args: M<"listRuns">["args"]): Promise<M<"listRuns">["result"]>;
78
+ listRecoveredLeaseRunsPage(...args: M<"listRecoveredLeaseRunsPage">["args"]): Promise<RecoveredLeaseRunPage>;
65
79
  writeRunReceipt(...args: M<"writeRunReceipt">["args"]): Promise<M<"writeRunReceipt">["result"]>;
66
80
  getRunReceipt(...args: M<"getRunReceipt">["args"]): Promise<M<"getRunReceipt">["result"]>;
67
81
  listRunReceipts(...args: M<"listRunReceipts">["args"]): Promise<M<"listRunReceipts">["result"]>;
@@ -71,9 +85,7 @@ export declare class PostgresLoopStorage implements LoopStorageContract {
71
85
  * Recover expired run leases. Divergence from sqlite (documented): the remote
72
86
  * backend cannot inspect local process liveness, so an expired lease is always
73
87
  * abandoned (never "deferred because the local process is still alive"). The
74
- * `deferred` array is therefore always empty here. The generated-route
75
- * workflow archival side effect is not ported (route automation is a TIER 2
76
- * path); the core guarantee — no run stays `running` past its lease — holds.
88
+ * `deferred` array is therefore always empty here.
77
89
  */
78
90
  recoverExpiredRunLeasesDetailed(...args: M<"recoverExpiredRunLeasesDetailed">["args"]): Promise<RecoverExpiredRunLeasesResult>;
79
91
  pruneHistory(...args: M<"pruneHistory">["args"]): Promise<M<"pruneHistory">["result"]>;
@@ -103,18 +115,32 @@ export declare class PostgresLoopStorage implements LoopStorageContract {
103
115
  archiveWorkflow(...args: M<"archiveWorkflow">["args"]): Promise<M<"archiveWorkflow">["result"]>;
104
116
  createWorkflowInvocation(...args: M<"createWorkflowInvocation">["args"]): Promise<M<"createWorkflowInvocation">["result"]>;
105
117
  upsertWorkflowWorkItem(...args: M<"upsertWorkflowWorkItem">["args"]): Promise<M<"upsertWorkflowWorkItem">["result"]>;
106
- admitWorkflowWorkItem(): never;
107
- createGoal(): never;
108
- createGoalPlanNodes(): never;
109
- updateGoalStatus(): never;
110
- updateGoalPlanNode(): never;
111
- recordGoalEvent(): never;
112
- createWorkflowRun(): never;
113
- startWorkflowStepRun(): never;
114
- recoverWorkflowRun(): never;
115
- finalizeWorkflowStepRun(): never;
116
- finalizeWorkflowRun(): never;
117
- appendWorkflowEvent(): never;
118
+ admitWorkflowWorkItem(...args: M<"admitWorkflowWorkItem">["args"]): Promise<M<"admitWorkflowWorkItem">["result"]>;
119
+ createGoal(...args: M<"createGoal">["args"]): Promise<M<"createGoal">["result"]>;
120
+ requireGoal(...args: M<"requireGoal">["args"]): Promise<M<"requireGoal">["result"]>;
121
+ findGoalByContext(...args: M<"findGoalByContext">["args"]): Promise<M<"findGoalByContext">["result"]>;
122
+ private mapGoalPlanNode;
123
+ createGoalPlanNodes(...args: M<"createGoalPlanNodes">["args"]): Promise<M<"createGoalPlanNodes">["result"]>;
124
+ updateGoalStatus(...args: M<"updateGoalStatus">["args"]): Promise<M<"updateGoalStatus">["result"]>;
125
+ updateGoalPlanNode(...args: M<"updateGoalPlanNode">["args"]): Promise<M<"updateGoalPlanNode">["result"]>;
126
+ recordGoalEvent(...args: M<"recordGoalEvent">["args"]): Promise<M<"recordGoalEvent">["result"]>;
127
+ requireWorkflow(...args: M<"requireWorkflow">["args"]): Promise<M<"requireWorkflow">["result"]>;
128
+ createWorkflowRun(...args: M<"createWorkflowRun">["args"]): Promise<M<"createWorkflowRun">["result"]>;
129
+ requireWorkflowRun(...args: M<"requireWorkflowRun">["args"]): Promise<M<"requireWorkflowRun">["result"]>;
130
+ isWorkflowRunTerminal(...args: M<"isWorkflowRunTerminal">["args"]): Promise<M<"isWorkflowRunTerminal">["result"]>;
131
+ startWorkflowStepRun(...args: M<"startWorkflowStepRun">["args"]): Promise<M<"startWorkflowStepRun">["result"]>;
132
+ markWorkflowStepPid(...args: M<"markWorkflowStepPid">["args"]): Promise<M<"markWorkflowStepPid">["result"]>;
133
+ recordWorkflowStepProgress(...args: M<"recordWorkflowStepProgress">["args"]): Promise<M<"recordWorkflowStepProgress">["result"]>;
134
+ recoverWorkflowRun(...args: M<"recoverWorkflowRun">["args"]): Promise<M<"recoverWorkflowRun">["result"]>;
135
+ finalizeWorkflowStepRun(...args: M<"finalizeWorkflowStepRun">["args"]): Promise<M<"finalizeWorkflowStepRun">["result"]>;
136
+ skipWorkflowStepRun(...args: M<"skipWorkflowStepRun">["args"]): Promise<M<"skipWorkflowStepRun">["result"]>;
137
+ private setWorkflowWorkItemsForWorkflowRun;
138
+ private demoteNonProductiveWorkItems;
139
+ finalizeWorkflowRun(...args: M<"finalizeWorkflowRun">["args"]): Promise<M<"finalizeWorkflowRun">["result"]>;
140
+ private appendWorkflowEventWithClient;
141
+ appendWorkflowEvent(...args: M<"appendWorkflowEvent">["args"]): Promise<M<"appendWorkflowEvent">["result"]>;
118
142
  }
119
- export declare function createPostgresLoopStorage(client: PoolQueryClient): PostgresLoopStorage;
143
+ export declare function createPostgresLoopStorage(client: PoolQueryClient, context: TenantStorageContext, opts?: {
144
+ contextAlreadyBound?: boolean;
145
+ }): PostgresLoopStorage;
120
146
  export {};
@@ -1,4 +1,12 @@
1
1
  import type { StorageMigration } from "./contract.js";
2
2
  export declare const POSTGRES_MIGRATION_LEDGER_TABLE = "open_loops_schema_migrations";
3
+ export declare const POSTGRES_MIGRATION_ADVISORY_LOCK_SQL = "SELECT pg_advisory_xact_lock(1330466384, 1280262987)";
3
4
  export declare function checksumStorageSql(sql: string): string;
5
+ export declare const POSTGRES_TENANT_BOOTSTRAP_ROLES_SQL: string;
6
+ export declare const POSTGRES_TENANT_CLUSTER_ROLE_EXCLUSIVITY_SQL: string;
7
+ export declare const POSTGRES_TENANT_BOOTSTRAP_MEMBERSHIPS_SQL: string;
8
+ export declare const POSTGRES_TENANT_PRIVILEGED_MEMBERSHIPS_SQL: string;
9
+ export declare const POSTGRES_TENANT_SERVICE_ROLE_MEMBERSHIPS_SQL: string;
10
+ export declare const POSTGRES_TENANT_UNSAFE_SERVICE_MEMBERSHIPS_SQL: string;
11
+ export declare const POSTGRES_TENANT_SERVICE_MEMBER_CLEANUP_SQL: string;
4
12
  export declare const POSTGRES_STORAGE_MIGRATIONS: readonly StorageMigration[];