@pulsefield/protocol 0.0.2 → 0.0.3

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 (29) hide show
  1. package/PROTOCOL_GUIDELINES.md +123 -0
  2. package/Package.swift +34 -0
  3. package/README.md +92 -4
  4. package/buf.yaml +1 -1
  5. package/docs/session-scope.md +27 -0
  6. package/gen/python/pulsefield/protocol/py.typed +1 -0
  7. package/gen/python/pulsefield/protocol/v1/core_pb2.py +34 -0
  8. package/gen/python/pulsefield/protocol/v1/core_pb2.pyi +76 -0
  9. package/gen/python/pulsefield/protocol/v1/envelope_pb2.py +6 -23
  10. package/gen/python/pulsefield/protocol/v1/envelope_pb2.pyi +26 -105
  11. package/gen/python/pulsefield/protocol/v1/inference_pb2.py +48 -0
  12. package/gen/python/pulsefield/protocol/v1/inference_pb2.pyi +160 -0
  13. package/gen/python/pulsefield/protocol/v1/mapper_pb2.py +28 -0
  14. package/gen/python/pulsefield/protocol/v1/mapper_pb2.pyi +23 -0
  15. package/gen/swift/pulsefield/protocol/v1/core.pb.swift +323 -0
  16. package/gen/swift/pulsefield/protocol/v1/envelope.pb.swift +335 -671
  17. package/gen/swift/pulsefield/protocol/v1/inference.pb.swift +929 -0
  18. package/gen/swift/pulsefield/protocol/v1/mapper.pb.swift +143 -0
  19. package/package.json +17 -11
  20. package/proto/pulsefield/protocol/v1/core.proto +57 -0
  21. package/proto/pulsefield/protocol/v1/envelope.proto +30 -58
  22. package/proto/pulsefield/protocol/v1/inference.proto +145 -0
  23. package/proto/pulsefield/protocol/v1/mapper.proto +17 -0
  24. package/pyproject.toml +38 -0
  25. package/tools/check-generated.mjs +222 -0
  26. package/tools/check-python-package.mjs +63 -0
  27. package/tools/ensure-python-typed.mjs +10 -0
  28. package/fixtures/json/v1/audio-request.json +0 -12
  29. package/fixtures/json/v1/hit-object-token-event.json +0 -9
