oh-my-claude-sisyphus 3.2.5 → 3.3.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.
Files changed (56) hide show
  1. package/README.md +37 -2
  2. package/agents/scientist-high.md +1003 -0
  3. package/agents/scientist-low.md +232 -0
  4. package/agents/scientist.md +1180 -0
  5. package/bridge/__pycache__/gyoshu_bridge.cpython-310.pyc +0 -0
  6. package/bridge/gyoshu_bridge.py +846 -0
  7. package/commands/research.md +511 -0
  8. package/dist/agents/definitions.d.ts +9 -0
  9. package/dist/agents/definitions.d.ts.map +1 -1
  10. package/dist/agents/definitions.js +25 -0
  11. package/dist/agents/definitions.js.map +1 -1
  12. package/dist/agents/index.d.ts +2 -1
  13. package/dist/agents/index.d.ts.map +1 -1
  14. package/dist/agents/index.js +2 -1
  15. package/dist/agents/index.js.map +1 -1
  16. package/dist/agents/scientist.d.ts +16 -0
  17. package/dist/agents/scientist.d.ts.map +1 -0
  18. package/dist/agents/scientist.js +370 -0
  19. package/dist/agents/scientist.js.map +1 -0
  20. package/dist/lib/atomic-write.d.ts +29 -0
  21. package/dist/lib/atomic-write.d.ts.map +1 -0
  22. package/dist/lib/atomic-write.js +111 -0
  23. package/dist/lib/atomic-write.js.map +1 -0
  24. package/dist/tools/index.d.ts +1 -0
  25. package/dist/tools/index.d.ts.map +1 -1
  26. package/dist/tools/index.js +4 -1
  27. package/dist/tools/index.js.map +1 -1
  28. package/dist/tools/python-repl/bridge-manager.d.ts +65 -0
  29. package/dist/tools/python-repl/bridge-manager.d.ts.map +1 -0
  30. package/dist/tools/python-repl/bridge-manager.js +478 -0
  31. package/dist/tools/python-repl/bridge-manager.js.map +1 -0
  32. package/dist/tools/python-repl/index.d.ts +40 -0
  33. package/dist/tools/python-repl/index.d.ts.map +1 -0
  34. package/dist/tools/python-repl/index.js +36 -0
  35. package/dist/tools/python-repl/index.js.map +1 -0
  36. package/dist/tools/python-repl/paths.d.ts +84 -0
  37. package/dist/tools/python-repl/paths.d.ts.map +1 -0
  38. package/dist/tools/python-repl/paths.js +213 -0
  39. package/dist/tools/python-repl/paths.js.map +1 -0
  40. package/dist/tools/python-repl/session-lock.d.ts +111 -0
  41. package/dist/tools/python-repl/session-lock.d.ts.map +1 -0
  42. package/dist/tools/python-repl/session-lock.js +510 -0
  43. package/dist/tools/python-repl/session-lock.js.map +1 -0
  44. package/dist/tools/python-repl/socket-client.d.ts +42 -0
  45. package/dist/tools/python-repl/socket-client.d.ts.map +1 -0
  46. package/dist/tools/python-repl/socket-client.js +157 -0
  47. package/dist/tools/python-repl/socket-client.js.map +1 -0
  48. package/dist/tools/python-repl/tool.d.ts +100 -0
  49. package/dist/tools/python-repl/tool.d.ts.map +1 -0
  50. package/dist/tools/python-repl/tool.js +575 -0
  51. package/dist/tools/python-repl/tool.js.map +1 -0
  52. package/dist/tools/python-repl/types.d.ts +95 -0
  53. package/dist/tools/python-repl/types.d.ts.map +1 -0
  54. package/dist/tools/python-repl/types.js +2 -0
  55. package/dist/tools/python-repl/types.js.map +1 -0
  56. package/package.json +2 -1
