@electric-ax/agents-server-conformance-tests 0.1.10 → 0.1.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.
- package/dist/index.cjs +7 -17
- package/dist/index.d.cts +1 -4
- package/dist/index.d.ts +1 -4
- package/dist/index.js +7 -17
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -328,11 +328,8 @@ var ElectricAgentsScenario = class {
|
|
|
328
328
|
});
|
|
329
329
|
return this;
|
|
330
330
|
}
|
|
331
|
-
readStream(
|
|
332
|
-
this.steps.push({
|
|
333
|
-
kind: `readStream`,
|
|
334
|
-
stream
|
|
335
|
-
});
|
|
331
|
+
readStream() {
|
|
332
|
+
this.steps.push({ kind: `readStream` });
|
|
336
333
|
return this;
|
|
337
334
|
}
|
|
338
335
|
list(filter) {
|
|
@@ -671,7 +668,6 @@ async function executeStep(ctx, step) {
|
|
|
671
668
|
(0, vitest.expect)(entity, `Webhook payload must contain entity context`).toBeDefined();
|
|
672
669
|
(0, vitest.expect)(entity.url).toBeTruthy();
|
|
673
670
|
(0, vitest.expect)(entity.streams.main).toBeTruthy();
|
|
674
|
-
(0, vitest.expect)(entity.streams.error).toBeTruthy();
|
|
675
671
|
if (step.checks?.url) (0, vitest.expect)(entity.url).toBe(step.checks.url);
|
|
676
672
|
if (step.checks?.type) (0, vitest.expect)(entity.type).toBe(step.checks.type);
|
|
677
673
|
if (step.checks?.status) (0, vitest.expect)(entity.status).toBe(step.checks.status);
|
|
@@ -712,7 +708,7 @@ async function executeStep(ctx, step) {
|
|
|
712
708
|
}
|
|
713
709
|
case `readStream`: {
|
|
714
710
|
if (!ctx.currentEntityStreams) throw new Error(`No current entity streams`);
|
|
715
|
-
const streamPath =
|
|
711
|
+
const streamPath = ctx.currentEntityStreams.main;
|
|
716
712
|
const res = await fetch(appendPathToUrl(ctx.baseUrl, `${streamPath}?offset=0000000000000000_0000000000000000`));
|
|
717
713
|
if (res.status === 200) {
|
|
718
714
|
const text = await res.text();
|
|
@@ -1207,14 +1203,11 @@ function checkEntityContextOnWebhook(history) {
|
|
|
1207
1203
|
}
|
|
1208
1204
|
}
|
|
1209
1205
|
/**
|
|
1210
|
-
* Spec S5 — Structural: stream
|
|
1206
|
+
* Spec S5 — Structural: stream path must match {entity.url}/main.
|
|
1211
1207
|
* Soundness: Sound | Completeness: Complete (within trace)
|
|
1212
1208
|
*/
|
|
1213
1209
|
function checkStreamPathsMatchEntityUrl(history) {
|
|
1214
|
-
for (const event of history) if (event.type === `entity_spawned`) {
|
|
1215
|
-
(0, vitest.expect)(event.streams.main).toBe(`${event.entityUrl}/main`);
|
|
1216
|
-
(0, vitest.expect)(event.streams.error).toBe(`${event.entityUrl}/error`);
|
|
1217
|
-
}
|
|
1210
|
+
for (const event of history) if (event.type === `entity_spawned`) (0, vitest.expect)(event.streams.main).toBe(`${event.entityUrl}/main`);
|
|
1218
1211
|
}
|
|
1219
1212
|
/**
|
|
1220
1213
|
* Spec S4 — Safety: entity status transitions must be valid.
|
|
@@ -1276,8 +1269,8 @@ function checkAdditiveSchemaEvolution(history) {
|
|
|
1276
1269
|
}
|
|
1277
1270
|
/**
|
|
1278
1271
|
* Spec R4 — Registry stream consistency: every entity_spawned must refer to an
|
|
1279
|
-
* entity that has not already been killed, and stream
|
|
1280
|
-
* convention {entity.url}/main
|
|
1272
|
+
* entity that has not already been killed, and stream URL must follow the
|
|
1273
|
+
* convention {entity.url}/main.
|
|
1281
1274
|
* Soundness: Sound | Completeness: Complete (within trace)
|
|
1282
1275
|
*/
|
|
1283
1276
|
function checkRegistryStreamConsistency(history) {
|
|
@@ -1287,7 +1280,6 @@ function checkRegistryStreamConsistency(history) {
|
|
|
1287
1280
|
if (event.type === `entity_spawned`) {
|
|
1288
1281
|
(0, vitest.expect)(!killedEntities.has(event.entityUrl), `Registry consistency: entity_spawned for ${event.entityUrl} but entity was already killed`).toBe(true);
|
|
1289
1282
|
(0, vitest.expect)(event.streams.main, `Registry consistency: entity ${event.entityUrl} streams.main must be ${event.entityUrl}/main`).toBe(`${event.entityUrl}/main`);
|
|
1290
|
-
(0, vitest.expect)(event.streams.error, `Registry consistency: entity ${event.entityUrl} streams.error must be ${event.entityUrl}/error`).toBe(`${event.entityUrl}/error`);
|
|
1291
1283
|
}
|
|
1292
1284
|
}
|
|
1293
1285
|
}
|
|
@@ -1832,8 +1824,6 @@ function runElectricAgentsConformanceTests(config) {
|
|
|
1832
1824
|
}).spawn(`spawn-test-agent`, `entity-1`).expectStatus(`running`).custom(async (ctx) => {
|
|
1833
1825
|
const mainRes = await fetch(appendPathToUrl(ctx.baseUrl, ctx.currentEntityStreams.main), { method: `HEAD` });
|
|
1834
1826
|
(0, vitest.expect)(mainRes.status).toBe(200);
|
|
1835
|
-
const errorRes = await fetch(appendPathToUrl(ctx.baseUrl, ctx.currentEntityStreams.error), { method: `HEAD` });
|
|
1836
|
-
(0, vitest.expect)(errorRes.status).toBe(200);
|
|
1837
1827
|
}).run());
|
|
1838
1828
|
(0, vitest.test)(`spawn at unregistered type returns UNKNOWN_ENTITY_TYPE`, () => electricAgents(config.baseUrl).custom(async (ctx) => {
|
|
1839
1829
|
const res = await fetch(appendPathToUrl(ctx.baseUrl, routeControlPlanePath(`/unregistered/entity-1`)), {
|
package/dist/index.d.cts
CHANGED
|
@@ -64,7 +64,6 @@ type HistoryEvent = {
|
|
|
64
64
|
status: string;
|
|
65
65
|
streams: {
|
|
66
66
|
main: string;
|
|
67
|
-
error: string;
|
|
68
67
|
};
|
|
69
68
|
parent?: string;
|
|
70
69
|
} | {
|
|
@@ -184,7 +183,6 @@ interface WebhookEntityContext {
|
|
|
184
183
|
url: string;
|
|
185
184
|
streams: {
|
|
186
185
|
main: string;
|
|
187
|
-
error: string;
|
|
188
186
|
};
|
|
189
187
|
tags?: Record<string, string>;
|
|
190
188
|
}
|
|
@@ -273,7 +271,6 @@ interface RunContext {
|
|
|
273
271
|
currentEntityUrl: string | null;
|
|
274
272
|
currentEntityStreams: {
|
|
275
273
|
main: string;
|
|
276
|
-
error: string;
|
|
277
274
|
} | null;
|
|
278
275
|
currentWriteToken: string | null;
|
|
279
276
|
notification: WebhookNotification | null;
|
|
@@ -320,7 +317,7 @@ declare class ElectricAgentsScenario {
|
|
|
320
317
|
expectEntityContext(checks?: EntityContextChecks): this;
|
|
321
318
|
expectStatus(status: string): this;
|
|
322
319
|
expectStreamContains(messageType: string): this;
|
|
323
|
-
readStream(
|
|
320
|
+
readStream(): this;
|
|
324
321
|
list(filter?: {
|
|
325
322
|
type?: string;
|
|
326
323
|
status?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -64,7 +64,6 @@ type HistoryEvent = {
|
|
|
64
64
|
status: string;
|
|
65
65
|
streams: {
|
|
66
66
|
main: string;
|
|
67
|
-
error: string;
|
|
68
67
|
};
|
|
69
68
|
parent?: string;
|
|
70
69
|
} | {
|
|
@@ -184,7 +183,6 @@ interface WebhookEntityContext {
|
|
|
184
183
|
url: string;
|
|
185
184
|
streams: {
|
|
186
185
|
main: string;
|
|
187
|
-
error: string;
|
|
188
186
|
};
|
|
189
187
|
tags?: Record<string, string>;
|
|
190
188
|
}
|
|
@@ -273,7 +271,6 @@ interface RunContext {
|
|
|
273
271
|
currentEntityUrl: string | null;
|
|
274
272
|
currentEntityStreams: {
|
|
275
273
|
main: string;
|
|
276
|
-
error: string;
|
|
277
274
|
} | null;
|
|
278
275
|
currentWriteToken: string | null;
|
|
279
276
|
notification: WebhookNotification | null;
|
|
@@ -320,7 +317,7 @@ declare class ElectricAgentsScenario {
|
|
|
320
317
|
expectEntityContext(checks?: EntityContextChecks): this;
|
|
321
318
|
expectStatus(status: string): this;
|
|
322
319
|
expectStreamContains(messageType: string): this;
|
|
323
|
-
readStream(
|
|
320
|
+
readStream(): this;
|
|
324
321
|
list(filter?: {
|
|
325
322
|
type?: string;
|
|
326
323
|
status?: string;
|
package/dist/index.js
CHANGED
|
@@ -304,11 +304,8 @@ var ElectricAgentsScenario = class {
|
|
|
304
304
|
});
|
|
305
305
|
return this;
|
|
306
306
|
}
|
|
307
|
-
readStream(
|
|
308
|
-
this.steps.push({
|
|
309
|
-
kind: `readStream`,
|
|
310
|
-
stream
|
|
311
|
-
});
|
|
307
|
+
readStream() {
|
|
308
|
+
this.steps.push({ kind: `readStream` });
|
|
312
309
|
return this;
|
|
313
310
|
}
|
|
314
311
|
list(filter) {
|
|
@@ -647,7 +644,6 @@ async function executeStep(ctx, step) {
|
|
|
647
644
|
expect(entity, `Webhook payload must contain entity context`).toBeDefined();
|
|
648
645
|
expect(entity.url).toBeTruthy();
|
|
649
646
|
expect(entity.streams.main).toBeTruthy();
|
|
650
|
-
expect(entity.streams.error).toBeTruthy();
|
|
651
647
|
if (step.checks?.url) expect(entity.url).toBe(step.checks.url);
|
|
652
648
|
if (step.checks?.type) expect(entity.type).toBe(step.checks.type);
|
|
653
649
|
if (step.checks?.status) expect(entity.status).toBe(step.checks.status);
|
|
@@ -688,7 +684,7 @@ async function executeStep(ctx, step) {
|
|
|
688
684
|
}
|
|
689
685
|
case `readStream`: {
|
|
690
686
|
if (!ctx.currentEntityStreams) throw new Error(`No current entity streams`);
|
|
691
|
-
const streamPath =
|
|
687
|
+
const streamPath = ctx.currentEntityStreams.main;
|
|
692
688
|
const res = await fetch(appendPathToUrl(ctx.baseUrl, `${streamPath}?offset=0000000000000000_0000000000000000`));
|
|
693
689
|
if (res.status === 200) {
|
|
694
690
|
const text = await res.text();
|
|
@@ -1183,14 +1179,11 @@ function checkEntityContextOnWebhook(history) {
|
|
|
1183
1179
|
}
|
|
1184
1180
|
}
|
|
1185
1181
|
/**
|
|
1186
|
-
* Spec S5 — Structural: stream
|
|
1182
|
+
* Spec S5 — Structural: stream path must match {entity.url}/main.
|
|
1187
1183
|
* Soundness: Sound | Completeness: Complete (within trace)
|
|
1188
1184
|
*/
|
|
1189
1185
|
function checkStreamPathsMatchEntityUrl(history) {
|
|
1190
|
-
for (const event of history) if (event.type === `entity_spawned`) {
|
|
1191
|
-
expect(event.streams.main).toBe(`${event.entityUrl}/main`);
|
|
1192
|
-
expect(event.streams.error).toBe(`${event.entityUrl}/error`);
|
|
1193
|
-
}
|
|
1186
|
+
for (const event of history) if (event.type === `entity_spawned`) expect(event.streams.main).toBe(`${event.entityUrl}/main`);
|
|
1194
1187
|
}
|
|
1195
1188
|
/**
|
|
1196
1189
|
* Spec S4 — Safety: entity status transitions must be valid.
|
|
@@ -1252,8 +1245,8 @@ function checkAdditiveSchemaEvolution(history) {
|
|
|
1252
1245
|
}
|
|
1253
1246
|
/**
|
|
1254
1247
|
* Spec R4 — Registry stream consistency: every entity_spawned must refer to an
|
|
1255
|
-
* entity that has not already been killed, and stream
|
|
1256
|
-
* convention {entity.url}/main
|
|
1248
|
+
* entity that has not already been killed, and stream URL must follow the
|
|
1249
|
+
* convention {entity.url}/main.
|
|
1257
1250
|
* Soundness: Sound | Completeness: Complete (within trace)
|
|
1258
1251
|
*/
|
|
1259
1252
|
function checkRegistryStreamConsistency(history) {
|
|
@@ -1263,7 +1256,6 @@ function checkRegistryStreamConsistency(history) {
|
|
|
1263
1256
|
if (event.type === `entity_spawned`) {
|
|
1264
1257
|
expect(!killedEntities.has(event.entityUrl), `Registry consistency: entity_spawned for ${event.entityUrl} but entity was already killed`).toBe(true);
|
|
1265
1258
|
expect(event.streams.main, `Registry consistency: entity ${event.entityUrl} streams.main must be ${event.entityUrl}/main`).toBe(`${event.entityUrl}/main`);
|
|
1266
|
-
expect(event.streams.error, `Registry consistency: entity ${event.entityUrl} streams.error must be ${event.entityUrl}/error`).toBe(`${event.entityUrl}/error`);
|
|
1267
1259
|
}
|
|
1268
1260
|
}
|
|
1269
1261
|
}
|
|
@@ -1808,8 +1800,6 @@ function runElectricAgentsConformanceTests(config) {
|
|
|
1808
1800
|
}).spawn(`spawn-test-agent`, `entity-1`).expectStatus(`running`).custom(async (ctx) => {
|
|
1809
1801
|
const mainRes = await fetch(appendPathToUrl(ctx.baseUrl, ctx.currentEntityStreams.main), { method: `HEAD` });
|
|
1810
1802
|
expect(mainRes.status).toBe(200);
|
|
1811
|
-
const errorRes = await fetch(appendPathToUrl(ctx.baseUrl, ctx.currentEntityStreams.error), { method: `HEAD` });
|
|
1812
|
-
expect(errorRes.status).toBe(200);
|
|
1813
1803
|
}).run());
|
|
1814
1804
|
test(`spawn at unregistered type returns UNKNOWN_ENTITY_TYPE`, () => electricAgents(config.baseUrl).custom(async (ctx) => {
|
|
1815
1805
|
const res = await fetch(appendPathToUrl(ctx.baseUrl, routeControlPlanePath(`/unregistered/entity-1`)), {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@electric-ax/agents-server-conformance-tests",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Conformance test suite for Electric Agents server implementations",
|
|
5
5
|
"author": "Durable Stream contributors",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@mariozechner/pi-agent-core": "^0.70.2",
|
|
44
44
|
"tsdown": "^0.9.0",
|
|
45
45
|
"typescript": "^5.0.0",
|
|
46
|
-
"@electric-ax/agents-server": "0.4.
|
|
46
|
+
"@electric-ax/agents-server": "0.4.16"
|
|
47
47
|
},
|
|
48
48
|
"engines": {
|
|
49
49
|
"node": ">=18.0.0"
|