mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-12 08:05:44 +00:00
* refactor: make flow chat code edits explicit * refactor: centralize flow tree lookups Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: simplify flow chat tree mutations Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: reuse flow tree lookup in schema map Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: remove flow lookup alias Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: reuse flow tree in previous results Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: reuse canonical flow module lookup * fix: align rebased flow helpers Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: remove flow chat cleanup plan Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: remove flow chat helper wrappers Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: preserve non-flowmodule AI agent tools in skeleton and previous_result Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: consolidate flow module ID collectors into flowTree Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: search full flow tree in test_run_step to find special modules Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix: recurse into aiagent tools in collectAllFlowModuleIds Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
196 lines
4.5 KiB
TypeScript
196 lines
4.5 KiB
TypeScript
import { expect } from 'vitest'
|
|
import type {
|
|
FlowValue,
|
|
FlowModule,
|
|
RawScript,
|
|
AiAgent,
|
|
Identity,
|
|
ForloopFlow,
|
|
WhileloopFlow,
|
|
BranchOne,
|
|
BranchAll
|
|
} from '$lib/gen'
|
|
import type { ExtendedOpenFlow } from './types'
|
|
import type { StateStore } from '$lib/utils'
|
|
|
|
// ============================================================================
|
|
// Module Creation Helpers
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Creates a minimal RawScript module for testing
|
|
*/
|
|
export function createRawScriptModule(id: string, content: string): FlowModule {
|
|
return {
|
|
id,
|
|
value: {
|
|
type: 'rawscript',
|
|
content,
|
|
language: 'bun',
|
|
input_transforms: {}
|
|
} as RawScript
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a minimal Identity module (useful for type-change tests)
|
|
*/
|
|
export function createIdentityModule(id: string): FlowModule {
|
|
return {
|
|
id,
|
|
value: {
|
|
type: 'identity'
|
|
} as Identity
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a ForloopFlow module with nested modules
|
|
*/
|
|
export function createForloopModule(id: string, nestedModules: FlowModule[]): FlowModule {
|
|
return {
|
|
id,
|
|
value: {
|
|
type: 'forloopflow',
|
|
modules: nestedModules,
|
|
iterator: { type: 'javascript', expr: '[1,2,3]' },
|
|
skip_failures: false
|
|
} as ForloopFlow
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a WhileloopFlow module with nested modules
|
|
*/
|
|
export function createWhileloopModule(id: string, nestedModules: FlowModule[]): FlowModule {
|
|
return {
|
|
id,
|
|
value: {
|
|
type: 'whileloopflow',
|
|
modules: nestedModules,
|
|
skip_failures: false
|
|
} as WhileloopFlow
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a BranchOne module with default and conditional branches
|
|
*/
|
|
export function createBranchOneModule(
|
|
id: string,
|
|
defaultModules: FlowModule[],
|
|
branches: { expr: string; modules: FlowModule[] }[]
|
|
): FlowModule {
|
|
return {
|
|
id,
|
|
value: {
|
|
type: 'branchone',
|
|
default: defaultModules,
|
|
branches: branches.map((b) => ({ expr: b.expr, modules: b.modules }))
|
|
} as BranchOne
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a BranchAll module with parallel branches
|
|
*/
|
|
export function createBranchAllModule(id: string, branches: { modules: FlowModule[] }[]): FlowModule {
|
|
return {
|
|
id,
|
|
value: {
|
|
type: 'branchall',
|
|
branches: branches.map((b) => ({ modules: b.modules }))
|
|
} as BranchAll
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wraps a FlowModule as an AI agent flowmodule tool.
|
|
*/
|
|
export function createFlowModuleTool(module: FlowModule): FlowModule {
|
|
return {
|
|
id: module.id,
|
|
summary: module.summary,
|
|
value: {
|
|
tool_type: 'flowmodule',
|
|
...module.value
|
|
} as any
|
|
} as FlowModule
|
|
}
|
|
|
|
/**
|
|
* Creates an AI agent module with the provided tools.
|
|
*/
|
|
export function createAiAgentModule(id: string, tools: FlowModule[]): FlowModule {
|
|
return {
|
|
id,
|
|
value: {
|
|
type: 'aiagent',
|
|
tools,
|
|
input_transforms: {}
|
|
} as AiAgent
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// Flow Creation Helpers
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Creates a FlowValue with the given modules
|
|
*/
|
|
export function createFlow(modules: FlowModule[]): FlowValue {
|
|
return { modules }
|
|
}
|
|
|
|
/**
|
|
* Creates a FlowValue with optional special modules (failure_module, preprocessor_module)
|
|
*/
|
|
export function createFlowWithSpecialModules(options: {
|
|
modules?: FlowModule[]
|
|
failure_module?: FlowModule
|
|
preprocessor_module?: FlowModule
|
|
}): FlowValue {
|
|
return {
|
|
modules: options.modules ?? [],
|
|
...(options.failure_module && { failure_module: options.failure_module }),
|
|
...(options.preprocessor_module && { preprocessor_module: options.preprocessor_module })
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wraps a FlowValue in an ExtendedOpenFlow for manager tests
|
|
*/
|
|
export function createExtendedOpenFlow(
|
|
flowValue: FlowValue,
|
|
schema?: Record<string, unknown>
|
|
): ExtendedOpenFlow {
|
|
return { value: flowValue, summary: '', schema }
|
|
}
|
|
|
|
/**
|
|
* Creates a minimal StateStore for manager tests
|
|
*/
|
|
export function createFlowStore(flow: ExtendedOpenFlow): StateStore<ExtendedOpenFlow> {
|
|
return { val: flow }
|
|
}
|
|
|
|
// ============================================================================
|
|
// Utility Helpers
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Deep clones an object via JSON serialization
|
|
*/
|
|
export function deepClone<T>(obj: T): T {
|
|
return JSON.parse(JSON.stringify(obj))
|
|
}
|
|
|
|
/**
|
|
* Asserts that modules appear in the exact order specified.
|
|
* Also implicitly verifies the count of modules.
|
|
*/
|
|
export function expectModuleOrder(modules: FlowModule[], expectedIds: string[]): void {
|
|
expect(modules.map((m) => m.id)).toEqual(expectedIds)
|
|
}
|