@@ -0,0 +1,478 @@
1
+ /**
2
+ * Bridge Manager - Python process lifecycle management
3
+ *
4
+ * Manages the gyoshu_bridge.py process:
5
+ * - Spawning with proper environment detection
6
+ * - Ensuring single bridge per session with security validations
7
+ * - Graceful shutdown with signal escalation
8
+ * - PID reuse detection via process identity verification
9
+ */
10
+ import { spawn } from 'child_process';
11
+ import * as fs from 'fs';
12
+ import * as fsPromises from 'fs/promises';
13
+ import * as path from 'path';
14
+ import { fileURLToPath } from 'url';
15
+ import { execFile } from 'child_process';
16
+ import { promisify } from 'util';
17
+ import { getSessionDir, getBridgeSocketPath, getBridgeMetaPath } from './paths.js';
18
+ import { atomicWriteJson, safeReadJson, ensureDirSync } from '../../lib/atomic-write.js';
19
+ const execFileAsync = promisify(execFile);
20
+ // =============================================================================
21
+ // CONSTANTS
22
+ // =============================================================================
23
+ const BRIDGE_SPAWN_TIMEOUT_MS = 30000; // 30 seconds to wait for socket
24
+ const DEFAULT_GRACE_PERIOD_MS = 5000; // 5 seconds for SIGINT
25
+ const SIGTERM_GRACE_MS = 2500; // 2.5 seconds for SIGTERM
26
+ // =============================================================================
27
+ // BRIDGE PATH RESOLUTION
28
+ // =============================================================================
29
+ /**
30
+ * Resolve the path to gyoshu_bridge.py relative to this module.
31
+ * The bridge script is at: <package-root>/bridge/gyoshu_bridge.py
32
+ */
33
+ function getBridgeScriptPath() {
34
+ // In ESM, __dirname equivalent is:
35
+ const __filename = fileURLToPath(import.meta.url);
36
+ const __dirname = path.dirname(__filename);
37
+ // From src/tools/python-repl/ -> ../../.. -> package root -> bridge/
38
+ const packageRoot = path.resolve(__dirname, '..', '..', '..');
39
+ return path.join(packageRoot, 'bridge', 'gyoshu_bridge.py');
40
+ }
41
+ // =============================================================================
42
+ // PYTHON ENVIRONMENT DETECTION
43
+ // =============================================================================
44
+ /**
45
+ * Detect an existing Python virtual environment in the project directory.
46
+ * Returns null if no .venv is found.
47
+ */
48
+ function detectExistingPythonEnv(projectRoot) {
49
+ const isWindows = process.platform === 'win32';
50
+ const binDir = isWindows ? 'Scripts' : 'bin';
51
+ const pythonExe = isWindows ? 'python.exe' : 'python';
52
+ const venvPython = path.join(projectRoot, '.venv', binDir, pythonExe);
53
+ if (fs.existsSync(venvPython)) {
54
+ return { pythonPath: venvPython, type: 'venv' };
55
+ }
56
+ return null;
57
+ }
58
+ /**
59
+ * Ensure a Python environment is available for the project.
60
+ * Currently requires an existing .venv - does not auto-create.
61
+ */
62
+ async function ensurePythonEnvironment(projectRoot) {
63
+ const existing = detectExistingPythonEnv(projectRoot);
64
+ if (existing) {
65
+ return existing;
66
+ }
67
+ // Fallback: try system python3
68
+ try {
69
+ await execFileAsync('python3', ['--version']);
70
+ return { pythonPath: 'python3', type: 'venv' };
71
+ }
72
+ catch {
73
+ // python3 not available
74
+ }
75
+ throw new Error('No Python environment found. Create a virtual environment first:\n' +
76
+ ' python -m venv .venv\n' +
77
+ ' .venv/bin/pip install pandas numpy matplotlib');
78
+ }
79
+ // =============================================================================
80
+ // PROCESS IDENTITY VERIFICATION
81
+ // =============================================================================
82
+ /**
83
+ * Get process start time on Linux via /proc/{pid}/stat field 22.
84
+ */
85
+ async function getProcessStartTimeLinux(pid) {
86
+ try {
87
+ const stat = await fsPromises.readFile(`/proc/${pid}/stat`, 'utf8');
88
+ const closeParen = stat.lastIndexOf(')');
89
+ if (closeParen === -1)
90
+ return undefined;
91
+ const fieldsAfterComm = stat.substring(closeParen + 2).split(' ');
92
+ // starttime is field 22 in /proc/pid/stat, index 19 after removing pid and comm
93
+ const startTimeField = fieldsAfterComm[19];
94
+ if (!startTimeField)
95
+ return undefined;
96
+ const startTime = parseInt(startTimeField, 10);
97
+ return isNaN(startTime) ? undefined : startTime;
98
+ }
99
+ catch {
100
+ return undefined;
101
+ }
102
+ }
103
+ /**
104
+ * Get process start time on macOS via `ps -p {pid} -o lstart=`.
105
+ */
106
+ async function getProcessStartTimeMacOS(pid) {
107
+ if (typeof pid !== 'number' || !Number.isInteger(pid) || pid <= 0)
108
+ return undefined;
109
+ try {
110
+ const { stdout } = await execFileAsync('ps', ['-p', String(pid), '-o', 'lstart='], {
111
+ env: { ...process.env, LC_ALL: 'C' },
112
+ });
113
+ const lstart = stdout.trim();
114
+ if (!lstart)
115
+ return undefined;
116
+ const date = new Date(lstart);
117
+ if (isNaN(date.getTime()))
118
+ return undefined;
119
+ return date.getTime();
120
+ }
121
+ catch {
122
+ return undefined;
123
+ }
124
+ }
125
+ /**
126
+ * Get process start time for a given PID (cross-platform).
127
+ */
128
+ async function getProcessStartTime(pid) {
129
+ if (process.platform === 'linux') {
130
+ return getProcessStartTimeLinux(pid);
131
+ }
132
+ else if (process.platform === 'darwin') {
133
+ return getProcessStartTimeMacOS(pid);
134
+ }
135
+ return undefined;
136
+ }
137
+ /**
138
+ * Check if a process is alive (basic check, no start time verification).
139
+ */
140
+ function isProcessAliveBasic(pid) {
141
+ try {
142
+ process.kill(pid, 0);
143
+ return true;
144
+ }
145
+ catch {
146
+ return false;
147
+ }
148
+ }
149
+ /**
150
+ * Verify that a bridge process is still running and is the same process
151
+ * that was originally spawned (guards against PID reuse).
152
+ *
153
+ * Returns false if:
154
+ * - Process is not alive
155
+ * - Start time was recorded but doesn't match (PID reused)
156
+ * - Start time was recorded but cannot be retrieved (fail-closed)
157
+ */
158
+ export async function verifyProcessIdentity(meta) {
159
+ // Basic alive check first
160
+ if (!isProcessAliveBasic(meta.pid)) {
161
+ return false;
162
+ }
163
+ // If we have a recorded start time, verify it matches
164
+ if (meta.processStartTime !== undefined) {
165
+ const currentStartTime = await getProcessStartTime(meta.pid);
166
+ // Fail-closed: if we can't get current start time but we have a recorded one,
167
+ // assume PID reuse has occurred (safer than assuming same process)
168
+ if (currentStartTime === undefined) {
169
+ return false;
170
+ }
171
+ if (currentStartTime !== meta.processStartTime) {
172
+ return false; // PID reuse detected
173
+ }
174
+ }
175
+ return true;
176
+ }
177
+ // =============================================================================
178
+ // SOCKET UTILITIES
179
+ // =============================================================================
180
+ /**
181
+ * Check if a path points to a Unix socket.
182
+ */
183
+ function isSocket(socketPath) {
184
+ try {
185
+ const stat = fs.lstatSync(socketPath);
186
+ return stat.isSocket();
187
+ }
188
+ catch {
189
+ return false;
190
+ }
191
+ }
192
+ /**
193
+ * Safely unlink a socket file if it exists within the expected directory.
194
+ */
195
+ function safeUnlinkSocket(socketPath) {
196
+ try {
197
+ if (fs.existsSync(socketPath)) {
198
+ fs.unlinkSync(socketPath);
199
+ }
200
+ }
201
+ catch {
202
+ // Ignore errors
203
+ }
204
+ }
205
+ // =============================================================================
206
+ // BRIDGE METADATA VALIDATION
207
+ // =============================================================================
208
+ /**
209
+ * Validate that parsed JSON matches BridgeMeta schema.
210
+ */
211
+ function isValidBridgeMeta(data) {
212
+ if (typeof data !== 'object' || data === null)
213
+ return false;
214
+ const obj = data;
215
+ return (typeof obj.pid === 'number' &&
216
+ Number.isInteger(obj.pid) &&
217
+ obj.pid > 0 &&
218
+ typeof obj.socketPath === 'string' &&
219
+ typeof obj.startedAt === 'string' &&
220
+ typeof obj.sessionId === 'string' &&
221
+ typeof obj.pythonEnv === 'object' &&
222
+ obj.pythonEnv !== null &&
223
+ typeof obj.pythonEnv.pythonPath === 'string' &&
224
+ (obj.processStartTime === undefined || typeof obj.processStartTime === 'number'));
225
+ }
226
+ // =============================================================================
227
+ // PROCESS GROUP MANAGEMENT
228
+ // =============================================================================
229
+ /**
230
+ * Kill a process group (process + children).
231
+ * Uses negative PID to target the process group.
232
+ */
233
+ function killProcessGroup(pid, signal) {
234
+ try {
235
+ // Negative PID sends signal to process group
236
+ process.kill(-pid, signal);
237
+ return true;
238
+ }
239
+ catch {
240
+ // Process might already be dead
241
+ try {
242
+ // Fallback: kill just the process
243
+ process.kill(pid, signal);
244
+ return true;
245
+ }
246
+ catch {
247
+ return false;
248
+ }
249
+ }
250
+ }
251
+ // =============================================================================
252
+ // SPAWN BRIDGE SERVER
253
+ // =============================================================================
254
+ /**
255
+ * Spawn a new bridge server process for the given session.
256
+ *
257
+ * @param sessionId - Unique session identifier
258
+ * @param projectDir - Optional project directory (defaults to cwd)
259
+ * @returns BridgeMeta containing process information
260
+ */
261
+ export async function spawnBridgeServer(sessionId, projectDir) {
262
+ const sessionDir = getSessionDir(sessionId);
263
+ ensureDirSync(sessionDir);
264
+ const socketPath = getBridgeSocketPath(sessionId);
265
+ const bridgePath = getBridgeScriptPath();
266
+ // Verify bridge script exists
267
+ if (!fs.existsSync(bridgePath)) {
268
+ throw new Error(`Bridge script not found: ${bridgePath}`);
269
+ }
270
+ // Clean up any stale socket
271
+ safeUnlinkSocket(socketPath);
272
+ const effectiveProjectDir = projectDir || process.cwd();
273
+ const pythonEnv = await ensurePythonEnvironment(effectiveProjectDir);
274
+ // Pass socket path as positional argument (matches gyoshu_bridge.py argparse)
275
+ const bridgeArgs = [bridgePath, socketPath];
276
+ const proc = spawn(pythonEnv.pythonPath, bridgeArgs, {
277
+ stdio: ['ignore', 'ignore', 'pipe'],
278
+ cwd: effectiveProjectDir,
279
+ env: { ...process.env, PYTHONUNBUFFERED: '1' },
280
+ detached: true,
281
+ });
282
+ proc.unref();
283
+ // Capture stderr for error reporting (capped at 64KB)
284
+ const MAX_STDERR_CHARS = 64 * 1024;
285
+ let stderrBuffer = '';
286
+ let stderrTruncated = false;
287
+ proc.stderr?.on('data', (chunk) => {
288
+ if (stderrTruncated)
289
+ return;
290
+ const text = chunk.toString();
291
+ if (stderrBuffer.length + text.length > MAX_STDERR_CHARS) {
292
+ stderrBuffer = stderrBuffer.slice(0, MAX_STDERR_CHARS - 20) + '\n...[truncated]';
293
+ stderrTruncated = true;
294
+ }
295
+ else {
296
+ stderrBuffer += text;
297
+ }
298
+ });
299
+ // Wait for socket to appear
300
+ const startTime = Date.now();
301
+ while (!isSocket(socketPath)) {
302
+ if (Date.now() - startTime > BRIDGE_SPAWN_TIMEOUT_MS) {
303
+ // Kill the process on timeout
304
+ if (proc.pid) {
305
+ killProcessGroup(proc.pid, 'SIGKILL');
306
+ }
307
+ // Clean up any non-socket file that might exist (poisoning attempt)
308
+ if (fs.existsSync(socketPath) && !isSocket(socketPath)) {
309
+ safeUnlinkSocket(socketPath);
310
+ }
311
+ throw new Error(`Bridge failed to create socket in ${BRIDGE_SPAWN_TIMEOUT_MS}ms. ` +
312
+ `Stderr: ${stderrBuffer || '(empty)'}`);
313
+ }
314
+ await sleep(100);
315
+ }
316
+ // Get process start time for PID reuse detection
317
+ const processStartTime = proc.pid ? await getProcessStartTime(proc.pid) : undefined;
318
+ const meta = {
319
+ pid: proc.pid,
320
+ socketPath,
321
+ startedAt: new Date().toISOString(),
322
+ sessionId,
323
+ pythonEnv,
324
+ processStartTime,
325
+ };
326
+ // Persist metadata
327
+ const metaPath = getBridgeMetaPath(sessionId);
328
+ await atomicWriteJson(metaPath, meta);
329
+ return meta;
330
+ }
331
+ // =============================================================================
332
+ // ENSURE BRIDGE
333
+ // =============================================================================
334
+ /**
335
+ * Get or spawn a bridge server for the session.
336
+ *
337
+ * Implements security validations:
338
+ * - Anti-poisoning: Verifies sessionId in metadata matches expected
339
+ * - Anti-hijack: Verifies socketPath is the expected canonical path
340
+ * - Socket type: Verifies the socket path is actually a socket
341
+ * - Process identity: Verifies PID + start time match
342
+ *
343
+ * @param sessionId - Unique session identifier
344
+ * @param projectDir - Optional project directory (defaults to cwd)
345
+ * @returns BridgeMeta for the active bridge
346
+ */
347
+ export async function ensureBridge(sessionId, projectDir) {
348
+ const metaPath = getBridgeMetaPath(sessionId);
349
+ const expectedSocketPath = getBridgeSocketPath(sessionId);
350
+ const meta = await safeReadJson(metaPath);
351
+ if (meta && isValidBridgeMeta(meta)) {
352
+ // Security validation 1: Anti-poisoning - verify sessionId matches
353
+ if (meta.sessionId !== sessionId) {
354
+ await deleteBridgeMeta(sessionId);
355
+ return spawnBridgeServer(sessionId, projectDir);
356
+ }
357
+ // Security validation 2: Anti-hijack - verify socket path is expected
358
+ if (meta.socketPath !== expectedSocketPath) {
359
+ await deleteBridgeMeta(sessionId);
360
+ return spawnBridgeServer(sessionId, projectDir);
361
+ }
362
+ // Security validation 3: Process identity - verify PID is still our process
363
+ const stillOurs = await verifyProcessIdentity(meta);
364
+ if (stillOurs) {
365
+ // Security validation 4: Socket type - verify it's actually a socket
366
+ if (isSocket(meta.socketPath)) {
367
+ return meta;
368
+ }
369
+ else {
370
+ // Socket missing or wrong type - kill the orphan process
371
+ try {
372
+ process.kill(meta.pid, 'SIGKILL');
373
+ }
374
+ catch {
375
+ // Process might already be dead
376
+ }
377
+ }
378
+ }
379
+ await deleteBridgeMeta(sessionId);
380
+ }
381
+ return spawnBridgeServer(sessionId, projectDir);
382
+ }
383
+ // =============================================================================
384
+ // KILL BRIDGE WITH ESCALATION
385
+ // =============================================================================
386
+ /**
387
+ * Terminate a bridge process with signal escalation.
388
+ *
389
+ * Escalation order:
390
+ * 1. SIGINT - wait gracePeriodMs (default 5000ms)
391
+ * 2. SIGTERM - wait 2500ms
392
+ * 3. SIGKILL - immediate termination
393
+ *
394
+ * Uses process group kill (-pid) to also terminate child processes.
395
+ *
396
+ * @param sessionId - Session whose bridge to kill
397
+ * @param options - Optional configuration
398
+ * @returns EscalationResult with termination details
399
+ */
400
+ export async function killBridgeWithEscalation(sessionId, options) {
401
+ const gracePeriod = options?.gracePeriodMs ?? DEFAULT_GRACE_PERIOD_MS;
402
+ const startTime = Date.now();
403
+ const metaPath = getBridgeMetaPath(sessionId);
404
+ const meta = await safeReadJson(metaPath);
405
+ if (!meta || !isValidBridgeMeta(meta)) {
406
+ return { terminated: true }; // Already dead or no metadata
407
+ }
408
+ // Anti-poisoning check
409
+ if (meta.sessionId !== sessionId) {
410
+ await deleteBridgeMeta(sessionId);
411
+ return { terminated: true };
412
+ }
413
+ // Verify we're killing the right process
414
+ if (!(await verifyProcessIdentity(meta))) {
415
+ await deleteBridgeMeta(sessionId);
416
+ return { terminated: true }; // Process already dead or PID reused
417
+ }
418
+ // Helper to wait for process exit with identity verification
419
+ const waitForExit = async (timeoutMs) => {
420
+ const checkStart = Date.now();
421
+ while (Date.now() - checkStart < timeoutMs) {
422
+ const stillOurs = await verifyProcessIdentity(meta);
423
+ if (!stillOurs) {
424
+ return true; // Process is gone or PID reused
425
+ }
426
+ await sleep(100);
427
+ }
428
+ return false;
429
+ };
430
+ let terminatedBy = 'SIGINT';
431
+ // Stage 1: SIGINT
432
+ killProcessGroup(meta.pid, 'SIGINT');
433
+ if (!(await waitForExit(gracePeriod))) {
434
+ // Stage 2: SIGTERM
435
+ terminatedBy = 'SIGTERM';
436
+ killProcessGroup(meta.pid, 'SIGTERM');
437
+ if (!(await waitForExit(SIGTERM_GRACE_MS))) {
438
+ // Stage 3: SIGKILL
439
+ terminatedBy = 'SIGKILL';
440
+ killProcessGroup(meta.pid, 'SIGKILL');
441
+ await waitForExit(1000); // Brief wait for SIGKILL
442
+ }
443
+ }
444
+ // Cleanup
445
+ await deleteBridgeMeta(sessionId);
446
+ const sessionDir = getSessionDir(sessionId);
447
+ const socketPath = meta.socketPath;
448
+ if (socketPath.startsWith(sessionDir)) {
449
+ safeUnlinkSocket(socketPath);
450
+ }
451
+ return {
452
+ terminated: true,
453
+ terminatedBy,
454
+ terminationTimeMs: Date.now() - startTime,
455
+ };
456
+ }
457
+ // =============================================================================
458
+ // HELPER FUNCTIONS
459
+ // =============================================================================
460
+ /**
461
+ * Delete bridge metadata file.
462
+ */
463
+ async function deleteBridgeMeta(sessionId) {
464
+ const metaPath = getBridgeMetaPath(sessionId);
465
+ try {
466
+ await fsPromises.unlink(metaPath);
467
+ }
468
+ catch {
469
+ // Ignore errors (file might not exist)
470
+ }
471
+ }
472
+ /**
473
+ * Sleep for specified milliseconds.
474
+ */
475
+ function sleep(ms) {
476
+ return new Promise((resolve) => setTimeout(resolve, ms));
477
+ }
478
+ //# sourceMappingURL=bridge-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-manager.js","sourceRoot":"","sources":["../../../src/tools/python-repl/bridge-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Python REPL Tool - Persistent Python execution environment
3
+ *
4
+ * Provides a persistent Python REPL with variable persistence across
5
+ * tool invocations, session locking, and structured output markers.
6
+ */
7
+ import { pythonReplHandler } from './tool.js';
8
+ export declare const pythonReplTool: {
9
+ name: string;
10
+ description: string;
11
+ schema: import("zod").ZodObject<{
12
+ action: import("zod").ZodEnum<["execute", "interrupt", "reset", "get_state"]>;
13
+ researchSessionID: import("zod").ZodString;
14
+ code: import("zod").ZodOptional<import("zod").ZodString>;
15
+ executionLabel: import("zod").ZodOptional<import("zod").ZodString>;
16
+ executionTimeout: import("zod").ZodDefault<import("zod").ZodNumber>;
17
+ queueTimeout: import("zod").ZodDefault<import("zod").ZodNumber>;
18
+ projectDir: import("zod").ZodOptional<import("zod").ZodString>;
19
+ }, "strip", import("zod").ZodTypeAny, {
20
+ action: "execute" | "interrupt" | "reset" | "get_state";
21
+ researchSessionID: string;
22
+ executionTimeout: number;
23
+ queueTimeout: number;
24
+ code?: string | undefined;
25
+ executionLabel?: string | undefined;
26
+ projectDir?: string | undefined;
27
+ }, {
28
+ action: "execute" | "interrupt" | "reset" | "get_state";
29
+ researchSessionID: string;
30
+ code?: string | undefined;
31
+ executionLabel?: string | undefined;
32
+ executionTimeout?: number | undefined;
33
+ queueTimeout?: number | undefined;
34
+ projectDir?: string | undefined;
35
+ }>;
36
+ handler: typeof pythonReplHandler;
37
+ };
38
+ export * from './types.js';
39
+ export { pythonReplSchema, pythonReplHandler } from './tool.js';
40
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/python-repl/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAoB,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEhE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyB1B,CAAC;AAGF,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Python REPL Tool - Persistent Python execution environment
3
+ *
4
+ * Provides a persistent Python REPL with variable persistence across
5
+ * tool invocations, session locking, and structured output markers.
6
+ */
7
+ import { pythonReplSchema, pythonReplHandler } from './tool.js';
8
+ export const pythonReplTool = {
9
+ name: 'python_repl',
10
+ description: `Execute Python code in a persistent REPL environment with variable persistence across invocations.
11
+
12
+ Actions:
13
+ - execute: Run Python code (variables persist between calls)
14
+ - reset: Clear namespace and reset environment
15
+ - get_state: Get memory usage and list of defined variables
16
+ - interrupt: Stop long-running execution
17
+
18
+ Features:
19
+ - Variables persist across tool calls within the same session
20
+ - Structured output markers: [OBJECTIVE], [DATA], [FINDING], [STAT:*], [LIMITATION]
21
+ - Memory tracking (RSS/VMS)
22
+ - Automatic timeout handling (default 5 minutes)
23
+ - Session locking for safe concurrent access
24
+
25
+ Use this instead of Bash heredocs when you need:
26
+ - Multi-step analysis with state persistence
27
+ - Large datasets that shouldn't be reloaded
28
+ - Iterative ML model training
29
+ - Any workflow benefiting from Python state persistence`,
30
+ schema: pythonReplSchema,
31
+ handler: pythonReplHandler
32
+ };
33
+ // Re-export types for convenience
34
+ export * from './types.js';
35
+ export { pythonReplSchema, pythonReplHandler } from './tool.js';
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/python-repl/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEhE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE;;;;;;;;;;;;;;;;;;;wDAmByC;IAEtD,MAAM,EAAE,gBAAgB;IACxB,OAAO,EAAE,iBAAiB;CAC3B,CAAC;AAEF,kCAAkC;AAClC,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Path utilities for Python REPL tool
3
+ *
4
+ * Provides secure path resolution for session directories, sockets, and metadata.
5
+ * Uses OS-appropriate runtime directories outside the project root.
6
+ */
7
+ /**
8
+ * Get the path to the runtime directory.
9
+ * Contains ephemeral session data like locks and sockets.
10
+ * Uses OS-appropriate temp directories.
11
+ *
12
+ * Priority:
13
+ * 1. XDG_RUNTIME_DIR/omc (Linux standard, usually /run/user/{uid})
14
+ * 2. Platform-specific user cache directory
15
+ * 3. os.tmpdir() fallback
16
+ *
17
+ * @returns Path to runtime directory
18
+ *
19
+ * @example
20
+ * getRuntimeDir();
21
+ * // Linux with XDG: '/run/user/1000/omc'
22
+ * // macOS: '~/Library/Caches/omc/runtime'
23
+ * // Fallback: '/tmp/omc/runtime'
24
+ */
25
+ export declare function getRuntimeDir(): string;
26
+ /**
27
+ * Shorten a session ID to fit within Unix socket path constraints.
28
+ * Uses SHA256 hash truncated to 12 hex chars (48 bits).
29
+ *
30
+ * Unix sockets have path length limits (UNIX_PATH_MAX):
31
+ * - Linux: 108 bytes
32
+ * - macOS: 104 bytes
33
+ *
34
+ * SECURITY: Always hashes the input, even for short IDs.
35
+ * This prevents path traversal attacks via malicious short IDs like ".." or "../x".
36
+ *
37
+ * @param sessionId - Original session identifier (can be any length)
38
+ * @returns Short identifier (12 hex chars) suitable for socket paths
39
+ */
40
+ export declare function shortenSessionId(sessionId: string): string;
41
+ /**
42
+ * Get the path to a specific session's runtime directory.
43
+ * Uses shortened session ID to ensure socket paths stay within limits.
44
+ *
45
+ * @param sessionId - Unique identifier for the session
46
+ * @returns Path to runtime/{shortId}/ in OS temp directory
47
+ */
48
+ export declare function getSessionDir(sessionId: string): string;
49
+ /**
50
+ * Get the path to a session's bridge socket.
51
+ * Path is kept short to respect Unix socket path limits (~108 bytes).
52
+ *
53
+ * @param sessionId - Unique identifier for the session
54
+ * @returns Path to bridge.sock in session's runtime directory
55
+ */
56
+ export declare function getBridgeSocketPath(sessionId: string): string;
57
+ /**
58
+ * Get the path to a session's bridge metadata file.
59
+ *
60
+ * @param sessionId - Unique identifier for the session
61
+ * @returns Path to bridge_meta.json in session's runtime directory
62
+ */
63
+ export declare function getBridgeMetaPath(sessionId: string): string;
64
+ /**
65
+ * Get the path to a session's lock file.
66
+ *
67
+ * @param sessionId - Unique identifier for the session
68
+ * @returns Path to session.lock in session's runtime directory
69
+ */
70
+ export declare function getSessionLockPath(sessionId: string): string;
71
+ /**
72
+ * Validates that a path segment is safe to use in file paths.
73
+ * Prevents directory traversal and path injection attacks.
74
+ *
75
+ * @param segment - The path segment to validate (e.g., session ID, file name)
76
+ * @param name - Name of the parameter for error messages (e.g., "sessionId", "filename")
77
+ * @throws Error if segment is invalid
78
+ *
79
+ * @example
80
+ * validatePathSegment("my-session-123", "sessionId"); // OK
81
+ * validatePathSegment("../evil", "sessionId"); // throws Error
82
+ */
83
+ export declare function validatePathSegment(segment: string, name: string): void;
84
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/tools/python-repl/paths.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2DH;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAkBtC;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAQ1D;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE5D;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAyCvE"}