pynect 0.0.0-stage → 0.2.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 (177) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +478 -2
  3. package/SECURITY.md +34 -0
  4. package/binding.gyp +60 -0
  5. package/dist/cli/codegen.d.ts +3 -0
  6. package/dist/cli/codegen.d.ts.map +1 -0
  7. package/dist/cli/codegen.js +543 -0
  8. package/dist/cli/codegen.js.map +1 -0
  9. package/dist/cli/sync.d.ts +3 -0
  10. package/dist/cli/sync.d.ts.map +1 -0
  11. package/dist/cli/sync.js +48 -0
  12. package/dist/cli/sync.js.map +1 -0
  13. package/dist/config/project.d.ts +57 -0
  14. package/dist/config/project.d.ts.map +1 -0
  15. package/dist/config/project.js +176 -0
  16. package/dist/config/project.js.map +1 -0
  17. package/dist/core/IsolatedWorker.d.ts +39 -0
  18. package/dist/core/IsolatedWorker.d.ts.map +1 -0
  19. package/dist/core/IsolatedWorker.js +178 -0
  20. package/dist/core/IsolatedWorker.js.map +1 -0
  21. package/dist/core/PyCallable.d.ts +67 -0
  22. package/dist/core/PyCallable.d.ts.map +1 -0
  23. package/dist/core/PyCallable.js +104 -0
  24. package/dist/core/PyCallable.js.map +1 -0
  25. package/dist/core/PyContext.d.ts +76 -0
  26. package/dist/core/PyContext.d.ts.map +1 -0
  27. package/dist/core/PyContext.js +239 -0
  28. package/dist/core/PyContext.js.map +1 -0
  29. package/dist/core/PyIterator.d.ts +84 -0
  30. package/dist/core/PyIterator.d.ts.map +1 -0
  31. package/dist/core/PyIterator.js +243 -0
  32. package/dist/core/PyIterator.js.map +1 -0
  33. package/dist/core/PyModule.d.ts +53 -0
  34. package/dist/core/PyModule.d.ts.map +1 -0
  35. package/dist/core/PyModule.js +162 -0
  36. package/dist/core/PyModule.js.map +1 -0
  37. package/dist/core/PyProxy.d.ts +75 -0
  38. package/dist/core/PyProxy.d.ts.map +1 -0
  39. package/dist/core/PyProxy.js +563 -0
  40. package/dist/core/PyProxy.js.map +1 -0
  41. package/dist/core/PyRuntime.d.ts +112 -0
  42. package/dist/core/PyRuntime.d.ts.map +1 -0
  43. package/dist/core/PyRuntime.js +546 -0
  44. package/dist/core/PyRuntime.js.map +1 -0
  45. package/dist/env/PackageInstaller.d.ts +232 -0
  46. package/dist/env/PackageInstaller.d.ts.map +1 -0
  47. package/dist/env/PackageInstaller.js +628 -0
  48. package/dist/env/PackageInstaller.js.map +1 -0
  49. package/dist/env/ProjectEnvironment.d.ts +63 -0
  50. package/dist/env/ProjectEnvironment.d.ts.map +1 -0
  51. package/dist/env/ProjectEnvironment.js +379 -0
  52. package/dist/env/ProjectEnvironment.js.map +1 -0
  53. package/dist/env/PyfigAdapter.d.ts +32 -0
  54. package/dist/env/PyfigAdapter.d.ts.map +1 -0
  55. package/dist/env/PyfigAdapter.js +10 -0
  56. package/dist/env/PyfigAdapter.js.map +1 -0
  57. package/dist/env/PythonDetector.d.ts +48 -0
  58. package/dist/env/PythonDetector.d.ts.map +1 -0
  59. package/dist/env/PythonDetector.js +182 -0
  60. package/dist/env/PythonDetector.js.map +1 -0
  61. package/dist/env/PythonProvisioner.d.ts +16 -0
  62. package/dist/env/PythonProvisioner.d.ts.map +1 -0
  63. package/dist/env/PythonProvisioner.js +42 -0
  64. package/dist/env/PythonProvisioner.js.map +1 -0
  65. package/dist/env/VenvManager.d.ts +55 -0
  66. package/dist/env/VenvManager.d.ts.map +1 -0
  67. package/dist/env/VenvManager.js +153 -0
  68. package/dist/env/VenvManager.js.map +1 -0
  69. package/dist/env/executables.d.ts +3 -0
  70. package/dist/env/executables.d.ts.map +1 -0
  71. package/dist/env/executables.js +14 -0
  72. package/dist/env/executables.js.map +1 -0
  73. package/dist/index.d.ts +182 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +393 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/native/NativeAddonLoader.d.ts +11 -0
  78. package/dist/native/NativeAddonLoader.d.ts.map +1 -0
  79. package/dist/native/NativeAddonLoader.js +75 -0
  80. package/dist/native/NativeAddonLoader.js.map +1 -0
  81. package/dist/plugins/Plugin.interface.d.ts +41 -0
  82. package/dist/plugins/Plugin.interface.d.ts.map +1 -0
  83. package/dist/plugins/Plugin.interface.js +12 -0
  84. package/dist/plugins/Plugin.interface.js.map +1 -0
  85. package/dist/plugins/PluginManager.d.ts +26 -0
  86. package/dist/plugins/PluginManager.d.ts.map +1 -0
  87. package/dist/plugins/PluginManager.js +174 -0
  88. package/dist/plugins/PluginManager.js.map +1 -0
  89. package/dist/plugins/builtin/NumpyPlugin.d.ts +17 -0
  90. package/dist/plugins/builtin/NumpyPlugin.d.ts.map +1 -0
  91. package/dist/plugins/builtin/NumpyPlugin.js +41 -0
  92. package/dist/plugins/builtin/NumpyPlugin.js.map +1 -0
  93. package/dist/plugins/builtin/PandasPlugin.d.ts +19 -0
  94. package/dist/plugins/builtin/PandasPlugin.d.ts.map +1 -0
  95. package/dist/plugins/builtin/PandasPlugin.js +57 -0
  96. package/dist/plugins/builtin/PandasPlugin.js.map +1 -0
  97. package/dist/plugins/builtin/TorchPlugin.d.ts +23 -0
  98. package/dist/plugins/builtin/TorchPlugin.d.ts.map +1 -0
  99. package/dist/plugins/builtin/TorchPlugin.js +50 -0
  100. package/dist/plugins/builtin/TorchPlugin.js.map +1 -0
  101. package/dist/plugins/index.d.ts +7 -0
  102. package/dist/plugins/index.d.ts.map +1 -0
  103. package/dist/plugins/index.js +12 -0
  104. package/dist/plugins/index.js.map +1 -0
  105. package/dist/serialization/DataFrameBridge.d.ts +141 -0
  106. package/dist/serialization/DataFrameBridge.d.ts.map +1 -0
  107. package/dist/serialization/DataFrameBridge.js +355 -0
  108. package/dist/serialization/DataFrameBridge.js.map +1 -0
  109. package/dist/serialization/MsgPackSerializer.d.ts +45 -0
  110. package/dist/serialization/MsgPackSerializer.d.ts.map +1 -0
  111. package/dist/serialization/MsgPackSerializer.js +242 -0
  112. package/dist/serialization/MsgPackSerializer.js.map +1 -0
  113. package/dist/serialization/NumpyBridge.d.ts +96 -0
  114. package/dist/serialization/NumpyBridge.d.ts.map +1 -0
  115. package/dist/serialization/NumpyBridge.js +323 -0
  116. package/dist/serialization/NumpyBridge.js.map +1 -0
  117. package/dist/serialization/Serializer.d.ts +78 -0
  118. package/dist/serialization/Serializer.d.ts.map +1 -0
  119. package/dist/serialization/Serializer.js +281 -0
  120. package/dist/serialization/Serializer.js.map +1 -0
  121. package/dist/types/addon.d.ts +131 -0
  122. package/dist/types/addon.d.ts.map +1 -0
  123. package/dist/types/addon.js +32 -0
  124. package/dist/types/addon.js.map +1 -0
  125. package/dist/types/config.d.ts +233 -0
  126. package/dist/types/config.d.ts.map +1 -0
  127. package/dist/types/config.js +60 -0
  128. package/dist/types/config.js.map +1 -0
  129. package/dist/types/index.d.ts +10 -0
  130. package/dist/types/index.d.ts.map +1 -0
  131. package/dist/types/index.js +12 -0
  132. package/dist/types/index.js.map +1 -0
  133. package/dist/types/python.d.ts +235 -0
  134. package/dist/types/python.d.ts.map +1 -0
  135. package/dist/types/python.js +7 -0
  136. package/dist/types/python.js.map +1 -0
  137. package/dist/utils/ErrorTranslator.d.ts +83 -0
  138. package/dist/utils/ErrorTranslator.d.ts.map +1 -0
  139. package/dist/utils/ErrorTranslator.js +210 -0
  140. package/dist/utils/ErrorTranslator.js.map +1 -0
  141. package/dist/utils/Locking.d.ts +3 -0
  142. package/dist/utils/Locking.d.ts.map +1 -0
  143. package/dist/utils/Locking.js +10 -0
  144. package/dist/utils/Locking.js.map +1 -0
  145. package/dist/utils/Logger.d.ts +27 -0
  146. package/dist/utils/Logger.d.ts.map +1 -0
  147. package/dist/utils/Logger.js +115 -0
  148. package/dist/utils/Logger.js.map +1 -0
  149. package/dist/utils/MemoryMonitor.d.ts +43 -0
  150. package/dist/utils/MemoryMonitor.d.ts.map +1 -0
  151. package/dist/utils/MemoryMonitor.js +143 -0
  152. package/dist/utils/MemoryMonitor.js.map +1 -0
  153. package/package.json +114 -4
  154. package/python/ast_inspector.py +248 -0
  155. package/python/error_handler.py +432 -0
  156. package/python/isolated_worker.py +94 -0
  157. package/python/pynect_dispatcher.py +382 -0
  158. package/python/pynect_runtime.py +574 -0
  159. package/python/serializer.py +373 -0
  160. package/python/type_inspector.py +315 -0
  161. package/scripts/build-native.js +50 -0
  162. package/scripts/cli.js +21 -0
  163. package/scripts/ensure-native.js +85 -0
  164. package/scripts/postinstall.js +40 -0
  165. package/scripts/pyfig.js +113 -0
  166. package/scripts/python-provisioner.js +23 -0
  167. package/scripts/smoke-python-boundary.js +103 -0
  168. package/src/native/NativeAddonLoader.ts +98 -0
  169. package/src/native/gil_guard.cpp +25 -0
  170. package/src/native/gil_guard.h +174 -0
  171. package/src/native/pynect_addon.cpp +942 -0
  172. package/src/native/python_bridge.cpp +904 -0
  173. package/src/native/python_bridge.h +263 -0
  174. package/src/native/thread_pool.cpp +375 -0
  175. package/src/native/thread_pool.h +185 -0
  176. package/src/native/type_converter.cpp +906 -0
  177. package/src/native/type_converter.h +271 -0
