tywrap 0.2.0 → 0.3.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.
Files changed (163) hide show
  1. package/README.md +65 -31
  2. package/dist/cli.js +49 -2
  3. package/dist/cli.js.map +1 -1
  4. package/dist/config/index.d.ts +11 -7
  5. package/dist/config/index.d.ts.map +1 -1
  6. package/dist/config/index.js +43 -7
  7. package/dist/config/index.js.map +1 -1
  8. package/dist/core/analyzer.d.ts +1 -0
  9. package/dist/core/analyzer.d.ts.map +1 -1
  10. package/dist/core/analyzer.js +47 -12
  11. package/dist/core/analyzer.js.map +1 -1
  12. package/dist/core/annotation-parser.d.ts +8 -0
  13. package/dist/core/annotation-parser.d.ts.map +1 -0
  14. package/dist/core/annotation-parser.js +409 -0
  15. package/dist/core/annotation-parser.js.map +1 -0
  16. package/dist/core/discovery.d.ts +1 -0
  17. package/dist/core/discovery.d.ts.map +1 -1
  18. package/dist/core/discovery.js +9 -9
  19. package/dist/core/discovery.js.map +1 -1
  20. package/dist/core/generator.d.ts +9 -1
  21. package/dist/core/generator.d.ts.map +1 -1
  22. package/dist/core/generator.js +738 -104
  23. package/dist/core/generator.js.map +1 -1
  24. package/dist/core/mapper.d.ts +9 -7
  25. package/dist/core/mapper.d.ts.map +1 -1
  26. package/dist/core/mapper.js +129 -44
  27. package/dist/core/mapper.js.map +1 -1
  28. package/dist/index.d.ts +23 -7
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +23 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/runtime/base.d.ts +17 -7
  33. package/dist/runtime/base.d.ts.map +1 -1
  34. package/dist/runtime/base.js +18 -1
  35. package/dist/runtime/base.js.map +1 -1
  36. package/dist/runtime/bounded-context.d.ts +252 -0
  37. package/dist/runtime/bounded-context.d.ts.map +1 -0
  38. package/dist/runtime/bounded-context.js +454 -0
  39. package/dist/runtime/bounded-context.js.map +1 -0
  40. package/dist/runtime/bridge-core.d.ts +1 -0
  41. package/dist/runtime/bridge-core.d.ts.map +1 -1
  42. package/dist/runtime/bridge-core.js +52 -17
  43. package/dist/runtime/bridge-core.js.map +1 -1
  44. package/dist/runtime/bridge-protocol.d.ts +184 -0
  45. package/dist/runtime/bridge-protocol.d.ts.map +1 -0
  46. package/dist/runtime/bridge-protocol.js +344 -0
  47. package/dist/runtime/bridge-protocol.js.map +1 -0
  48. package/dist/runtime/disposable.d.ts +40 -0
  49. package/dist/runtime/disposable.d.ts.map +1 -0
  50. package/dist/runtime/disposable.js +49 -0
  51. package/dist/runtime/disposable.js.map +1 -0
  52. package/dist/runtime/errors.d.ts +10 -0
  53. package/dist/runtime/errors.d.ts.map +1 -1
  54. package/dist/runtime/errors.js +9 -0
  55. package/dist/runtime/errors.js.map +1 -1
  56. package/dist/runtime/http-io.d.ts +91 -0
  57. package/dist/runtime/http-io.d.ts.map +1 -0
  58. package/dist/runtime/http-io.js +195 -0
  59. package/dist/runtime/http-io.js.map +1 -0
  60. package/dist/runtime/http.d.ts +48 -13
  61. package/dist/runtime/http.d.ts.map +1 -1
  62. package/dist/runtime/http.js +60 -73
  63. package/dist/runtime/http.js.map +1 -1
  64. package/dist/runtime/node.d.ts +97 -130
  65. package/dist/runtime/node.d.ts.map +1 -1
  66. package/dist/runtime/node.js +392 -521
  67. package/dist/runtime/node.js.map +1 -1
  68. package/dist/runtime/optimized-node.d.ts +1 -1
  69. package/dist/runtime/optimized-node.d.ts.map +1 -1
  70. package/dist/runtime/optimized-node.js +1 -1
  71. package/dist/runtime/optimized-node.js.map +1 -1
  72. package/dist/runtime/pooled-transport.d.ts +135 -0
  73. package/dist/runtime/pooled-transport.d.ts.map +1 -0
  74. package/dist/runtime/pooled-transport.js +177 -0
  75. package/dist/runtime/pooled-transport.js.map +1 -0
  76. package/dist/runtime/process-io.d.ts +209 -0
  77. package/dist/runtime/process-io.d.ts.map +1 -0
  78. package/dist/runtime/process-io.js +729 -0
  79. package/dist/runtime/process-io.js.map +1 -0
  80. package/dist/runtime/pyodide-io.d.ts +154 -0
  81. package/dist/runtime/pyodide-io.d.ts.map +1 -0
  82. package/dist/runtime/pyodide-io.js +459 -0
  83. package/dist/runtime/pyodide-io.js.map +1 -0
  84. package/dist/runtime/pyodide.d.ts +51 -19
  85. package/dist/runtime/pyodide.d.ts.map +1 -1
  86. package/dist/runtime/pyodide.js +57 -186
  87. package/dist/runtime/pyodide.js.map +1 -1
  88. package/dist/runtime/safe-codec.d.ts +103 -0
  89. package/dist/runtime/safe-codec.d.ts.map +1 -0
  90. package/dist/runtime/safe-codec.js +519 -0
  91. package/dist/runtime/safe-codec.js.map +1 -0
  92. package/dist/runtime/transport.d.ts +191 -0
  93. package/dist/runtime/transport.d.ts.map +1 -0
  94. package/dist/runtime/transport.js +86 -0
  95. package/dist/runtime/transport.js.map +1 -0
  96. package/dist/runtime/validators.d.ts +120 -0
  97. package/dist/runtime/validators.d.ts.map +1 -0
  98. package/dist/runtime/validators.js +229 -0
  99. package/dist/runtime/validators.js.map +1 -0
  100. package/dist/runtime/worker-pool.d.ts +208 -0
  101. package/dist/runtime/worker-pool.d.ts.map +1 -0
  102. package/dist/runtime/worker-pool.js +419 -0
  103. package/dist/runtime/worker-pool.js.map +1 -0
  104. package/dist/types/index.d.ts +51 -1
  105. package/dist/types/index.d.ts.map +1 -1
  106. package/dist/tywrap.d.ts.map +1 -1
  107. package/dist/tywrap.js +227 -328
  108. package/dist/tywrap.js.map +1 -1
  109. package/dist/utils/cache.d.ts.map +1 -1
  110. package/dist/utils/cache.js +53 -5
  111. package/dist/utils/cache.js.map +1 -1
  112. package/dist/utils/codec.d.ts.map +1 -1
  113. package/dist/utils/codec.js +114 -1
  114. package/dist/utils/codec.js.map +1 -1
  115. package/dist/utils/ir-cache.d.ts +28 -0
  116. package/dist/utils/ir-cache.d.ts.map +1 -0
  117. package/dist/utils/ir-cache.js +29 -0
  118. package/dist/utils/ir-cache.js.map +1 -0
  119. package/dist/utils/parallel-processor.d.ts +1 -1
  120. package/dist/utils/parallel-processor.d.ts.map +1 -1
  121. package/dist/utils/parallel-processor.js +111 -40
  122. package/dist/utils/parallel-processor.js.map +1 -1
  123. package/dist/utils/runtime.d.ts +5 -1
  124. package/dist/utils/runtime.d.ts.map +1 -1
  125. package/dist/utils/runtime.js +112 -18
  126. package/dist/utils/runtime.js.map +1 -1
  127. package/package.json +40 -18
  128. package/runtime/python_bridge.py +108 -15
  129. package/runtime/safe_codec.py +344 -0
  130. package/src/cli.ts +61 -2
  131. package/src/config/index.ts +63 -17
  132. package/src/core/analyzer.ts +52 -15
  133. package/src/core/annotation-parser.ts +500 -0
  134. package/src/core/discovery.ts +26 -12
  135. package/src/core/generator.ts +956 -116
  136. package/src/core/mapper.ts +158 -51
  137. package/src/index.ts +78 -6
  138. package/src/runtime/base.ts +18 -26
  139. package/src/runtime/bounded-context.ts +608 -0
  140. package/src/runtime/bridge-core.ts +58 -18
  141. package/src/runtime/bridge-protocol.ts +483 -0
  142. package/src/runtime/disposable.ts +65 -0
  143. package/src/runtime/errors.ts +14 -0
  144. package/src/runtime/http-io.ts +245 -0
  145. package/src/runtime/http.ts +76 -115
  146. package/src/runtime/node.ts +563 -676
  147. package/src/runtime/optimized-node.ts +4 -1
  148. package/src/runtime/pooled-transport.ts +263 -0
  149. package/src/runtime/process-io.ts +930 -0
  150. package/src/runtime/pyodide-io.ts +551 -0
  151. package/src/runtime/pyodide.ts +75 -215
  152. package/src/runtime/safe-codec.ts +651 -0
  153. package/src/runtime/transport.ts +278 -0
  154. package/src/runtime/validators.ts +252 -0
  155. package/src/runtime/worker-pool.ts +559 -0
  156. package/src/types/global.d.ts +11 -1
  157. package/src/types/index.ts +63 -0
  158. package/src/tywrap.ts +279 -358
  159. package/src/utils/cache.ts +59 -5
  160. package/src/utils/codec.ts +122 -1
  161. package/src/utils/ir-cache.ts +51 -0
  162. package/src/utils/parallel-processor.ts +119 -43
  163. package/src/utils/runtime.ts +129 -18
