@electric-ax/agents-server 0.4.7 → 0.4.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.
@@ -1 +1 @@
1
- export { DEFAULT_OUTPUT_SCHEMAS } from '@electric-ax/agents-runtime'
1
+ export { DEFAULT_STATE_SCHEMAS } from '@electric-ax/agents-runtime'
@@ -400,6 +400,7 @@ export interface TypedSpawnRequest {
400
400
  debounceMs?: number
401
401
  timeoutMs?: number
402
402
  includeResponse?: boolean
403
+ manifestKey?: string
403
404
  }
404
405
  }
405
406
 
@@ -456,4 +457,4 @@ export const ErrCodeForkWaitTimeout = `FORK_WAIT_TIMEOUT`
456
457
  export const ErrCodeEntityPersistFailed = `ENTITY_PERSIST_FAILED`
457
458
  export const ErrCodeAgentUiNotFound = `AGENT_UI_NOT_FOUND`
458
459
  export const ErrCodeSubscriptionNotFound = `SUBSCRIPTION_NOT_FOUND`
459
- export const ErrCodeCallbackNotFound = `CALLBACK_NOT_FOUND`
460
+ export const ErrCodeWakeCallbackNotFound = `WAKE_CALLBACK_NOT_FOUND`
@@ -6,6 +6,7 @@ import {
6
6
  getCronStreamPath,
7
7
  getSharedStateStreamPath,
8
8
  getNextCronFireAt,
9
+ eventSourceSubscriptionManifestKey,
9
10
  manifestChildKey,
10
11
  manifestSharedStateKey,
11
12
  manifestSourceKey,
@@ -50,6 +51,7 @@ import type { queueAsPromised } from 'fastq'
50
51
  import type { SchedulerClient } from './scheduler.js'
51
52
  import type { WakeEvalResult, WakeRegistry } from './wake-registry.js'
52
53
  import type { WakeMessage } from '@electric-ax/agents-runtime'
54
+ import type { EventSourceSubscription } from '@electric-ax/agents-runtime'
53
55
  import type { PostgresRegistry } from './entity-registry.js'
54
56
  import type { SchemaValidator } from './electric-agents/schema-validator.js'
55
57
  import type { StreamClient } from './stream-client.js'
@@ -554,6 +556,7 @@ export class EntityManager {
554
556
  timeoutMs: req.wake.timeoutMs,
555
557
  oneShot: false,
556
558
  includeResponse: req.wake.includeResponse,
559
+ manifestKey: req.wake.manifestKey,
557
560
  })
558
561
  }
559
562
 