@@ -0,0 +1,242 @@
1
+ "use strict";
2
+ /**
3
+ * pynect - MsgPackSerializer
4
+ * MessagePack encoder/decoder for high-performance binary serialization.
5
+ * Used for large arrays, complex objects, and bulk data transfer.
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.MsgPackSerializer = void 0;
42
+ const msgpack = __importStar(require("@msgpack/msgpack"));
43
+ const Logger_1 = require("../utils/Logger");
44
+ const logger = new Logger_1.Logger('MsgPackSerializer');
45
+ /**
46
+ * Extension type definitions for custom Python types.
47
+ * Extension type 1 = Python datetime
48
+ * Extension type 2 = Python complex number
49
+ * Extension type 3 = Python set
50
+ * Extension type 4 = Python tuple
51
+ * Extension type 5 = Python bytes
52
+ */
53
+ var MsgPackExtType;
54
+ (function (MsgPackExtType) {
55
+ MsgPackExtType[MsgPackExtType["DATETIME"] = 1] = "DATETIME";
56
+ MsgPackExtType[MsgPackExtType["COMPLEX"] = 2] = "COMPLEX";
57
+ MsgPackExtType[MsgPackExtType["SET"] = 3] = "SET";
58
+ MsgPackExtType[MsgPackExtType["TUPLE"] = 4] = "TUPLE";
59
+ MsgPackExtType[MsgPackExtType["BYTES"] = 5] = "BYTES";
60
+ MsgPackExtType[MsgPackExtType["NUMPY_DTYPE"] = 10] = "NUMPY_DTYPE";
61
+ })(MsgPackExtType || (MsgPackExtType = {}));
62
+ /**
63
+ * MsgPackSerializer - encodes/decodes JavaScript <-> MessagePack binary.
64
+ *
65
+ * Handles Python-specific types via extension codecs:
66
+ * - Python datetime -> JS Date
67
+ * - Python set -> JS Set
68
+ * - Python tuple -> JS Array (immutable semantics lost, acceptable)
69
+ * - Python bytes -> JS Uint8Array
70
+ * - Python complex -> JS {real, imag}
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const serializer = new MsgPackSerializer();
75
+ * const encoded = serializer.encode({ key: 'value', nums: [1, 2, 3] });
76
+ * const decoded = serializer.decode(encoded);
77
+ * ```
78
+ */
79
+ class MsgPackSerializer {
80
+ _encoderOptions;
81
+ _decoderOptions;
82
+ constructor() {
83
+ this._encoderOptions = {
84
+ extensionCodec: this._createExtensionCodec(),
85
+ forceIntegerToFloat: false,
86
+ forceFloat32: false,
87
+ sortKeys: false,
88
+ maxDepth: 64,
89
+ };
90
+ this._decoderOptions = {
91
+ extensionCodec: this._createExtensionCodec(),
92
+ // rawBinaryType: 'Uint8Array',
93
+ useBigInt64: false,
94
+ };
95
+ }
96
+ /**
97
+ * Encode a JavaScript value to MessagePack binary.
98
+ */
99
+ encode(value) {
100
+ try {
101
+ return msgpack.encode(value, this._encoderOptions);
102
+ }
103
+ catch (err) {
104
+ logger.error('MsgPack encoding failed', err);
105
+ // Fallback: try encoding as JSON string
106
+ try {
107
+ const json = JSON.stringify(value);
108
+ return msgpack.encode(json, this._encoderOptions);
109
+ }
110
+ catch {
111
+ // Last resort: empty bytes
112
+ return new Uint8Array(0);
113
+ }
114
+ }
115
+ }
116
+ /**
117
+ * Decode a MessagePack binary to a JavaScript value.
118
+ */
119
+ decode(data) {
120
+ if (!data || data.length === 0) {
121
+ return null;
122
+ }
123
+ try {
124
+ return msgpack.decode(data, this._decoderOptions);
125
+ }
126
+ catch (err) {
127
+ logger.error('MsgPack decoding failed', err);
128
+ return null;
129
+ }
130
+ }
131
+ /**
132
+ * Encode a stream of values (for streaming large datasets).
133
+ */
134
+ encodeStream(values) {
135
+ const chunks = [];
136
+ let totalLength = 0;
137
+ for (const value of values) {
138
+ const encoded = this.encode(value);
139
+ chunks.push(encoded);
140
+ totalLength += encoded.length;
141
+ }
142
+ // Concatenate all chunks
143
+ const result = new Uint8Array(totalLength);
144
+ let offset = 0;
145
+ for (const chunk of chunks) {
146
+ result.set(chunk, offset);
147
+ offset += chunk.length;
148
+ }
149
+ return result;
150
+ }
151
+ /**
152
+ * Decode a stream of values from MessagePack binary.
153
+ */
154
+ *decodeStream(data) {
155
+ if (!data || data.length === 0) {
156
+ return;
157
+ }
158
+ try {
159
+ for (const item of msgpack.decodeMulti(data, this._decoderOptions)) {
160
+ yield item;
161
+ }
162
+ }
163
+ catch (err) {
164
+ logger.error('MsgPack stream decoding failed', err);
165
+ }
166
+ }
167
+ // Extension Codec
168
+ _createExtensionCodec() {
169
+ const codec = new msgpack.ExtensionCodec();
170
+ // Python datetime -> JS Date
171
+ codec.register({
172
+ type: MsgPackExtType.DATETIME,
173
+ encode: (value) => {
174
+ if (value instanceof Date) {
175
+ const ms = value.getTime();
176
+ const buf = new ArrayBuffer(8);
177
+ new DataView(buf).setFloat64(0, ms, false);
178
+ return new Uint8Array(buf);
179
+ }
180
+ return null;
181
+ },
182
+ decode: (data) => {
183
+ const ms = new DataView(data.buffer, data.byteOffset, data.byteLength).getFloat64(0, false);
184
+ return new Date(ms);
185
+ },
186
+ });
187
+ // Python complex -> {real, imag}
188
+ codec.register({
189
+ type: MsgPackExtType.COMPLEX,
190
+ encode: (value) => {
191
+ if (value !== null &&
192
+ typeof value === 'object' &&
193
+ 'real' in value &&
194
+ 'imag' in value) {
195
+ const buf = new ArrayBuffer(16);
196
+ const dv = new DataView(buf);
197
+ dv.setFloat64(0, value.real, false);
198
+ dv.setFloat64(8, value.imag, false);
199
+ return new Uint8Array(buf);
200
+ }
201
+ return null;
202
+ },
203
+ decode: (data) => {
204
+ const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);
205
+ return {
206
+ real: dv.getFloat64(0, false),
207
+ imag: dv.getFloat64(8, false),
208
+ };
209
+ },
210
+ });
211
+ // Python set -> JS Set
212
+ codec.register({
213
+ type: MsgPackExtType.SET,
214
+ encode: (value) => {
215
+ if (value instanceof Set) {
216
+ const arr = Array.from(value);
217
+ return this.encode(arr);
218
+ }
219
+ return null;
220
+ },
221
+ decode: (data) => {
222
+ const arr = this.decode(data);
223
+ return new Set(arr);
224
+ },
225
+ });
226
+ // Python tuple -> JS Array
227
+ codec.register({
228
+ type: MsgPackExtType.TUPLE,
229
+ encode: (_value) => {
230
+ // Tuples are encoded as arrays by Python side
231
+ return null;
232
+ },
233
+ decode: (data) => {
234
+ const decoded = this.decode(data);
235
+ return Array.isArray(decoded) ? decoded : [decoded];
236
+ },
237
+ });
238
+ return codec;
239
+ }
240
+ }
241
+ exports.MsgPackSerializer = MsgPackSerializer;
242
+ //# sourceMappingURL=MsgPackSerializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MsgPackSerializer.js","sourceRoot":"","sources":["../../src/serialization/MsgPackSerializer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * pynect - NumpyBridge
3
+ * Converts NumPy arrays to/from JavaScript TypedArrays.
4
+ *
5
+ * Wire protocol (binary layout for NUMPY_ARRAY format):
6
+ * Bytes 0-3 : uint32 LE - ndim (number of dimensions)
7
+ * Bytes 4-7 : uint32 LE - dtype code (see NumpyDTypeCode)
8
+ * Bytes 8-11 : uint32 LE - itemsize in bytes
9
+ * Bytes 12-15 : uint32 LE - total element count
10
+ * Bytes 16.. : ndim x uint32 LE - shape dimensions
11
+ * After shape : raw element bytes (C-contiguous order)
12
+ *
13
+ * When SharedArrayBuffer is enabled the element bytes are placed in a
14
+ * SharedArrayBuffer so the data can be read from Node.js worker threads
15
+ * without copying.
16
+ */
17
+ import type { SerializedValue, NumPyArrayResult } from '../types/python';
18
+ export declare enum NumpyDTypeCode {
19
+ BOOL = 0,
20
+ INT8 = 1,
21
+ INT16 = 2,
22
+ INT32 = 3,
23
+ INT64 = 4,
24
+ UINT8 = 5,
25
+ UINT16 = 6,
26
+ UINT32 = 7,
27
+ UINT64 = 8,
28
+ FLOAT32 = 9,
29
+ FLOAT64 = 10,
30
+ COMPLEX64 = 11,
31
+ COMPLEX128 = 12
32
+ }
33
+ export type NumpyDType = 'bool' | 'int8' | 'int16' | 'int32' | 'int64' | 'uint8' | 'uint16' | 'uint32' | 'uint64' | 'float32' | 'float64' | 'complex64' | 'complex128';
34
+ interface NumpyBridgeOptions {
35
+ /**
36
+ * Use SharedArrayBuffer for large arrays.
37
+ * Requires `Cross-Origin-Opener-Policy: same-origin` and
38
+ * `Cross-Origin-Embedder-Policy: require-corp` response headers.
39
+ */
40
+ useSharedArrayBuffer?: boolean;
41
+ /** Threshold in bytes above which SharedArrayBuffer is used. Default: 1 MB */
42
+ sharedArrayBufferThreshold?: number;
43
+ }
44
+ /**
45
+ * NumpyBridge - converts NumPy arrays <-> TypedArrays.
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const bridge = new NumpyBridge();
50
+ *
51
+ * // Serialize a Float32Array -> NumPy wire format
52
+ * const sv = bridge.serializeTypedArray(new Float32Array([1, 2, 3]), 'float32');
53
+ *
54
+ * // Deserialize NumPy wire format -> TypedArray
55
+ * const arr = bridge.deserialize(sv) as Float32Array;
56
+ * ```
57
+ */
58
+ export declare class NumpyBridge {
59
+ private readonly _useShared;
60
+ private readonly _sharedThreshold;
61
+ constructor(options?: NumpyBridgeOptions);
62
+ /**
63
+ * Deserialize a NUMPY_ARRAY SerializedValue to a TypedArray.
64
+ */
65
+ deserialize(sv: SerializedValue): NumPyArrayResult | null;
66
+ /**
67
+ * Serialize a TypedArray to a NUMPY_ARRAY SerializedValue.
68
+ *
69
+ * @param arr - the typed array
70
+ * @param dtype - NumPy dtype string
71
+ * @param shape - optional explicit shape; defaults to [arr.length]
72
+ */
73
+ serializeTypedArray(arr: ArrayBufferView, dtype: NumpyDType | {
74
+ dtype: string;
75
+ itemsize: number;
76
+ }, shape?: number[]): SerializedValue;
77
+ /**
78
+ * Create an empty NumPy array SerializedValue (used for zero-size results).
79
+ */
80
+ serializeEmpty(dtype?: NumpyDType): SerializedValue;
81
+ private _decodeBuffer;
82
+ private _buildTypedArray;
83
+ /**
84
+ * Detect dtype code from a TypedArray instance.
85
+ */
86
+ static detectDType(arr: ArrayBufferView): {
87
+ dtype: NumpyDType;
88
+ itemsize: number;
89
+ };
90
+ /**
91
+ * Return the item size in bytes for a dtype string.
92
+ */
93
+ static itemSizeOf(dtype: NumpyDType): number;
94
+ }
95
+ export {};
96
+ //# sourceMappingURL=NumpyBridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NumpyBridge.d.ts","sourceRoot":"","sources":["../../src/serialization/NumpyBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAoB,gBAAgB,EAAmB,MAAM,iBAAiB,CAAC;AAO5G,oBAAY,cAAc;IACxB,IAAI,IAAQ;IACZ,IAAI,IAAQ;IACZ,KAAK,IAAO;IACZ,KAAK,IAAO;IACZ,KAAK,IAAO;IACZ,KAAK,IAAO;IACZ,MAAM,IAAM;IACZ,MAAM,IAAM;IACZ,MAAM,IAAM;IACZ,OAAO,IAAK;IACZ,OAAO,KAAK;IACZ,SAAS,KAAM;IACf,UAAU,KAAK;CAChB;AAED,MAAM,MAAM,UAAU,GAClB,MAAM,GACN,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GACpC,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GACxC,SAAS,GAAG,SAAS,GACrB,WAAW,GAAG,YAAY,CAAC;AAE/B,UAAU,kBAAkB;IAC1B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,8EAA8E;IAC9E,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC;AAyCD;;;;;;;;;;;;;GAaG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAU;IACrC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;gBAE9B,OAAO,GAAE,kBAAuB;IAO5C;;OAEG;IACH,WAAW,CAAC,EAAE,EAAE,eAAe,GAAG,gBAAgB,GAAG,IAAI;IAiCzD;;;;;;OAMG;IACH,mBAAmB,CACjB,GAAG,EAAE,eAAe,EACpB,KAAK,EAAE,UAAU,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EACvD,KAAK,CAAC,EAAE,MAAM,EAAE,GACf,eAAe;IA8ClB;;OAEG;IACH,cAAc,CAAC,KAAK,GAAE,UAAsB,GAAG,eAAe;IAM9D,OAAO,CAAC,aAAa;IA6BrB,OAAO,CAAC,gBAAgB;IAkDxB;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE;IAiBjF;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM;CAI7C"}
@@ -0,0 +1,323 @@
1
+ "use strict";
2
+ /**
3
+ * pynect - NumpyBridge
4
+ * Converts NumPy arrays to/from JavaScript TypedArrays.
5
+ *
6
+ * Wire protocol (binary layout for NUMPY_ARRAY format):
7
+ * Bytes 0-3 : uint32 LE - ndim (number of dimensions)
8
+ * Bytes 4-7 : uint32 LE - dtype code (see NumpyDTypeCode)
9
+ * Bytes 8-11 : uint32 LE - itemsize in bytes
10
+ * Bytes 12-15 : uint32 LE - total element count
11
+ * Bytes 16.. : ndim x uint32 LE - shape dimensions
12
+ * After shape : raw element bytes (C-contiguous order)
13
+ *
14
+ * When SharedArrayBuffer is enabled the element bytes are placed in a
15
+ * SharedArrayBuffer so the data can be read from Node.js worker threads
16
+ * without copying.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.NumpyBridge = exports.NumpyDTypeCode = void 0;
20
+ const Logger_1 = require("../utils/Logger");
21
+ const logger = new Logger_1.Logger('NumpyBridge');
22
+ // NumPy dtype codes (must match Python side pynect_runtime.py)
23
+ var NumpyDTypeCode;
24
+ (function (NumpyDTypeCode) {
25
+ NumpyDTypeCode[NumpyDTypeCode["BOOL"] = 0] = "BOOL";
26
+ NumpyDTypeCode[NumpyDTypeCode["INT8"] = 1] = "INT8";
27
+ NumpyDTypeCode[NumpyDTypeCode["INT16"] = 2] = "INT16";
28
+ NumpyDTypeCode[NumpyDTypeCode["INT32"] = 3] = "INT32";
29
+ NumpyDTypeCode[NumpyDTypeCode["INT64"] = 4] = "INT64";
30
+ NumpyDTypeCode[NumpyDTypeCode["UINT8"] = 5] = "UINT8";
31
+ NumpyDTypeCode[NumpyDTypeCode["UINT16"] = 6] = "UINT16";
32
+ NumpyDTypeCode[NumpyDTypeCode["UINT32"] = 7] = "UINT32";
33
+ NumpyDTypeCode[NumpyDTypeCode["UINT64"] = 8] = "UINT64";
34
+ NumpyDTypeCode[NumpyDTypeCode["FLOAT32"] = 9] = "FLOAT32";
35
+ NumpyDTypeCode[NumpyDTypeCode["FLOAT64"] = 10] = "FLOAT64";
36
+ NumpyDTypeCode[NumpyDTypeCode["COMPLEX64"] = 11] = "COMPLEX64";
37
+ NumpyDTypeCode[NumpyDTypeCode["COMPLEX128"] = 12] = "COMPLEX128";
38
+ })(NumpyDTypeCode || (exports.NumpyDTypeCode = NumpyDTypeCode = {}));
39
+ /** Header size in bytes (see layout above) */
40
+ const HEADER_BYTES = 16;
41
+ // dtype string -> NumpyDTypeCode
42
+ const DTYPE_STRING_TO_CODE = {
43
+ bool: NumpyDTypeCode.BOOL,
44
+ int8: NumpyDTypeCode.INT8,
45
+ int16: NumpyDTypeCode.INT16,
46
+ int32: NumpyDTypeCode.INT32,
47
+ int64: NumpyDTypeCode.INT64,
48
+ uint8: NumpyDTypeCode.UINT8,
49
+ uint16: NumpyDTypeCode.UINT16,
50
+ uint32: NumpyDTypeCode.UINT32,
51
+ uint64: NumpyDTypeCode.UINT64,
52
+ float32: NumpyDTypeCode.FLOAT32,
53
+ float64: NumpyDTypeCode.FLOAT64,
54
+ complex64: NumpyDTypeCode.COMPLEX64,
55
+ complex128: NumpyDTypeCode.COMPLEX128,
56
+ };
57
+ // NumpyDTypeCode -> item size in bytes
58
+ const DTYPE_CODE_TO_ITEMSIZE = {
59
+ [NumpyDTypeCode.BOOL]: 1,
60
+ [NumpyDTypeCode.INT8]: 1,
61
+ [NumpyDTypeCode.INT16]: 2,
62
+ [NumpyDTypeCode.INT32]: 4,
63
+ [NumpyDTypeCode.INT64]: 8,
64
+ [NumpyDTypeCode.UINT8]: 1,
65
+ [NumpyDTypeCode.UINT16]: 2,
66
+ [NumpyDTypeCode.UINT32]: 4,
67
+ [NumpyDTypeCode.UINT64]: 8,
68
+ [NumpyDTypeCode.FLOAT32]: 4,
69
+ [NumpyDTypeCode.FLOAT64]: 8,
70
+ [NumpyDTypeCode.COMPLEX64]: 8,
71
+ [NumpyDTypeCode.COMPLEX128]: 16,
72
+ };
73
+ /**
74
+ * NumpyBridge - converts NumPy arrays <-> TypedArrays.
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * const bridge = new NumpyBridge();
79
+ *
80
+ * // Serialize a Float32Array -> NumPy wire format
81
+ * const sv = bridge.serializeTypedArray(new Float32Array([1, 2, 3]), 'float32');
82
+ *
83
+ * // Deserialize NumPy wire format -> TypedArray
84
+ * const arr = bridge.deserialize(sv) as Float32Array;
85
+ * ```
86
+ */
87
+ class NumpyBridge {
88
+ _useShared;
89
+ _sharedThreshold;
90
+ constructor(options = {}) {
91
+ this._useShared = options.useSharedArrayBuffer ?? false;
92
+ this._sharedThreshold = options.sharedArrayBufferThreshold ?? 1_048_576; // 1 MB
93
+ }
94
+ // Python wire format -> TypedArray
95
+ /**
96
+ * Deserialize a NUMPY_ARRAY SerializedValue to a TypedArray.
97
+ */
98
+ deserialize(sv) {
99
+ if (sv.format !== 'numpy_array') {
100
+ return null;
101
+ }
102
+ const rawData = sv.data;
103
+ if (!rawData) {
104
+ logger.warn('NumpyBridge.deserialize: invalid data');
105
+ return null;
106
+ }
107
+ try {
108
+ let u8;
109
+ if (typeof rawData === 'string') {
110
+ // base64-encoded binary
111
+ const buf = Buffer.from(rawData, 'base64');
112
+ u8 = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
113
+ }
114
+ else if (rawData instanceof Uint8Array) {
115
+ u8 = rawData;
116
+ }
117
+ else {
118
+ logger.warn('NumpyBridge.deserialize: unsupported data type');
119
+ return null;
120
+ }
121
+ if (u8.length < HEADER_BYTES) {
122
+ logger.warn('NumpyBridge.deserialize: buffer too small');
123
+ return null;
124
+ }
125
+ return this._decodeBuffer(u8);
126
+ }
127
+ catch (err) {
128
+ logger.error('NumpyBridge.deserialize failed', err);
129
+ return null;
130
+ }
131
+ }
132
+ // TypedArray -> Python wire format
133
+ /**
134
+ * Serialize a TypedArray to a NUMPY_ARRAY SerializedValue.
135
+ *
136
+ * @param arr - the typed array
137
+ * @param dtype - NumPy dtype string
138
+ * @param shape - optional explicit shape; defaults to [arr.length]
139
+ */
140
+ serializeTypedArray(arr, dtype, shape) {
141
+ const dtypeStr = (typeof dtype === 'string' ? dtype : dtype.dtype);
142
+ const dtypeCode = DTYPE_STRING_TO_CODE[dtypeStr] ?? NumpyDTypeCode.FLOAT64;
143
+ const itemSize = DTYPE_CODE_TO_ITEMSIZE[dtypeCode];
144
+ const dims = shape ?? [arr.byteLength / itemSize];
145
+ const ndim = dims.length;
146
+ const count = dims.reduce((a, b) => a * b, 1);
147
+ const dataBytes = count * itemSize;
148
+ const totalBytes = HEADER_BYTES + ndim * 4 + dataBytes;
149
+ const buffer = new ArrayBuffer(totalBytes);
150
+ const dv = new DataView(buffer);
151
+ const u8 = new Uint8Array(buffer);
152
+ // Write header
153
+ dv.setUint32(0, ndim, true);
154
+ dv.setUint32(4, dtypeCode, true);
155
+ dv.setUint32(8, itemSize, true);
156
+ dv.setUint32(12, count, true);
157
+ // Write shape
158
+ for (let i = 0; i < ndim; i++) {
159
+ dv.setUint32(HEADER_BYTES + i * 4, dims[i], true);
160
+ }
161
+ // Write data
162
+ const srcU8 = new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);
163
+ u8.set(srcU8, HEADER_BYTES + ndim * 4);
164
+ return {
165
+ format: 'numpy_array',
166
+ data: u8,
167
+ metadata: {
168
+ dtype: dtypeStr,
169
+ shape: dims,
170
+ itemSize,
171
+ size: dataBytes,
172
+ length: count,
173
+ },
174
+ };
175
+ }
176
+ /**
177
+ * Create an empty NumPy array SerializedValue (used for zero-size results).
178
+ */
179
+ serializeEmpty(dtype = 'float64') {
180
+ return this.serializeTypedArray(new Float64Array(0), dtype, [0]);
181
+ }
182
+ // Helpers
183
+ _decodeBuffer(u8) {
184
+ const dv = new DataView(u8.buffer, u8.byteOffset, u8.byteLength);
185
+ const ndim = dv.getUint32(0, true);
186
+ const dtypeCode = dv.getUint32(4, true);
187
+ const itemSize = dv.getUint32(8, true);
188
+ const count = dv.getUint32(12, true);
189
+ // Read shape
190
+ const shape = [];
191
+ for (let i = 0; i < ndim; i++) {
192
+ shape.push(dv.getUint32(HEADER_BYTES + i * 4, true));
193
+ }
194
+ const dataOffset = HEADER_BYTES + ndim * 4;
195
+ const dataLength = count * itemSize;
196
+ if (u8.length < dataOffset + dataLength) {
197
+ throw new Error(`NumpyBridge: buffer too small. ` +
198
+ `Expected ${dataOffset + dataLength} bytes, got ${u8.length}`);
199
+ }
200
+ const srcBuffer = u8.buffer;
201
+ const srcByteOffset = u8.byteOffset + dataOffset;
202
+ return this._buildTypedArray(dtypeCode, srcBuffer, srcByteOffset, count, shape, ndim);
203
+ }
204
+ _buildTypedArray(code, srcBuffer, byteOffset, count, shape = [], ndim = 1) {
205
+ const useShared = this._useShared &&
206
+ typeof SharedArrayBuffer !== 'undefined' &&
207
+ count * DTYPE_CODE_TO_ITEMSIZE[code] >= this._sharedThreshold;
208
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
209
+ const targetBuffer = (useShared
210
+ ? new SharedArrayBuffer(count * DTYPE_CODE_TO_ITEMSIZE[code])
211
+ : new ArrayBuffer(count * DTYPE_CODE_TO_ITEMSIZE[code]));
212
+ // Copy data
213
+ const src = new Uint8Array(srcBuffer, byteOffset, count * DTYPE_CODE_TO_ITEMSIZE[code]);
214
+ const dest = new Uint8Array(targetBuffer);
215
+ dest.set(src);
216
+ let data;
217
+ let dtypeStr;
218
+ switch (code) {
219
+ case NumpyDTypeCode.BOOL:
220
+ case NumpyDTypeCode.UINT8:
221
+ data = new Uint8Array(targetBuffer);
222
+ dtypeStr = code === NumpyDTypeCode.BOOL ? 'bool' : 'uint8';
223
+ break;
224
+ case NumpyDTypeCode.INT8:
225
+ data = new Int8Array(targetBuffer);
226
+ dtypeStr = 'int8';
227
+ break;
228
+ case NumpyDTypeCode.INT16:
229
+ data = new Int16Array(targetBuffer);
230
+ dtypeStr = 'int16';
231
+ break;
232
+ case NumpyDTypeCode.INT32:
233
+ data = new Int32Array(targetBuffer);
234
+ dtypeStr = 'int32';
235
+ break;
236
+ case NumpyDTypeCode.INT64:
237
+ data = new BigInt64Array(targetBuffer);
238
+ dtypeStr = 'int64';
239
+ break;
240
+ case NumpyDTypeCode.UINT16:
241
+ data = new Uint16Array(targetBuffer);
242
+ dtypeStr = 'uint16';
243
+ break;
244
+ case NumpyDTypeCode.UINT32:
245
+ data = new Uint32Array(targetBuffer);
246
+ dtypeStr = 'uint32';
247
+ break;
248
+ case NumpyDTypeCode.UINT64:
249
+ data = new BigUint64Array(targetBuffer);
250
+ dtypeStr = 'uint64';
251
+ break;
252
+ case NumpyDTypeCode.FLOAT32:
253
+ data = new Float32Array(targetBuffer);
254
+ dtypeStr = 'float32';
255
+ break;
256
+ case NumpyDTypeCode.COMPLEX64:
257
+ data = new Float32Array(targetBuffer);
258
+ dtypeStr = 'complex64';
259
+ break;
260
+ case NumpyDTypeCode.COMPLEX128:
261
+ data = new Float64Array(targetBuffer);
262
+ dtypeStr = 'complex128';
263
+ break;
264
+ case NumpyDTypeCode.FLOAT64:
265
+ default:
266
+ data = new Float64Array(targetBuffer);
267
+ dtypeStr = 'float64';
268
+ break;
269
+ }
270
+ return { data, dtype: dtypeStr, shape, ndim };
271
+ }
272
+ // Static helpers
273
+ /**
274
+ * Detect dtype code from a TypedArray instance.
275
+ */
276
+ static detectDType(arr) {
277
+ let dtype;
278
+ if (arr instanceof Float32Array) {
279
+ dtype = 'float32';
280
+ }
281
+ else if (arr instanceof Float64Array) {
282
+ dtype = 'float64';
283
+ }
284
+ else if (arr instanceof Int8Array) {
285
+ dtype = 'int8';
286
+ }
287
+ else if (arr instanceof Int16Array) {
288
+ dtype = 'int16';
289
+ }
290
+ else if (arr instanceof Int32Array) {
291
+ dtype = 'int32';
292
+ }
293
+ else if (arr instanceof BigInt64Array) {
294
+ dtype = 'int64';
295
+ }
296
+ else if (arr instanceof Uint8Array) {
297
+ dtype = 'uint8';
298
+ }
299
+ else if (arr instanceof Uint16Array) {
300
+ dtype = 'uint16';
301
+ }
302
+ else if (arr instanceof Uint32Array) {
303
+ dtype = 'uint32';
304
+ }
305
+ else if (arr instanceof BigUint64Array) {
306
+ dtype = 'uint64';
307
+ }
308
+ else {
309
+ dtype = 'float64';
310
+ }
311
+ const code = DTYPE_STRING_TO_CODE[dtype] ?? NumpyDTypeCode.FLOAT64;
312
+ return { dtype, itemsize: DTYPE_CODE_TO_ITEMSIZE[code] };
313
+ }
314
+ /**
315
+ * Return the item size in bytes for a dtype string.
316
+ */
317
+ static itemSizeOf(dtype) {
318
+ const code = DTYPE_STRING_TO_CODE[dtype] ?? NumpyDTypeCode.FLOAT64;
319
+ return DTYPE_CODE_TO_ITEMSIZE[code];
320
+ }
321
+ }
322
+ exports.NumpyBridge = NumpyBridge;
323
+ //# sourceMappingURL=NumpyBridge.js.map