@@ -0,0 +1,123 @@
1
+ # Protocol Guidelines
2
+
3
+ ## Intent
4
+
5
+ This package defines the shared protobuf contract for Pulsefield clients and model services. The goal is to keep the protocol easy to evolve while avoiding accidental wire-format breakage.
6
+
7
+ ## Change Policy
8
+
9
+ During early `0.x` development, breaking changes are allowed when all known consumers are updated in the same release.
10
+
11
+ Once the protocol is used by independently updated clients, prefer additive changes:
12
+
13
+ - Add new fields with fresh numbers.
14
+ - Add new enum values with fresh numbers.
15
+ - Add new `Envelope.payload` variants with fresh numbers.
16
+
17
+ Avoid reusing field numbers from published schemas. If a field was removed after publication, reserve its old number and name when practical.
18
+
19
+ Moving a message to another `.proto` file can preserve its fully qualified protobuf type name and binary wire compatibility, but it changes generated module/file boundaries in languages such as Python. Treat those moves as generated API breaks during `0.x`, document the import migration, and update known consumers in the same release.
20
+
21
+ ## Source Of Truth
22
+
23
+ - `.proto` files under `proto/` are the source of truth.
24
+ - Keep transport, graph/core vocabulary, inference, and opaque mapper token events in separate source files when the concepts can evolve independently.
25
+ - Breaking-change checks use package-level compatibility so source files can be reorganized without treating stable fully qualified type moves as wire breaks.
26
+ - Generated code under `gen/` is committed for Swift/Python consumers.
27
+ - WebSocket payloads should use binary protobuf `Envelope`.
28
+
29
+ ## Responsibility Boundary
30
+
31
+ This package should contain stable, cross-process protocol contracts:
32
+
33
+ - Node graph identity, roles, and capability announcements for host, player client, model service, hardware, and debug-tool processes.
34
+ - Inference endpoint messages and lifecycle states.
35
+ - Machine-readable enums and error codes shared by Swift, Python, and npm consumers.
36
+ - Opaque token-stream events tagged with the token-contract version needed by Swift/model-side decoders.
37
+ - Generated artifacts that prove those contracts are stable.
38
+
39
+ Keep implementation details in their owning repositories:
40
+
41
+ - Model training, Torch runtime, checkpoint loading, mel/control features, grammar decoding, and timing fitting algorithms stay in `Pulsefield-model`.
42
+ - Token decoding, decoded Mania4K/domain state, SwiftUI view state, AVFoundation clocks, input routing, rendering, judgement, scoring, and local-library/recognition integrations stay in `Pulsefield`.
43
+ - Full `.osu` import/export behavior stays outside this protocol.
44
+
45
+ ## Inference Lifecycle
46
+
47
+ The v1 endpoint lifecycle is:
48
+
49
+ ```text
50
+ ready -> audio_preparing -> audio_ready -> streaming -> stopped
51
+ \-> failed
52
+ ```
53
+
54
+ Use `StatusEvent` when a service sends lifecycle transitions over the protocol. The current model endpoint logs `ws_status`; new protobuf consumers should prefer `StatusEvent`.
55
+
56
+ ## Token Contract
57
+
58
+ The protobuf layer treats mapper tokens as opaque ids plus `token_contract_version`. Token decoding tables, lane actions, quantization rules, and reducer/domain state belong in the Swift and model repositories that share the token-stream transport definitions.
59
+
60
+ ## Comments
61
+
62
+ Comments should explain protocol meaning, not restate the field name.
63
+
64
+ Add comments when:
65
+
66
+ - A message represents a wire-level event or request.
67
+ - A field has units, clock source, ordering semantics, or lifecycle assumptions.
68
+ - A field is optional and absence has a distinct meaning.
69
+ - An enum value is non-obvious.
70
+ - A value is experimental or temporary.
71
+ - A field exists for compatibility with a specific consumer.
72
+
73
+ Prefer comments like:
74
+
75
+ ```proto
76
+ // Sent by the client to request beatmap inference for an audio source.
77
+ message AudioRequest {
78
+ // Local or sandbox-relative path understood by the receiving model service.
79
+ string audio_path = 1;
80
+
81
+ // Duration of the selected audio in milliseconds, when known by the client.
82
+ optional uint32 audio_length_ms = 2;
83
+ }
84
+ ```
85
+
86
+ Avoid comments like:
87
+
88
+ ```proto
89
+ // The audio path.
90
+ string audio_path = 1;
91
+ ```
92
+
93
+ ## Naming And Units
94
+
95
+ - Use `snake_case` field names.
96
+ - Include units in names when they clarify meaning, such as `_ms`, `_unix_ms`, `_count`, or `_id`.
97
+ - Use `*_UNSPECIFIED = 0` for enum defaults.
98
+ - Prefer enums for machine-readable state.
99
+ - Use strings for human-facing or debug messages.
100
+
101
+ ## Validation
102
+
103
+ The schema defines shape. Runtime code still validates behavior:
104
+
105
+ - Payload is present.
106
+ - `session_id` is known.
107
+ - `sequence` ordering is acceptable.
108
+ - Time values are in expected ranges.
109
+ - State transitions make sense.
110
+
111
+ ## Workflow
112
+
113
+ Use local npm scripts:
114
+
115
+ ```sh
116
+ npm run generate
117
+ npm run proto:format
118
+ npm run proto:lint
119
+ npm run generated:check
120
+ npm run check
121
+ ```
122
+
123
+ Generated Swift/Python files must be updated in the same change as proto edits. `npm run generated:check` compares committed outputs with fresh Buf generation and checks that Python stubs and Swift generated code expose the same proto surface.
package/Package.swift ADDED
@@ -0,0 +1,34 @@
1
+ // swift-tools-version: 6.0
2
+
3
+ import PackageDescription
4
+
5
+ let package = Package(
6
+ name: "PulsefieldProtocol",
7
+ products: [
8
+ .library(
9
+ name: "PulsefieldProtocol",
10
+ targets: ["PulsefieldProtocol"]
11
+ )
12
+ ],
13
+ dependencies: [
14
+ .package(
15
+ url: "https://github.com/apple/swift-protobuf.git",
16
+ from: "1.38.0"
17
+ )
18
+ ],
19
+ targets: [
20
+ .target(
21
+ name: "PulsefieldProtocol",
22
+ dependencies: [
23
+ .product(name: "SwiftProtobuf", package: "swift-protobuf")
24
+ ],
25
+ path: "gen/swift",
26
+ sources: [
27
+ "pulsefield/protocol/v1/core.pb.swift",
28
+ "pulsefield/protocol/v1/envelope.pb.swift",
29
+ "pulsefield/protocol/v1/inference.pb.swift",
30
+ "pulsefield/protocol/v1/mapper.pb.swift",
31
+ ]
32
+ )
33
+ ]
34
+ )
package/README.md CHANGED
@@ -8,12 +8,95 @@ Shared protocol package for projects under [github.com/Pulsefield](https://githu
8
8
  proto/ Protocol Buffers source of truth.
9
9
  gen/swift/ Generated SwiftProtobuf code, committed and shipped.
10
10
  gen/python/ Generated Python protobuf code and type stubs, committed and shipped.
11
- fixtures/json/ Protobuf JSON mapping fixtures for debug and tests.
11
+ docs/ Protocol notes shipped with the npm package.
12
+ tools/ Local generation and drift-check scripts.
13
+ Package.swift SwiftPM manifest for Swift/Xcode consumers.
14
+ pyproject.toml Python package metadata for wheel/sdist consumers.
12
15
  buf.yaml Proto lint and breaking-change configuration.
13
16
  buf.gen.yaml Swift and Python generation configuration.
14
17
  ```
15
18
 
16
- The Swift app and Python model consume generated code from `gen/`. The `.proto` files remain the protocol source of truth. WebSocket payloads should be binary protobuf `Envelope` messages. JSON is reserved for debug, logs, and fixtures.
19
+ The Swift app and Python model consume generated code from `gen/`. The `.proto` files remain the protocol source of truth. WebSocket payloads should be binary protobuf `Envelope` messages. JSON is reserved for debug and logs.
20
+
21
+ See [Protocol Guidelines](./PROTOCOL_GUIDELINES.md) for schema evolution, naming, and comment conventions. See [Session Scope](./docs/session-scope.md) for `Envelope.session_id` requirements by payload.
22
+
23
+ The v1 protobuf source is split by responsibility:
24
+
25
+ ```text
26
+ proto/pulsefield/protocol/v1/core.proto
27
+ Node identity, roles, and advertised capabilities.
28
+
29
+ proto/pulsefield/protocol/v1/envelope.proto
30
+ Transport envelope, routing metadata, correlation ids, and payload union.
31
+
32
+ proto/pulsefield/protocol/v1/inference.proto
33
+ Inference requests, lifecycle status, errors, and end-of-stream events.
34
+
35
+ proto/pulsefield/protocol/v1/mapper.proto
36
+ Opaque mapper token events.
37
+ ```
38
+
39
+ ## Current Scope
40
+
41
+ This package owns the stable cross-language contract between Pulsefield clients, the Python model endpoint, and npm consumers:
42
+
43
+ - Node graph identity for host, player client, model service, hardware, and debug-tool processes.
44
+ - Inference WebSocket envelopes: ready, audio, reference time, stop, status, error, hitobject token, and end-of-stream.
45
+ - Opaque mapper token stream events tagged with a token-contract version.
46
+
47
+ This package does not own token decoding, decoded Mania4K/domain state, model inference internals, Torch checkpoints, timing fitting algorithms, SwiftUI state, rendering, judgement, input routing, audio clock implementations, or full `.osu` parsing/export.
48
+
49
+ ## Distribution Surfaces
50
+
51
+ This repository publishes the same protocol contract through multiple language-native surfaces. Downstream Swift and Python projects do not need their own `package.json`.
52
+
53
+ ### npm
54
+
55
+ The npm package remains useful for Node tooling, registry-backed tarballs, and consumers that want direct access to `proto/` and `gen/`:
56
+
57
+ ```sh
58
+ npm install @pulsefield/protocol
59
+ ```
60
+
61
+ ### SwiftPM
62
+
63
+ Swift/Xcode consumers should depend on this Git repository directly:
64
+
65
+ ```swift
66
+ .package(
67
+ url: "https://github.com/Pulsefield/protocol.git",
68
+ from: "0.0.3"
69
+ )
70
+ ```
71
+
72
+ Then add the product to a target:
73
+
74
+ ```swift
75
+ .product(name: "PulsefieldProtocol", package: "protocol")
76
+ ```
77
+
78
+ SwiftPM publication is Git-tag based. Create and push a semver tag such as `0.0.3`; no central Swift registry is required for this bootstrap path.
79
+
80
+ ### Python
81
+
82
+ Python consumers should eventually use the PyPI package:
83
+
84
+ ```sh
85
+ pip install pulsefield-protocol==0.0.3
86
+ ```
87
+
88
+ The local bootstrap build is:
89
+
90
+ ```sh
91
+ python3 -m pip install build
92
+ python3 -m build --sdist --wheel --outdir dist/
93
+ python3 -m pip install dist/*.whl
94
+ python3 -c "from pulsefield.protocol.v1 import envelope_pb2; envelope_pb2.Envelope()"
95
+ ```
96
+
97
+ Generated Python classes live in the module for their source `.proto` file. For example, import `Envelope` from `envelope_pb2`, inference messages from `inference_pb2`, mapper token messages from `mapper_pb2`, and node graph messages from `core_pb2`.
98
+
99
+ The `Publish Python package` GitHub workflow is manual and expects PyPI trusted publishing to be configured for the repository/environment before it is run.
17
100
 
18
101
  ## Development Tools
19
102
 
@@ -23,18 +106,23 @@ The Swift app and Python model consume generated code from `gen/`. The `.proto`
23
106
  - Proto lint/generation: `@bufbuild/buf`.
24
107
  - Swift generation: Buf remote plugin `buf.build/apple/swift`.
25
108
  - Python generation: Buf remote plugins `buf.build/protocolbuffers/python` and `buf.build/protocolbuffers/pyi`.
26
- - TypeScript checks: `typescript`.
27
- - Tests: `vitest`.
28
109
  - Formatting: `prettier`.
29
110
 
30
111
  ## Commands
31
112
 
32
113
  ```sh
114
+ npm run generate
33
115
  npm run proto:lint
34
116
  npm run proto:generate
117
+ npm run generated:check
35
118
  npm run check
119
+ npm run python:check
120
+ npm run swift:build
121
+ npm run bootstrap:check
36
122
  ```
37
123
 
124
+ `npm run generated:check` regenerates Swift and Python outputs in a temporary directory and compares them byte-for-byte with `gen/`. It also verifies that the generated Python stubs and Swift file expose the same message, enum, and field surface declared by the proto.
125
+
38
126
  ## License
39
127
 
40
128
  Licensed under the Apache License, Version 2.0. See [LICENSE](./LICENSE).
package/buf.yaml CHANGED
@@ -6,4 +6,4 @@ lint:
6
6
  - STANDARD
7
7
  breaking:
8
8
  use:
9
- - FILE
9
+ - PACKAGE
@@ -0,0 +1,27 @@
1
+ # Session Scope
2
+
3
+ `Envelope.session_id` defines the session scope for the envelope payload. Payload
4
+ messages do not duplicate `session_id`; receivers validate the payload against the
5
+ session id carried by the envelope.
6
+
7
+ ## Rules
8
+
9
+ | Payload | `Envelope.session_id` |
10
+ | ---------------------- | ----------------------------------------------------------------------------------------- |
11
+ | `NodeHello` | MUST be empty |
12
+ | `ReadyRequest` | SHOULD be empty |
13
+ | `AudioRequest` | MUST be non-empty |
14
+ | `ReferenceTimeRequest` | MUST be non-empty |
15
+ | `HitObjectTokenEvent` | MUST be non-empty |
16
+ | `StopSessionRequest` | MUST be non-empty |
17
+ | `StatusEvent` | MAY be empty for endpoint/node-scoped status; MUST be non-empty for session-scoped status |
18
+
19
+ `StopSessionRequest` intentionally has no `session_id` field. It targets the
20
+ active session identified by `Envelope.session_id`; therefore an envelope with
21
+ `payload.stop_session` and an empty `Envelope.session_id` is invalid.
22
+
23
+ `StatusEvent` is the only payload in this list that can validly cross the
24
+ session boundary. Endpoint-level statuses such as cold startup or readiness can
25
+ use an empty `Envelope.session_id`. Statuses describing an active session, a
26
+ missing session, or a session transition use the relevant non-empty
27
+ `Envelope.session_id`.
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # source: pulsefield/protocol/v1/core.proto
4
+ # Protobuf Python Version: 5.26.1
5
+ """Generated protocol buffer code."""
6
+ from google.protobuf import descriptor as _descriptor
7
+ from google.protobuf import descriptor_pool as _descriptor_pool
8
+ from google.protobuf import symbol_database as _symbol_database
9
+ from google.protobuf.internal import builder as _builder
10
+ # @@protoc_insertion_point(imports)
11
+
12
+ _sym_db = _symbol_database.Default()
13
+
14
+
15
+
16
+
17
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n!pulsefield/protocol/v1/core.proto\x12\x16pulsefield.protocol.v1\"\xcd\x01\n\x0eNodeCapability\x12>\n\x04kind\x18\x01 \x01(\x0e\x32*.pulsefield.protocol.v1.NodeCapabilityKindR\x04kind\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12\x18\n\x07version\x18\x03 \x01(\tR\x07version\x12M\n\tdirection\x18\x04 \x01(\x0e\x32/.pulsefield.protocol.v1.NodeCapabilityDirectionR\tdirection\"\xe8\x01\n\tNodeHello\x12\x17\n\x07node_id\x18\x01 \x01(\tR\x06nodeId\x12\x34\n\x04role\x18\x02 \x01(\x0e\x32 .pulsefield.protocol.v1.NodeRoleR\x04role\x12J\n\x0c\x63\x61pabilities\x18\x03 \x03(\x0b\x32&.pulsefield.protocol.v1.NodeCapabilityR\x0c\x63\x61pabilities\x12)\n\x10protocol_version\x18\x04 \x01(\tR\x0fprotocolVersion\x12\x15\n\x06\x61pp_id\x18\x05 \x01(\tR\x05\x61ppId*\xa5\x01\n\x08NodeRole\x12\x19\n\x15NODE_ROLE_UNSPECIFIED\x10\x00\x12\x12\n\x0eNODE_ROLE_HOST\x10\x01\x12\x1b\n\x17NODE_ROLE_PLAYER_CLIENT\x10\x02\x12\x1b\n\x17NODE_ROLE_MODEL_SERVICE\x10\x03\x12\x16\n\x12NODE_ROLE_HARDWARE\x10\x04\x12\x18\n\x14NODE_ROLE_DEBUG_TOOL\x10\x05*\x8d\x02\n\x12NodeCapabilityKind\x12$\n NODE_CAPABILITY_KIND_UNSPECIFIED\x10\x00\x12$\n NODE_CAPABILITY_KIND_RECOGNITION\x10\x01\x12\x1f\n\x1bNODE_CAPABILITY_KIND_TIMING\x10\x02\x12\x1f\n\x1bNODE_CAPABILITY_KIND_MAPPER\x10\x03\x12&\n\"NODE_CAPABILITY_KIND_PLAYER_STREAM\x10\x04\x12!\n\x1dNODE_CAPABILITY_KIND_HARDWARE\x10\x05\x12\x1e\n\x1aNODE_CAPABILITY_KIND_DEBUG\x10\x06*\xc1\x01\n\x17NodeCapabilityDirection\x12)\n%NODE_CAPABILITY_DIRECTION_UNSPECIFIED\x10\x00\x12&\n\"NODE_CAPABILITY_DIRECTION_PRODUCER\x10\x01\x12&\n\"NODE_CAPABILITY_DIRECTION_CONSUMER\x10\x02\x12+\n\'NODE_CAPABILITY_DIRECTION_BIDIRECTIONAL\x10\x03\x62\x06proto3')
18
+
19
+ _globals = globals()
20
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
21
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'pulsefield.protocol.v1.core_pb2', _globals)
22
+ if not _descriptor._USE_C_DESCRIPTORS:
23
+ DESCRIPTOR._loaded_options = None
24
+ _globals['_NODEROLE']._serialized_start=505
25
+ _globals['_NODEROLE']._serialized_end=670
26
+ _globals['_NODECAPABILITYKIND']._serialized_start=673
27
+ _globals['_NODECAPABILITYKIND']._serialized_end=942
28
+ _globals['_NODECAPABILITYDIRECTION']._serialized_start=945
29
+ _globals['_NODECAPABILITYDIRECTION']._serialized_end=1138
30
+ _globals['_NODECAPABILITY']._serialized_start=62
31
+ _globals['_NODECAPABILITY']._serialized_end=267
32
+ _globals['_NODEHELLO']._serialized_start=270
33
+ _globals['_NODEHELLO']._serialized_end=502
34
+ # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,76 @@
1
+ from google.protobuf.internal import containers as _containers
2
+ from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
3
+ from google.protobuf import descriptor as _descriptor
4
+ from google.protobuf import message as _message
5
+ from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union
6
+
7
+ DESCRIPTOR: _descriptor.FileDescriptor
8
+
9
+ class NodeRole(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
10
+ __slots__ = ()
11
+ NODE_ROLE_UNSPECIFIED: _ClassVar[NodeRole]
12
+ NODE_ROLE_HOST: _ClassVar[NodeRole]
13
+ NODE_ROLE_PLAYER_CLIENT: _ClassVar[NodeRole]
14
+ NODE_ROLE_MODEL_SERVICE: _ClassVar[NodeRole]
15
+ NODE_ROLE_HARDWARE: _ClassVar[NodeRole]
16
+ NODE_ROLE_DEBUG_TOOL: _ClassVar[NodeRole]
17
+
18
+ class NodeCapabilityKind(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
19
+ __slots__ = ()
20
+ NODE_CAPABILITY_KIND_UNSPECIFIED: _ClassVar[NodeCapabilityKind]
21
+ NODE_CAPABILITY_KIND_RECOGNITION: _ClassVar[NodeCapabilityKind]
22
+ NODE_CAPABILITY_KIND_TIMING: _ClassVar[NodeCapabilityKind]
23
+ NODE_CAPABILITY_KIND_MAPPER: _ClassVar[NodeCapabilityKind]
24
+ NODE_CAPABILITY_KIND_PLAYER_STREAM: _ClassVar[NodeCapabilityKind]
25
+ NODE_CAPABILITY_KIND_HARDWARE: _ClassVar[NodeCapabilityKind]
26
+ NODE_CAPABILITY_KIND_DEBUG: _ClassVar[NodeCapabilityKind]
27
+
28
+ class NodeCapabilityDirection(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
29
+ __slots__ = ()
30
+ NODE_CAPABILITY_DIRECTION_UNSPECIFIED: _ClassVar[NodeCapabilityDirection]
31
+ NODE_CAPABILITY_DIRECTION_PRODUCER: _ClassVar[NodeCapabilityDirection]
32
+ NODE_CAPABILITY_DIRECTION_CONSUMER: _ClassVar[NodeCapabilityDirection]
33
+ NODE_CAPABILITY_DIRECTION_BIDIRECTIONAL: _ClassVar[NodeCapabilityDirection]
34
+ NODE_ROLE_UNSPECIFIED: NodeRole
35
+ NODE_ROLE_HOST: NodeRole
36
+ NODE_ROLE_PLAYER_CLIENT: NodeRole
37
+ NODE_ROLE_MODEL_SERVICE: NodeRole
38
+ NODE_ROLE_HARDWARE: NodeRole
39
+ NODE_ROLE_DEBUG_TOOL: NodeRole
40
+ NODE_CAPABILITY_KIND_UNSPECIFIED: NodeCapabilityKind
41
+ NODE_CAPABILITY_KIND_RECOGNITION: NodeCapabilityKind
42
+ NODE_CAPABILITY_KIND_TIMING: NodeCapabilityKind
43
+ NODE_CAPABILITY_KIND_MAPPER: NodeCapabilityKind
44
+ NODE_CAPABILITY_KIND_PLAYER_STREAM: NodeCapabilityKind
45
+ NODE_CAPABILITY_KIND_HARDWARE: NodeCapabilityKind
46
+ NODE_CAPABILITY_KIND_DEBUG: NodeCapabilityKind
47
+ NODE_CAPABILITY_DIRECTION_UNSPECIFIED: NodeCapabilityDirection
48
+ NODE_CAPABILITY_DIRECTION_PRODUCER: NodeCapabilityDirection
49
+ NODE_CAPABILITY_DIRECTION_CONSUMER: NodeCapabilityDirection
50
+ NODE_CAPABILITY_DIRECTION_BIDIRECTIONAL: NodeCapabilityDirection
51
+
52
+ class NodeCapability(_message.Message):
53
+ __slots__ = ("kind", "name", "version", "direction")
54
+ KIND_FIELD_NUMBER: _ClassVar[int]
55
+ NAME_FIELD_NUMBER: _ClassVar[int]
56
+ VERSION_FIELD_NUMBER: _ClassVar[int]
57
+ DIRECTION_FIELD_NUMBER: _ClassVar[int]
58
+ kind: NodeCapabilityKind
59
+ name: str
60
+ version: str
61
+ direction: NodeCapabilityDirection
62
+ def __init__(self, kind: _Optional[_Union[NodeCapabilityKind, str]] = ..., name: _Optional[str] = ..., version: _Optional[str] = ..., direction: _Optional[_Union[NodeCapabilityDirection, str]] = ...) -> None: ...
63
+
64
+ class NodeHello(_message.Message):
65
+ __slots__ = ("node_id", "role", "capabilities", "protocol_version", "app_id")
66
+ NODE_ID_FIELD_NUMBER: _ClassVar[int]
67
+ ROLE_FIELD_NUMBER: _ClassVar[int]
68
+ CAPABILITIES_FIELD_NUMBER: _ClassVar[int]
69
+ PROTOCOL_VERSION_FIELD_NUMBER: _ClassVar[int]
70
+ APP_ID_FIELD_NUMBER: _ClassVar[int]
71
+ node_id: str
72
+ role: NodeRole
73
+ capabilities: _containers.RepeatedCompositeFieldContainer[NodeCapability]
74
+ protocol_version: str
75
+ app_id: str
76
+ def __init__(self, node_id: _Optional[str] = ..., role: _Optional[_Union[NodeRole, str]] = ..., capabilities: _Optional[_Iterable[_Union[NodeCapability, _Mapping]]] = ..., protocol_version: _Optional[str] = ..., app_id: _Optional[str] = ...) -> None: ...
@@ -12,35 +12,18 @@ from google.protobuf.internal import builder as _builder
12
12
  _sym_db = _symbol_database.Default()
13
13
 
14
14
 
15
+ from pulsefield.protocol.v1 import core_pb2 as pulsefield_dot_protocol_dot_v1_dot_core__pb2
16
+ from pulsefield.protocol.v1 import inference_pb2 as pulsefield_dot_protocol_dot_v1_dot_inference__pb2
17
+ from pulsefield.protocol.v1 import mapper_pb2 as pulsefield_dot_protocol_dot_v1_dot_mapper__pb2
15
18
 
16
19
 
17
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%pulsefield/protocol/v1/envelope.proto\x12\x16pulsefield.protocol.v1\"\xef\x04\n\x08\x45nvelope\x12\x1d\n\nsession_id\x18\x01 \x01(\tR\tsessionId\x12\x1a\n\x08sequence\x18\x02 \x01(\x04R\x08sequence\x12%\n\x0fsent_at_unix_ms\x18\x03 \x01(\x03R\x0csentAtUnixMs\x12<\n\x05ready\x18\n \x01(\x0b\x32$.pulsefield.protocol.v1.ReadyRequestH\x00R\x05ready\x12<\n\x05\x61udio\x18\x0b \x01(\x0b\x32$.pulsefield.protocol.v1.AudioRequestH\x00R\x05\x61udio\x12U\n\x0ereference_time\x18\x0c \x01(\x0b\x32,.pulsefield.protocol.v1.ReferenceTimeRequestH\x00R\rreferenceTime\x12O\n\x0cstop_session\x18\r \x01(\x0b\x32*.pulsefield.protocol.v1.StopSessionRequestH\x00R\x0bstopSession\x12W\n\x10hit_object_token\x18\x14 \x01(\x0b\x32+.pulsefield.protocol.v1.HitObjectTokenEventH\x00R\x0ehitObjectToken\x12:\n\x05\x65rror\x18\x15 \x01(\x0b\x32\".pulsefield.protocol.v1.ErrorEventH\x00R\x05\x65rror\x12=\n\x06status\x18\x16 \x01(\x0b\x32#.pulsefield.protocol.v1.StatusEventH\x00R\x06statusB\t\n\x07payload\"\x0e\n\x0cReadyRequest\"\xa8\x02\n\x0c\x41udioRequest\x12\x1d\n\naudio_path\x18\x01 \x01(\tR\taudioPath\x12+\n\x0f\x61udio_length_ms\x18\x02 \x01(\rH\x00R\raudioLengthMs\x88\x01\x01\x12\x46\n\x0cmusic_source\x18\x03 \x01(\x0e\x32#.pulsefield.protocol.v1.MusicSourceR\x0bmusicSource\x12#\n\ndifficulty\x18\x04 \x01(\x01H\x01R\ndifficulty\x88\x01\x01\x12<\n\x05route\x18\x05 \x01(\x0e\x32&.pulsefield.protocol.v1.InferenceRouteR\x05routeB\x12\n\x10_audio_length_msB\r\n\x0b_difficulty\"\xad\x01\n\x14ReferenceTimeRequest\x12\x1e\n\x0bref_time_ms\x18\x01 \x01(\rR\trefTimeMs\x12\x34\n\x17local_host_time_send_ms\x18\x02 \x01(\x01R\x13localHostTimeSendMs\x12+\n\x0f\x61udio_length_ms\x18\x03 \x01(\rH\x00R\raudioLengthMs\x88\x01\x01\x42\x12\n\x10_audio_length_ms\",\n\x12StopSessionRequest\x12\x16\n\x06reason\x18\x01 \x01(\tR\x06reason\"W\n\x13HitObjectTokenEvent\x12\x19\n\x08token_id\x18\x01 \x01(\rR\x07tokenId\x12%\n\x0fms_in_ref_audio\x18\x02 \x01(\rR\x0cmsInRefAudio\":\n\nErrorEvent\x12\x12\n\x04\x63ode\x18\x01 \x01(\tR\x04\x63ode\x12\x18\n\x07message\x18\x02 \x01(\tR\x07message\"\xb4\x01\n\x0bStatusEvent\x12>\n\x06status\x18\x01 \x01(\x0e\x32&.pulsefield.protocol.v1.EndpointStatusR\x06status\x12\x18\n\x07message\x18\x02 \x01(\tR\x07message\x12\x1e\n\x0bref_time_ms\x18\x03 \x01(\rR\trefTimeMs\x12+\n\x12local_host_time_ms\x18\x04 \x01(\x01R\x0flocalHostTimeMs*g\n\x0bMusicSource\x12\x1c\n\x18MUSIC_SOURCE_UNSPECIFIED\x10\x00\x12\x1b\n\x17MUSIC_SOURCE_BACKGROUND\x10\x01\x12\x1d\n\x19MUSIC_SOURCE_SYSTEM_AUDIO\x10\x02*n\n\x0eInferenceRoute\x12\x1f\n\x1bINFERENCE_ROUTE_UNSPECIFIED\x10\x00\x12\x1a\n\x16INFERENCE_ROUTE_MAPPER\x10\x01\x12\x1f\n\x1bINFERENCE_ROUTE_TIMING_MOCK\x10\x02*\xce\x01\n\x0e\x45ndpointStatus\x12\x1f\n\x1b\x45NDPOINT_STATUS_UNSPECIFIED\x10\x00\x12\x19\n\x15\x45NDPOINT_STATUS_READY\x10\x01\x12#\n\x1f\x45NDPOINT_STATUS_AUDIO_PREPARING\x10\x02\x12\x1f\n\x1b\x45NDPOINT_STATUS_AUDIO_READY\x10\x03\x12\x1d\n\x19\x45NDPOINT_STATUS_STREAMING\x10\x04\x12\x1b\n\x17\x45NDPOINT_STATUS_STOPPED\x10\x05\x62\x06proto3')
20
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n%pulsefield/protocol/v1/envelope.proto\x12\x16pulsefield.protocol.v1\x1a!pulsefield/protocol/v1/core.proto\x1a&pulsefield/protocol/v1/inference.proto\x1a#pulsefield/protocol/v1/mapper.proto\"\xf7\x07\n\x08\x45nvelope\x12\x1d\n\nsession_id\x18\x01 \x01(\tR\tsessionId\x12\x1a\n\x08sequence\x18\x02 \x01(\x04R\x08sequence\x12%\n\x0fsent_at_unix_ms\x18\x03 \x01(\x03R\x0csentAtUnixMs\x12$\n\x0esource_node_id\x18\x04 \x01(\tR\x0csourceNodeId\x12$\n\x0etarget_node_id\x18\x05 \x01(\tR\x0ctargetNodeId\x12\x1d\n\nmessage_id\x18\x06 \x01(\tR\tmessageId\x12%\n\x0e\x63orrelation_id\x18\x07 \x01(\tR\rcorrelationId\x12\x42\n\nnode_hello\x18\x08 \x01(\x0b\x32!.pulsefield.protocol.v1.NodeHelloH\x00R\tnodeHello\x12<\n\x05ready\x18\n \x01(\x0b\x32$.pulsefield.protocol.v1.ReadyRequestH\x00R\x05ready\x12<\n\x05\x61udio\x18\x0b \x01(\x0b\x32$.pulsefield.protocol.v1.AudioRequestH\x00R\x05\x61udio\x12U\n\x0ereference_time\x18\x0c \x01(\x0b\x32,.pulsefield.protocol.v1.ReferenceTimeRequestH\x00R\rreferenceTime\x12O\n\x0cstop_session\x18\r \x01(\x0b\x32*.pulsefield.protocol.v1.StopSessionRequestH\x00R\x0bstopSession\x12`\n\x13mapper_stream_begin\x18\x13 \x01(\x0b\x32..pulsefield.protocol.v1.MapperStreamBeginEventH\x00R\x11mapperStreamBegin\x12W\n\x10hit_object_token\x18\x14 \x01(\x0b\x32+.pulsefield.protocol.v1.HitObjectTokenEventH\x00R\x0ehitObjectToken\x12:\n\x05\x65rror\x18\x15 \x01(\x0b\x32\".pulsefield.protocol.v1.ErrorEventH\x00R\x05\x65rror\x12=\n\x06status\x18\x16 \x01(\x0b\x32#.pulsefield.protocol.v1.StatusEventH\x00R\x06status\x12N\n\rend_of_stream\x18\x17 \x01(\x0b\x32(.pulsefield.protocol.v1.EndOfStreamEventH\x00R\x0b\x65ndOfStreamB\t\n\x07payloadb\x06proto3')
18
21
 
19
22
  _globals = globals()
20
23
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
21
24
  _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'pulsefield.protocol.v1.envelope_pb2', _globals)
22
25
  if not _descriptor._USE_C_DESCRIPTORS:
23
26
  DESCRIPTOR._loaded_options = None
24
- _globals['_MUSICSOURCE']._serialized_start=1560
25
- _globals['_MUSICSOURCE']._serialized_end=1663
26
- _globals['_INFERENCEROUTE']._serialized_start=1665
27
- _globals['_INFERENCEROUTE']._serialized_end=1775
28
- _globals['_ENDPOINTSTATUS']._serialized_start=1778
29
- _globals['_ENDPOINTSTATUS']._serialized_end=1984
30
- _globals['_ENVELOPE']._serialized_start=66
31
- _globals['_ENVELOPE']._serialized_end=689
32
- _globals['_READYREQUEST']._serialized_start=691
33
- _globals['_READYREQUEST']._serialized_end=705
34
- _globals['_AUDIOREQUEST']._serialized_start=708
35
- _globals['_AUDIOREQUEST']._serialized_end=1004
36
- _globals['_REFERENCETIMEREQUEST']._serialized_start=1007
37
- _globals['_REFERENCETIMEREQUEST']._serialized_end=1180
38
- _globals['_STOPSESSIONREQUEST']._serialized_start=1182
39
- _globals['_STOPSESSIONREQUEST']._serialized_end=1226
40
- _globals['_HITOBJECTTOKENEVENT']._serialized_start=1228
41
- _globals['_HITOBJECTTOKENEVENT']._serialized_end=1315
42
- _globals['_ERROREVENT']._serialized_start=1317
43
- _globals['_ERROREVENT']._serialized_end=1375
44
- _globals['_STATUSEVENT']._serialized_start=1378
45
- _globals['_STATUSEVENT']._serialized_end=1558
27
+ _globals['_ENVELOPE']._serialized_start=178
28
+ _globals['_ENVELOPE']._serialized_end=1193
46
29
  # @@protoc_insertion_point(module_scope)
@@ -1,125 +1,46 @@
1
- from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
1
+ from pulsefield.protocol.v1 import core_pb2 as _core_pb2
2
+ from pulsefield.protocol.v1 import inference_pb2 as _inference_pb2
3
+ from pulsefield.protocol.v1 import mapper_pb2 as _mapper_pb2
2
4
  from google.protobuf import descriptor as _descriptor
3
5
  from google.protobuf import message as _message
4
6
  from typing import ClassVar as _ClassVar, Mapping as _Mapping, Optional as _Optional, Union as _Union
5
7
 
6
8
  DESCRIPTOR: _descriptor.FileDescriptor
7
9
 
8
- class MusicSource(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
9
- __slots__ = ()
10
- MUSIC_SOURCE_UNSPECIFIED: _ClassVar[MusicSource]
11
- MUSIC_SOURCE_BACKGROUND: _ClassVar[MusicSource]
12
- MUSIC_SOURCE_SYSTEM_AUDIO: _ClassVar[MusicSource]
13
-
14
- class InferenceRoute(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
15
- __slots__ = ()
16
- INFERENCE_ROUTE_UNSPECIFIED: _ClassVar[InferenceRoute]
17
- INFERENCE_ROUTE_MAPPER: _ClassVar[InferenceRoute]
18
- INFERENCE_ROUTE_TIMING_MOCK: _ClassVar[InferenceRoute]
19
-
20
- class EndpointStatus(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):
21
- __slots__ = ()
22
- ENDPOINT_STATUS_UNSPECIFIED: _ClassVar[EndpointStatus]
23
- ENDPOINT_STATUS_READY: _ClassVar[EndpointStatus]
24
- ENDPOINT_STATUS_AUDIO_PREPARING: _ClassVar[EndpointStatus]
25
- ENDPOINT_STATUS_AUDIO_READY: _ClassVar[EndpointStatus]
26
- ENDPOINT_STATUS_STREAMING: _ClassVar[EndpointStatus]
27
- ENDPOINT_STATUS_STOPPED: _ClassVar[EndpointStatus]
28
- MUSIC_SOURCE_UNSPECIFIED: MusicSource
29
- MUSIC_SOURCE_BACKGROUND: MusicSource
30
- MUSIC_SOURCE_SYSTEM_AUDIO: MusicSource
31
- INFERENCE_ROUTE_UNSPECIFIED: InferenceRoute
32
- INFERENCE_ROUTE_MAPPER: InferenceRoute
33
- INFERENCE_ROUTE_TIMING_MOCK: InferenceRoute
34
- ENDPOINT_STATUS_UNSPECIFIED: EndpointStatus
35
- ENDPOINT_STATUS_READY: EndpointStatus
36
- ENDPOINT_STATUS_AUDIO_PREPARING: EndpointStatus
37
- ENDPOINT_STATUS_AUDIO_READY: EndpointStatus
38
- ENDPOINT_STATUS_STREAMING: EndpointStatus
39
- ENDPOINT_STATUS_STOPPED: EndpointStatus
40
-
41
10
  class Envelope(_message.Message):
42
- __slots__ = ("session_id", "sequence", "sent_at_unix_ms", "ready", "audio", "reference_time", "stop_session", "hit_object_token", "error", "status")
11
+ __slots__ = ("session_id", "sequence", "sent_at_unix_ms", "source_node_id", "target_node_id", "message_id", "correlation_id", "node_hello", "ready", "audio", "reference_time", "stop_session", "mapper_stream_begin", "hit_object_token", "error", "status", "end_of_stream")
43
12
  SESSION_ID_FIELD_NUMBER: _ClassVar[int]
44
13
  SEQUENCE_FIELD_NUMBER: _ClassVar[int]
45
14
  SENT_AT_UNIX_MS_FIELD_NUMBER: _ClassVar[int]
15
+ SOURCE_NODE_ID_FIELD_NUMBER: _ClassVar[int]
16
+ TARGET_NODE_ID_FIELD_NUMBER: _ClassVar[int]
17
+ MESSAGE_ID_FIELD_NUMBER: _ClassVar[int]
18
+ CORRELATION_ID_FIELD_NUMBER: _ClassVar[int]
19
+ NODE_HELLO_FIELD_NUMBER: _ClassVar[int]
46
20
  READY_FIELD_NUMBER: _ClassVar[int]
47
21
  AUDIO_FIELD_NUMBER: _ClassVar[int]
48
22
  REFERENCE_TIME_FIELD_NUMBER: _ClassVar[int]
49
23
  STOP_SESSION_FIELD_NUMBER: _ClassVar[int]
24
+ MAPPER_STREAM_BEGIN_FIELD_NUMBER: _ClassVar[int]
50
25
  HIT_OBJECT_TOKEN_FIELD_NUMBER: _ClassVar[int]
51
26
  ERROR_FIELD_NUMBER: _ClassVar[int]
52
27
  STATUS_FIELD_NUMBER: _ClassVar[int]
28
+ END_OF_STREAM_FIELD_NUMBER: _ClassVar[int]
53
29
  session_id: str
54
30
  sequence: int
55
31
  sent_at_unix_ms: int
56
- ready: ReadyRequest
57
- audio: AudioRequest
58
- reference_time: ReferenceTimeRequest
59
- stop_session: StopSessionRequest
60
- hit_object_token: HitObjectTokenEvent
61
- error: ErrorEvent
62
- status: StatusEvent
63
- def __init__(self, session_id: _Optional[str] = ..., sequence: _Optional[int] = ..., sent_at_unix_ms: _Optional[int] = ..., ready: _Optional[_Union[ReadyRequest, _Mapping]] = ..., audio: _Optional[_Union[AudioRequest, _Mapping]] = ..., reference_time: _Optional[_Union[ReferenceTimeRequest, _Mapping]] = ..., stop_session: _Optional[_Union[StopSessionRequest, _Mapping]] = ..., hit_object_token: _Optional[_Union[HitObjectTokenEvent, _Mapping]] = ..., error: _Optional[_Union[ErrorEvent, _Mapping]] = ..., status: _Optional[_Union[StatusEvent, _Mapping]] = ...) -> None: ...
64
-
65
- class ReadyRequest(_message.Message):
66
- __slots__ = ()
67
- def __init__(self) -> None: ...
68
-
69
- class AudioRequest(_message.Message):
70
- __slots__ = ("audio_path", "audio_length_ms", "music_source", "difficulty", "route")
71
- AUDIO_PATH_FIELD_NUMBER: _ClassVar[int]
72
- AUDIO_LENGTH_MS_FIELD_NUMBER: _ClassVar[int]
73
- MUSIC_SOURCE_FIELD_NUMBER: _ClassVar[int]
74
- DIFFICULTY_FIELD_NUMBER: _ClassVar[int]
75
- ROUTE_FIELD_NUMBER: _ClassVar[int]
76
- audio_path: str
77
- audio_length_ms: int
78
- music_source: MusicSource
79
- difficulty: float
80
- route: InferenceRoute
81
- def __init__(self, audio_path: _Optional[str] = ..., audio_length_ms: _Optional[int] = ..., music_source: _Optional[_Union[MusicSource, str]] = ..., difficulty: _Optional[float] = ..., route: _Optional[_Union[InferenceRoute, str]] = ...) -> None: ...
82
-
83
- class ReferenceTimeRequest(_message.Message):
84
- __slots__ = ("ref_time_ms", "local_host_time_send_ms", "audio_length_ms")
85
- REF_TIME_MS_FIELD_NUMBER: _ClassVar[int]
86
- LOCAL_HOST_TIME_SEND_MS_FIELD_NUMBER: _ClassVar[int]
87
- AUDIO_LENGTH_MS_FIELD_NUMBER: _ClassVar[int]
88
- ref_time_ms: int
89
- local_host_time_send_ms: float
90
- audio_length_ms: int
91
- def __init__(self, ref_time_ms: _Optional[int] = ..., local_host_time_send_ms: _Optional[float] = ..., audio_length_ms: _Optional[int] = ...) -> None: ...
92
-
93
- class StopSessionRequest(_message.Message):
94
- __slots__ = ("reason",)
95
- REASON_FIELD_NUMBER: _ClassVar[int]
96
- reason: str
97
- def __init__(self, reason: _Optional[str] = ...) -> None: ...
98
-
99
- class HitObjectTokenEvent(_message.Message):
100
- __slots__ = ("token_id", "ms_in_ref_audio")
101
- TOKEN_ID_FIELD_NUMBER: _ClassVar[int]
102
- MS_IN_REF_AUDIO_FIELD_NUMBER: _ClassVar[int]
103
- token_id: int
104
- ms_in_ref_audio: int
105
- def __init__(self, token_id: _Optional[int] = ..., ms_in_ref_audio: _Optional[int] = ...) -> None: ...
106
-
107
- class ErrorEvent(_message.Message):
108
- __slots__ = ("code", "message")
109
- CODE_FIELD_NUMBER: _ClassVar[int]
110
- MESSAGE_FIELD_NUMBER: _ClassVar[int]
111
- code: str
112
- message: str
113
- def __init__(self, code: _Optional[str] = ..., message: _Optional[str] = ...) -> None: ...
114
-
115
- class StatusEvent(_message.Message):
116
- __slots__ = ("status", "message", "ref_time_ms", "local_host_time_ms")
117
- STATUS_FIELD_NUMBER: _ClassVar[int]
118
- MESSAGE_FIELD_NUMBER: _ClassVar[int]
119
- REF_TIME_MS_FIELD_NUMBER: _ClassVar[int]
120
- LOCAL_HOST_TIME_MS_FIELD_NUMBER: _ClassVar[int]
121
- status: EndpointStatus
122
- message: str
123
- ref_time_ms: int
124
- local_host_time_ms: float
125
- def __init__(self, status: _Optional[_Union[EndpointStatus, str]] = ..., message: _Optional[str] = ..., ref_time_ms: _Optional[int] = ..., local_host_time_ms: _Optional[float] = ...) -> None: ...
32
+ source_node_id: str
33
+ target_node_id: str
34
+ message_id: str
35
+ correlation_id: str
36
+ node_hello: _core_pb2.NodeHello
37
+ ready: _inference_pb2.ReadyRequest
38
+ audio: _inference_pb2.AudioRequest
39
+ reference_time: _inference_pb2.ReferenceTimeRequest
40
+ stop_session: _inference_pb2.StopSessionRequest
41
+ mapper_stream_begin: _mapper_pb2.MapperStreamBeginEvent
42
+ hit_object_token: _mapper_pb2.HitObjectTokenEvent
43
+ error: _inference_pb2.ErrorEvent
44
+ status: _inference_pb2.StatusEvent
45
+ end_of_stream: _inference_pb2.EndOfStreamEvent
46
+ def __init__(self, session_id: _Optional[str] = ..., sequence: _Optional[int] = ..., sent_at_unix_ms: _Optional[int] = ..., source_node_id: _Optional[str] = ..., target_node_id: _Optional[str] = ..., message_id: _Optional[str] = ..., correlation_id: _Optional[str] = ..., node_hello: _Optional[_Union[_core_pb2.NodeHello, _Mapping]] = ..., ready: _Optional[_Union[_inference_pb2.ReadyRequest, _Mapping]] = ..., audio: _Optional[_Union[_inference_pb2.AudioRequest, _Mapping]] = ..., reference_time: _Optional[_Union[_inference_pb2.ReferenceTimeRequest, _Mapping]] = ..., stop_session: _Optional[_Union[_inference_pb2.StopSessionRequest, _Mapping]] = ..., mapper_stream_begin: _Optional[_Union[_mapper_pb2.MapperStreamBeginEvent, _Mapping]] = ..., hit_object_token: _Optional[_Union[_mapper_pb2.HitObjectTokenEvent, _Mapping]] = ..., error: _Optional[_Union[_inference_pb2.ErrorEvent, _Mapping]] = ..., status: _Optional[_Union[_inference_pb2.StatusEvent, _Mapping]] = ..., end_of_stream: _Optional[_Union[_inference_pb2.EndOfStreamEvent, _Mapping]] = ...) -> None: ...