|
5 | 5 | import type { ExtendedOpenFlow, FlowEditorContext } from '$lib/components/flows/types' |
6 | 6 | import { dfs } from '$lib/components/flows/previousResults' |
7 | 7 | import { dfs as dfsApply } from '$lib/components/flows/dfs' |
8 | | - import { getSubModules } from '$lib/components/flows/flowExplorer' |
9 | | - import type { FlowModule, OpenFlow } from '$lib/gen' |
10 | | - import { getIndexInNestedModules, getNestedModules } from './utils' |
| 8 | + import type { OpenFlow } from '$lib/gen' |
| 9 | + import { getIndexInNestedModules } from './utils' |
11 | 10 | import type { AIModuleAction, FlowAIChatHelpers } from './core' |
12 | | - import { |
13 | | - insertNewFailureModule, |
14 | | - insertNewPreprocessorModule |
15 | | - } from '$lib/components/flows/flowStateUtils.svelte' |
16 | 11 | import { loadSchemaFromModule } from '$lib/components/flows/flowInfers' |
17 | 12 | import { aiChatManager } from '../AIChatManager.svelte' |
18 | 13 | import { refreshStateStore } from '$lib/svelte5Utils.svelte' |
19 | 14 | import DiffDrawer from '$lib/components/DiffDrawer.svelte' |
20 | | - import type { AgentTool } from '$lib/components/flows/agentToolUtils' |
21 | 15 | import YAML from 'yaml' |
22 | 16 |
|
23 | 17 | /** |
|
140 | 134 | } |
141 | 135 | }, |
142 | 136 | showModuleDiff(id: string) { |
143 | | - // In debug mode, create a snapshot if none exists |
144 | | - // This allows testing the diff UI even without real AI changes |
145 | | - if (!lastSnapshot && isDebugDiffModeEnabled()) { |
146 | | - lastSnapshot = $state.snapshot(flowStore).val |
147 | | - } |
148 | | -
|
149 | 137 | if (!lastSnapshot) { |
150 | 138 | return |
151 | 139 | } |
|
169 | 157 | }) |
170 | 158 | } |
171 | 159 | }, |
172 | | - getModuleAction: (id: string) => { |
173 | | - return affectedModules[id]?.action |
174 | | - }, |
175 | 160 | revertModuleAction: (id: string) => { |
176 | 161 | { |
177 | 162 | const action = affectedModules[id]?.action |
|
257 | 242 | } |
258 | 243 | setModuleStatus(id, 'modified') |
259 | 244 | }, |
260 | | - insertStep: async (location, step) => { |
261 | | - const { index, modules } = |
262 | | - location.type === 'start' |
263 | | - ? { |
264 | | - index: -1, |
265 | | - modules: flowStore.val.value.modules |
266 | | - } |
267 | | - : location.type === 'start_inside_forloop' |
268 | | - ? { |
269 | | - index: -1, |
270 | | - modules: getNestedModules(flowStore.val, location.inside) |
271 | | - } |
272 | | - : location.type === 'start_inside_branch' |
273 | | - ? { |
274 | | - index: -1, |
275 | | - modules: getNestedModules(flowStore.val, location.inside, location.branchIndex) |
276 | | - } |
277 | | - : location.type === 'after' |
278 | | - ? getIndexInNestedModules(flowStore.val, location.afterId) |
279 | | - : { |
280 | | - index: -1, |
281 | | - modules: flowStore.val.value.modules |
282 | | - } |
283 | | -
|
284 | | - const indexToInsertAt = index + 1 |
285 | | -
|
286 | | - let newModules: FlowModule[] | AgentTool[] | undefined = undefined |
287 | | - switch (step.type) { |
288 | | - case 'rawscript': { |
289 | | - const inlineScript = { |
290 | | - language: step.language, |
291 | | - kind: 'script' as const, |
292 | | - subkind: 'flow' as const, |
293 | | - summary: step.summary |
294 | | - } |
295 | | - if (location.type === 'preprocessor') { |
296 | | - await insertNewPreprocessorModule(flowStore, flowStateStore, inlineScript) |
297 | | - } else if (location.type === 'failure') { |
298 | | - await insertNewFailureModule(flowStore, flowStateStore, inlineScript) |
299 | | - } else { |
300 | | - newModules = await flowModuleSchemaMap?.insertNewModuleAtIndex( |
301 | | - modules, |
302 | | - indexToInsertAt, |
303 | | - 'script', |
304 | | - undefined, |
305 | | - undefined, |
306 | | - inlineScript |
307 | | - ) |
308 | | - } |
309 | | - break |
310 | | - } |
311 | | - case 'script': { |
312 | | - const wsScript = { |
313 | | - path: step.path, |
314 | | - summary: '', |
315 | | - hash: undefined |
316 | | - } |
317 | | - if (location.type === 'preprocessor') { |
318 | | - await insertNewPreprocessorModule(flowStore, flowStateStore, undefined, wsScript) |
319 | | - } else if (location.type === 'failure') { |
320 | | - await insertNewFailureModule(flowStore, flowStateStore, undefined, wsScript) |
321 | | - } else { |
322 | | - newModules = await flowModuleSchemaMap?.insertNewModuleAtIndex( |
323 | | - modules, |
324 | | - indexToInsertAt, |
325 | | - 'script', |
326 | | - wsScript |
327 | | - ) |
328 | | - } |
329 | | - break |
330 | | - } |
331 | | - case 'forloop': |
332 | | - case 'branchall': |
333 | | - case 'branchone': { |
334 | | - if (location.type === 'preprocessor' || location.type === 'failure') { |
335 | | - throw new Error('Cannot insert a non-script module for preprocessing or error handling') |
336 | | - } |
337 | | - newModules = await flowModuleSchemaMap?.insertNewModuleAtIndex( |
338 | | - modules, |
339 | | - indexToInsertAt, |
340 | | - step.type |
341 | | - ) |
342 | | - break |
343 | | - } |
344 | | - default: { |
345 | | - throw new Error('Unknown step type') |
346 | | - } |
347 | | - } |
348 | | -
|
349 | | - if (location.type === 'preprocessor' || location.type === 'failure') { |
350 | | - refreshStateStore(flowStore) |
351 | | -
|
352 | | - setModuleStatus(location.type, 'added') |
353 | | -
|
354 | | - return location.type |
355 | | - } else { |
356 | | - const newModule = newModules?.[indexToInsertAt] |
357 | | -
|
358 | | - if (!newModule) { |
359 | | - throw new Error('Failed to insert module') |
360 | | - } |
361 | | -
|
362 | | - if (['branchone', 'branchall'].includes(step.type)) { |
363 | | - await flowModuleSchemaMap?.addBranch(newModule.id) |
364 | | - } |
365 | | -
|
366 | | - refreshStateStore(flowStore) |
367 | | -
|
368 | | - setModuleStatus(newModule.id, 'added') |
369 | | -
|
370 | | - return newModule.id |
371 | | - } |
372 | | - }, |
373 | | - removeStep: (id) => { |
374 | | - setModuleStatus(id, 'removed') |
375 | | - }, |
376 | | - getStepInputs: async (id) => { |
377 | | - const module = getModule(id) |
378 | | - if (!module) { |
379 | | - throw new Error('Module not found') |
380 | | - } |
381 | | - const inputs = |
382 | | - module.value.type === 'script' || module.value.type === 'rawscript' |
383 | | - ? module.value.input_transforms |
384 | | - : {} |
385 | | -
|
386 | | - return inputs |
387 | | - }, |
388 | | - setStepInputs: async (id, inputs) => { |
389 | | - if (id === 'preprocessor') { |
390 | | - throw new Error('Cannot set inputs for preprocessor') |
391 | | - } |
392 | | -
|
393 | | - const regex = /\[\[(.+?)\]\]\s*\n([\s\S]*?)(?=\n\[\[|$)/g |
394 | | -
|
395 | | - const parsedInputs = Array.from(inputs.matchAll(regex)).map((match) => ({ |
396 | | - input: match[1], |
397 | | - value: match[2].trim() |
398 | | - })) |
399 | | -
|
400 | | - if (id === $selectedId) { |
401 | | - exprsToSet?.set({}) |
402 | | - const argsToUpdate = {} |
403 | | - for (const { input, value } of parsedInputs) { |
404 | | - argsToUpdate[input] = { |
405 | | - type: 'javascript', |
406 | | - expr: value |
407 | | - } |
408 | | - } |
409 | | - exprsToSet?.set(argsToUpdate) |
410 | | - } else { |
411 | | - const module = getModule(id) |
412 | | - if (!module) { |
413 | | - throw new Error('Module not found') |
414 | | - } |
415 | | -
|
416 | | - if (module.value.type !== 'script' && module.value.type !== 'rawscript') { |
417 | | - throw new Error('Module is not a script or rawscript') |
418 | | - } |
419 | | -
|
420 | | - for (const { input, value } of parsedInputs) { |
421 | | - module.value.input_transforms[input] = { |
422 | | - type: 'javascript', |
423 | | - expr: value |
424 | | - } |
425 | | - } |
426 | | - refreshStateStore(flowStore) |
427 | | - } |
428 | | -
|
429 | | - setModuleStatus(id, 'modified') |
430 | | - }, |
431 | | - getFlowInputsSchema: async () => { |
432 | | - return flowStore.val.schema ?? {} |
433 | | - }, |
434 | | - setFlowInputsSchema: async (newInputs) => { |
435 | | - flowStore.val.schema = newInputs |
436 | | - setModuleStatus('Input', 'modified') |
437 | | - }, |
438 | | - selectStep: (id) => { |
439 | | - $selectedId = id |
440 | | - }, |
441 | 245 | getStepCode: (id) => { |
442 | 246 | const module = getModule(id) |
443 | 247 | if (!module) { |
|
449 | 253 | throw new Error('Module is not a rawscript') |
450 | 254 | } |
451 | 255 | }, |
452 | | - getModules: (id?: string) => { |
453 | | - if (id) { |
454 | | - const module = getModule(id) |
455 | | -
|
456 | | - if (!module) { |
457 | | - throw new Error('Module not found') |
458 | | - } |
459 | | -
|
460 | | - return getSubModules(module).flat() |
461 | | - } |
462 | | - return flowStore.val.value.modules |
463 | | - }, |
464 | | - setBranchPredicate: async (id, branchIndex, expression) => { |
465 | | - const module = getModule(id) |
466 | | - if (!module) { |
467 | | - throw new Error('Module not found') |
468 | | - } |
469 | | - if (module.value.type !== 'branchone') { |
470 | | - throw new Error('Module is not a branchall or branchone') |
471 | | - } |
472 | | - const branch = module.value.branches[branchIndex] |
473 | | - if (!branch) { |
474 | | - throw new Error('Branch not found') |
475 | | - } |
476 | | - branch.expr = expression |
477 | | - refreshStateStore(flowStore) |
478 | | -
|
479 | | - setModuleStatus(id, 'modified') |
480 | | - }, |
481 | | - addBranch: async (id) => { |
482 | | - flowModuleSchemaMap?.addBranch(id) |
483 | | - refreshStateStore(flowStore) |
484 | | -
|
485 | | - setModuleStatus(id, 'modified') |
486 | | - }, |
487 | | - removeBranch: async (id, branchIndex) => { |
488 | | - const module = getModule(id) |
489 | | - if (!module) { |
490 | | - throw new Error('Module not found') |
491 | | - } |
492 | | - if (module.value.type !== 'branchall' && module.value.type !== 'branchone') { |
493 | | - throw new Error('Module is not a branchall or branchone') |
494 | | - } |
495 | | -
|
496 | | - // for branch one, we set index + 1 because the removeBranch function assumes the index is shifted by 1 because of the default branch |
497 | | - flowModuleSchemaMap?.removeBranch( |
498 | | - module.id, |
499 | | - module.value.type === 'branchone' ? branchIndex + 1 : branchIndex |
500 | | - ) |
501 | | - refreshStateStore(flowStore) |
502 | | -
|
503 | | - setModuleStatus(id, 'modified') |
504 | | - }, |
505 | | - setForLoopIteratorExpression: async (id, expression) => { |
506 | | - if ($currentEditor && $currentEditor.type === 'iterator' && $currentEditor.stepId === id) { |
507 | | - $currentEditor.editor.setCode(expression) |
508 | | - } else { |
509 | | - const module = getModule(id) |
510 | | - if (!module) { |
511 | | - throw new Error('Module not found') |
512 | | - } |
513 | | - if (module.value.type !== 'forloopflow') { |
514 | | - throw new Error('Module is not a forloopflow') |
515 | | - } |
516 | | - module.value.iterator = { type: 'javascript', expr: expression } |
517 | | - refreshStateStore(flowStore) |
518 | | - } |
519 | | -
|
520 | | - setModuleStatus(id, 'modified') |
521 | | - }, |
522 | | - setForLoopOptions: async (id, opts) => { |
523 | | - const module = getModule(id) |
524 | | - if (!module) { |
525 | | - throw new Error('Module not found') |
526 | | - } |
527 | | - if (module.value.type !== 'forloopflow') { |
528 | | - throw new Error('Module is not a forloopflow') |
529 | | - } |
530 | | -
|
531 | | - // Apply skip_failures if provided |
532 | | - if (typeof opts.skip_failures === 'boolean') { |
533 | | - module.value.skip_failures = opts.skip_failures |
534 | | - } |
535 | | -
|
536 | | - // Apply parallel if provided |
537 | | - if (typeof opts.parallel === 'boolean') { |
538 | | - module.value.parallel = opts.parallel |
539 | | - } |
540 | | -
|
541 | | - // Handle parallelism |
542 | | - if (opts.parallel === false) { |
543 | | - // If parallel is disabled, clear parallelism |
544 | | - module.value.parallelism = undefined |
545 | | - } else if (opts.parallelism !== undefined) { |
546 | | - if (opts.parallelism === null) { |
547 | | - // Explicitly clear parallelism |
548 | | - module.value.parallelism = undefined |
549 | | - } else if (module.value.parallel || opts.parallel === true) { |
550 | | - // Only set parallelism if parallel is enabled |
551 | | - const n = Math.max(1, Math.floor(Math.abs(opts.parallelism))) |
552 | | - module.value.parallelism = { |
553 | | - type: 'static', |
554 | | - value: n |
555 | | - } |
556 | | - } |
557 | | - } |
558 | | -
|
559 | | - refreshStateStore(flowStore) |
560 | | - setModuleStatus(id, 'modified') |
561 | | - }, |
562 | | - setModuleControlOptions: async (id, opts) => { |
563 | | - const module = getModule(id) |
564 | | - if (!module) { |
565 | | - throw new Error('Module not found') |
566 | | - } |
567 | | -
|
568 | | - // Handle stop_after_if |
569 | | - if (typeof opts.stop_after_if === 'boolean') { |
570 | | - if (opts.stop_after_if === false) { |
571 | | - module.stop_after_if = undefined |
572 | | - } else { |
573 | | - module.stop_after_if = { |
574 | | - expr: opts.stop_after_if_expr ?? '', |
575 | | - skip_if_stopped: opts.stop_after_if |
576 | | - } |
577 | | - } |
578 | | - } |
579 | | -
|
580 | | - // Handle skip_if |
581 | | - if (typeof opts.skip_if === 'boolean') { |
582 | | - if (opts.skip_if === false) { |
583 | | - module.skip_if = undefined |
584 | | - } else { |
585 | | - module.skip_if = { |
586 | | - expr: opts.skip_if_expr ?? '' |
587 | | - } |
588 | | - } |
589 | | - } |
590 | | -
|
591 | | - refreshStateStore(flowStore) |
592 | | - setModuleStatus(id, 'modified') |
593 | | - }, |
594 | 256 | setFlowYaml: async (yaml: string) => { |
595 | 257 | try { |
596 | 258 | // Parse YAML to JavaScript object |
|
0 commit comments