tywrap 0.1.2 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -4
- package/dist/index.d.ts +20 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -2
- package/dist/index.js.map +1 -1
- package/dist/runtime/base.d.ts +17 -7
- package/dist/runtime/base.d.ts.map +1 -1
- package/dist/runtime/base.js +18 -1
- package/dist/runtime/base.js.map +1 -1
- package/dist/runtime/bounded-context.d.ts +252 -0
- package/dist/runtime/bounded-context.d.ts.map +1 -0
- package/dist/runtime/bounded-context.js +454 -0
- package/dist/runtime/bounded-context.js.map +1 -0
- package/dist/runtime/bridge-protocol.d.ts +167 -0
- package/dist/runtime/bridge-protocol.d.ts.map +1 -0
- package/dist/runtime/bridge-protocol.js +247 -0
- package/dist/runtime/bridge-protocol.js.map +1 -0
- package/dist/runtime/disposable.d.ts +40 -0
- package/dist/runtime/disposable.d.ts.map +1 -0
- package/dist/runtime/disposable.js +49 -0
- package/dist/runtime/disposable.js.map +1 -0
- package/dist/runtime/http-io.d.ts +91 -0
- package/dist/runtime/http-io.d.ts.map +1 -0
- package/dist/runtime/http-io.js +195 -0
- package/dist/runtime/http-io.js.map +1 -0
- package/dist/runtime/http.d.ts +47 -13
- package/dist/runtime/http.d.ts.map +1 -1
- package/dist/runtime/http.js +55 -74
- package/dist/runtime/http.js.map +1 -1
- package/dist/runtime/node.d.ts +142 -28
- package/dist/runtime/node.d.ts.map +1 -1
- package/dist/runtime/node.js +321 -168
- package/dist/runtime/node.js.map +1 -1
- package/dist/runtime/optimized-node.d.ts +19 -125
- package/dist/runtime/optimized-node.d.ts.map +1 -1
- package/dist/runtime/optimized-node.js +19 -550
- package/dist/runtime/optimized-node.js.map +1 -1
- package/dist/runtime/pooled-transport.d.ts +131 -0
- package/dist/runtime/pooled-transport.d.ts.map +1 -0
- package/dist/runtime/pooled-transport.js +175 -0
- package/dist/runtime/pooled-transport.js.map +1 -0
- package/dist/runtime/process-io.d.ts +204 -0
- package/dist/runtime/process-io.d.ts.map +1 -0
- package/dist/runtime/process-io.js +695 -0
- package/dist/runtime/process-io.js.map +1 -0
- package/dist/runtime/pyodide-io.d.ts +155 -0
- package/dist/runtime/pyodide-io.d.ts.map +1 -0
- package/dist/runtime/pyodide-io.js +397 -0
- package/dist/runtime/pyodide-io.js.map +1 -0
- package/dist/runtime/pyodide.d.ts +51 -19
- package/dist/runtime/pyodide.d.ts.map +1 -1
- package/dist/runtime/pyodide.js +57 -186
- package/dist/runtime/pyodide.js.map +1 -1
- package/dist/runtime/safe-codec.d.ts +81 -0
- package/dist/runtime/safe-codec.d.ts.map +1 -0
- package/dist/runtime/safe-codec.js +345 -0
- package/dist/runtime/safe-codec.js.map +1 -0
- package/dist/runtime/transport.d.ts +186 -0
- package/dist/runtime/transport.d.ts.map +1 -0
- package/dist/runtime/transport.js +86 -0
- package/dist/runtime/transport.js.map +1 -0
- package/dist/runtime/validators.d.ts +131 -0
- package/dist/runtime/validators.d.ts.map +1 -0
- package/dist/runtime/validators.js +219 -0
- package/dist/runtime/validators.js.map +1 -0
- package/dist/runtime/worker-pool.d.ts +196 -0
- package/dist/runtime/worker-pool.d.ts.map +1 -0
- package/dist/runtime/worker-pool.js +371 -0
- package/dist/runtime/worker-pool.js.map +1 -0
- package/dist/utils/codec.d.ts.map +1 -1
- package/dist/utils/codec.js +120 -1
- package/dist/utils/codec.js.map +1 -1
- package/package.json +2 -2
- package/runtime/python_bridge.py +30 -3
- package/runtime/safe_codec.py +344 -0
- package/src/index.ts +48 -5
- package/src/runtime/base.ts +18 -26
- package/src/runtime/bounded-context.ts +608 -0
- package/src/runtime/bridge-protocol.ts +319 -0
- package/src/runtime/disposable.ts +65 -0
- package/src/runtime/http-io.ts +244 -0
- package/src/runtime/http.ts +71 -117
- package/src/runtime/node.ts +460 -217
- package/src/runtime/optimized-node.ts +19 -761
- package/src/runtime/pooled-transport.ts +252 -0
- package/src/runtime/process-io.ts +902 -0
- package/src/runtime/pyodide-io.ts +485 -0
- package/src/runtime/pyodide.ts +75 -215
- package/src/runtime/safe-codec.ts +443 -0
- package/src/runtime/transport.ts +273 -0
- package/src/runtime/validators.ts +241 -0
- package/src/runtime/worker-pool.ts +498 -0
- package/src/utils/codec.ts +126 -1
package/dist/runtime/node.js
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Node.js runtime bridge
|
|
2
|
+
* Node.js runtime bridge for BridgeProtocol.
|
|
3
|
+
*
|
|
4
|
+
* NodeBridge extends BridgeProtocol and uses ProcessIO transports with
|
|
5
|
+
* optional pooling for concurrent Python execution.
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/bbopen/tywrap/issues/149
|
|
3
8
|
*/
|
|
4
9
|
import { existsSync } from 'node:fs';
|
|
5
10
|
import { delimiter, isAbsolute, join, resolve } from 'node:path';
|
|
6
11
|
import { fileURLToPath } from 'node:url';
|
|
7
12
|
import { createRequire } from 'node:module';
|
|
8
|
-
import { autoRegisterArrowDecoder
|
|
13
|
+
import { autoRegisterArrowDecoder } from '../utils/codec.js';
|
|
9
14
|
import { getDefaultPythonPath } from '../utils/python.js';
|
|
10
15
|
import { getVenvBinDir, getVenvPythonExe } from '../utils/runtime.js';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
16
|
+
import { globalCache } from '../utils/cache.js';
|
|
17
|
+
import { BridgeProtocol } from './bridge-protocol.js';
|
|
18
|
+
import { BridgeProtocolError } from './errors.js';
|
|
19
|
+
import { ProcessIO } from './process-io.js';
|
|
20
|
+
import { PooledTransport } from './pooled-transport.js';
|
|
21
|
+
// =============================================================================
|
|
22
|
+
// UTILITIES
|
|
23
|
+
// =============================================================================
|
|
24
|
+
/**
|
|
25
|
+
* Resolve the default bridge script path.
|
|
26
|
+
*/
|
|
14
27
|
function resolveDefaultScriptPath() {
|
|
15
28
|
try {
|
|
16
29
|
return fileURLToPath(new URL('../../runtime/python_bridge.py', import.meta.url));
|
|
@@ -19,212 +32,352 @@ function resolveDefaultScriptPath() {
|
|
|
19
32
|
return 'runtime/python_bridge.py';
|
|
20
33
|
}
|
|
21
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolve virtual environment paths.
|
|
37
|
+
*/
|
|
22
38
|
function resolveVirtualEnv(virtualEnv, cwd) {
|
|
23
39
|
const venvPath = resolve(cwd, virtualEnv);
|
|
24
40
|
const binDir = join(venvPath, getVenvBinDir());
|
|
25
41
|
const pythonPath = join(binDir, getVenvPythonExe());
|
|
26
42
|
return { venvPath, binDir, pythonPath };
|
|
27
43
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Get the environment variable key for PATH (case-insensitive on Windows).
|
|
46
|
+
*/
|
|
47
|
+
function getPathKey(env) {
|
|
48
|
+
for (const key of Object.keys(env)) {
|
|
49
|
+
if (key.toLowerCase() === 'path') {
|
|
50
|
+
return key;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return 'PATH';
|
|
54
|
+
}
|
|
55
|
+
// =============================================================================
|
|
56
|
+
// NODE BRIDGE
|
|
57
|
+
// =============================================================================
|
|
58
|
+
/**
|
|
59
|
+
* Node.js runtime bridge for executing Python code.
|
|
60
|
+
*
|
|
61
|
+
* NodeBridge provides subprocess-based Python execution with optional pooling
|
|
62
|
+
* for high-throughput workloads. By default, it runs in single-process mode.
|
|
63
|
+
*
|
|
64
|
+
* Features:
|
|
65
|
+
* - Single or multi-process execution via process pooling
|
|
66
|
+
* - Virtual environment support
|
|
67
|
+
* - Full SafeCodec validation (NaN/Infinity rejection, key validation)
|
|
68
|
+
* - Automatic Arrow decoding for DataFrames/ndarrays
|
|
69
|
+
* - Optional result caching for pure functions
|
|
70
|
+
* - Process warmup commands
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* // Single-process mode (default)
|
|
75
|
+
* const bridge = new NodeBridge();
|
|
76
|
+
* await bridge.init();
|
|
77
|
+
*
|
|
78
|
+
* const result = await bridge.call('math', 'sqrt', [16]);
|
|
79
|
+
* console.log(result); // 4.0
|
|
80
|
+
*
|
|
81
|
+
* await bridge.dispose();
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* // Multi-process pooling for high throughput
|
|
87
|
+
* const pooledBridge = new NodeBridge({
|
|
88
|
+
* maxProcesses: 4,
|
|
89
|
+
* maxConcurrentPerProcess: 2,
|
|
90
|
+
* enableCache: true,
|
|
91
|
+
* });
|
|
92
|
+
* await pooledBridge.init();
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export class NodeBridge extends BridgeProtocol {
|
|
96
|
+
resolvedOptions;
|
|
97
|
+
pooledTransport;
|
|
98
|
+
/**
|
|
99
|
+
* Create a new NodeBridge instance.
|
|
100
|
+
*
|
|
101
|
+
* @param options - Configuration options for the bridge
|
|
102
|
+
*/
|
|
35
103
|
constructor(options = {}) {
|
|
36
|
-
super();
|
|
37
104
|
const cwd = options.cwd ?? process.cwd();
|
|
38
105
|
const virtualEnv = options.virtualEnv ? resolve(cwd, options.virtualEnv) : undefined;
|
|
39
106
|
const venv = virtualEnv ? resolveVirtualEnv(virtualEnv, cwd) : undefined;
|
|
40
107
|
const scriptPath = options.scriptPath ?? resolveDefaultScriptPath();
|
|
41
108
|
const resolvedScriptPath = isAbsolute(scriptPath) ? scriptPath : resolve(cwd, scriptPath);
|
|
42
|
-
|
|
109
|
+
const maxProcesses = options.maxProcesses ?? 1;
|
|
110
|
+
const minProcesses = Math.min(options.minProcesses ?? 1, maxProcesses);
|
|
111
|
+
const resolvedOptions = {
|
|
112
|
+
minProcesses,
|
|
113
|
+
maxProcesses,
|
|
114
|
+
maxConcurrentPerProcess: options.maxConcurrentPerProcess ?? 10,
|
|
43
115
|
pythonPath: options.pythonPath ?? venv?.pythonPath ?? getDefaultPythonPath(),
|
|
44
116
|
scriptPath: resolvedScriptPath,
|
|
45
117
|
virtualEnv,
|
|
46
118
|
cwd,
|
|
47
119
|
timeoutMs: options.timeoutMs ?? 30000,
|
|
48
|
-
|
|
120
|
+
queueTimeoutMs: options.queueTimeoutMs ?? 30000,
|
|
49
121
|
inheritProcessEnv: options.inheritProcessEnv ?? false,
|
|
50
|
-
|
|
122
|
+
enableCache: options.enableCache ?? false,
|
|
51
123
|
env: options.env ?? {},
|
|
124
|
+
codec: options.codec,
|
|
125
|
+
warmupCommands: options.warmupCommands ?? [],
|
|
52
126
|
};
|
|
127
|
+
// Build environment for ProcessIO
|
|
128
|
+
const processEnv = buildProcessEnv(resolvedOptions);
|
|
129
|
+
// Create warmup callback for per-worker initialization
|
|
130
|
+
const onWorkerReady = resolvedOptions.warmupCommands.length > 0
|
|
131
|
+
? createWarmupCallback(resolvedOptions.warmupCommands, resolvedOptions.timeoutMs)
|
|
132
|
+
: undefined;
|
|
133
|
+
// Create pooled transport with ProcessIO workers
|
|
134
|
+
const transport = new PooledTransport({
|
|
135
|
+
createTransport: () => new ProcessIO({
|
|
136
|
+
pythonPath: resolvedOptions.pythonPath,
|
|
137
|
+
bridgeScript: resolvedOptions.scriptPath,
|
|
138
|
+
env: processEnv,
|
|
139
|
+
cwd: resolvedOptions.cwd,
|
|
140
|
+
}),
|
|
141
|
+
maxWorkers: resolvedOptions.maxProcesses,
|
|
142
|
+
minWorkers: resolvedOptions.minProcesses,
|
|
143
|
+
queueTimeoutMs: resolvedOptions.queueTimeoutMs,
|
|
144
|
+
maxConcurrentPerWorker: resolvedOptions.maxConcurrentPerProcess,
|
|
145
|
+
onWorkerReady,
|
|
146
|
+
});
|
|
147
|
+
// Initialize BridgeProtocol with pooled transport
|
|
148
|
+
const protocolOptions = {
|
|
149
|
+
transport,
|
|
150
|
+
codec: resolvedOptions.codec,
|
|
151
|
+
defaultTimeoutMs: resolvedOptions.timeoutMs,
|
|
152
|
+
};
|
|
153
|
+
super(protocolOptions);
|
|
154
|
+
this.resolvedOptions = resolvedOptions;
|
|
155
|
+
this.pooledTransport = transport;
|
|
53
156
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
157
|
+
// ===========================================================================
|
|
158
|
+
// LIFECYCLE
|
|
159
|
+
// ===========================================================================
|
|
160
|
+
/**
|
|
161
|
+
* Initialize the bridge.
|
|
162
|
+
*
|
|
163
|
+
* Validates the bridge script exists, registers Arrow decoder,
|
|
164
|
+
* and initializes the transport pool (which runs warmup commands per-worker).
|
|
165
|
+
*/
|
|
166
|
+
async doInit() {
|
|
167
|
+
// Validate script exists
|
|
64
168
|
// eslint-disable-next-line security/detect-non-literal-fs-filename -- script path is user-configured
|
|
65
|
-
if (!existsSync(this.
|
|
66
|
-
throw new BridgeProtocolError(`Python bridge script not found at ${this.
|
|
67
|
-
}
|
|
68
|
-
this.initPromise = this.startProcess();
|
|
69
|
-
return this.initPromise;
|
|
70
|
-
}
|
|
71
|
-
async getBridgeInfo(options = {}) {
|
|
72
|
-
await this.init();
|
|
73
|
-
if (!this.bridgeInfo || options.refresh) {
|
|
74
|
-
await this.refreshBridgeInfo();
|
|
75
|
-
}
|
|
76
|
-
if (!this.bridgeInfo) {
|
|
77
|
-
throw new BridgeProtocolError('Bridge info unavailable');
|
|
169
|
+
if (!existsSync(this.resolvedOptions.scriptPath)) {
|
|
170
|
+
throw new BridgeProtocolError(`Python bridge script not found at ${this.resolvedOptions.scriptPath}`);
|
|
78
171
|
}
|
|
79
|
-
|
|
172
|
+
// Register Arrow decoder for DataFrames/ndarrays
|
|
173
|
+
const require = createRequire(import.meta.url);
|
|
174
|
+
await autoRegisterArrowDecoder({
|
|
175
|
+
loader: () => require('apache-arrow'),
|
|
176
|
+
});
|
|
177
|
+
// Initialize parent (which initializes transport and runs warmup per-worker)
|
|
178
|
+
await super.doInit();
|
|
80
179
|
}
|
|
180
|
+
// ===========================================================================
|
|
181
|
+
// CACHING OVERRIDE
|
|
182
|
+
// ===========================================================================
|
|
183
|
+
/**
|
|
184
|
+
* Override call() to add optional caching.
|
|
185
|
+
*/
|
|
81
186
|
async call(module, functionName, args, kwargs) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
187
|
+
// Check cache if enabled
|
|
188
|
+
if (this.resolvedOptions.enableCache) {
|
|
189
|
+
const cacheKey = this.safeCacheKey('runtime_call', module, functionName, args, kwargs);
|
|
190
|
+
if (cacheKey) {
|
|
191
|
+
const cached = await globalCache.get(cacheKey);
|
|
192
|
+
if (cached !== null) {
|
|
193
|
+
return cached;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Execute and cache if pure function
|
|
197
|
+
const startTime = performance.now();
|
|
198
|
+
const result = await super.call(module, functionName, args, kwargs);
|
|
199
|
+
const duration = performance.now() - startTime;
|
|
200
|
+
if (cacheKey && this.isPureFunctionCandidate(functionName, args)) {
|
|
201
|
+
await globalCache.set(cacheKey, result, {
|
|
202
|
+
computeTime: duration,
|
|
203
|
+
dependencies: [module],
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
// No caching - direct call
|
|
209
|
+
return super.call(module, functionName, args, kwargs);
|
|
88
210
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
211
|
+
// ===========================================================================
|
|
212
|
+
// POOL STATISTICS
|
|
213
|
+
// ===========================================================================
|
|
214
|
+
/**
|
|
215
|
+
* Get current pool statistics.
|
|
216
|
+
*/
|
|
217
|
+
getPoolStats() {
|
|
218
|
+
return {
|
|
219
|
+
workerCount: this.pooledTransport.workerCount,
|
|
220
|
+
queueLength: this.pooledTransport.queueLength,
|
|
221
|
+
totalInFlight: this.pooledTransport.totalInFlight,
|
|
222
|
+
};
|
|
92
223
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Get bridge statistics.
|
|
226
|
+
*
|
|
227
|
+
* @deprecated Use getPoolStats() instead. This method is provided for
|
|
228
|
+
* backwards compatibility and returns a subset of the previous stats.
|
|
229
|
+
*/
|
|
230
|
+
getStats() {
|
|
231
|
+
const poolStats = this.getPoolStats();
|
|
232
|
+
return {
|
|
233
|
+
// Legacy stats (no longer tracked, return 0)
|
|
234
|
+
totalRequests: 0,
|
|
235
|
+
totalTime: 0,
|
|
236
|
+
cacheHits: 0,
|
|
237
|
+
poolHits: 0,
|
|
238
|
+
poolMisses: 0,
|
|
239
|
+
processSpawns: 0,
|
|
240
|
+
processDeaths: 0,
|
|
241
|
+
memoryPeak: 0,
|
|
242
|
+
averageTime: 0,
|
|
243
|
+
cacheHitRate: 0,
|
|
244
|
+
// Current pool stats
|
|
245
|
+
poolSize: poolStats.workerCount,
|
|
246
|
+
busyWorkers: poolStats.totalInFlight,
|
|
247
|
+
};
|
|
96
248
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
249
|
+
// ===========================================================================
|
|
250
|
+
// PRIVATE HELPERS
|
|
251
|
+
// ===========================================================================
|
|
252
|
+
/**
|
|
253
|
+
* Generate a cache key, returning null if generation fails.
|
|
254
|
+
*/
|
|
255
|
+
safeCacheKey(prefix, ...inputs) {
|
|
256
|
+
try {
|
|
257
|
+
return globalCache.generateKey(prefix, ...inputs);
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
return null;
|
|
261
|
+
}
|
|
101
262
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
263
|
+
/**
|
|
264
|
+
* Heuristic to determine if function result should be cached.
|
|
265
|
+
*/
|
|
266
|
+
isPureFunctionCandidate(functionName, args) {
|
|
267
|
+
const pureFunctionPatterns = [
|
|
268
|
+
/^(get|fetch|read|load|find|search|query|select)_/i,
|
|
269
|
+
/^(compute|calculate|process|transform|convert)_/i,
|
|
270
|
+
/^(encode|decode|serialize|deserialize)_/i,
|
|
271
|
+
];
|
|
272
|
+
const impureFunctionPatterns = [
|
|
273
|
+
/^(set|save|write|update|insert|delete|create|modify)_/i,
|
|
274
|
+
/^(send|post|put|patch)_/i,
|
|
275
|
+
/random|uuid|timestamp|now|current/i,
|
|
276
|
+
];
|
|
277
|
+
if (impureFunctionPatterns.some(pattern => pattern.test(functionName))) {
|
|
278
|
+
return false;
|
|
105
279
|
}
|
|
106
|
-
if (
|
|
107
|
-
|
|
280
|
+
if (pureFunctionPatterns.some(pattern => pattern.test(functionName))) {
|
|
281
|
+
return true;
|
|
108
282
|
}
|
|
109
|
-
|
|
283
|
+
const hasComplexArgs = args.some(arg => arg !== null && typeof arg === 'object' && !(arg instanceof Date));
|
|
284
|
+
return !hasComplexArgs && args.length <= 3;
|
|
110
285
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
286
|
+
}
|
|
287
|
+
// =============================================================================
|
|
288
|
+
// WARMUP CALLBACK
|
|
289
|
+
// =============================================================================
|
|
290
|
+
/**
|
|
291
|
+
* Simple request ID generator for warmup commands.
|
|
292
|
+
*/
|
|
293
|
+
let warmupRequestId = 0;
|
|
294
|
+
function generateWarmupId() {
|
|
295
|
+
return `warmup_${++warmupRequestId}_${Date.now()}`;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Create a callback that runs warmup commands on each worker.
|
|
299
|
+
*
|
|
300
|
+
* The callback sends warmup commands directly to the worker's transport,
|
|
301
|
+
* bypassing the pool to ensure each worker gets warmed up individually.
|
|
302
|
+
*/
|
|
303
|
+
function createWarmupCallback(warmupCommands, timeoutMs) {
|
|
304
|
+
return async (worker) => {
|
|
305
|
+
for (const cmd of warmupCommands) {
|
|
121
306
|
try {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
307
|
+
// Handle both new and legacy warmup command formats
|
|
308
|
+
if ('module' in cmd && 'functionName' in cmd) {
|
|
309
|
+
// Build the protocol message
|
|
310
|
+
const message = JSON.stringify({
|
|
311
|
+
id: generateWarmupId(),
|
|
312
|
+
type: 'call',
|
|
313
|
+
module: cmd.module,
|
|
314
|
+
functionName: cmd.functionName,
|
|
315
|
+
args: cmd.args ?? [],
|
|
316
|
+
kwargs: {},
|
|
317
|
+
});
|
|
318
|
+
// Send directly to this worker's transport
|
|
319
|
+
await worker.transport.send(message, timeoutMs);
|
|
320
|
+
}
|
|
321
|
+
// Legacy format { method, params } is ignored as it's not supported
|
|
130
322
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
child.once('spawn', () => done(null));
|
|
134
|
-
});
|
|
135
|
-
if (startupError) {
|
|
136
|
-
throw new BridgeProtocolError(`Failed to start Python process: ${startupError.message}`);
|
|
323
|
+
catch {
|
|
324
|
+
// Ignore warmup errors - they're not critical
|
|
137
325
|
}
|
|
138
|
-
this.child = child;
|
|
139
|
-
this.core = new BridgeCore({
|
|
140
|
-
write: (data) => {
|
|
141
|
-
if (!this.child?.stdin) {
|
|
142
|
-
throw new BridgeProtocolError('Python process not available');
|
|
143
|
-
}
|
|
144
|
-
this.child.stdin.write(data);
|
|
145
|
-
},
|
|
146
|
-
}, {
|
|
147
|
-
timeoutMs: this.options.timeoutMs,
|
|
148
|
-
maxLineLength,
|
|
149
|
-
decodeValue: decodeValueAsync,
|
|
150
|
-
onFatalError: () => this.resetProcess(),
|
|
151
|
-
});
|
|
152
|
-
this.child.stdout?.on('data', chunk => {
|
|
153
|
-
this.core?.handleStdoutData(chunk);
|
|
154
|
-
});
|
|
155
|
-
this.child.stderr?.on('data', chunk => {
|
|
156
|
-
this.core?.handleStderrData(chunk);
|
|
157
|
-
});
|
|
158
|
-
this.child.on('error', err => {
|
|
159
|
-
this.core?.handleProcessError(err);
|
|
160
|
-
});
|
|
161
|
-
this.child.on('exit', () => {
|
|
162
|
-
this.core?.handleProcessExit();
|
|
163
|
-
this.resetProcess();
|
|
164
|
-
});
|
|
165
|
-
await this.refreshBridgeInfo();
|
|
166
|
-
}
|
|
167
|
-
catch (err) {
|
|
168
|
-
this.resetProcess();
|
|
169
|
-
throw err;
|
|
170
326
|
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
// =============================================================================
|
|
330
|
+
// ENVIRONMENT BUILDING
|
|
331
|
+
// =============================================================================
|
|
332
|
+
/**
|
|
333
|
+
* Build environment variables for ProcessIO.
|
|
334
|
+
*/
|
|
335
|
+
function buildProcessEnv(options) {
|
|
336
|
+
const allowedPrefixes = ['TYWRAP_'];
|
|
337
|
+
const allowedKeys = new Set(['path', 'pythonpath', 'virtual_env', 'pythonhome']);
|
|
338
|
+
const env = {};
|
|
339
|
+
// Copy allowed env vars from process.env
|
|
340
|
+
if (options.inheritProcessEnv) {
|
|
341
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
342
|
+
if (value !== undefined) {
|
|
343
|
+
env[key] = value;
|
|
180
344
|
}
|
|
181
345
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
349
|
+
if (value !== undefined &&
|
|
350
|
+
(allowedKeys.has(key.toLowerCase()) || allowedPrefixes.some(p => key.startsWith(p)))) {
|
|
351
|
+
env[key] = value;
|
|
189
352
|
}
|
|
190
353
|
}
|
|
191
|
-
let env = normalizeEnv(baseEnv, this.options.env);
|
|
192
|
-
if (this.options.virtualEnv) {
|
|
193
|
-
const venv = resolveVirtualEnv(this.options.virtualEnv, this.options.cwd);
|
|
194
|
-
env.VIRTUAL_ENV = venv.venvPath;
|
|
195
|
-
const pathKey = getPathKey(env);
|
|
196
|
-
// eslint-disable-next-line security/detect-object-injection -- env keys are dynamic by design
|
|
197
|
-
const currentPath = env[pathKey] ?? '';
|
|
198
|
-
// eslint-disable-next-line security/detect-object-injection -- env keys are dynamic by design
|
|
199
|
-
env[pathKey] = `${venv.binDir}${delimiter}${currentPath}`;
|
|
200
|
-
}
|
|
201
|
-
ensurePythonEncoding(env);
|
|
202
|
-
// Respect explicit request for JSON fallback only; otherwise fast-fail by default
|
|
203
|
-
ensureJsonFallback(env, this.options.enableJsonFallback);
|
|
204
|
-
env = normalizeEnv(env, {});
|
|
205
|
-
return env;
|
|
206
354
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
try {
|
|
212
|
-
if (this.child.exitCode === null) {
|
|
213
|
-
this.child.kill('SIGTERM');
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
catch {
|
|
217
|
-
// ignore
|
|
218
|
-
}
|
|
355
|
+
// Apply user overrides
|
|
356
|
+
for (const [key, value] of Object.entries(options.env)) {
|
|
357
|
+
if (value !== undefined) {
|
|
358
|
+
env[key] = value;
|
|
219
359
|
}
|
|
220
|
-
this.child = undefined;
|
|
221
|
-
this.initPromise = undefined;
|
|
222
|
-
this.bridgeInfo = undefined;
|
|
223
360
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
361
|
+
// Configure virtual environment
|
|
362
|
+
if (options.virtualEnv) {
|
|
363
|
+
const venv = resolveVirtualEnv(options.virtualEnv, options.cwd);
|
|
364
|
+
env.VIRTUAL_ENV = venv.venvPath;
|
|
365
|
+
const pathKey = getPathKey(env);
|
|
366
|
+
const currentPath = env[pathKey] ?? '';
|
|
367
|
+
env[pathKey] = `${venv.binDir}${delimiter}${currentPath}`;
|
|
368
|
+
}
|
|
369
|
+
// Add cwd to PYTHONPATH so Python can find modules in the working directory
|
|
370
|
+
if (options.cwd) {
|
|
371
|
+
const currentPythonPath = env.PYTHONPATH ?? '';
|
|
372
|
+
env.PYTHONPATH = currentPythonPath
|
|
373
|
+
? `${options.cwd}${delimiter}${currentPythonPath}`
|
|
374
|
+
: options.cwd;
|
|
228
375
|
}
|
|
376
|
+
// Ensure Python uses UTF-8
|
|
377
|
+
env.PYTHONUTF8 = '1';
|
|
378
|
+
env.PYTHONIOENCODING = 'UTF-8';
|
|
379
|
+
env.PYTHONUNBUFFERED = '1';
|
|
380
|
+
env.PYTHONDONTWRITEBYTECODE = '1';
|
|
381
|
+
return env;
|
|
229
382
|
}
|
|
230
383
|
//# sourceMappingURL=node.js.map
|
package/dist/runtime/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/runtime/node.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/runtime/node.ts"],"names":[],"mappings":"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"}
|