@openwop/openwop-conformance 1.21.0 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -2
- package/README.md +61 -63
- package/api/asyncapi.yaml +54 -38
- package/api/openapi.yaml +34 -6
- package/coverage.md +381 -202
- package/fixtures/connection-packs/connection-pack-github.json +31 -0
- package/fixtures.md +120 -101
- package/package.json +1 -1
- package/schemas/README.md +1 -0
- package/schemas/capabilities.schema.json +49 -0
- package/schemas/connection-pack-manifest.schema.json +161 -0
- package/schemas/run-event-payloads.schema.json +6 -5
- package/schemas/run-event.schema.json +11 -2
- package/schemas/run-options.schema.json +1 -2
- package/schemas/run-snapshot.schema.json +2 -1
- package/schemas/suspend-request.schema.json +5 -0
- package/src/scenarios/connection-pack-manifest-valid.test.ts +122 -0
- package/src/scenarios/connection-pack-no-credential-material.test.ts +125 -0
- package/src/scenarios/connection-pack-reach-exclusive.test.ts +85 -0
- package/src/scenarios/connection-pack-write-reconsent.test.ts +91 -0
- package/src/scenarios/connection-provider-resolution.test.ts +153 -0
- package/src/scenarios/cross-host-traceparent-propagation.test.ts +3 -3
- package/src/scenarios/fixtures-valid.test.ts +34 -0
- package/src/scenarios/grpc-transport.test.ts +108 -0
- package/src/scenarios/i18n-negotiation.test.ts +181 -0
- package/src/scenarios/interrupt-token-matrix.test.ts +2 -2
- package/src/scenarios/media-url-inline-cap.test.ts +5 -3
- package/src/scenarios/spec-corpus-validity.test.ts +107 -0
- package/src/scenarios/stream-text-fixture.test.ts +212 -0
- package/src/scenarios/version-fold.test.ts +193 -0
- package/src/scenarios/wasm-pack-memory-cap.test.ts +4 -2
- package/src/scenarios/webhook-tenant-isolation.test.ts +184 -0
package/api/asyncapi.yaml
CHANGED
|
@@ -2,12 +2,12 @@ asyncapi: 3.1.0
|
|
|
2
2
|
|
|
3
3
|
info:
|
|
4
4
|
title: Workflow Orchestration Protocol (openwop) SSE Event Stream
|
|
5
|
-
version: "1.0"
|
|
5
|
+
version: "1.1.0"
|
|
6
6
|
externalDocs:
|
|
7
7
|
description: openwop spec v1 corpus
|
|
8
8
|
url: https://openwop.dev/spec/v1/
|
|
9
9
|
description: |
|
|
10
|
-
Canonical AsyncAPI 3.0 specification for the openwop server's
|
|
10
|
+
Canonical AsyncAPI 3.1.0 specification for the openwop server's
|
|
11
11
|
Server-Sent Events surface. Formalizes `stream-modes.md`
|
|
12
12
|
and references the run-event JSON Schema via `$ref` so external SDK
|
|
13
13
|
authors can codegen typed consumers without re-reading the prose.
|
|
@@ -55,18 +55,27 @@ servers:
|
|
|
55
55
|
channels:
|
|
56
56
|
|
|
57
57
|
heartbeatEvents:
|
|
58
|
-
address:
|
|
58
|
+
# Logical channel — `address: null` per AsyncAPI 3.x ("address not
|
|
59
|
+
# applicable / host-defined"). RFC 0094 §I: host-capabilities.md
|
|
60
|
+
# §host.heartbeat defines the two heartbeat events but documents NO
|
|
61
|
+
# HTTP delivery path for them (they are heartbeat-scoped, NOT
|
|
62
|
+
# run-event-log entries, so they do not ride /runs/{runId}/events
|
|
63
|
+
# either). The previous `/heartbeats/{heartbeatId}/events` address
|
|
64
|
+
# implied an undocumented REST surface; the delivery transport is a
|
|
65
|
+
# host concern until an RFC specifies one.
|
|
66
|
+
address: null
|
|
59
67
|
title: Heartbeat evaluation events (RFC 0060)
|
|
60
|
-
summary: Per-tick heartbeat evaluation + state-change notifications.
|
|
68
|
+
summary: Per-tick heartbeat evaluation + state-change notifications (logical channel).
|
|
61
69
|
description: |
|
|
62
70
|
RFC 0060 `host.heartbeat`. Heartbeat-scoped (NOT a run-event
|
|
63
71
|
stream): a host advertising `capabilities.heartbeat.supported: true`
|
|
64
72
|
emits `heartbeat.evaluated` every tick and `heartbeat.stateChanged`
|
|
65
73
|
only on a predicate-state transition. Both are observability-only;
|
|
66
74
|
consumers MAY ignore them.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
|
|
76
|
+
LOGICAL channel: `host-capabilities.md` §host.heartbeat documents
|
|
77
|
+
the event shapes but no HTTP address; how a host delivers them
|
|
78
|
+
(webhook, host-internal bus, vendor stream) is host-defined.
|
|
70
79
|
messages:
|
|
71
80
|
heartbeatEvaluated: { $ref: '#/components/messages/HeartbeatEvaluated' }
|
|
72
81
|
heartbeatStateChanged: { $ref: '#/components/messages/HeartbeatStateChanged' }
|
|
@@ -200,6 +209,13 @@ operations:
|
|
|
200
209
|
for resumption — server begins streaming from the sequence
|
|
201
210
|
AFTER the supplied ID and MUST NOT re-emit the resumption
|
|
202
211
|
point itself.
|
|
212
|
+
|
|
213
|
+
Mixed mode (RFC 0094 §I note): the binding's single-value
|
|
214
|
+
`streamMode` enum below describes THIS mode's pure subscription;
|
|
215
|
+
`streamMode` additionally accepts comma-separated combinations
|
|
216
|
+
(e.g. `updates,messages`) per `stream-modes.md` §"Mixed mode" —
|
|
217
|
+
union-of-filters semantics, per-event `event:` labels.
|
|
218
|
+
`values` MUST NOT combine with other modes.
|
|
203
219
|
bindings:
|
|
204
220
|
http:
|
|
205
221
|
method: GET
|
|
@@ -217,6 +233,11 @@ operations:
|
|
|
217
233
|
$ref: '#/channels/runEventsValues'
|
|
218
234
|
title: Subscribe to values stream
|
|
219
235
|
summary: Receive full state snapshots after every transition.
|
|
236
|
+
description: |
|
|
237
|
+
Mixed mode (RFC 0094 §I note): `values` is EXCLUSIVE — it MUST NOT
|
|
238
|
+
be combined in a comma-separated `streamMode` list
|
|
239
|
+
(`stream-modes.md` §"Mixed mode": state.snapshot semantics need
|
|
240
|
+
exclusive ownership). The binding's single-value enum is exact here.
|
|
220
241
|
bindings:
|
|
221
242
|
http:
|
|
222
243
|
method: GET
|
|
@@ -234,6 +255,12 @@ operations:
|
|
|
234
255
|
$ref: '#/channels/runEventsMessages'
|
|
235
256
|
title: Subscribe to messages stream
|
|
236
257
|
summary: Receive per-token AI chunks.
|
|
258
|
+
description: |
|
|
259
|
+
Mixed mode (RFC 0094 §I note): the binding's single-value
|
|
260
|
+
`streamMode` enum below describes the pure `messages` subscription;
|
|
261
|
+
`streamMode` additionally accepts comma-separated combinations
|
|
262
|
+
(e.g. `updates,messages`) per `stream-modes.md` §"Mixed mode".
|
|
263
|
+
`values` MUST NOT combine with other modes.
|
|
237
264
|
bindings:
|
|
238
265
|
http:
|
|
239
266
|
method: GET
|
|
@@ -251,6 +278,12 @@ operations:
|
|
|
251
278
|
$ref: '#/channels/runEventsDebug'
|
|
252
279
|
title: Subscribe to debug stream
|
|
253
280
|
summary: Receive every engine event including internal/log/lease.
|
|
281
|
+
description: |
|
|
282
|
+
Mixed mode (RFC 0094 §I note): the binding's single-value
|
|
283
|
+
`streamMode` enum below describes the pure `debug` subscription;
|
|
284
|
+
`streamMode` additionally accepts comma-separated combinations
|
|
285
|
+
(e.g. `updates,debug`) per `stream-modes.md` §"Mixed mode".
|
|
286
|
+
`values` MUST NOT combine with other modes.
|
|
254
287
|
bindings:
|
|
255
288
|
http:
|
|
256
289
|
method: GET
|
|
@@ -496,7 +529,10 @@ components:
|
|
|
496
529
|
name: interrupt.requested
|
|
497
530
|
title: Interrupt requested (canonical HITL primitive)
|
|
498
531
|
summary: |
|
|
499
|
-
The discriminated-union form of
|
|
532
|
+
The discriminated-union form of the full `interrupt.md` kind union
|
|
533
|
+
(RFC 0094 §E): approval / clarification / external-event / custom /
|
|
534
|
+
conversation.start / conversation.exchange / conversation.close /
|
|
535
|
+
low-confidence.
|
|
500
536
|
Servers emitting `interrupt.requested` SHOULD also emit the legacy
|
|
501
537
|
kind-specific event (`approval.requested` etc) for backward compat
|
|
502
538
|
until consumers migrate.
|
|
@@ -605,33 +641,13 @@ components:
|
|
|
605
641
|
$ref: '../schemas/run-snapshot.schema.json'
|
|
606
642
|
|
|
607
643
|
AiMessageChunkPayload:
|
|
608
|
-
# S2 closure (2026-04-27)
|
|
609
|
-
#
|
|
610
|
-
#
|
|
611
|
-
#
|
|
612
|
-
#
|
|
613
|
-
#
|
|
614
|
-
#
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
nodeId: { type: string }
|
|
619
|
-
runId: { type: string }
|
|
620
|
-
chunk:
|
|
621
|
-
type: string
|
|
622
|
-
description: The new token(s) since the previous chunk.
|
|
623
|
-
isLast:
|
|
624
|
-
type: boolean
|
|
625
|
-
description: True for the final chunk of a given AI node call.
|
|
626
|
-
meta:
|
|
627
|
-
type: object
|
|
628
|
-
description: |
|
|
629
|
-
Tiered metadata. Tier 1: typed slots — `finishReason`
|
|
630
|
-
("stop"|"length"|"tool_calls"|"content_filter"), `logprobs`,
|
|
631
|
-
`toolCalls`, `model`, `usage` ({promptTokens,
|
|
632
|
-
completionTokens, totalTokens}). Tier 2: provider-pass-through
|
|
633
|
-
via `provider` + `providerExtensions`. Consumers SHOULD prefer
|
|
634
|
-
Tier 1; Tier 2 is the escape hatch for fields the spec hasn't
|
|
635
|
-
typed yet. See run-event-payloads.schema.json#$defs._chunkMeta
|
|
636
|
-
for the full definition + per-field constraints.
|
|
637
|
-
additionalProperties: true
|
|
644
|
+
# S2 closure (2026-04-27) + RFC 0094 §D single-sourcing: the payload
|
|
645
|
+
# is the canonical `outputChunk` definition in
|
|
646
|
+
# run-event-payloads.schema.json — referenced (not hand-copied, the
|
|
647
|
+
# prior inline copy was one of the three drifting definitions) so the
|
|
648
|
+
# SSE consumer + run-event log share exactly one shape contract.
|
|
649
|
+
# Minimum compliant payload: {nodeId, runId, chunk, isLast} per
|
|
650
|
+
# stream-modes.md §messages; `meta` adds Tier 1 typed slots
|
|
651
|
+
# (finishReason / logprobs / toolCalls / model / usage) and a Tier 2
|
|
652
|
+
# provider-pass-through escape hatch (see #$defs/_chunkMeta).
|
|
653
|
+
$ref: '../schemas/run-event-payloads.schema.json#/$defs/outputChunk'
|
package/api/openapi.yaml
CHANGED
|
@@ -2,7 +2,7 @@ openapi: 3.1.0
|
|
|
2
2
|
|
|
3
3
|
info:
|
|
4
4
|
title: Workflow Orchestration Protocol (openwop) API
|
|
5
|
-
version: "1.0"
|
|
5
|
+
version: "1.1.0"
|
|
6
6
|
summary: REST surface for declaring, executing, suspending, resuming, and observing multi-step workflows.
|
|
7
7
|
description: |
|
|
8
8
|
Canonical OpenAPI 3.1 specification for openwop-compliant servers. Generated from `rest-endpoints.md` and references the JSON Schemas in `schemas/`.
|
|
@@ -16,6 +16,16 @@ info:
|
|
|
16
16
|
- `run-options.md` — `configurable`/`tags`/`metadata`
|
|
17
17
|
- `interrupt.md` — HITL primitive
|
|
18
18
|
- `replay.md` — `:fork` endpoint
|
|
19
|
+
|
|
20
|
+
**Registry scope (RFC 0094 §I).** This document specifies the HOST
|
|
21
|
+
surface. The production node-pack registry surface (`/v1/packs/*` —
|
|
22
|
+
publish/get/delete/sig, deprecation, yank, key rotation) is specified in
|
|
23
|
+
`spec/v1/node-packs.md` §"Registry HTTP API" + `spec/v1/registry-operations.md`
|
|
24
|
+
and is served by a registry service (e.g. the planned hosted reference
|
|
25
|
+
registry `packs.openwop.dev`, or a third-party/private registry
|
|
26
|
+
implementation) — a distinct deployable, out of scope for this host
|
|
27
|
+
OpenAPI document. Only the test-mode mirror (`/v1/packs-test/*`, RFC 0025)
|
|
28
|
+
is host-mounted and documented here.
|
|
19
29
|
contact:
|
|
20
30
|
name: openwop spec working group
|
|
21
31
|
url: https://openwop.dev/spec/v1/
|
|
@@ -75,6 +85,11 @@ tags:
|
|
|
75
85
|
19-code publish error catalog without `packs:publish` scope on the real registry. Hosts that haven't
|
|
76
86
|
mounted this surface MUST return `404 Not Found` for every path under `/v1/packs-test/`.
|
|
77
87
|
|
|
88
|
+
Scope note (RFC 0094 §I): the PRODUCTION `/v1/packs/*` surface these paths mirror is specified in
|
|
89
|
+
`spec/v1/registry-operations.md` + `node-packs.md` §"Registry HTTP API" and is served by a registry
|
|
90
|
+
service (a distinct deployable from the host), so it is intentionally NOT defined in this host
|
|
91
|
+
OpenAPI document.
|
|
92
|
+
|
|
78
93
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
79
94
|
# PATHS
|
|
80
95
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -178,7 +193,13 @@ paths:
|
|
|
178
193
|
# routing fields, plus the openwop RunOptions overlay (configurable,
|
|
179
194
|
# tags, metadata) hoisted into a first-class JSON Schema at
|
|
180
195
|
# ../schemas/run-options.schema.json. allOf composes the two
|
|
181
|
-
# so callers see one unified body shape.
|
|
196
|
+
# so callers see one unified body shape. RFC 0094 §A: neither
|
|
197
|
+
# allOf branch is closed via additionalProperties (two closed
|
|
198
|
+
# branches inside one allOf made every documented body
|
|
199
|
+
# unsatisfiable); the composed request is closed here with
|
|
200
|
+
# `unevaluatedProperties: false` (JSON Schema 2020-12), so
|
|
201
|
+
# undeclared properties still fail at the composition level.
|
|
202
|
+
unevaluatedProperties: false
|
|
182
203
|
allOf:
|
|
183
204
|
- type: object
|
|
184
205
|
properties:
|
|
@@ -215,7 +236,6 @@ paths:
|
|
|
215
236
|
type: string
|
|
216
237
|
minLength: 1
|
|
217
238
|
description: RFC 0081 — the manifest agent the eval suite targets. Required when mode is `eval`.
|
|
218
|
-
additionalProperties: false
|
|
219
239
|
if:
|
|
220
240
|
properties: { mode: { const: eval } }
|
|
221
241
|
required: [mode]
|
|
@@ -1843,6 +1863,9 @@ paths:
|
|
|
1843
1863
|
`conflict`/`version_conflict`) MUST be served verbatim. The
|
|
1844
1864
|
test catalog MUST be isolated per RFC 0025 §C — a pack PUT'd
|
|
1845
1865
|
here MUST NOT appear in `GET /v1/packs/{name}` listings.
|
|
1866
|
+
The mirrored production path is registry-service surface
|
|
1867
|
+
(`registry-operations.md`), not defined in this host document
|
|
1868
|
+
(see the `packs-test` tag scope note).
|
|
1846
1869
|
operationId: putTestPackTarball
|
|
1847
1870
|
parameters:
|
|
1848
1871
|
- in: header
|
|
@@ -1914,7 +1937,7 @@ paths:
|
|
|
1914
1937
|
get:
|
|
1915
1938
|
tags: [packs-test]
|
|
1916
1939
|
summary: Fetch a published test-catalog tarball.
|
|
1917
|
-
description: 'Mirror of `GET /v1/packs/{name}/-/{version}.tgz`. Returns the gzipped tarball bytes with `Content-Type: application/tar+gzip` and an `ETag: "sha256-..."` matching the manifest''s `tarballSha256`.'
|
|
1940
|
+
description: 'Mirror of `GET /v1/packs/{name}/-/{version}.tgz`. Returns the gzipped tarball bytes with `Content-Type: application/tar+gzip` and an `ETag: "sha256-..."` matching the manifest''s `tarballSha256`. The mirrored production path is registry-service surface (`registry-operations.md`), not defined in this host document (see the `packs-test` tag scope note).'
|
|
1918
1941
|
operationId: getTestPackTarball
|
|
1919
1942
|
responses:
|
|
1920
1943
|
'200':
|
|
@@ -1951,7 +1974,10 @@ paths:
|
|
|
1951
1974
|
for versions older than the registry's unpublish window
|
|
1952
1975
|
(default 72h). Test-mode implementations MAY shorten the
|
|
1953
1976
|
window for tractable conformance fixtures but MUST surface
|
|
1954
|
-
the same error code.
|
|
1977
|
+
the same error code. The mirrored production path is
|
|
1978
|
+
registry-service surface (`registry-operations.md`), not
|
|
1979
|
+
defined in this host document (see the `packs-test` tag
|
|
1980
|
+
scope note).
|
|
1955
1981
|
operationId: deleteTestPackVersion
|
|
1956
1982
|
responses:
|
|
1957
1983
|
'204':
|
|
@@ -1983,7 +2009,9 @@ paths:
|
|
|
1983
2009
|
description: |
|
|
1984
2010
|
Mirror of `GET /v1/packs/{name}/-/{version}.sig`. Returns the
|
|
1985
2011
|
signature blob over `pack.json` for this version. MAY 302-redirect
|
|
1986
|
-
to a storage-backend signed URL.
|
|
2012
|
+
to a storage-backend signed URL. The mirrored production path is
|
|
2013
|
+
registry-service surface (`registry-operations.md`), not defined
|
|
2014
|
+
in this host document (see the `packs-test` tag scope note).
|
|
1987
2015
|
operationId: getTestPackSignature
|
|
1988
2016
|
responses:
|
|
1989
2017
|
'200':
|