@relayfx/sdk 0.7.9 → 0.7.11

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 (73) hide show
  1. package/dist/ai.js +1 -1
  2. package/dist/http-server.js +1 -1
  3. package/dist/{index-0gd9t134.js → index-d1je4njg.js} +4089 -3765
  4. package/dist/{index-72hhs3mp.js → index-d5563j6w.js} +46 -46
  5. package/dist/{index-nb078xsy.js → index-j8k41y47.js} +26 -4
  6. package/dist/{index-qjad95s5.js → index-skcp0xvt.js} +1 -1
  7. package/dist/index.js +11 -11
  8. package/dist/migrations/20260723190000_transactional_event_head/migration.sql +22 -0
  9. package/dist/migrations/20260724010000_execution_event_archive_manifests/migration.sql +66 -0
  10. package/dist/migrations/20260724120000_execution_event_identity_directory/migration.sql +15 -0
  11. package/dist/migrations/20260724230000_idempotent_steering/migration.sql +7 -0
  12. package/dist/migrations/mysql/0015_transactional_event_head.sql +32 -0
  13. package/dist/migrations/mysql/0016_execution_event_archive_manifests.sql +65 -0
  14. package/dist/migrations/mysql/0017_execution_event_identity_directory.sql +20 -0
  15. package/dist/migrations/mysql/0018_idempotent_steering.sql +7 -0
  16. package/dist/migrations/pg/20260723190000_transactional_event_head/migration.sql +22 -0
  17. package/dist/migrations/pg/20260724010000_execution_event_archive_manifests/migration.sql +66 -0
  18. package/dist/migrations/pg/20260724120000_execution_event_identity_directory/migration.sql +15 -0
  19. package/dist/migrations/pg/20260724230000_idempotent_steering/migration.sql +7 -0
  20. package/dist/migrations/sqlite/0015_transactional_event_head.sql +22 -0
  21. package/dist/migrations/sqlite/0016_execution_event_archive_manifests.sql +45 -0
  22. package/dist/migrations/sqlite/0017_execution_event_identity_directory.sql +13 -0
  23. package/dist/migrations/sqlite/0018_idempotent_steering.sql +5 -0
  24. package/dist/mysql.js +50 -9
  25. package/dist/postgres.js +136 -14
  26. package/dist/sqlite.js +116 -5
  27. package/dist/types/relay/client-public-executions.d.ts +1 -1
  28. package/dist/types/relay/client-public.d.ts +2 -2
  29. package/dist/types/relay/http-server.d.ts +2 -2
  30. package/dist/types/relay/mysql-migrations.d.ts +1 -1
  31. package/dist/types/relay/operation.d.ts +9 -0
  32. package/dist/types/relay/sqlite-migrations.d.ts +21 -1
  33. package/dist/types/runtime/agent/agent-loop-events.d.ts +10 -9
  34. package/dist/types/runtime/agent/agent-loop-service.d.ts +1 -0
  35. package/dist/types/runtime/agent/emission-ordinal-allocator.d.ts +7 -0
  36. package/dist/types/runtime/agent/relay-permissions.d.ts +4 -7
  37. package/dist/types/runtime/agent/relay-steering.d.ts +5 -5
  38. package/dist/types/runtime/agent/relay-tool-executor.d.ts +3 -2
  39. package/dist/types/runtime/envelope/envelope-service.d.ts +2 -1
  40. package/dist/types/runtime/execution/event-log-service.d.ts +5 -4
  41. package/dist/types/runtime/execution/execution-service.d.ts +1 -1
  42. package/dist/types/runtime/inbox/inbox-service.d.ts +6 -6
  43. package/dist/types/runtime/schedule/scheduler-service.d.ts +3 -4
  44. package/dist/types/runtime/state/execution-state-service.d.ts +2 -2
  45. package/dist/types/runtime/tool/tool-runtime-contract.d.ts +2 -0
  46. package/dist/types/runtime/tool/tool-runtime-identifiers.d.ts +6 -0
  47. package/dist/types/runtime/wait/wait-service.d.ts +5 -5
  48. package/dist/types/runtime/workflow/execution-workflow.d.ts +2 -3
  49. package/dist/types/runtime/workspace/workspace-planner-service.d.ts +2 -0
  50. package/dist/types/schema/workflow-schema.d.ts +1 -0
  51. package/dist/types/store-sql/execution/archive-compression.d.ts +11 -0
  52. package/dist/types/store-sql/execution/event-history-file-system.d.ts +7 -0
  53. package/dist/types/store-sql/execution/event-history-store.d.ts +93 -0
  54. package/dist/types/store-sql/execution/execution-event-archive-codec.d.ts +69 -0
  55. package/dist/types/store-sql/execution/execution-event-archive-repository-memory.d.ts +28 -0
  56. package/dist/types/store-sql/execution/execution-event-archive-repository-sql.d.ts +19 -0
  57. package/dist/types/store-sql/execution/execution-event-archive-repository.d.ts +175 -0
  58. package/dist/types/store-sql/execution/execution-event-head-memory.d.ts +13 -0
  59. package/dist/types/store-sql/execution/execution-event-head.d.ts +40 -0
  60. package/dist/types/store-sql/execution/execution-event-identity-directory.d.ts +26 -0
  61. package/dist/types/store-sql/execution/execution-event-repository-archive-aware.d.ts +7 -0
  62. package/dist/types/store-sql/execution/execution-event-repository-memory.d.ts +6 -1
  63. package/dist/types/store-sql/execution/execution-event-repository.d.ts +6 -4
  64. package/dist/types/store-sql/inbox/inbox-repository.d.ts +6 -2
  65. package/dist/types/store-sql/schema/communication-schema.d.ts +15 -0
  66. package/dist/types/store-sql/schema/execution-schema.d.ts +583 -0
  67. package/dist/types/store-sql/schema/relay-schema.d.ts +1 -1
  68. package/dist/types/store-sql/state/execution-state-repository.d.ts +2 -1
  69. package/dist/types/store-sql/steering/steering-model.d.ts +60 -0
  70. package/dist/types/store-sql/steering/steering-repository.d.ts +5 -50
  71. package/package.json +5 -5
  72. package/dist/types/relay/client-event-sequence.d.ts +0 -3
  73. package/dist/types/runtime/agent/sequence-allocator.d.ts +0 -9