@@ -1672,7 +1675,7 @@ export class EntityManager {
1672
1675
  // ==========================================================================
1673
1676
 
1674
1677
  /**
1675
- * Deliver a message to an entity's main stream, with optional input schema
1678
+ * Deliver a message to an entity's main stream, with optional inbox schema
1676
1679
  * validation.
1677
1680
  */
1678
1681
  async send(
@@ -1885,7 +1888,7 @@ export class EntityManager {
1885
1888
  return updated
1886
1889
  }
1887
1890
 
1888
- async removeTag(
1891
+ async deleteTag(
1889
1892
  entityUrl: string,
1890
1893
  key: string,
1891
1894
  token: string
@@ -1927,7 +1930,7 @@ export class EntityManager {
1927
1930
  return updated
1928
1931
  }
1929
1932
 
1930
- async registerEntitiesSource(tags: Record<string, string>): Promise<{
1933
+ async ensureEntitiesMembershipStream(tags: Record<string, string>): Promise<{
1931
1934
  sourceRef: string
1932
1935
  streamUrl: string
1933
1936
  }> {
@@ -2162,6 +2165,67 @@ export class EntityManager {
2162
2165
  return { txid }
2163
2166
  }
2164
2167
 
2168
+ async upsertEventSourceSubscription(
2169
+ entityUrl: string,
2170
+ req: {
2171
+ subscription: EventSourceSubscription
2172
+ manifest: Record<string, unknown>
2173
+ }
2174
+ ): Promise<{ txid: string; subscription: EventSourceSubscription }> {
2175
+ const manifestKey = req.subscription.manifestKey
2176
+ const txid = randomUUID()
2177
+ await this.writeManifestEntry(
2178
+ entityUrl,
2179
+ manifestKey,
2180
+ `upsert`,
2181
+ req.manifest,
2182
+ {
2183
+ txid,
2184
+ }
2185
+ )
2186
+
2187
+ // The manifest is the durable source of truth. Register side effects after
2188
+ // it is appended so failures can be repaired by manifest replay.
2189
+ await this.wakeRegistry.unregisterByManifestKey(
2190
+ entityUrl,
2191
+ manifestKey,
2192
+ this.tenantId
2193
+ )
2194
+ await this.wakeRegistry.register({
2195
+ tenantId: this.tenantId,
2196
+ subscriberUrl: entityUrl,
2197
+ sourceUrl: req.subscription.sourceUrl,
2198
+ condition: {
2199
+ on: `change`,
2200
+ collections: [`webhook_event`],
2201
+ ops: [`insert`],
2202
+ },
2203
+ oneShot: false,
2204
+ manifestKey,
2205
+ })
2206
+
2207
+ return { txid, subscription: req.subscription }
2208
+ }
2209
+
2210
+ async deleteEventSourceSubscription(
2211
+ entityUrl: string,
2212
+ req: { id: string }
2213
+ ): Promise<{ txid: string }> {
2214
+ const manifestKey = eventSourceSubscriptionManifestKey(req.id)
2215
+ const txid = randomUUID()
2216
+ await this.writeManifestEntry(entityUrl, manifestKey, `delete`, undefined, {
2217
+ txid,
2218
+ })
2219
+
2220
+ await this.wakeRegistry.unregisterByManifestKey(
2221
+ entityUrl,
2222
+ manifestKey,
2223
+ this.tenantId
2224
+ )
2225
+
2226
+ return { txid }
2227
+ }
2228
+
2165
2229
  // ==========================================================================
2166
2230
  // Wake Evaluation
2167
2231
  // ==========================================================================
@@ -2678,7 +2742,7 @@ export class EntityManager {
2678
2742
  // ==========================================================================
2679
2743
 
2680
2744
  /**
2681
- * Add new input/output schema keys to an entity type directly in Postgres.
2745
+ * Add new inbox/state schema keys to an entity type directly in Postgres.
2682
2746
  */
2683
2747
  async amendSchemas(
2684
2748
  typeName: string,
@@ -2767,7 +2831,7 @@ export class EntityManager {
2767
2831
 
2768
2832
  /**
2769
2833
  * Enrich webhook payload with entity context.
2770
- * Called by ElectricAgentsServer during webhook forwarding to inject entity context.
2834
+ * Called by ElectricAgentsServer during subscription webhook dispatch to inject entity context.
2771
2835
  */
2772
2836
  async enrichPayload(
2773
2837
  payload: Record<string, unknown>,
package/src/index.ts CHANGED
@@ -53,10 +53,18 @@ export type {
53
53
  SignalResponse,
54
54
  TypedSpawnRequest,
55
55
  } from './electric-agents-types.js'
56
+ export type {
57
+ EventSourceBucket,
58
+ EventSourceContract,
59
+ EventSourceFilter,
60
+ EventSourceSubscription,
61
+ EventSourceSubscriptionInput,
62
+ SubscriptionLifetime,
63
+ } from '@electric-ax/agents-runtime'
56
64
  export type { Principal, PrincipalKind } from './principal.js'
57
65
  export { globalRouter } from './routing/global-router.js'
58
66
  export type { GlobalRoutes } from './routing/global-router.js'
59
- export type { TenantContext } from './routing/context.js'
67
+ export type { EventSourceCatalog, TenantContext } from './routing/context.js'
60
68
  export {
61
69
  streamRootDurableStreamsRoutingAdapter,
62
70
  pathPrefixedSingleTenantDurableStreamsRoutingAdapter,
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  getCronStreamPathFromSpec,
3
+ getWebhookStreamPath,
3
4
  getSharedStateStreamPath,
4
5
  resolveCronScheduleSpec,
5
6
  } from '@electric-ax/agents-runtime'
@@ -56,6 +57,16 @@ export function extractManifestSourceUrl(
56
57
  : undefined
57
58
  }
58
59
 
60
+ if (manifest.sourceType === `webhook`) {
61
+ if (typeof config?.streamUrl === `string`) return config.streamUrl
62
+ if (typeof config?.endpointKey === `string`) {
63
+ return getWebhookStreamPath(
64
+ config.endpointKey,
65
+ typeof config.bucket === `string` ? config.bucket : undefined
66
+ )
67
+ }
68
+ }
69
+
59
70
  return undefined
60
71
  }
61
72
 
@@ -1,5 +1,8 @@
1
1
  import type { Agent } from 'undici'
2
- import type { WebhookSignatureVerifierConfig } from '@electric-ax/agents-runtime'
2
+ import type {
3
+ EventSourceContract,
4
+ WebhookSignatureVerifierConfig,
5
+ } from '@electric-ax/agents-runtime'
3
6
  import type { DrizzleDB } from '../db/index.js'
4
7
  import type { EntityBridgeCoordinator } from '../entity-bridge-manager.js'
5
8
  import type { EntityManager } from '../entity-manager.js'
@@ -10,6 +13,18 @@ import type { Principal } from '../principal.js'
10
13
  import type { DurableStreamsBearerProvider } from '../stream-client.js'
11
14
  import type { WebhookSigner } from '../webhook-signing.js'
12
15
 
16
+ export interface EventSourceCatalog {
17
+ listEventSources: () =>
18
+ | Array<EventSourceContract>
19
+ | Promise<Array<EventSourceContract>>
20
+ getEventSource: (
21
+ sourceKey: string
22
+ ) =>
23
+ | EventSourceContract
24
+ | undefined
25
+ | Promise<EventSourceContract | undefined>
26
+ }
27
+
13
28
  /**
14
29
  * Per-request tenant context passed through every router and handler.
15
30
  *
@@ -38,5 +53,7 @@ export interface TenantContext {
38
53
  streamClient: StreamClient
39
54
  runtime: ElectricAgentsTenantRuntime
40
55
  entityBridgeManager: EntityBridgeCoordinator
56
+ eventSources?: EventSourceCatalog
57
+ ensureEventSourceWakeSource?: (sourceUrl: string) => Promise<void> | void
41
58
  isShuttingDown: () => boolean
42
59
  }
@@ -326,7 +326,7 @@ async function linkStreamToTargetSubscription(
326
326
  }
327
327
  const forwardUrl = appendPathToUrl(
328
328
  ctx.publicUrl,
329
- `/_electric/webhook-forward/${encodeURIComponent(subscriptionId)}`
329
+ `/_electric/subscription-webhooks/${encodeURIComponent(subscriptionId)}`
330
330
  )
331
331
  await ensureSubscriptionIncludesStream(
332
332
  ctx,
@@ -332,7 +332,7 @@ async function rewriteSubscriptionRequestBody(
332
332
  targetWebhookUrl = rewriteLoopbackWebhookUrl(payload.webhook.url) ?? null
333
333
  payload.webhook.url = appendPathToUrl(
334
334
  ctx.publicUrl,
335
- `/_electric/webhook-forward/${encodeURIComponent(subscriptionId)}`
335
+ `/_electric/subscription-webhooks/${encodeURIComponent(subscriptionId)}`
336
336
  )
337
337
  }
338
338
 
@@ -13,9 +13,7 @@ export interface DurableStreamsRoutingAdapter {
13
13
 
14
14
  function appendSearch(target: URL, source: URL): URL {
15
15
  source.searchParams.forEach((value, key) => {
16
- if (key !== `service`) {
17
- target.searchParams.append(key, value)
18
- }
16
+ target.searchParams.append(key, value)
19
17
  })
20
18
  return target
21
19
  }
@@ -3,6 +3,10 @@
3
3
  */
4
4
 
5
5
  import { Type, type Static } from '@sinclair/typebox'
6
+ import {
7
+ buildEventSourceManifestEntry,
8
+ resolveEventSourceSubscription,
9
+ } from '@electric-ax/agents-runtime'
6
10
  import { Router, json, status } from 'itty-router'
7
11
  import { apiError } from '../electric-agents-http.js'
8
12
  import { parsePrincipalKey, principalUrl } from '../principal.js'
@@ -26,6 +30,7 @@ import type { ElectricAgentsEntity } from '../electric-agents-types.js'
26
30
  import type { JsonRouteRequest } from './schema.js'
27
31
  import type { RouterType } from 'itty-router'
28
32
  import type { TenantContext } from './context.js'
33
+ import type { EventSourceSubscriptionInput } from '@electric-ax/agents-runtime'
29
34
 
30
35
  interface AgentsRouteRequest extends JsonRouteRequest {
31
36
  entityRoute?: ExistingEntityRoute
@@ -84,6 +89,7 @@ const spawnBodySchema = Type.Object({
84
89
  debounceMs: Type.Optional(Type.Number()),
85
90
  timeoutMs: Type.Optional(Type.Number()),
86
91
  includeResponse: Type.Optional(Type.Boolean()),
92
+ manifestKey: Type.Optional(Type.String()),
87
93
  })
88
94
  ),
89
95
  })
@@ -169,8 +175,22 @@ const scheduleBodySchema = Type.Union([
169
175
  }),
170
176
  ])
171
177
 
172
- const entitiesRegisterBodySchema = Type.Object({
173
- tags: Type.Optional(stringRecordSchema),
178
+ const subscriptionLifetimeSchema = Type.Union([
179
+ Type.Object({ kind: Type.Literal(`until_entity_stopped`) }),
180
+ Type.Object({
181
+ kind: Type.Literal(`expires_at`),
182
+ at: Type.String(),
183
+ }),
184
+ Type.Object({ kind: Type.Literal(`manual`) }),
185
+ ])
186
+
187
+ const eventSourceSubscriptionBodySchema = Type.Object({
188
+ sourceKey: Type.String(),
189
+ bucketKey: Type.Optional(Type.String()),
190
+ params: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
191
+ filterKey: Type.Optional(Type.String()),
192
+ lifetime: Type.Optional(subscriptionLifetimeSchema),
193
+ reason: Type.Optional(Type.String()),
174
194
  })
175
195
 
176
196
  type SpawnBody = Static<typeof spawnBodySchema>
@@ -180,7 +200,9 @@ type ForkBody = Static<typeof forkBodySchema>
180
200
  type SetTagBody = Static<typeof setTagBodySchema>
181
201
  type SignalBody = Static<typeof signalBodySchema>
182
202
  type ScheduleBody = Static<typeof scheduleBodySchema>
183
- type EntitiesRegisterBody = Static<typeof entitiesRegisterBodySchema>
203
+ type EventSourceSubscriptionBody = Static<
204
+ typeof eventSourceSubscriptionBodySchema
205
+ >
184
206
 
185
207
  export const entitiesRouter: EntitiesRoutes = Router<
186
208
  AgentsRouteRequest,
@@ -191,11 +213,6 @@ export const entitiesRouter: EntitiesRoutes = Router<
191
213
  })
192
214
 
193
215
  entitiesRouter.get(`/`, listEntities)
194
- entitiesRouter.post(
195
- `/register`,
196
- withSchema(entitiesRegisterBodySchema),
197
- registerEntitiesSource
198
- )
199
216
  entitiesRouter.put(
200
217
  `/:type/:instanceId`,
201
218
  withSpawnableEntityType,
@@ -243,7 +260,7 @@ entitiesRouter.post(
243
260
  entitiesRouter.delete(
244
261
  `/:type/:instanceId/tags/:tagKey`,
245
262
  withExistingEntity,
246
- removeTag
263
+ deleteTag
247
264
  )
248
265
  entitiesRouter.put(
249
266
  `/:type/:instanceId/schedules/:scheduleId`,
@@ -256,6 +273,17 @@ entitiesRouter.delete(
256
273
  withExistingEntity,
257
274
  deleteSchedule
258
275
  )
276
+ entitiesRouter.put(
277
+ `/:type/:instanceId/event-source-subscriptions/:subscriptionId`,
278
+ withExistingEntity,
279
+ withSchema(eventSourceSubscriptionBodySchema),
280
+ upsertEventSourceSubscription
281
+ )
282
+ entitiesRouter.delete(
283
+ `/:type/:instanceId/event-source-subscriptions/:subscriptionId`,
284
+ withExistingEntity,
285
+ deleteEventSourceSubscription
286
+ )
259
287
 
260
288
  function entityUrlFromSegments(
261
289
  type: string,
@@ -391,17 +419,6 @@ async function listEntities(
391
419
  return json(entities.map((entity) => toPublicEntity(entity)))
392
420
  }
393
421
 
394
- async function registerEntitiesSource(
395
- request: AgentsRouteRequest,
396
- ctx: TenantContext
397
- ): Promise<Response> {
398
- const parsed = routeBody<EntitiesRegisterBody>(request)
399
- const result = await ctx.entityManager.registerEntitiesSource(
400
- parsed.tags ?? {}
401
- )
402
- return json(result)
403
- }
404
-
405
422
  async function upsertSchedule(
406
423
  request: AgentsRouteRequest,
407
424
  ctx: TenantContext
@@ -467,13 +484,105 @@ async function deleteSchedule(
467
484
  return json(result)
468
485
  }
469
486
 
487
+ async function upsertEventSourceSubscription(
488
+ request: AgentsRouteRequest,
489
+ ctx: TenantContext
490
+ ): Promise<Response> {
491
+ const principalMutationError = rejectPrincipalEntityMutation(
492
+ request,
493
+ `subscribed to event sources`
494
+ )
495
+ if (principalMutationError) return principalMutationError
496
+
497
+ const catalog = ctx.eventSources
498
+ if (!catalog) {
499
+ return apiError(
500
+ 404,
501
+ ErrCodeNotFound,
502
+ `No event source catalog is configured`
503
+ )
504
+ }
505
+
506
+ const { entityUrl } = requireExistingEntityRoute(request)
507
+ const parsed = routeBody<EventSourceSubscriptionBody>(request)
508
+ const source = await catalog.getEventSource(parsed.sourceKey)
509
+ if (!source) {
510
+ return apiError(
511
+ 404,
512
+ ErrCodeNotFound,
513
+ `Event source "${parsed.sourceKey}" not found`
514
+ )
515
+ }
516
+
517
+ if (parsed.lifetime?.kind === `expires_at`) {
518
+ const expiresAt = new Date(parsed.lifetime.at)
519
+ if (Number.isNaN(expiresAt.getTime())) {
520
+ return apiError(
521
+ 400,
522
+ ErrCodeInvalidRequest,
523
+ `Invalid expires_at lifetime timestamp`
524
+ )
525
+ }
526
+ }
527
+
528
+ let resolved: ReturnType<typeof resolveEventSourceSubscription>
529
+ try {
530
+ resolved = resolveEventSourceSubscription({
531
+ contract: source,
532
+ entityUrl,
533
+ request: {
534
+ ...(parsed as EventSourceSubscriptionInput),
535
+ id: decodeURIComponent(request.params.subscriptionId),
536
+ },
537
+ createdBy: `tool`,
538
+ })
539
+ } catch (error) {
540
+ return apiError(
541
+ 400,
542
+ ErrCodeInvalidRequest,
543
+ error instanceof Error ? error.message : String(error)
544
+ )
545
+ }
546
+
547
+ await ctx.ensureEventSourceWakeSource?.(resolved.subscription.sourceUrl)
548
+
549
+ const result = await ctx.entityManager.upsertEventSourceSubscription(
550
+ entityUrl,
551
+ {
552
+ subscription: resolved.subscription,
553
+ manifest: buildEventSourceManifestEntry(resolved),
554
+ }
555
+ )
556
+ return json(result)
557
+ }
558
+
559
+ async function deleteEventSourceSubscription(
560
+ request: AgentsRouteRequest,
561
+ ctx: TenantContext
562
+ ): Promise<Response> {
563
+ const principalMutationError = rejectPrincipalEntityMutation(
564
+ request,
565
+ `unsubscribed from event sources`
566
+ )
567
+ if (principalMutationError) return principalMutationError
568
+
569
+ const { entityUrl } = requireExistingEntityRoute(request)
570
+ const result = await ctx.entityManager.deleteEventSourceSubscription(
571
+ entityUrl,
572
+ {
573
+ id: decodeURIComponent(request.params.subscriptionId),
574
+ }
575
+ )
576
+ return json(result)
577
+ }
578
+
470
579
  async function setTag(
471
580
  request: AgentsRouteRequest,
472
581
  ctx: TenantContext
473
582
  ): Promise<Response> {
474
583
  const principalMutationError = rejectPrincipalEntityMutation(
475
584
  request,
476
- `tagged`
585
+ `tag updated`
477
586
  )
478
587
  if (principalMutationError) return principalMutationError
479
588
 
@@ -489,19 +598,19 @@ async function setTag(
489
598
  return json(toPublicEntity(updated))
490
599
  }
491
600
 
492
- async function removeTag(
601
+ async function deleteTag(
493
602
  request: AgentsRouteRequest,
494
603
  ctx: TenantContext
495
604
  ): Promise<Response> {
496
605
  const principalMutationError = rejectPrincipalEntityMutation(
497
606
  request,
498
- `untagged`
607
+ `tag deleted`
499
608
  )
500
609
  if (principalMutationError) return principalMutationError
501
610
 
502
611
  const { entityUrl } = requireExistingEntityRoute(request)
503
612
  const token = writeTokenFromRequest(request)
504
- const updated = await ctx.entityManager.removeTag(
613
+ const updated = await ctx.entityManager.deleteTag(
505
614
  entityUrl,
506
615
  decodeURIComponent(request.params.tagKey),
507
616
  token
@@ -35,32 +35,32 @@ export type ElectricAgentsEntityTypeRoutes = RouterType<
35
35
  >
36
36
 
37
37
  type PublicEntityTypeResponse = ElectricAgentsEntityType & {
38
- input_schemas?: Record<string, Record<string, unknown>>
39
- output_schemas?: Record<string, Record<string, unknown>>
40
38
  revision: number
41
39
  }
42
40
 
43
41
  const jsonObjectSchema = Type.Record(Type.String(), Type.Unknown())
44
42
  const schemaMapSchema = Type.Record(Type.String(), jsonObjectSchema)
45
43
 
46
- const registerEntityTypeBodySchema = Type.Object({
47
- name: Type.Optional(Type.String()),
48
- description: Type.Optional(Type.String()),
49
- creation_schema: Type.Optional(jsonObjectSchema),
50
- inbox_schemas: Type.Optional(schemaMapSchema),
51
- state_schemas: Type.Optional(schemaMapSchema),
52
- input_schemas: Type.Optional(schemaMapSchema),
53
- output_schemas: Type.Optional(schemaMapSchema),
54
- serve_endpoint: Type.Optional(Type.String()),
55
- default_dispatch_policy: Type.Optional(dispatchPolicySchema),
56
- })
44
+ const registerEntityTypeBodySchema = Type.Object(
45
+ {
46
+ name: Type.Optional(Type.String()),
47
+ description: Type.Optional(Type.String()),
48
+ creation_schema: Type.Optional(jsonObjectSchema),
49
+ inbox_schemas: Type.Optional(schemaMapSchema),
50
+ state_schemas: Type.Optional(schemaMapSchema),
51
+ serve_endpoint: Type.Optional(Type.String()),
52
+ default_dispatch_policy: Type.Optional(dispatchPolicySchema),
53
+ },
54
+ { additionalProperties: false }
55
+ )
57
56
 
58
- const amendEntityTypeSchemasBodySchema = Type.Object({
59
- input_schemas: Type.Optional(schemaMapSchema),
60
- output_schemas: Type.Optional(schemaMapSchema),
61
- inbox_schemas: Type.Optional(schemaMapSchema),
62
- state_schemas: Type.Optional(schemaMapSchema),
63
- })
57
+ const amendEntityTypeSchemasBodySchema = Type.Object(
58
+ {
59
+ inbox_schemas: Type.Optional(schemaMapSchema),
60
+ state_schemas: Type.Optional(schemaMapSchema),
61
+ },
62
+ { additionalProperties: false }
63
+ )
64
64
 
65
65
  type RegisterEntityTypeBody = Static<typeof registerEntityTypeBodySchema>
66
66
  type AmendEntityTypeSchemasBody = Static<
@@ -181,8 +181,8 @@ async function amendSchemas(
181
181
  const parsed = routeBody<AmendEntityTypeSchemasBody>(request)
182
182
 
183
183
  const updated = await ctx.entityManager.amendSchemas(request.params.name, {
184
- inbox_schemas: parsed.inbox_schemas ?? parsed.input_schemas,
185
- state_schemas: parsed.state_schemas ?? parsed.output_schemas,
184
+ inbox_schemas: parsed.inbox_schemas,
185
+ state_schemas: parsed.state_schemas,
186
186
  })
187
187
  return json(toPublicEntityType(updated))
188
188
  }
@@ -199,13 +199,12 @@ function normalizeEntityTypeRequest(
199
199
  parsed: RegisterEntityTypeBody | RegisterEntityTypeRequest
200
200
  ): RegisterEntityTypeRequest {
201
201
  const serveEndpoint = rewriteLoopbackWebhookUrl(parsed.serve_endpoint)
202
- const compatibilityFields = parsed as RegisterEntityTypeBody
203
202
  return {
204
203
  name: parsed.name ?? ``,
205
204
  description: parsed.description ?? ``,
206
205
  creation_schema: parsed.creation_schema,
207
- inbox_schemas: parsed.inbox_schemas ?? compatibilityFields.input_schemas,
208
- state_schemas: parsed.state_schemas ?? compatibilityFields.output_schemas,
206
+ inbox_schemas: parsed.inbox_schemas,
207
+ state_schemas: parsed.state_schemas,
209
208
  serve_endpoint: serveEndpoint,
210
209
  default_dispatch_policy:
211
210
  parsed.default_dispatch_policy ??
@@ -222,8 +221,6 @@ function toPublicEntityType(
222
221
  ): PublicEntityTypeResponse {
223
222
  return {
224
223
  ...entityType,
225
- input_schemas: entityType.inbox_schemas,
226
- output_schemas: entityType.state_schemas,
227
224
  revision: entityType.revision,
228
225
  }
229
226
  }
@@ -121,7 +121,7 @@ export function rejectIfShuttingDown(
121
121
  ): Response | undefined {
122
122
  if (!ctx.isShuttingDown()) return undefined
123
123
  const path = new URL(req.url).pathname
124
- if (!path.startsWith(`/_electric/webhook-forward/`)) return undefined
124
+ if (!path.startsWith(`/_electric/subscription-webhooks/`)) return undefined
125
125
  return apiError(503, `SERVER_STOPPING`, `Server is shutting down`)
126
126
  }
127
127