@@ -0,0 +1,184 @@
1
+ /**
2
+ * BridgeProtocol - Unified abstraction for JS<->Python communication.
3
+ *
4
+ * Combines BoundedContext + SafeCodec + Transport into a single base class
5
+ * that handles all cross-boundary concerns:
6
+ * - Lifecycle management (init/dispose state machine)
7
+ * - Request/response encoding with validation
8
+ * - Transport-agnostic message passing
9
+ * - Bounded execution (timeout, retry, abort)
10
+ *
11
+ * Subclasses (NodeBridge, HttpBridge, PyodideBridge) only need to:
12
+ * 1. Create their transport in their constructor
13
+ * 2. Pass it to super() via BridgeProtocolOptions
14
+ * 3. Optionally override doInit() and doDispose() for additional setup/teardown
15
+ *
16
+ * @see https://github.com/bbopen/tywrap/issues/149
17
+ */
18
+ import type { BridgeInfo } from '../types/index.js';
19
+ import { BoundedContext, type ExecuteOptions } from './bounded-context.js';
20
+ import { SafeCodec, type CodecOptions } from './safe-codec.js';
21
+ import { type Transport, type ProtocolMessage } from './transport.js';
22
+ export interface GetBridgeInfoOptions {
23
+ /**
24
+ * If true, bypasses the cached info and queries the bridge again.
25
+ * This is useful when you want up-to-date instance counts or diagnostics.
26
+ */
27
+ refresh?: boolean;
28
+ }
29
+ /**
30
+ * Configuration options for BridgeProtocol.
31
+ */
32
+ export interface BridgeProtocolOptions {
33
+ /** The transport to use for communication */
34
+ transport: Transport;
35
+ /** Codec options for validation/serialization */
36
+ codec?: CodecOptions;
37
+ /** Default timeout for operations in ms. Default: 30000 (30s) */
38
+ defaultTimeoutMs?: number;
39
+ }
40
+ /**
41
+ * BridgeProtocol combines BoundedContext + SafeCodec + Transport
42
+ * into a unified abstraction for all JS<->Python communication.
43
+ *
44
+ * This class provides:
45
+ * - Automatic transport lifecycle management
46
+ * - Request encoding with guardrails (special float rejection, key validation)
47
+ * - Response decoding with Arrow support
48
+ * - Full RuntimeExecution interface implementation
49
+ *
50
+ * Subclasses should:
51
+ * 1. Create their transport in their constructor
52
+ * 2. Pass it to super() via BridgeProtocolOptions
53
+ * 3. Optionally override doInit() and doDispose() for additional setup/teardown
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * class NodeBridge extends BridgeProtocol {
58
+ * constructor(options: NodeBridgeOptions) {
59
+ * const transport = new ProcessIO(options);
60
+ * super({ transport, defaultTimeoutMs: options.timeout });
61
+ * }
62
+ * }
63
+ * ```
64
+ */
65
+ export declare class BridgeProtocol extends BoundedContext {
66
+ /** Codec instance for validation and serialization */
67
+ protected readonly codec: SafeCodec;
68
+ /** Transport instance for message passing */
69
+ protected readonly transport: Transport;
70
+ /** Default timeout for operations in milliseconds */
71
+ protected readonly defaultTimeoutMs: number;
72
+ /** Counter for generating unique request IDs */
73
+ private requestId;
74
+ /** Cached bridge diagnostics info (populated by getBridgeInfo). */
75
+ private bridgeInfoCache?;
76
+ /**
77
+ * Create a new BridgeProtocol instance.
78
+ *
79
+ * @param options - Configuration options including transport and codec settings
80
+ */
81
+ constructor(options: BridgeProtocolOptions);
82
+ /**
83
+ * Initialize the protocol.
84
+ *
85
+ * Initializes the underlying transport. Subclasses can override this
86
+ * to add additional initialization logic, but must call super.doInit().
87
+ */
88
+ protected doInit(): Promise<void>;
89
+ /**
90
+ * Dispose the protocol.
91
+ *
92
+ * The transport is tracked as a resource and will be disposed automatically
93
+ * by BoundedContext. Subclasses can override this to add additional cleanup,
94
+ * but should not need to dispose the transport manually.
95
+ */
96
+ protected doDispose(): Promise<void>;
97
+ /**
98
+ * Send a protocol message and receive a typed response.
99
+ *
100
+ * This method:
101
+ * 1. Generates a unique request ID
102
+ * 2. Encodes the request with validation (special float rejection, etc.)
103
+ * 3. Sends via transport with timeout/abort support
104
+ * 4. Decodes and validates the response
105
+ *
106
+ * @param message - The protocol message (without id field)
107
+ * @param options - Execution options (timeout, retries, validation)
108
+ * @returns The typed response from Python
109
+ *
110
+ * @throws BridgeProtocolError if encoding/decoding fails
111
+ * @throws BridgeExecutionError if Python returns an error
112
+ * @throws BridgeTimeoutError if the operation times out
113
+ */
114
+ protected sendMessage<T>(message: Omit<ProtocolMessage, 'id' | 'protocol'>, options?: ExecuteOptions<T>): Promise<T>;
115
+ /**
116
+ * Async version that uses decodeResponseAsync for Arrow support.
117
+ *
118
+ * Use this method when the response may contain encoded DataFrames,
119
+ * ndarrays, or other Arrow-encoded data structures.
120
+ *
121
+ * @param message - The protocol message (without id field)
122
+ * @param options - Execution options (timeout, retries, validation)
123
+ * @returns The typed response from Python with Arrow decoding applied
124
+ *
125
+ * @throws BridgeProtocolError if encoding/decoding fails
126
+ * @throws BridgeExecutionError if Python returns an error
127
+ * @throws BridgeTimeoutError if the operation times out
128
+ */
129
+ protected sendMessageAsync<T>(message: Omit<ProtocolMessage, 'id' | 'protocol'>, options?: ExecuteOptions<T>): Promise<T>;
130
+ /**
131
+ * Generate a unique request ID.
132
+ *
133
+ * Returns a monotonically increasing integer that ensures uniqueness
134
+ * within a process lifetime.
135
+ */
136
+ private generateId;
137
+ /**
138
+ * Call a Python function.
139
+ *
140
+ * @param module - Python module path (e.g., 'numpy', 'mypackage.submodule')
141
+ * @param functionName - Function name to call
142
+ * @param args - Positional arguments
143
+ * @param kwargs - Keyword arguments
144
+ * @returns The function result
145
+ */
146
+ call<T = unknown>(module: string, functionName: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
147
+ /**
148
+ * Instantiate a Python class.
149
+ *
150
+ * @param module - Python module path containing the class
151
+ * @param className - Class name to instantiate
152
+ * @param args - Positional constructor arguments
153
+ * @param kwargs - Keyword constructor arguments
154
+ * @returns A handle to the created instance
155
+ */
156
+ instantiate<T = unknown>(module: string, className: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
157
+ /**
158
+ * Call a method on a Python instance.
159
+ *
160
+ * @param handle - Instance handle returned from instantiate()
161
+ * @param methodName - Method name to call
162
+ * @param args - Positional arguments
163
+ * @param kwargs - Keyword arguments
164
+ * @returns The method result
165
+ */
166
+ callMethod<T = unknown>(handle: string, methodName: string, args: unknown[], kwargs?: Record<string, unknown>): Promise<T>;
167
+ /**
168
+ * Dispose a Python instance.
169
+ *
170
+ * Releases the instance handle on the Python side, allowing
171
+ * the object to be garbage collected.
172
+ *
173
+ * @param handle - Instance handle to dispose
174
+ */
175
+ disposeInstance(handle: string): Promise<void>;
176
+ /**
177
+ * Fetch bridge diagnostics and feature availability.
178
+ *
179
+ * The Python bridge supports a `meta` method that returns protocol and environment info
180
+ * (including optional codec availability and current instance count).
181
+ */
182
+ getBridgeInfo(options?: GetBridgeInfoOptions): Promise<BridgeInfo>;
183
+ }
184
+ //# sourceMappingURL=bridge-protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-protocol.d.ts","sourceRoot":"","sources":["../../src/runtime/bridge-protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3E,OAAO,EAAE,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EAAe,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAMnF,MAAM,WAAW,oBAAoB;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,6CAA6C;IAC7C,SAAS,EAAE,SAAS,CAAC;IAErB,iDAAiD;IACjD,KAAK,CAAC,EAAE,YAAY,CAAC;IAErB,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAiID;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,cAAe,SAAQ,cAAc;IAChD,sDAAsD;IACtD,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAEpC,6CAA6C;IAC7C,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAExC,qDAAqD;IACrD,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAE5C,gDAAgD;IAChD,OAAO,CAAC,SAAS,CAAK;IAEtB,mEAAmE;IACnE,OAAO,CAAC,eAAe,CAAC,CAAa;IAErC;;;;OAIG;gBACS,OAAO,EAAE,qBAAqB;IAc1C;;;;;OAKG;cACa,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAIvC;;;;;;OAMG;cACa,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAU1C;;;;;;;;;;;;;;;;OAgBG;cACa,WAAW,CAAC,CAAC,EAC3B,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,UAAU,CAAC,EACjD,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,CAAC,CAAC;IAuBb;;;;;;;;;;;;;OAaG;cACa,gBAAgB,CAAC,CAAC,EAChC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,IAAI,GAAG,UAAU,CAAC,EACjD,OAAO,CAAC,EAAE,cAAc,CAAC,CAAC,CAAC,GAC1B,OAAO,CAAC,CAAC,CAAC;IAuBb;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAQlB;;;;;;;;OAQG;IACG,IAAI,CAAC,CAAC,GAAG,OAAO,EACpB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,OAAO,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAYb;;;;;;;;OAQG;IACG,WAAW,CAAC,CAAC,GAAG,OAAO,EAC3B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,OAAO,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAYb;;;;;;;;OAQG;IACG,UAAU,CAAC,CAAC,GAAG,OAAO,EAC1B,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,EAAE,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC;IAYb;;;;;;;OAOG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASpD;;;;;OAKG;IACG,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,UAAU,CAAC;CAkB7E"}
@@ -0,0 +1,344 @@
1
+ /**
2
+ * BridgeProtocol - Unified abstraction for JS<->Python communication.
3
+ *
4
+ * Combines BoundedContext + SafeCodec + Transport into a single base class
5
+ * that handles all cross-boundary concerns:
6
+ * - Lifecycle management (init/dispose state machine)
7
+ * - Request/response encoding with validation
8
+ * - Transport-agnostic message passing
9
+ * - Bounded execution (timeout, retry, abort)
10
+ *
11
+ * Subclasses (NodeBridge, HttpBridge, PyodideBridge) only need to:
12
+ * 1. Create their transport in their constructor
13
+ * 2. Pass it to super() via BridgeProtocolOptions
14
+ * 3. Optionally override doInit() and doDispose() for additional setup/teardown
15
+ *
16
+ * @see https://github.com/bbopen/tywrap/issues/149
17
+ */
18
+ import { BoundedContext } from './bounded-context.js';
19
+ import { BridgeProtocolError } from './errors.js';
20
+ import { SafeCodec } from './safe-codec.js';
21
+ import { TYWRAP_PROTOCOL_VERSION } from './protocol.js';
22
+ import { PROTOCOL_ID } from './transport.js';
23
+ function validateBridgeInfoPayload(value) {
24
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
25
+ const kind = value === null ? 'null' : Array.isArray(value) ? 'array' : typeof value;
26
+ throw new BridgeProtocolError(`Invalid bridge info payload: expected object, got ${kind}`);
27
+ }
28
+ const formatValue = (val) => {
29
+ try {
30
+ const serialized = JSON.stringify(val);
31
+ return serialized ?? String(val);
32
+ }
33
+ catch {
34
+ return String(val);
35
+ }
36
+ };
37
+ const obj = value;
38
+ const protocol = obj.protocol;
39
+ if (protocol !== PROTOCOL_ID) {
40
+ throw new BridgeProtocolError(`Invalid bridge info payload: protocol expected "${PROTOCOL_ID}", got ${formatValue(protocol)}`);
41
+ }
42
+ const protocolVersion = obj.protocolVersion;
43
+ if (protocolVersion !== TYWRAP_PROTOCOL_VERSION) {
44
+ throw new BridgeProtocolError(`Invalid bridge info payload: protocolVersion expected ${TYWRAP_PROTOCOL_VERSION}, got ${formatValue(protocolVersion)}`);
45
+ }
46
+ const bridge = obj.bridge;
47
+ if (bridge !== 'python-subprocess') {
48
+ throw new BridgeProtocolError(`Invalid bridge info payload: bridge expected "python-subprocess", got ${formatValue(bridge)}`);
49
+ }
50
+ const pythonVersion = obj.pythonVersion;
51
+ if (typeof pythonVersion !== 'string' || pythonVersion.length === 0) {
52
+ throw new BridgeProtocolError(`Invalid bridge info payload: pythonVersion expected non-empty string, got ${formatValue(pythonVersion)}`);
53
+ }
54
+ const pid = obj.pid;
55
+ if (typeof pid !== 'number' || !Number.isInteger(pid) || pid <= 0) {
56
+ throw new BridgeProtocolError(`Invalid bridge info payload: pid expected positive integer, got ${formatValue(pid)}`);
57
+ }
58
+ const codecFallback = obj.codecFallback;
59
+ if (codecFallback !== 'json' && codecFallback !== 'none') {
60
+ throw new BridgeProtocolError(`Invalid bridge info payload: codecFallback expected "json" or "none", got ${formatValue(codecFallback)}`);
61
+ }
62
+ const arrowAvailable = obj.arrowAvailable;
63
+ if (typeof arrowAvailable !== 'boolean') {
64
+ throw new BridgeProtocolError(`Invalid bridge info payload: arrowAvailable expected boolean, got ${formatValue(arrowAvailable)}`);
65
+ }
66
+ const scipyAvailable = obj.scipyAvailable;
67
+ if (typeof scipyAvailable !== 'boolean') {
68
+ throw new BridgeProtocolError(`Invalid bridge info payload: scipyAvailable expected boolean, got ${formatValue(scipyAvailable)}`);
69
+ }
70
+ const torchAvailable = obj.torchAvailable;
71
+ if (typeof torchAvailable !== 'boolean') {
72
+ throw new BridgeProtocolError(`Invalid bridge info payload: torchAvailable expected boolean, got ${formatValue(torchAvailable)}`);
73
+ }
74
+ const sklearnAvailable = obj.sklearnAvailable;
75
+ if (typeof sklearnAvailable !== 'boolean') {
76
+ throw new BridgeProtocolError(`Invalid bridge info payload: sklearnAvailable expected boolean, got ${formatValue(sklearnAvailable)}`);
77
+ }
78
+ const instances = obj.instances;
79
+ if (typeof instances !== 'number' || !Number.isInteger(instances) || instances < 0) {
80
+ throw new BridgeProtocolError(`Invalid bridge info payload: instances expected non-negative integer, got ${formatValue(instances)}`);
81
+ }
82
+ return {
83
+ protocol: PROTOCOL_ID,
84
+ protocolVersion: TYWRAP_PROTOCOL_VERSION,
85
+ bridge: 'python-subprocess',
86
+ pythonVersion,
87
+ pid,
88
+ codecFallback,
89
+ arrowAvailable,
90
+ scipyAvailable,
91
+ torchAvailable,
92
+ sklearnAvailable,
93
+ instances,
94
+ };
95
+ }
96
+ // =============================================================================
97
+ // BRIDGE PROTOCOL BASE CLASS
98
+ // =============================================================================
99
+ /**
100
+ * BridgeProtocol combines BoundedContext + SafeCodec + Transport
101
+ * into a unified abstraction for all JS<->Python communication.
102
+ *
103
+ * This class provides:
104
+ * - Automatic transport lifecycle management
105
+ * - Request encoding with guardrails (special float rejection, key validation)
106
+ * - Response decoding with Arrow support
107
+ * - Full RuntimeExecution interface implementation
108
+ *
109
+ * Subclasses should:
110
+ * 1. Create their transport in their constructor
111
+ * 2. Pass it to super() via BridgeProtocolOptions
112
+ * 3. Optionally override doInit() and doDispose() for additional setup/teardown
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * class NodeBridge extends BridgeProtocol {
117
+ * constructor(options: NodeBridgeOptions) {
118
+ * const transport = new ProcessIO(options);
119
+ * super({ transport, defaultTimeoutMs: options.timeout });
120
+ * }
121
+ * }
122
+ * ```
123
+ */
124
+ export class BridgeProtocol extends BoundedContext {
125
+ /** Codec instance for validation and serialization */
126
+ codec;
127
+ /** Transport instance for message passing */
128
+ transport;
129
+ /** Default timeout for operations in milliseconds */
130
+ defaultTimeoutMs;
131
+ /** Counter for generating unique request IDs */
132
+ requestId = 0;
133
+ /** Cached bridge diagnostics info (populated by getBridgeInfo). */
134
+ bridgeInfoCache;
135
+ /**
136
+ * Create a new BridgeProtocol instance.
137
+ *
138
+ * @param options - Configuration options including transport and codec settings
139
+ */
140
+ constructor(options) {
141
+ super();
142
+ this.codec = new SafeCodec(options.codec);
143
+ this.transport = options.transport;
144
+ this.defaultTimeoutMs = options.defaultTimeoutMs ?? 30000;
145
+ // Track the transport for automatic cleanup during dispose
146
+ this.trackResource(this.transport);
147
+ }
148
+ // ===========================================================================
149
+ // LIFECYCLE
150
+ // ===========================================================================
151
+ /**
152
+ * Initialize the protocol.
153
+ *
154
+ * Initializes the underlying transport. Subclasses can override this
155
+ * to add additional initialization logic, but must call super.doInit().
156
+ */
157
+ async doInit() {
158
+ await this.transport.init();
159
+ }
160
+ /**
161
+ * Dispose the protocol.
162
+ *
163
+ * The transport is tracked as a resource and will be disposed automatically
164
+ * by BoundedContext. Subclasses can override this to add additional cleanup,
165
+ * but should not need to dispose the transport manually.
166
+ */
167
+ async doDispose() {
168
+ this.bridgeInfoCache = undefined;
169
+ // Transport is tracked and will be disposed by BoundedContext
170
+ // Subclasses can override to add additional cleanup
171
+ }
172
+ // ===========================================================================
173
+ // MESSAGE SENDING
174
+ // ===========================================================================
175
+ /**
176
+ * Send a protocol message and receive a typed response.
177
+ *
178
+ * This method:
179
+ * 1. Generates a unique request ID
180
+ * 2. Encodes the request with validation (special float rejection, etc.)
181
+ * 3. Sends via transport with timeout/abort support
182
+ * 4. Decodes and validates the response
183
+ *
184
+ * @param message - The protocol message (without id field)
185
+ * @param options - Execution options (timeout, retries, validation)
186
+ * @returns The typed response from Python
187
+ *
188
+ * @throws BridgeProtocolError if encoding/decoding fails
189
+ * @throws BridgeExecutionError if Python returns an error
190
+ * @throws BridgeTimeoutError if the operation times out
191
+ */
192
+ async sendMessage(message, options) {
193
+ const fullMessage = {
194
+ ...message,
195
+ id: this.generateId(),
196
+ protocol: PROTOCOL_ID,
197
+ };
198
+ return this.execute(async () => {
199
+ // 1. Encode request (validates args)
200
+ const encoded = this.codec.encodeRequest(fullMessage);
201
+ // 2. Send via transport
202
+ const responseStr = await this.transport.send(encoded, options?.timeoutMs ?? this.defaultTimeoutMs, options?.signal);
203
+ // 3. Decode response (validates result)
204
+ return this.codec.decodeResponse(responseStr);
205
+ }, options);
206
+ }
207
+ /**
208
+ * Async version that uses decodeResponseAsync for Arrow support.
209
+ *
210
+ * Use this method when the response may contain encoded DataFrames,
211
+ * ndarrays, or other Arrow-encoded data structures.
212
+ *
213
+ * @param message - The protocol message (without id field)
214
+ * @param options - Execution options (timeout, retries, validation)
215
+ * @returns The typed response from Python with Arrow decoding applied
216
+ *
217
+ * @throws BridgeProtocolError if encoding/decoding fails
218
+ * @throws BridgeExecutionError if Python returns an error
219
+ * @throws BridgeTimeoutError if the operation times out
220
+ */
221
+ async sendMessageAsync(message, options) {
222
+ const fullMessage = {
223
+ ...message,
224
+ id: this.generateId(),
225
+ protocol: PROTOCOL_ID,
226
+ };
227
+ return this.execute(async () => {
228
+ // 1. Encode request (validates args)
229
+ const encoded = this.codec.encodeRequest(fullMessage);
230
+ // 2. Send via transport
231
+ const responseStr = await this.transport.send(encoded, options?.timeoutMs ?? this.defaultTimeoutMs, options?.signal);
232
+ // 3. Decode response with Arrow support
233
+ return this.codec.decodeResponseAsync(responseStr);
234
+ }, options);
235
+ }
236
+ /**
237
+ * Generate a unique request ID.
238
+ *
239
+ * Returns a monotonically increasing integer that ensures uniqueness
240
+ * within a process lifetime.
241
+ */
242
+ generateId() {
243
+ return ++this.requestId;
244
+ }
245
+ // ===========================================================================
246
+ // RUNTIME EXECUTION INTERFACE
247
+ // ===========================================================================
248
+ /**
249
+ * Call a Python function.
250
+ *
251
+ * @param module - Python module path (e.g., 'numpy', 'mypackage.submodule')
252
+ * @param functionName - Function name to call
253
+ * @param args - Positional arguments
254
+ * @param kwargs - Keyword arguments
255
+ * @returns The function result
256
+ */
257
+ async call(module, functionName, args, kwargs) {
258
+ return this.sendMessageAsync({
259
+ method: 'call',
260
+ params: {
261
+ module,
262
+ functionName,
263
+ args,
264
+ kwargs,
265
+ },
266
+ });
267
+ }
268
+ /**
269
+ * Instantiate a Python class.
270
+ *
271
+ * @param module - Python module path containing the class
272
+ * @param className - Class name to instantiate
273
+ * @param args - Positional constructor arguments
274
+ * @param kwargs - Keyword constructor arguments
275
+ * @returns A handle to the created instance
276
+ */
277
+ async instantiate(module, className, args, kwargs) {
278
+ return this.sendMessageAsync({
279
+ method: 'instantiate',
280
+ params: {
281
+ module,
282
+ className,
283
+ args,
284
+ kwargs,
285
+ },
286
+ });
287
+ }
288
+ /**
289
+ * Call a method on a Python instance.
290
+ *
291
+ * @param handle - Instance handle returned from instantiate()
292
+ * @param methodName - Method name to call
293
+ * @param args - Positional arguments
294
+ * @param kwargs - Keyword arguments
295
+ * @returns The method result
296
+ */
297
+ async callMethod(handle, methodName, args, kwargs) {
298
+ return this.sendMessageAsync({
299
+ method: 'call_method',
300
+ params: {
301
+ handle,
302
+ methodName,
303
+ args,
304
+ kwargs,
305
+ },
306
+ });
307
+ }
308
+ /**
309
+ * Dispose a Python instance.
310
+ *
311
+ * Releases the instance handle on the Python side, allowing
312
+ * the object to be garbage collected.
313
+ *
314
+ * @param handle - Instance handle to dispose
315
+ */
316
+ async disposeInstance(handle) {
317
+ await this.sendMessageAsync({
318
+ method: 'dispose_instance',
319
+ params: {
320
+ handle,
321
+ },
322
+ });
323
+ }
324
+ /**
325
+ * Fetch bridge diagnostics and feature availability.
326
+ *
327
+ * The Python bridge supports a `meta` method that returns protocol and environment info
328
+ * (including optional codec availability and current instance count).
329
+ */
330
+ async getBridgeInfo(options = {}) {
331
+ if (!options.refresh && this.bridgeInfoCache) {
332
+ return this.bridgeInfoCache;
333
+ }
334
+ const info = await this.sendMessage({
335
+ method: 'meta',
336
+ params: {},
337
+ }, {
338
+ validate: validateBridgeInfoPayload,
339
+ });
340
+ this.bridgeInfoCache = info;
341
+ return info;
342
+ }
343
+ }
344
+ //# sourceMappingURL=bridge-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-protocol.js","sourceRoot":"","sources":["../../src/runtime/bridge-protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Disposable interface for resources that need cleanup.
3
+ *
4
+ * This interface enables the BoundedContext resource tracking system
5
+ * to automatically dispose of owned resources when the context is disposed.
6
+ */
7
+ /**
8
+ * Interface for resources that require explicit cleanup.
9
+ */
10
+ export interface Disposable {
11
+ /**
12
+ * Release resources held by this object.
13
+ * This method should be idempotent (safe to call multiple times).
14
+ */
15
+ dispose(): Promise<void>;
16
+ }
17
+ /**
18
+ * Type guard to check if a value implements the Disposable interface.
19
+ *
20
+ * @param value - The value to check
21
+ * @returns True if the value has a dispose method
22
+ */
23
+ export declare function isDisposable(value: unknown): value is Disposable;
24
+ /**
25
+ * Safely dispose a value if it implements Disposable.
26
+ * Does nothing if the value is not disposable.
27
+ *
28
+ * @param value - The value to dispose
29
+ * @returns Promise that resolves when disposal is complete
30
+ */
31
+ export declare function safeDispose(value: unknown): Promise<void>;
32
+ /**
33
+ * Dispose multiple resources, collecting any errors.
34
+ * All resources will be attempted even if some fail.
35
+ *
36
+ * @param resources - Iterable of Disposable resources
37
+ * @returns Array of errors that occurred during disposal (empty if all succeeded)
38
+ */
39
+ export declare function disposeAll(resources: Iterable<Disposable>): Promise<Error[]>;
40
+ //# sourceMappingURL=disposable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disposable.d.ts","sourceRoot":"","sources":["../../src/runtime/disposable.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB;;;OAGG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAMhE;AAED;;;;;;GAMG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/D;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAYlF"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Disposable interface for resources that need cleanup.
3
+ *
4
+ * This interface enables the BoundedContext resource tracking system
5
+ * to automatically dispose of owned resources when the context is disposed.
6
+ */
7
+ /**
8
+ * Type guard to check if a value implements the Disposable interface.
9
+ *
10
+ * @param value - The value to check
11
+ * @returns True if the value has a dispose method
12
+ */
13
+ export function isDisposable(value) {
14
+ return (value !== null &&
15
+ typeof value === 'object' &&
16
+ typeof value.dispose === 'function');
17
+ }
18
+ /**
19
+ * Safely dispose a value if it implements Disposable.
20
+ * Does nothing if the value is not disposable.
21
+ *
22
+ * @param value - The value to dispose
23
+ * @returns Promise that resolves when disposal is complete
24
+ */
25
+ export async function safeDispose(value) {
26
+ if (isDisposable(value)) {
27
+ await value.dispose();
28
+ }
29
+ }
30
+ /**
31
+ * Dispose multiple resources, collecting any errors.
32
+ * All resources will be attempted even if some fail.
33
+ *
34
+ * @param resources - Iterable of Disposable resources
35
+ * @returns Array of errors that occurred during disposal (empty if all succeeded)
36
+ */
37
+ export async function disposeAll(resources) {
38
+ const errors = [];
39
+ for (const resource of resources) {
40
+ try {
41
+ await resource.dispose();
42
+ }
43
+ catch (e) {
44
+ errors.push(e instanceof Error ? e : new Error(String(e)));
45
+ }
46
+ }
47
+ return errors;
48
+ }
49
+ //# sourceMappingURL=disposable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disposable.js","sourceRoot":"","sources":["../../src/runtime/disposable.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,OAAO,CACL,KAAK,KAAK,IAAI;QACd,OAAO,KAAK,KAAK,QAAQ;QACzB,OAAQ,KAAoB,CAAC,OAAO,KAAK,UAAU,CACpD,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAc;IAC9C,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;IACxB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,SAA+B;IAC9D,MAAM,MAAM,GAAY,EAAE,CAAC;IAE3B,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -11,6 +11,16 @@ export declare class BridgeTimeoutError extends BridgeError {
11
11
  }