@@ -0,0 +1,66 @@
1
+ ALTER TABLE "relay_execution_event_heads" ADD COLUMN "archived_through" integer;
2
+ --> statement-breakpoint
3
+ ALTER TABLE "relay_execution_event_heads" ADD COLUMN "archive_generation" integer;
4
+ --> statement-breakpoint
5
+ ALTER TABLE "relay_execution_event_heads" ADD CONSTRAINT "ck_relay_execution_event_heads_archive_pointer" CHECK (("archived_through" IS NULL) = ("archive_generation" IS NULL));
6
+ --> statement-breakpoint
7
+ CREATE TABLE "relay_execution_event_archive_manifests" (
8
+ "tenant_id" text DEFAULT 'system' NOT NULL,
9
+ "execution_id" text NOT NULL,
10
+ "generation" integer NOT NULL,
11
+ "archived_through" integer NOT NULL,
12
+ "event_count" integer NOT NULL,
13
+ "max_sequence" integer NOT NULL,
14
+ "usage_tokens" bigint NOT NULL,
15
+ "schema_version" integer NOT NULL,
16
+ CONSTRAINT "pk_relay_execution_event_archive_manifests" PRIMARY KEY("tenant_id","execution_id","generation"),
17
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_generation" CHECK ("generation" > 0),
18
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_frontier" CHECK ("archived_through" >= 0),
19
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_count" CHECK ("event_count" > 0),
20
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_max" CHECK ("max_sequence" = "archived_through"),
21
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_gaps" CHECK ("event_count" <= "archived_through" + 1),
22
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_usage" CHECK ("usage_tokens" >= 0),
23
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_schema" CHECK ("schema_version" = 1)
24
+ );
25
+ --> statement-breakpoint
26
+ CREATE TABLE "relay_execution_event_archive_blocks" (
27
+ "tenant_id" text DEFAULT 'system' NOT NULL,
28
+ "execution_id" text NOT NULL,
29
+ "generation" integer NOT NULL,
30
+ "block_index" integer NOT NULL,
31
+ "first_sequence" integer NOT NULL,
32
+ "last_sequence" integer NOT NULL,
33
+ "event_count" integer NOT NULL,
34
+ "object_key" text NOT NULL,
35
+ "object_checksum" text NOT NULL,
36
+ "object_size" integer NOT NULL,
37
+ "codec_version" integer NOT NULL,
38
+ "encoding" text NOT NULL,
39
+ "compression" text NOT NULL,
40
+ "payload_checksum" text NOT NULL,
41
+ "stored_payload_bytes" integer NOT NULL,
42
+ "uncompressed_bytes" integer NOT NULL,
43
+ CONSTRAINT "pk_relay_execution_event_archive_blocks" PRIMARY KEY("tenant_id","execution_id","generation","block_index"),
44
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_index" CHECK ("block_index" >= 0),
45
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_first" CHECK ("first_sequence" >= 0),
46
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_bounds" CHECK ("last_sequence" >= "first_sequence"),
47
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_count" CHECK ("event_count" > 0),
48
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_count_limit" CHECK ("event_count" <= 4096),
49
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_gaps" CHECK ("event_count" <= "last_sequence" - "first_sequence" + 1),
50
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_object_size" CHECK ("object_size" > 0 AND "object_size" <= 16777216),
51
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_stored_payload_size" CHECK ("stored_payload_bytes" > 0 AND "stored_payload_bytes" <= 15728640),
52
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_uncompressed_size" CHECK ("uncompressed_bytes" > 0 AND "uncompressed_bytes" <= 15728640),
53
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_stored_size" CHECK ("stored_payload_bytes" < "object_size"),
54
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_expansion" CHECK ("stored_payload_bytes" <= "uncompressed_bytes"),
55
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_codec" CHECK ("codec_version" IN (1, 2)),
56
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_encoding" CHECK ("encoding" = 'json'),
57
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_compression" CHECK (("codec_version" = 1 AND "compression" = 'none' AND "stored_payload_bytes" = "uncompressed_bytes") OR ("codec_version" = 2 AND "compression" = 'gzip')),
58
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_object_key" CHECK (length("object_key") <= 80),
59
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_checksum" CHECK (length("object_checksum") = 64),
60
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_payload_checksum" CHECK (length("payload_checksum") = 64),
61
+ CONSTRAINT "uq_relay_execution_event_archive_blocks_first" UNIQUE("tenant_id","execution_id","generation","first_sequence")
62
+ );
63
+ --> statement-breakpoint
64
+ ALTER TABLE "relay_execution_event_archive_manifests" ADD CONSTRAINT "fk_relay_execution_event_archive_manifests_execution" FOREIGN KEY ("tenant_id","execution_id") REFERENCES "relay_executions"("tenant_id","id") ON DELETE no action ON UPDATE no action;
65
+ --> statement-breakpoint
66
+ ALTER TABLE "relay_execution_event_archive_blocks" ADD CONSTRAINT "fk_relay_execution_event_archive_blocks_manifest" FOREIGN KEY ("tenant_id","execution_id","generation") REFERENCES "relay_execution_event_archive_manifests"("tenant_id","execution_id","generation") ON DELETE no action ON UPDATE no action;
@@ -0,0 +1,15 @@
1
+ CREATE TABLE "relay_execution_event_identity_directory" (
2
+ "tenant_id" text NOT NULL,
3
+ "cursor" text NOT NULL,
4
+ "event_id" text NOT NULL,
5
+ "execution_id" text NOT NULL,
6
+ "sequence" integer NOT NULL,
7
+ CONSTRAINT "pk_relay_execution_event_identity_directory" PRIMARY KEY("tenant_id","cursor"),
8
+ CONSTRAINT "uq_relay_execution_event_identity_directory_event" UNIQUE("tenant_id","event_id"),
9
+ CONSTRAINT "uq_relay_execution_event_identity_directory_sequence" UNIQUE("tenant_id","execution_id","sequence")
10
+ );
11
+ --> statement-breakpoint
12
+ LOCK TABLE "relay_execution_events" IN SHARE ROW EXCLUSIVE MODE;
13
+ --> statement-breakpoint
14
+ INSERT INTO "relay_execution_event_identity_directory" ("tenant_id", "cursor", "event_id", "execution_id", "sequence")
15
+ SELECT "tenant_id", "cursor", "id", "execution_id", "sequence" FROM "relay_execution_events";
@@ -0,0 +1,7 @@
1
+ ALTER TABLE "relay_steering_messages" ADD COLUMN "idempotency_key" text;
2
+ --> statement-breakpoint
3
+ UPDATE "relay_steering_messages" SET "idempotency_key" = 'relay:legacy:' || "kind" || ':' || "sequence"::text;
4
+ --> statement-breakpoint
5
+ ALTER TABLE "relay_steering_messages" ALTER COLUMN "idempotency_key" SET NOT NULL;
6
+ --> statement-breakpoint
7
+ CREATE UNIQUE INDEX "uq_relay_steering_messages_idempotency" ON "relay_steering_messages" ("tenant_id", "execution_id", "idempotency_key");
@@ -0,0 +1,32 @@
1
+ ALTER TABLE `relay_execution_events`
2
+ MODIFY `id` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
3
+ MODIFY `cursor` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL;
4
+ --> statement-breakpoint
5
+ CREATE TABLE IF NOT EXISTS `relay_execution_event_heads` (
6
+ `tenant_id` VARCHAR(191) NOT NULL DEFAULT 'system',
7
+ `execution_id` VARCHAR(191) NOT NULL,
8
+ `next_sequence` INT NOT NULL DEFAULT 0,
9
+ `max_sequence` INT NULL,
10
+ `event_count` INT NOT NULL DEFAULT 0,
11
+ `usage_tokens` BIGINT NOT NULL DEFAULT 0,
12
+ CONSTRAINT `pk_relay_execution_event_heads` PRIMARY KEY (`tenant_id`, `execution_id`)
13
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
14
+ --> statement-breakpoint
15
+ -- Relay pins this migration to one reserved connection. These WRITE locks
16
+ -- block legacy execution creation and event appends until every head has been
17
+ -- backfilled and migration 15 is recorded. The runner guarantees UNLOCK TABLES
18
+ -- on success or failure.
19
+ LOCK TABLES
20
+ `relay_executions` WRITE,
21
+ `relay_execution_events` WRITE,
22
+ `relay_execution_event_heads` WRITE,
23
+ `relay_migrations` WRITE;
24
+ --> statement-breakpoint
25
+ DELETE FROM `relay_execution_event_heads`;
26
+ --> statement-breakpoint
27
+ INSERT INTO `relay_execution_event_heads` (`tenant_id`, `execution_id`, `next_sequence`, `max_sequence`, `event_count`, `usage_tokens`)
28
+ SELECT `relay_executions`.`tenant_id`, `relay_executions`.`id`, COALESCE(MAX(`relay_execution_events`.`sequence`) + 1, 0), MAX(`relay_execution_events`.`sequence`), COUNT(`relay_execution_events`.`id`), COALESCE(SUM(CASE WHEN `relay_execution_events`.`type` = 'model.usage.reported' THEN COALESCE(CAST(JSON_EXTRACT(`relay_execution_events`.`data_json`, '$.input_tokens') AS SIGNED), 0) + COALESCE(CAST(JSON_EXTRACT(`relay_execution_events`.`data_json`, '$.output_tokens') AS SIGNED), 0) ELSE 0 END), 0)
29
+ FROM `relay_executions`
30
+ LEFT JOIN `relay_execution_events`
31
+ ON `relay_execution_events`.`tenant_id` = `relay_executions`.`tenant_id` AND `relay_execution_events`.`execution_id` = `relay_executions`.`id`
32
+ GROUP BY `relay_executions`.`tenant_id`, `relay_executions`.`id`;
@@ -0,0 +1,65 @@
1
+ ALTER TABLE `relay_execution_event_heads`
2
+ ADD COLUMN `archived_through` INT NULL;
3
+ --> statement-breakpoint
4
+ ALTER TABLE `relay_execution_event_heads`
5
+ ADD COLUMN `archive_generation` INT NULL;
6
+ --> statement-breakpoint
7
+ ALTER TABLE `relay_execution_event_heads`
8
+ ADD CONSTRAINT `ck_relay_execution_event_heads_archive_pointer`
9
+ CHECK ((`archived_through` IS NULL) = (`archive_generation` IS NULL));
10
+ --> statement-breakpoint
11
+ CREATE TABLE IF NOT EXISTS `relay_execution_event_archive_manifests` (
12
+ `tenant_id` VARCHAR(191) NOT NULL DEFAULT 'system',
13
+ `execution_id` VARCHAR(191) NOT NULL,
14
+ `generation` INT NOT NULL,
15
+ `archived_through` INT NOT NULL,
16
+ `event_count` INT NOT NULL,
17
+ `max_sequence` INT NOT NULL,
18
+ `usage_tokens` BIGINT NOT NULL,
19
+ `schema_version` INT NOT NULL,
20
+ CONSTRAINT `pk_relay_execution_event_archive_manifests` PRIMARY KEY (`tenant_id`, `execution_id`, `generation`),
21
+ CONSTRAINT `fk_relay_execution_event_archive_manifests_execution` FOREIGN KEY (`tenant_id`, `execution_id`) REFERENCES `relay_executions` (`tenant_id`, `id`),
22
+ CONSTRAINT `ck_relay_execution_event_archive_manifests_generation` CHECK (`generation` > 0),
23
+ CONSTRAINT `ck_relay_execution_event_archive_manifests_frontier` CHECK (`archived_through` >= 0),
24
+ CONSTRAINT `ck_relay_execution_event_archive_manifests_count` CHECK (`event_count` > 0),
25
+ CONSTRAINT `ck_relay_execution_event_archive_manifests_max` CHECK (`max_sequence` = `archived_through`),
26
+ CONSTRAINT `ck_relay_execution_event_archive_manifests_gaps` CHECK (`event_count` <= `archived_through` + 1),
27
+ CONSTRAINT `ck_relay_execution_event_archive_manifests_usage` CHECK (`usage_tokens` >= 0),
28
+ CONSTRAINT `ck_relay_execution_event_archive_manifests_schema` CHECK (`schema_version` = 1)
29
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
30
+ --> statement-breakpoint
31
+ CREATE TABLE IF NOT EXISTS `relay_execution_event_archive_blocks` (
32
+ `tenant_id` VARCHAR(191) NOT NULL DEFAULT 'system',
33
+ `execution_id` VARCHAR(191) NOT NULL,
34
+ `generation` INT NOT NULL,
35
+ `block_index` INT NOT NULL,
36
+ `first_sequence` INT NOT NULL,
37
+ `last_sequence` INT NOT NULL,
38
+ `event_count` INT NOT NULL,
39
+ `object_key` VARCHAR(80) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
40
+ `object_checksum` CHAR(64) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
41
+ `object_size` INT NOT NULL,
42
+ `codec_version` INT NOT NULL,
43
+ `encoding` VARCHAR(16) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
44
+ `compression` VARCHAR(16) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
45
+ `payload_checksum` CHAR(64) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
46
+ `stored_payload_bytes` INT NOT NULL,
47
+ `uncompressed_bytes` INT NOT NULL,
48
+ CONSTRAINT `pk_relay_execution_event_archive_blocks` PRIMARY KEY (`tenant_id`, `execution_id`, `generation`, `block_index`),
49
+ CONSTRAINT `fk_relay_execution_event_archive_blocks_manifest` FOREIGN KEY (`tenant_id`, `execution_id`, `generation`) REFERENCES `relay_execution_event_archive_manifests` (`tenant_id`, `execution_id`, `generation`),
50
+ CONSTRAINT `uq_relay_execution_event_archive_blocks_first` UNIQUE (`tenant_id`, `execution_id`, `generation`, `first_sequence`),
51
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_index` CHECK (`block_index` >= 0),
52
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_first` CHECK (`first_sequence` >= 0),
53
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_bounds` CHECK (`last_sequence` >= `first_sequence`),
54
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_count` CHECK (`event_count` > 0),
55
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_count_limit` CHECK (`event_count` <= 4096),
56
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_gaps` CHECK (`event_count` <= `last_sequence` - `first_sequence` + 1),
57
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_object_size` CHECK (`object_size` > 0 AND `object_size` <= 16777216),
58
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_stored_payload_size` CHECK (`stored_payload_bytes` > 0 AND `stored_payload_bytes` <= 15728640),
59
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_uncompressed_size` CHECK (`uncompressed_bytes` > 0 AND `uncompressed_bytes` <= 15728640),
60
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_stored_size` CHECK (`stored_payload_bytes` < `object_size`),
61
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_expansion` CHECK (`stored_payload_bytes` <= `uncompressed_bytes`),
62
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_codec` CHECK (`codec_version` IN (1, 2)),
63
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_encoding` CHECK (`encoding` = 'json'),
64
+ CONSTRAINT `ck_relay_execution_event_archive_blocks_compression` CHECK ((`codec_version` = 1 AND `compression` = 'none' AND `stored_payload_bytes` = `uncompressed_bytes`) OR (`codec_version` = 2 AND `compression` = 'gzip'))
65
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
@@ -0,0 +1,20 @@
1
+ CREATE TABLE IF NOT EXISTS `relay_execution_event_identity_directory` (
2
+ `tenant_id` varchar(191) NOT NULL,
3
+ `cursor` varchar(512) COLLATE utf8mb4_bin NOT NULL,
4
+ `event_id` varchar(512) COLLATE utf8mb4_bin NOT NULL,
5
+ `execution_id` varchar(191) NOT NULL,
6
+ `sequence` int NOT NULL,
7
+ CONSTRAINT `pk_relay_execution_event_identity_directory` PRIMARY KEY (`tenant_id`, `cursor`),
8
+ CONSTRAINT `uq_relay_execution_event_identity_directory_event` UNIQUE (`tenant_id`, `event_id`),
9
+ CONSTRAINT `uq_relay_execution_event_identity_directory_sequence` UNIQUE (`tenant_id`, `execution_id`, `sequence`)
10
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
11
+ --> statement-breakpoint
12
+ LOCK TABLES
13
+ `relay_execution_events` WRITE,
14
+ `relay_execution_event_identity_directory` WRITE,
15
+ `relay_migrations` WRITE;
16
+ --> statement-breakpoint
17
+ DELETE FROM `relay_execution_event_identity_directory`;
18
+ --> statement-breakpoint
19
+ INSERT INTO `relay_execution_event_identity_directory` (`tenant_id`, `cursor`, `event_id`, `execution_id`, `sequence`)
20
+ SELECT `tenant_id`, `cursor`, `id`, `execution_id`, `sequence` FROM `relay_execution_events`;
@@ -0,0 +1,7 @@
1
+ ALTER TABLE `relay_steering_messages` ADD COLUMN `idempotency_key` varchar(191) COLLATE utf8mb4_bin;
2
+ --> statement-breakpoint
3
+ UPDATE `relay_steering_messages` SET `idempotency_key` = CONCAT('relay:legacy:', `kind`, ':', `sequence`);
4
+ --> statement-breakpoint
5
+ ALTER TABLE `relay_steering_messages` MODIFY COLUMN `idempotency_key` varchar(191) COLLATE utf8mb4_bin NOT NULL;
6
+ --> statement-breakpoint
7
+ CREATE UNIQUE INDEX `uq_relay_steering_messages_idempotency` ON `relay_steering_messages` (`tenant_id`, `execution_id`, `idempotency_key`);
@@ -0,0 +1,22 @@
1
+ CREATE TABLE "relay_execution_event_heads" (
2
+ "tenant_id" text DEFAULT 'system' NOT NULL,
3
+ "execution_id" text NOT NULL,
4
+ "next_sequence" integer DEFAULT 0 NOT NULL,
5
+ "max_sequence" integer,
6
+ "event_count" integer DEFAULT 0 NOT NULL,
7
+ "usage_tokens" bigint DEFAULT 0 NOT NULL,
8
+ CONSTRAINT "pk_relay_execution_event_heads" PRIMARY KEY("tenant_id","execution_id")
9
+ );
10
+ --> statement-breakpoint
11
+ -- Drizzle runs this migration in one transaction. SHARE ROW EXCLUSIVE blocks
12
+ -- legacy INSERT/UPDATE/DELETE writers while allowing ACCESS SHARE readers, so
13
+ -- the backfill and the newly created head rows become visible atomically.
14
+ LOCK TABLE "relay_executions", "relay_execution_events", "relay_execution_event_heads"
15
+ IN SHARE ROW EXCLUSIVE MODE;
16
+ --> statement-breakpoint
17
+ INSERT INTO "relay_execution_event_heads" ("tenant_id", "execution_id", "next_sequence", "max_sequence", "event_count", "usage_tokens")
18
+ SELECT execution."tenant_id", execution."id", COALESCE(MAX(event."sequence") + 1, 0), MAX(event."sequence"), COUNT(event."id"), COALESCE(SUM(CASE WHEN event."type" = 'model.usage.reported' THEN CASE WHEN jsonb_typeof(event."data_json" -> 'input_tokens') = 'number' THEN trunc((event."data_json" ->> 'input_tokens')::numeric)::bigint ELSE 0 END + CASE WHEN jsonb_typeof(event."data_json" -> 'output_tokens') = 'number' THEN trunc((event."data_json" ->> 'output_tokens')::numeric)::bigint ELSE 0 END ELSE 0 END), 0)
19
+ FROM "relay_executions" execution
20
+ LEFT JOIN "relay_execution_events" event
21
+ ON event."tenant_id" = execution."tenant_id" AND event."execution_id" = execution."id"
22
+ GROUP BY execution."tenant_id", execution."id";
@@ -0,0 +1,66 @@
1
+ ALTER TABLE "relay_execution_event_heads" ADD COLUMN "archived_through" integer;
2
+ --> statement-breakpoint
3
+ ALTER TABLE "relay_execution_event_heads" ADD COLUMN "archive_generation" integer;
4
+ --> statement-breakpoint
5
+ ALTER TABLE "relay_execution_event_heads" ADD CONSTRAINT "ck_relay_execution_event_heads_archive_pointer" CHECK (("archived_through" IS NULL) = ("archive_generation" IS NULL));
6
+ --> statement-breakpoint
7
+ CREATE TABLE "relay_execution_event_archive_manifests" (
8
+ "tenant_id" text DEFAULT 'system' NOT NULL,
9
+ "execution_id" text NOT NULL,
10
+ "generation" integer NOT NULL,
11
+ "archived_through" integer NOT NULL,
12
+ "event_count" integer NOT NULL,
13
+ "max_sequence" integer NOT NULL,
14
+ "usage_tokens" bigint NOT NULL,
15
+ "schema_version" integer NOT NULL,
16
+ CONSTRAINT "pk_relay_execution_event_archive_manifests" PRIMARY KEY("tenant_id","execution_id","generation"),
17
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_generation" CHECK ("generation" > 0),
18
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_frontier" CHECK ("archived_through" >= 0),
19
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_count" CHECK ("event_count" > 0),
20
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_max" CHECK ("max_sequence" = "archived_through"),
21
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_gaps" CHECK ("event_count" <= "archived_through" + 1),
22
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_usage" CHECK ("usage_tokens" >= 0),
23
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_schema" CHECK ("schema_version" = 1)
24
+ );
25
+ --> statement-breakpoint
26
+ CREATE TABLE "relay_execution_event_archive_blocks" (
27
+ "tenant_id" text DEFAULT 'system' NOT NULL,
28
+ "execution_id" text NOT NULL,
29
+ "generation" integer NOT NULL,
30
+ "block_index" integer NOT NULL,
31
+ "first_sequence" integer NOT NULL,
32
+ "last_sequence" integer NOT NULL,
33
+ "event_count" integer NOT NULL,
34
+ "object_key" text NOT NULL,
35
+ "object_checksum" text NOT NULL,
36
+ "object_size" integer NOT NULL,
37
+ "codec_version" integer NOT NULL,
38
+ "encoding" text NOT NULL,
39
+ "compression" text NOT NULL,
40
+ "payload_checksum" text NOT NULL,
41
+ "stored_payload_bytes" integer NOT NULL,
42
+ "uncompressed_bytes" integer NOT NULL,
43
+ CONSTRAINT "pk_relay_execution_event_archive_blocks" PRIMARY KEY("tenant_id","execution_id","generation","block_index"),
44
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_index" CHECK ("block_index" >= 0),
45
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_first" CHECK ("first_sequence" >= 0),
46
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_bounds" CHECK ("last_sequence" >= "first_sequence"),
47
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_count" CHECK ("event_count" > 0),
48
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_count_limit" CHECK ("event_count" <= 4096),
49
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_gaps" CHECK ("event_count" <= "last_sequence" - "first_sequence" + 1),
50
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_object_size" CHECK ("object_size" > 0 AND "object_size" <= 16777216),
51
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_stored_payload_size" CHECK ("stored_payload_bytes" > 0 AND "stored_payload_bytes" <= 15728640),
52
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_uncompressed_size" CHECK ("uncompressed_bytes" > 0 AND "uncompressed_bytes" <= 15728640),
53
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_stored_size" CHECK ("stored_payload_bytes" < "object_size"),
54
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_expansion" CHECK ("stored_payload_bytes" <= "uncompressed_bytes"),
55
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_codec" CHECK ("codec_version" IN (1, 2)),
56
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_encoding" CHECK ("encoding" = 'json'),
57
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_compression" CHECK (("codec_version" = 1 AND "compression" = 'none' AND "stored_payload_bytes" = "uncompressed_bytes") OR ("codec_version" = 2 AND "compression" = 'gzip')),
58
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_object_key" CHECK (length("object_key") <= 80),
59
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_checksum" CHECK (length("object_checksum") = 64),
60
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_payload_checksum" CHECK (length("payload_checksum") = 64),
61
+ CONSTRAINT "uq_relay_execution_event_archive_blocks_first" UNIQUE("tenant_id","execution_id","generation","first_sequence")
62
+ );
63
+ --> statement-breakpoint
64
+ ALTER TABLE "relay_execution_event_archive_manifests" ADD CONSTRAINT "fk_relay_execution_event_archive_manifests_execution" FOREIGN KEY ("tenant_id","execution_id") REFERENCES "relay_executions"("tenant_id","id") ON DELETE no action ON UPDATE no action;
65
+ --> statement-breakpoint
66
+ ALTER TABLE "relay_execution_event_archive_blocks" ADD CONSTRAINT "fk_relay_execution_event_archive_blocks_manifest" FOREIGN KEY ("tenant_id","execution_id","generation") REFERENCES "relay_execution_event_archive_manifests"("tenant_id","execution_id","generation") ON DELETE no action ON UPDATE no action;
@@ -0,0 +1,15 @@
1
+ CREATE TABLE "relay_execution_event_identity_directory" (
2
+ "tenant_id" text NOT NULL,
3
+ "cursor" text NOT NULL,
4
+ "event_id" text NOT NULL,
5
+ "execution_id" text NOT NULL,
6
+ "sequence" integer NOT NULL,
7
+ CONSTRAINT "pk_relay_execution_event_identity_directory" PRIMARY KEY("tenant_id","cursor"),
8
+ CONSTRAINT "uq_relay_execution_event_identity_directory_event" UNIQUE("tenant_id","event_id"),
9
+ CONSTRAINT "uq_relay_execution_event_identity_directory_sequence" UNIQUE("tenant_id","execution_id","sequence")
10
+ );
11
+ --> statement-breakpoint
12
+ LOCK TABLE "relay_execution_events" IN SHARE ROW EXCLUSIVE MODE;
13
+ --> statement-breakpoint
14
+ INSERT INTO "relay_execution_event_identity_directory" ("tenant_id", "cursor", "event_id", "execution_id", "sequence")
15
+ SELECT "tenant_id", "cursor", "id", "execution_id", "sequence" FROM "relay_execution_events";
@@ -0,0 +1,7 @@
1
+ ALTER TABLE "relay_steering_messages" ADD COLUMN "idempotency_key" text;
2
+ --> statement-breakpoint
3
+ UPDATE "relay_steering_messages" SET "idempotency_key" = 'relay:legacy:' || "kind" || ':' || "sequence"::text;
4
+ --> statement-breakpoint
5
+ ALTER TABLE "relay_steering_messages" ALTER COLUMN "idempotency_key" SET NOT NULL;
6
+ --> statement-breakpoint
7
+ CREATE UNIQUE INDEX "uq_relay_steering_messages_idempotency" ON "relay_steering_messages" ("tenant_id", "execution_id", "idempotency_key");
@@ -0,0 +1,22 @@
1
+ CREATE TABLE "relay_execution_event_heads" (
2
+ "tenant_id" TEXT NOT NULL DEFAULT 'system',
3
+ "execution_id" TEXT NOT NULL,
4
+ "next_sequence" INTEGER NOT NULL DEFAULT 0,
5
+ "max_sequence" INTEGER,
6
+ "event_count" INTEGER NOT NULL DEFAULT 0,
7
+ "usage_tokens" INTEGER NOT NULL DEFAULT 0,
8
+ CONSTRAINT "pk_relay_execution_event_heads" PRIMARY KEY ("tenant_id", "execution_id")
9
+ );
10
+ --> statement-breakpoint
11
+ INSERT INTO "relay_execution_event_heads" ("tenant_id", "execution_id", "next_sequence", "max_sequence", "event_count", "usage_tokens")
12
+ SELECT execution."tenant_id", execution."id", COALESCE(MAX(event."sequence") + 1, 0), MAX(event."sequence"), COUNT(event."id"),
13
+ COALESCE(SUM(CASE WHEN event."type" = 'model.usage.reported' AND json_valid(event."data_json") THEN
14
+ CASE WHEN json_type(event."data_json", '$.input_tokens') IN ('integer', 'real')
15
+ THEN CAST(json_extract(event."data_json", '$.input_tokens') AS INTEGER) ELSE 0 END +
16
+ CASE WHEN json_type(event."data_json", '$.output_tokens') IN ('integer', 'real')
17
+ THEN CAST(json_extract(event."data_json", '$.output_tokens') AS INTEGER) ELSE 0 END
18
+ ELSE 0 END), 0)
19
+ FROM "relay_executions" execution
20
+ LEFT JOIN "relay_execution_events" event
21
+ ON event."tenant_id" = execution."tenant_id" AND event."execution_id" = execution."id"
22
+ GROUP BY execution."tenant_id", execution."id";
@@ -0,0 +1,45 @@
1
+ ALTER TABLE "relay_execution_event_heads" ADD COLUMN "archived_through" INTEGER;
2
+ --> statement-breakpoint
3
+ ALTER TABLE "relay_execution_event_heads" ADD COLUMN "archive_generation" INTEGER;
4
+ --> statement-breakpoint
5
+ CREATE TABLE "relay_execution_event_archive_manifests" (
6
+ "tenant_id" TEXT NOT NULL DEFAULT 'system',
7
+ "execution_id" TEXT NOT NULL,
8
+ "generation" INTEGER NOT NULL CHECK ("generation" > 0),
9
+ "archived_through" INTEGER NOT NULL CHECK ("archived_through" >= 0),
10
+ "event_count" INTEGER NOT NULL CHECK ("event_count" > 0),
11
+ "max_sequence" INTEGER NOT NULL,
12
+ "usage_tokens" INTEGER NOT NULL CHECK ("usage_tokens" >= 0),
13
+ "schema_version" INTEGER NOT NULL CHECK ("schema_version" = 1),
14
+ CONSTRAINT "pk_relay_execution_event_archive_manifests" PRIMARY KEY ("tenant_id", "execution_id", "generation"),
15
+ CONSTRAINT "fk_relay_execution_event_archive_manifests_execution" FOREIGN KEY ("tenant_id", "execution_id") REFERENCES "relay_executions" ("tenant_id", "id"),
16
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_max" CHECK ("max_sequence" = "archived_through"),
17
+ CONSTRAINT "ck_relay_execution_event_archive_manifests_gaps" CHECK ("event_count" <= "archived_through" + 1)
18
+ );
19
+ --> statement-breakpoint
20
+ CREATE TABLE "relay_execution_event_archive_blocks" (
21
+ "tenant_id" TEXT NOT NULL DEFAULT 'system',
22
+ "execution_id" TEXT NOT NULL,
23
+ "generation" INTEGER NOT NULL,
24
+ "block_index" INTEGER NOT NULL CHECK ("block_index" >= 0),
25
+ "first_sequence" INTEGER NOT NULL CHECK ("first_sequence" >= 0),
26
+ "last_sequence" INTEGER NOT NULL,
27
+ "event_count" INTEGER NOT NULL CHECK ("event_count" > 0 AND "event_count" <= 4096),
28
+ "object_key" TEXT NOT NULL CHECK (length("object_key") <= 80),
29
+ "object_checksum" TEXT NOT NULL CHECK (length("object_checksum") = 64),
30
+ "object_size" INTEGER NOT NULL CHECK ("object_size" > 0 AND "object_size" <= 16777216),
31
+ "codec_version" INTEGER NOT NULL CHECK ("codec_version" IN (1, 2)),
32
+ "encoding" TEXT NOT NULL CHECK ("encoding" = 'json'),
33
+ "compression" TEXT NOT NULL,
34
+ "payload_checksum" TEXT NOT NULL CHECK (length("payload_checksum") = 64),
35
+ "stored_payload_bytes" INTEGER NOT NULL CHECK ("stored_payload_bytes" > 0 AND "stored_payload_bytes" <= 15728640),
36
+ "uncompressed_bytes" INTEGER NOT NULL CHECK ("uncompressed_bytes" > 0 AND "uncompressed_bytes" <= 15728640),
37
+ CONSTRAINT "pk_relay_execution_event_archive_blocks" PRIMARY KEY ("tenant_id", "execution_id", "generation", "block_index"),
38
+ CONSTRAINT "fk_relay_execution_event_archive_blocks_manifest" FOREIGN KEY ("tenant_id", "execution_id", "generation") REFERENCES "relay_execution_event_archive_manifests" ("tenant_id", "execution_id", "generation"),
39
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_bounds" CHECK ("last_sequence" >= "first_sequence"),
40
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_gaps" CHECK ("event_count" <= "last_sequence" - "first_sequence" + 1),
41
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_stored_size" CHECK ("stored_payload_bytes" < "object_size"),
42
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_expansion" CHECK ("stored_payload_bytes" <= "uncompressed_bytes"),
43
+ CONSTRAINT "ck_relay_execution_event_archive_blocks_compression" CHECK (("codec_version" = 1 AND "compression" = 'none' AND "stored_payload_bytes" = "uncompressed_bytes") OR ("codec_version" = 2 AND "compression" = 'gzip')),
44
+ CONSTRAINT "uq_relay_execution_event_archive_blocks_first" UNIQUE ("tenant_id", "execution_id", "generation", "first_sequence")
45
+ );
@@ -0,0 +1,13 @@
1
+ CREATE TABLE "relay_execution_event_identity_directory" (
2
+ "tenant_id" text NOT NULL,
3
+ "cursor" text NOT NULL,
4
+ "event_id" text NOT NULL,
5
+ "execution_id" text NOT NULL,
6
+ "sequence" integer NOT NULL,
7
+ CONSTRAINT "pk_relay_execution_event_identity_directory" PRIMARY KEY("tenant_id", "cursor"),
8
+ CONSTRAINT "uq_relay_execution_event_identity_directory_event" UNIQUE("tenant_id", "event_id"),
9
+ CONSTRAINT "uq_relay_execution_event_identity_directory_sequence" UNIQUE("tenant_id", "execution_id", "sequence")
10
+ );
11
+ --> statement-breakpoint
12
+ INSERT INTO "relay_execution_event_identity_directory" ("tenant_id", "cursor", "event_id", "execution_id", "sequence")
13
+ SELECT "tenant_id", "cursor", "id", "execution_id", "sequence" FROM "relay_execution_events";
@@ -0,0 +1,5 @@
1
+ ALTER TABLE "relay_steering_messages" ADD COLUMN "idempotency_key" text NOT NULL DEFAULT '';
2
+ --> statement-breakpoint
3
+ UPDATE "relay_steering_messages" SET "idempotency_key" = 'relay:legacy:' || "kind" || ':' || CAST("sequence" AS text);
4
+ --> statement-breakpoint
5
+ CREATE UNIQUE INDEX "uq_relay_steering_messages_idempotency" ON "relay_steering_messages" ("tenant_id", "execution_id", "idempotency_key");
package/dist/mysql.js CHANGED
@@ -2,14 +2,14 @@
2
2
  import {
3
3
  database,
4
4
  normalizeMigrationCause
5
- } from "./index-qjad95s5.js";
5
+ } from "./index-skcp0xvt.js";
6
6
  import {
7
7
  MigratorError,
8
8
  RuntimeMigrationError,
9
9
  SqlFailure
10
- } from "./index-0gd9t134.js";
11
- import"./index-72hhs3mp.js";
12
- import"./index-nb078xsy.js";
10
+ } from "./index-d1je4njg.js";
11
+ import"./index-d5563j6w.js";
12
+ import"./index-j8k41y47.js";
13
13
  import"./index-nb39b5ae.js";
14
14
 
15
15
  // src/mysql.ts
@@ -97,6 +97,18 @@ ALTER TABLE relay_sessions ADD COLUMN owner_epoch BIGINT NOT NULL DEFAULT 0;
97
97
  ALTER TABLE relay_sessions ADD COLUMN owner_released BOOLEAN NOT NULL DEFAULT TRUE;
98
98
  `;
99
99
 
100
+ // ../../migrations/mysql/0015_transactional_event_head.sql
101
+ var _0015_transactional_event_head_default = "ALTER TABLE `relay_execution_events`\n MODIFY `id` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,\n MODIFY `cursor` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL;\n--> statement-breakpoint\nCREATE TABLE IF NOT EXISTS `relay_execution_event_heads` (\n\t`tenant_id` VARCHAR(191) NOT NULL DEFAULT 'system',\n\t`execution_id` VARCHAR(191) NOT NULL,\n\t`next_sequence` INT NOT NULL DEFAULT 0,\n\t`max_sequence` INT NULL,\n\t`event_count` INT NOT NULL DEFAULT 0,\n\t`usage_tokens` BIGINT NOT NULL DEFAULT 0,\n\tCONSTRAINT `pk_relay_execution_event_heads` PRIMARY KEY (`tenant_id`, `execution_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;\n--> statement-breakpoint\n-- Relay pins this migration to one reserved connection. These WRITE locks\n-- block legacy execution creation and event appends until every head has been\n-- backfilled and migration 15 is recorded. The runner guarantees UNLOCK TABLES\n-- on success or failure.\nLOCK TABLES\n `relay_executions` WRITE,\n `relay_execution_events` WRITE,\n `relay_execution_event_heads` WRITE,\n `relay_migrations` WRITE;\n--> statement-breakpoint\nDELETE FROM `relay_execution_event_heads`;\n--> statement-breakpoint\nINSERT INTO `relay_execution_event_heads` (`tenant_id`, `execution_id`, `next_sequence`, `max_sequence`, `event_count`, `usage_tokens`)\nSELECT `relay_executions`.`tenant_id`, `relay_executions`.`id`, COALESCE(MAX(`relay_execution_events`.`sequence`) + 1, 0), MAX(`relay_execution_events`.`sequence`), COUNT(`relay_execution_events`.`id`), COALESCE(SUM(CASE WHEN `relay_execution_events`.`type` = 'model.usage.reported' THEN COALESCE(CAST(JSON_EXTRACT(`relay_execution_events`.`data_json`, '$.input_tokens') AS SIGNED), 0) + COALESCE(CAST(JSON_EXTRACT(`relay_execution_events`.`data_json`, '$.output_tokens') AS SIGNED), 0) ELSE 0 END), 0)\nFROM `relay_executions`\nLEFT JOIN `relay_execution_events`\n ON `relay_execution_events`.`tenant_id` = `relay_executions`.`tenant_id` AND `relay_execution_events`.`execution_id` = `relay_executions`.`id`\nGROUP BY `relay_executions`.`tenant_id`, `relay_executions`.`id`;\n";
102
+
103
+ // ../../migrations/mysql/0016_execution_event_archive_manifests.sql
104
+ var _0016_execution_event_archive_manifests_default = "ALTER TABLE `relay_execution_event_heads`\n ADD COLUMN `archived_through` INT NULL;\n--> statement-breakpoint\nALTER TABLE `relay_execution_event_heads`\n ADD COLUMN `archive_generation` INT NULL;\n--> statement-breakpoint\nALTER TABLE `relay_execution_event_heads`\n ADD CONSTRAINT `ck_relay_execution_event_heads_archive_pointer`\n CHECK ((`archived_through` IS NULL) = (`archive_generation` IS NULL));\n--> statement-breakpoint\nCREATE TABLE IF NOT EXISTS `relay_execution_event_archive_manifests` (\n\t`tenant_id` VARCHAR(191) NOT NULL DEFAULT 'system',\n\t`execution_id` VARCHAR(191) NOT NULL,\n\t`generation` INT NOT NULL,\n\t`archived_through` INT NOT NULL,\n\t`event_count` INT NOT NULL,\n\t`max_sequence` INT NOT NULL,\n\t`usage_tokens` BIGINT NOT NULL,\n\t`schema_version` INT NOT NULL,\n\tCONSTRAINT `pk_relay_execution_event_archive_manifests` PRIMARY KEY (`tenant_id`, `execution_id`, `generation`),\n\tCONSTRAINT `fk_relay_execution_event_archive_manifests_execution` FOREIGN KEY (`tenant_id`, `execution_id`) REFERENCES `relay_executions` (`tenant_id`, `id`),\n\tCONSTRAINT `ck_relay_execution_event_archive_manifests_generation` CHECK (`generation` > 0),\n\tCONSTRAINT `ck_relay_execution_event_archive_manifests_frontier` CHECK (`archived_through` >= 0),\n\tCONSTRAINT `ck_relay_execution_event_archive_manifests_count` CHECK (`event_count` > 0),\n\tCONSTRAINT `ck_relay_execution_event_archive_manifests_max` CHECK (`max_sequence` = `archived_through`),\n\tCONSTRAINT `ck_relay_execution_event_archive_manifests_gaps` CHECK (`event_count` <= `archived_through` + 1),\n\tCONSTRAINT `ck_relay_execution_event_archive_manifests_usage` CHECK (`usage_tokens` >= 0),\n\tCONSTRAINT `ck_relay_execution_event_archive_manifests_schema` CHECK (`schema_version` = 1)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;\n--> statement-breakpoint\nCREATE TABLE IF NOT EXISTS `relay_execution_event_archive_blocks` (\n\t`tenant_id` VARCHAR(191) NOT NULL DEFAULT 'system',\n\t`execution_id` VARCHAR(191) NOT NULL,\n\t`generation` INT NOT NULL,\n\t`block_index` INT NOT NULL,\n\t`first_sequence` INT NOT NULL,\n\t`last_sequence` INT NOT NULL,\n\t`event_count` INT NOT NULL,\n\t`object_key` VARCHAR(80) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,\n\t`object_checksum` CHAR(64) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,\n\t`object_size` INT NOT NULL,\n\t`codec_version` INT NOT NULL,\n\t`encoding` VARCHAR(16) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,\n\t`compression` VARCHAR(16) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,\n\t`payload_checksum` CHAR(64) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,\n\t`stored_payload_bytes` INT NOT NULL,\n\t`uncompressed_bytes` INT NOT NULL,\n\tCONSTRAINT `pk_relay_execution_event_archive_blocks` PRIMARY KEY (`tenant_id`, `execution_id`, `generation`, `block_index`),\n\tCONSTRAINT `fk_relay_execution_event_archive_blocks_manifest` FOREIGN KEY (`tenant_id`, `execution_id`, `generation`) REFERENCES `relay_execution_event_archive_manifests` (`tenant_id`, `execution_id`, `generation`),\n\tCONSTRAINT `uq_relay_execution_event_archive_blocks_first` UNIQUE (`tenant_id`, `execution_id`, `generation`, `first_sequence`),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_index` CHECK (`block_index` >= 0),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_first` CHECK (`first_sequence` >= 0),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_bounds` CHECK (`last_sequence` >= `first_sequence`),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_count` CHECK (`event_count` > 0),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_count_limit` CHECK (`event_count` <= 4096),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_gaps` CHECK (`event_count` <= `last_sequence` - `first_sequence` + 1),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_object_size` CHECK (`object_size` > 0 AND `object_size` <= 16777216),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_stored_payload_size` CHECK (`stored_payload_bytes` > 0 AND `stored_payload_bytes` <= 15728640),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_uncompressed_size` CHECK (`uncompressed_bytes` > 0 AND `uncompressed_bytes` <= 15728640),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_stored_size` CHECK (`stored_payload_bytes` < `object_size`),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_expansion` CHECK (`stored_payload_bytes` <= `uncompressed_bytes`),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_codec` CHECK (`codec_version` IN (1, 2)),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_encoding` CHECK (`encoding` = 'json'),\n\tCONSTRAINT `ck_relay_execution_event_archive_blocks_compression` CHECK ((`codec_version` = 1 AND `compression` = 'none' AND `stored_payload_bytes` = `uncompressed_bytes`) OR (`codec_version` = 2 AND `compression` = 'gzip'))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;\n";
105
+
106
+ // ../../migrations/mysql/0017_execution_event_identity_directory.sql
107
+ var _0017_execution_event_identity_directory_default = "CREATE TABLE IF NOT EXISTS `relay_execution_event_identity_directory` (\n `tenant_id` varchar(191) NOT NULL,\n `cursor` varchar(512) COLLATE utf8mb4_bin NOT NULL,\n `event_id` varchar(512) COLLATE utf8mb4_bin NOT NULL,\n `execution_id` varchar(191) NOT NULL,\n `sequence` int NOT NULL,\n CONSTRAINT `pk_relay_execution_event_identity_directory` PRIMARY KEY (`tenant_id`, `cursor`),\n CONSTRAINT `uq_relay_execution_event_identity_directory_event` UNIQUE (`tenant_id`, `event_id`),\n CONSTRAINT `uq_relay_execution_event_identity_directory_sequence` UNIQUE (`tenant_id`, `execution_id`, `sequence`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;\n--> statement-breakpoint\nLOCK TABLES\n `relay_execution_events` WRITE,\n `relay_execution_event_identity_directory` WRITE,\n `relay_migrations` WRITE;\n--> statement-breakpoint\nDELETE FROM `relay_execution_event_identity_directory`;\n--> statement-breakpoint\nINSERT INTO `relay_execution_event_identity_directory` (`tenant_id`, `cursor`, `event_id`, `execution_id`, `sequence`)\nSELECT `tenant_id`, `cursor`, `id`, `execution_id`, `sequence` FROM `relay_execution_events`;\n";
108
+
109
+ // ../../migrations/mysql/0018_idempotent_steering.sql
110
+ var _0018_idempotent_steering_default = "ALTER TABLE `relay_steering_messages` ADD COLUMN `idempotency_key` varchar(191) COLLATE utf8mb4_bin;\n--> statement-breakpoint\nUPDATE `relay_steering_messages` SET `idempotency_key` = CONCAT('relay:legacy:', `kind`, ':', `sequence`);\n--> statement-breakpoint\nALTER TABLE `relay_steering_messages` MODIFY COLUMN `idempotency_key` varchar(191) COLLATE utf8mb4_bin NOT NULL;\n--> statement-breakpoint\nCREATE UNIQUE INDEX `uq_relay_steering_messages_idempotency` ON `relay_steering_messages` (`tenant_id`, `execution_id`, `idempotency_key`);\n";
111
+
100
112
  // src/mysql-migrations.ts
101
113
  var migrations = [
102
114
  [1, "baseline", _0001_baseline_default],
@@ -112,7 +124,11 @@ var migrations = [
112
124
  [11, "execution_scoped_tool_calls", _0011_execution_scoped_tool_calls_default],
113
125
  [12, "rename_entity_to_resident", _0012_rename_entity_to_resident_default],
114
126
  [13, "steering_delivered", _0013_steering_delivered_default],
115
- [14, "session_writer_ownership", _0014_session_writer_ownership_default]
127
+ [14, "session_writer_ownership", _0014_session_writer_ownership_default],
128
+ [15, "transactional_event_head", _0015_transactional_event_head_default],
129
+ [16, "execution_event_archive_manifests", _0016_execution_event_archive_manifests_default],
130
+ [17, "execution_event_identity_directory", _0017_execution_event_identity_directory_default],
131
+ [18, "idempotent_steering", _0018_idempotent_steering_default]
116
132
  ];
117
133
 
118
134
  // src/mysql.ts
@@ -145,10 +161,35 @@ var runMigrations = Effect.gen(function* () {
145
161
  });
146
162
  }
147
163
  for (const [id, name, source] of migrations.slice(current.length)) {
148
- for (const statement of source.split("--> statement-breakpoint").map((value) => value.trim()).filter(Boolean)) {
149
- yield* sql.unsafe(statement);
150
- }
151
- yield* sql`INSERT INTO relay_migrations (migration_id, name) VALUES (${id}, ${name})`;
164
+ const statements = source.split("--> statement-breakpoint").map((value) => value.trim()).filter(Boolean);
165
+ yield* Effect.scoped(Effect.gen(function* () {
166
+ const connection = yield* sql.reserve;
167
+ return yield* Effect.gen(function* () {
168
+ const migration = yield* Effect.exit(Effect.gen(function* () {
169
+ for (const statement of statements) {
170
+ if (id === 16) {
171
+ const catalogQuery = statement.includes("ADD COLUMN") ? [
172
+ "SELECT COUNT(*) AS count FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'relay_execution_event_heads' AND column_name = ?",
173
+ [statement.includes("`archived_through`") ? "archived_through" : "archive_generation"]
174
+ ] : statement.includes("ADD CONSTRAINT") ? [
175
+ "SELECT COUNT(*) AS count FROM information_schema.table_constraints WHERE constraint_schema = DATABASE() AND table_name = 'relay_execution_event_heads' AND constraint_name = ?",
176
+ ["ck_relay_execution_event_heads_archive_pointer"]
177
+ ] : undefined;
178
+ if (catalogQuery !== undefined) {
179
+ const present = yield* connection.execute(catalogQuery[0], catalogQuery[1], undefined);
180
+ if (Number(present[0]?.count ?? 0) === 1) {
181
+ continue;
182
+ }
183
+ }
184
+ }
185
+ yield* connection.executeUnprepared(statement, [], undefined);
186
+ }
187
+ yield* connection.execute("INSERT INTO relay_migrations (migration_id, name) VALUES (?, ?)", [id, name], undefined);
188
+ }));
189
+ yield* connection.executeUnprepared("UNLOCK TABLES", [], undefined);
190
+ return yield* migration;
191
+ }).pipe(Effect.uninterruptible);
192
+ }));
152
193
  }
153
194
  });
154
195
  var database2 = (options) => database({