diff --git a/electron/main/ipc-handlers.ts b/electron/main/ipc-handlers.ts index a5f7423..4e022af 100644 --- a/electron/main/ipc-handlers.ts +++ b/electron/main/ipc-handlers.ts @@ -820,7 +820,7 @@ export function setupIpcHandlers(pythonBridge: PythonBridge, getWindow: WindowGe }) // Run a process extension in an isolated worker thread - ipcMain.handle('extensions:runProcess', async (_, extensionId: string, input: { filePath?: string; text?: string }, params: Record) => { + ipcMain.handle('extensions:runProcess', async (_, extensionId: string, nodeId: string, input: { filePath?: string; text?: string }, params: Record) => { const userData = app.getPath('userData') const { extensionsDir, workspaceDir } = getSettings(userData) @@ -848,7 +848,7 @@ export function setupIpcHandlers(pythonBridge: PythonBridge, getWindow: WindowGe runner = getProcessRunner(extensionId, extDir, entry, workspaceDir, app.getPath('temp')) } - const result = await runner.run(input, params) + const result = await runner.run(input, params, nodeId) return { success: true, result } } catch (err) { return { success: false, error: String(err) } diff --git a/electron/main/process-runner.ts b/electron/main/process-runner.ts index ca20fd3..d95322c 100644 --- a/electron/main/process-runner.ts +++ b/electron/main/process-runner.ts @@ -32,6 +32,7 @@ parentPort.on('message', async (msg) => { const context = { workspaceDir: workerData.workspaceDir, tempDir: workerData.tempDir, + nodeId: msg.nodeId ?? '', log: (m) => parentPort.postMessage({ type: 'log', message: String(m) }), progress: (pct, label) => parentPort.postMessage({ type: 'progress', percent: pct, label }), } @@ -59,6 +60,7 @@ export interface IProcessRunner { run( input: ProcessInput, params: Record, + nodeId?: string, onProgress?: (percent: number, label: string) => void, onLog?: (message: string) => void, ): Promise @@ -116,6 +118,7 @@ export class ProcessRunner implements IProcessRunner { async run( input: ProcessInput, params: Record, + nodeId?: string, onProgress?: (percent: number, label: string) => void, onLog?: (message: string) => void, ): Promise { @@ -138,7 +141,7 @@ export class ProcessRunner implements IProcessRunner { } worker.on('message', handler) - worker.postMessage({ action: 'run', input, params }) + worker.postMessage({ action: 'run', input, params, nodeId: nodeId ?? '' }) }) } @@ -170,6 +173,7 @@ export class PythonProcessRunner implements IProcessRunner { async run( input: ProcessInput, params: Record, + nodeId?: string, onProgress?: (percent: number, label: string) => void, onLog?: (message: string) => void, ): Promise { @@ -182,6 +186,7 @@ export class PythonProcessRunner implements IProcessRunner { proc.stdin.write(JSON.stringify({ input, params, + nodeId: nodeId ?? '', workspaceDir: this.workspaceDir, tempDir: this.tempDir, }) + '\n') diff --git a/electron/preload/index.ts b/electron/preload/index.ts index 24cf987..7828a9a 100644 --- a/electron/preload/index.ts +++ b/electron/preload/index.ts @@ -147,10 +147,11 @@ contextBridge.exposeInMainWorld('electron', { runProcess: ( extensionId: string, + nodeId: string, input: { filePath?: string; text?: string }, params: Record, ): Promise<{ success: boolean; result?: { filePath?: string; text?: string }; error?: string }> => - ipcRenderer.invoke('extensions:runProcess', extensionId, input, params), + ipcRenderer.invoke('extensions:runProcess', extensionId, nodeId, input, params), onInstallProgress: (cb: (data: { step: 'downloading' | 'extracting' | 'validating' | 'setting_up' | 'done' | 'error' diff --git a/src/areas/workflows/useWorkflowRunner.ts b/src/areas/workflows/useWorkflowRunner.ts index db6124b..0407820 100644 --- a/src/areas/workflows/useWorkflowRunner.ts +++ b/src/areas/workflows/useWorkflowRunner.ts @@ -175,9 +175,12 @@ export function useWorkflowRunner(allExtensions: WorkflowExtension[]) { } else { // ── Process extension ──────────────────────────────────────────────── - const extId = (node.data.extensionId ?? '').split('/')[0] + const parts = (node.data.extensionId ?? '').split('/') + const extId = parts[0] + const nodeId = parts[1] ?? '' const result = await window.electron.extensions.runProcess( extId, + nodeId, { filePath: nodeInputPath, text: nodeInputText }, node.data.params as Record, ) diff --git a/src/areas/workflows/workflowRunStore.ts b/src/areas/workflows/workflowRunStore.ts index 85b3a4d..42c15f0 100644 --- a/src/areas/workflows/workflowRunStore.ts +++ b/src/areas/workflows/workflowRunStore.ts @@ -196,9 +196,12 @@ export const useWorkflowRunStore = create((set) => ({ } } else { - const extId = (node.data.extensionId ?? '').split('/')[0] + const parts = (node.data.extensionId ?? '').split('/') + const extId = parts[0] + const nodeId = parts[1] ?? '' const result = await window.electron.extensions.runProcess( extId, + nodeId, { filePath: nodeInputPath, text: nodeInputText }, node.data.params as Record, ) diff --git a/src/shared/types/electron.d.ts b/src/shared/types/electron.d.ts index 7b1e60b..a6acbe8 100644 --- a/src/shared/types/electron.d.ts +++ b/src/shared/types/electron.d.ts @@ -214,7 +214,7 @@ declare global { uninstall: (extensionId: string) => Promise<{ success: boolean; error?: string }> repair: (extensionId: string) => Promise<{ success: boolean; error?: string }> reload: () => Promise<{ success: boolean; error?: string; errors?: Record }> - runProcess: (extensionId: string, input: ProcessInput, params: Record) => Promise<{ success: boolean; result?: ProcessResult; error?: string }> + runProcess: (extensionId: string, nodeId: string, input: ProcessInput, params: Record) => Promise<{ success: boolean; result?: ProcessResult; error?: string }> onInstallProgress: (cb: (data: { step: 'downloading' | 'extracting' | 'validating' | 'setting_up' | 'done' | 'error' percent?: number