12
12
  export declare class BridgeDisposedError extends BridgeError {
13
13
  }
14
+ export declare class BridgeCodecError extends BridgeError {
15
+ codecPhase?: string;
16
+ valueType?: string;
17
+ constructor(message: string, options?: {
18
+ code?: string;
19
+ cause?: unknown;
20
+ codecPhase?: string;
21
+ valueType?: string;
22
+ });
23
+ }
14
24
  export declare class BridgeExecutionError extends BridgeError {
15
25
  traceback?: string;
16
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/runtime/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,WAAY,SAAQ,KAAK;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;gBACF,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAQ1E;AAED,qBAAa,mBAAoB,SAAQ,WAAW;CAAG;AACvD,qBAAa,kBAAmB,SAAQ,WAAW;CAAG;AACtD,qBAAa,mBAAoB,SAAQ,WAAW;CAAG;AAEvD,qBAAa,oBAAqB,SAAQ,WAAW;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/runtime/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,WAAY,SAAQ,KAAK;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;gBACF,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAQ1E;AAED,qBAAa,mBAAoB,SAAQ,WAAW;CAAG;AACvD,qBAAa,kBAAmB,SAAQ,WAAW;CAAG;AACtD,qBAAa,mBAAoB,SAAQ,WAAW;CAAG;AAEvD,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;gBAGjB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;CAMxF;AAED,qBAAa,oBAAqB,SAAQ,WAAW;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB"}