@nyaruka/temba-components 0.129.10 → 0.130.0
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/CHANGELOG.md +16 -0
- package/demo/components/flow/example.html +5 -1
- package/demo/data/flows/sample-flow.json +217 -113
- package/dist/temba-components.js +310 -356
- package/dist/temba-components.js.map +1 -1
- package/out-tsc/src/events.js.map +1 -1
- package/out-tsc/src/flow/CanvasNode.js +3 -35
- package/out-tsc/src/flow/CanvasNode.js.map +1 -1
- package/out-tsc/src/flow/Editor.js +9 -6
- package/out-tsc/src/flow/Editor.js.map +1 -1
- package/out-tsc/src/flow/NodeEditor.js +44 -11
- package/out-tsc/src/flow/NodeEditor.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js +1 -1
- package/out-tsc/src/flow/actions/add_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js +1 -1
- package/out-tsc/src/flow/actions/add_contact_urn.js.map +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js +1 -1
- package/out-tsc/src/flow/actions/add_input_labels.js.map +1 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js +1 -1
- package/out-tsc/src/flow/actions/remove_contact_groups.js.map +1 -1
- package/out-tsc/src/flow/actions/send_email.js +9 -0
- package/out-tsc/src/flow/actions/send_email.js.map +1 -1
- package/out-tsc/src/flow/actions/send_msg.js +7 -8
- package/out-tsc/src/flow/actions/send_msg.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_channel.js +25 -4
- package/out-tsc/src/flow/actions/set_contact_channel.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_field.js +51 -1
- package/out-tsc/src/flow/actions/set_contact_field.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_language.js +70 -2
- package/out-tsc/src/flow/actions/set_contact_language.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_name.js +27 -2
- package/out-tsc/src/flow/actions/set_contact_name.js.map +1 -1
- package/out-tsc/src/flow/actions/set_contact_status.js +32 -2
- package/out-tsc/src/flow/actions/set_contact_status.js.map +1 -1
- package/out-tsc/src/flow/actions/set_run_result.js +13 -11
- package/out-tsc/src/flow/actions/set_run_result.js.map +1 -1
- package/out-tsc/src/flow/actions/split_by_expression_example.js +4 -4
- package/out-tsc/src/flow/actions/split_by_expression_example.js.map +1 -1
- package/out-tsc/src/flow/config.js +2 -8
- package/out-tsc/src/flow/config.js.map +1 -1
- package/out-tsc/src/flow/forms/index.js +2 -0
- package/out-tsc/src/flow/forms/index.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_llm.js +101 -0
- package/out-tsc/src/flow/nodes/split_by_llm.js.map +1 -0
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js +4 -89
- package/out-tsc/src/flow/nodes/split_by_llm_categorize.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_random.js +117 -0
- package/out-tsc/src/flow/nodes/split_by_random.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_subflow.js +123 -3
- package/out-tsc/src/flow/nodes/split_by_subflow.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_ticket.js +114 -13
- package/out-tsc/src/flow/nodes/split_by_ticket.js.map +1 -1
- package/out-tsc/src/flow/nodes/split_by_webhook.js +158 -12
- package/out-tsc/src/flow/nodes/split_by_webhook.js.map +1 -1
- package/out-tsc/src/flow/types.js.map +1 -1
- package/out-tsc/src/form/ArrayEditor.js +9 -25
- package/out-tsc/src/form/ArrayEditor.js.map +1 -1
- package/out-tsc/src/form/FieldRenderer.js +6 -64
- package/out-tsc/src/form/FieldRenderer.js.map +1 -1
- package/out-tsc/src/form/select/Select.js +29 -58
- package/out-tsc/src/form/select/Select.js.map +1 -1
- package/out-tsc/src/live/ContactChat.js +48 -66
- package/out-tsc/src/live/ContactChat.js.map +1 -1
- package/out-tsc/src/utils.js +118 -0
- package/out-tsc/src/utils.js.map +1 -1
- package/out-tsc/test/nodes/split_by_llm.test.js +174 -0
- package/out-tsc/test/nodes/split_by_llm.test.js.map +1 -0
- package/out-tsc/test/nodes/split_by_random.test.js +0 -6
- package/out-tsc/test/nodes/split_by_random.test.js.map +1 -1
- package/out-tsc/test/temba-field-renderer.test.js +6 -3
- package/out-tsc/test/temba-field-renderer.test.js.map +1 -1
- package/out-tsc/test/utils.test.js +18 -0
- package/out-tsc/test/utils.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/actions/add_contact_groups/editor/descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/long-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/multiple-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/editor/single-group.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/long-group-names.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/add_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/information-extraction.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/sentiment-analysis.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/summarization.png +0 -0
- package/screenshots/truth/actions/call_llm/editor/translation-task.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/cleanup-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/many-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/editor/single-group.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/cleanup-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/long-descriptive-group-names.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/many-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/multiple-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/remove-from-all-groups.png +0 -0
- package/screenshots/truth/actions/remove_contact_groups/render/single-group.png +0 -0
- package/screenshots/truth/actions/send_email/editor/complex-business-email.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/empty-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/long-subject.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiline-body.png +0 -0
- package/screenshots/truth/actions/send_email/editor/multiple-recipients.png +0 -0
- package/screenshots/truth/actions/send_email/editor/simple-email.png +0 -0
- package/screenshots/truth/actions/send_email/editor/with-expressions.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/long-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/multiline-text-with-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/simple-text.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-linebreaks.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-many-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-with-quick-replies.png +0 -0
- package/screenshots/truth/actions/send_msg/editor/text-without-quick-replies.png +0 -0
- package/screenshots/truth/checkbox/checkbox-label-background-hover.png +0 -0
- package/screenshots/truth/checkbox/checkbox-no-label-no-background-hover.png +0 -0
- package/screenshots/truth/checkbox/checkbox-whitespace-label-no-background-hover.png +0 -0
- package/screenshots/truth/checkbox/checkbox-with-help-text.png +0 -0
- package/screenshots/truth/checkbox/checked.png +0 -0
- package/screenshots/truth/checkbox/default.png +0 -0
- package/screenshots/truth/colorpicker/default.png +0 -0
- package/screenshots/truth/colorpicker/focused.png +0 -0
- package/screenshots/truth/colorpicker/initialized.png +0 -0
- package/screenshots/truth/colorpicker/selected.png +0 -0
- package/screenshots/truth/compose/attachments-tab.png +0 -0
- package/screenshots/truth/compose/attachments-with-files.png +0 -0
- package/screenshots/truth/compose/intial-text.png +0 -0
- package/screenshots/truth/compose/no-counter.png +0 -0
- package/screenshots/truth/compose/wraps-text-and-spaces.png +0 -0
- package/screenshots/truth/compose/wraps-text-and-url.png +0 -0
- package/screenshots/truth/compose/wraps-text-no-spaces.png +0 -0
- package/screenshots/truth/contacts/chat-failure.png +0 -0
- package/screenshots/truth/contacts/chat-for-active-contact.png +0 -0
- package/screenshots/truth/contacts/chat-sends-attachments-only.png +0 -0
- package/screenshots/truth/contacts/chat-sends-text-and-attachments.png +0 -0
- package/screenshots/truth/contacts/chat-sends-text-only.png +0 -0
- package/screenshots/truth/counter/summary.png +0 -0
- package/screenshots/truth/counter/text.png +0 -0
- package/screenshots/truth/counter/unicode-variables.png +0 -0
- package/screenshots/truth/counter/unicode.png +0 -0
- package/screenshots/truth/counter/variable.png +0 -0
- package/screenshots/truth/datepicker/date-truncated-time.png +0 -0
- package/screenshots/truth/datepicker/date.png +0 -0
- package/screenshots/truth/datepicker/initial-timezone.png +0 -0
- package/screenshots/truth/datepicker/range-picker-editing-start.png +0 -0
- package/screenshots/truth/datepicker/updated-keyboard-date.png +0 -0
- package/screenshots/truth/dialog/focused.png +0 -0
- package/screenshots/truth/dropdown/right-edge-collision.png +0 -0
- package/screenshots/truth/editor/router.png +0 -0
- package/screenshots/truth/editor/send_msg.png +0 -0
- package/screenshots/truth/editor/set_contact_language.png +0 -0
- package/screenshots/truth/editor/set_contact_name.png +0 -0
- package/screenshots/truth/editor/set_run_result.png +0 -0
- package/screenshots/truth/editor/wait.png +0 -0
- package/screenshots/truth/field-renderer/checkbox-checked.png +0 -0
- package/screenshots/truth/field-renderer/checkbox-unchecked.png +0 -0
- package/screenshots/truth/field-renderer/checkbox-with-errors.png +0 -0
- package/screenshots/truth/field-renderer/context-comparison.png +0 -0
- package/screenshots/truth/field-renderer/key-value-with-label.png +0 -0
- package/screenshots/truth/field-renderer/message-editor-with-label.png +0 -0
- package/screenshots/truth/field-renderer/select-multi.png +0 -0
- package/screenshots/truth/field-renderer/select-no-label.png +0 -0
- package/screenshots/truth/field-renderer/select-with-label.png +0 -0
- package/screenshots/truth/field-renderer/text-evaluated.png +0 -0
- package/screenshots/truth/field-renderer/text-no-label.png +0 -0
- package/screenshots/truth/field-renderer/text-with-errors.png +0 -0
- package/screenshots/truth/field-renderer/text-with-label.png +0 -0
- package/screenshots/truth/field-renderer/textarea-evaluated.png +0 -0
- package/screenshots/truth/field-renderer/textarea-with-label.png +0 -0
- package/screenshots/truth/integration/checkbox-markdown-errors.png +0 -0
- package/screenshots/truth/list/fields-dragging.png +0 -0
- package/screenshots/truth/list/fields-filtered.png +0 -0
- package/screenshots/truth/list/fields-hovered.png +0 -0
- package/screenshots/truth/list/fields.png +0 -0
- package/screenshots/truth/list/items-selected.png +0 -0
- package/screenshots/truth/list/items-updated.png +0 -0
- package/screenshots/truth/list/items.png +0 -0
- package/screenshots/truth/menu/menu-focused-with items.png +0 -0
- package/screenshots/truth/menu/menu-refresh-1.png +0 -0
- package/screenshots/truth/menu/menu-refresh-2.png +0 -0
- package/screenshots/truth/menu/menu-submenu.png +0 -0
- package/screenshots/truth/menu/menu-tasks-nextup.png +0 -0
- package/screenshots/truth/menu/menu-tasks.png +0 -0
- package/screenshots/truth/message-editor/autogrow-initial-content.png +0 -0
- package/screenshots/truth/message-editor/default.png +0 -0
- package/screenshots/truth/message-editor/drag-highlight.png +0 -0
- package/screenshots/truth/message-editor/filtered-attachments.png +0 -0
- package/screenshots/truth/message-editor/with-completion.png +0 -0
- package/screenshots/truth/message-editor/with-properties.png +0 -0
- package/screenshots/truth/modax/form.png +0 -0
- package/screenshots/truth/modax/simple.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/editor/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/information-extraction.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/sentiment-analysis.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/summarization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm/render/translation-task.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/basic-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/custom-input-and-result-name.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/feedback-categorization.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/many-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_llm_categorize/editor/minimal-categories.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/ab-test-multiple-variants.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/sampling-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/three-way-split.png +0 -0
- package/screenshots/truth/nodes/split_by_random/editor/two-bucket-split.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/basic-digits-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/phone-number-collection.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/single-digit-with-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_digits/editor/verification-code.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/basic-wait.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/custom-result-name.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/no-timeout.png +0 -0
- package/screenshots/truth/nodes/wait_for_response/editor/short-timeout.png +0 -0
- package/screenshots/truth/omnibox/selected.png +0 -0
- package/screenshots/truth/options/block.png +0 -0
- package/screenshots/truth/run-list/basic.png +0 -0
- package/screenshots/truth/select/disabled-multi-selection.png +0 -0
- package/screenshots/truth/select/disabled-selection.png +0 -0
- package/screenshots/truth/select/disabled.png +0 -0
- package/screenshots/truth/select/embedded.png +0 -0
- package/screenshots/truth/select/empty-options.png +0 -0
- package/screenshots/truth/select/expression-selected.png +0 -0
- package/screenshots/truth/select/expressions.png +0 -0
- package/screenshots/truth/select/functions.png +0 -0
- package/screenshots/truth/select/local-options.png +0 -0
- package/screenshots/truth/select/multi-with-endpoint.png +0 -0
- package/screenshots/truth/select/multiple-initial-values.png +0 -0
- package/screenshots/truth/select/remote-options.png +0 -0
- package/screenshots/truth/select/search-enabled.png +0 -0
- package/screenshots/truth/select/search-multi-no-matches.png +0 -0
- package/screenshots/truth/select/search-selected-focus.png +0 -0
- package/screenshots/truth/select/search-selected.png +0 -0
- package/screenshots/truth/select/search-with-selected.png +0 -0
- package/screenshots/truth/select/searching.png +0 -0
- package/screenshots/truth/select/selected-multi-maxitems-reached.png +0 -0
- package/screenshots/truth/select/selected-multi.png +0 -0
- package/screenshots/truth/select/selected-single.png +0 -0
- package/screenshots/truth/select/selection-clearable.png +0 -0
- package/screenshots/truth/select/static-initial-value.png +0 -0
- package/screenshots/truth/select/static-initial-via-selected.png +0 -0
- package/screenshots/truth/select/truncated-selection.png +0 -0
- package/screenshots/truth/select/with-placeholder.png +0 -0
- package/screenshots/truth/select/without-placeholder.png +0 -0
- package/screenshots/truth/slider/update-slider-on-circle-dragged.png +0 -0
- package/screenshots/truth/templates/default.png +0 -0
- package/screenshots/truth/templates/unapproved.png +0 -0
- package/screenshots/truth/textinput/autogrow-initial.png +0 -0
- package/screenshots/truth/textinput/input-disabled.png +0 -0
- package/screenshots/truth/textinput/input-focused.png +0 -0
- package/screenshots/truth/textinput/input-form.png +0 -0
- package/screenshots/truth/textinput/input-inserted.png +0 -0
- package/screenshots/truth/textinput/input-placeholder.png +0 -0
- package/screenshots/truth/textinput/input-updated.png +0 -0
- package/screenshots/truth/textinput/input.png +0 -0
- package/screenshots/truth/textinput/textarea-focused.png +0 -0
- package/screenshots/truth/textinput/textarea.png +0 -0
- package/src/events.ts +4 -2
- package/src/flow/CanvasNode.ts +2 -39
- package/src/flow/Editor.ts +6 -3
- package/src/flow/NodeEditor.ts +54 -13
- package/src/flow/actions/add_contact_groups.ts +1 -1
- package/src/flow/actions/add_contact_urn.ts +1 -1
- package/src/flow/actions/add_input_labels.ts +1 -1
- package/src/flow/actions/remove_contact_groups.ts +1 -1
- package/src/flow/actions/send_email.ts +11 -1
- package/src/flow/actions/send_msg.ts +20 -11
- package/src/flow/actions/set_contact_channel.ts +28 -5
- package/src/flow/actions/set_contact_field.ts +56 -2
- package/src/flow/actions/set_contact_language.ts +74 -3
- package/src/flow/actions/set_contact_name.ts +31 -3
- package/src/flow/actions/set_contact_status.ts +36 -3
- package/src/flow/actions/set_run_result.ts +13 -15
- package/src/flow/actions/split_by_expression_example.ts +4 -4
- package/src/flow/config.ts +2 -8
- package/src/flow/forms/index.ts +1 -0
- package/src/flow/nodes/split_by_llm.ts +119 -0
- package/src/flow/nodes/split_by_llm_categorize.ts +13 -116
- package/src/flow/nodes/split_by_random.ts +148 -0
- package/src/flow/nodes/split_by_subflow.ts +153 -3
- package/src/flow/nodes/split_by_ticket.ts +134 -12
- package/src/flow/nodes/split_by_webhook.ts +185 -12
- package/src/flow/types.ts +2 -1
- package/src/form/ArrayEditor.ts +6 -20
- package/src/form/FieldRenderer.ts +6 -65
- package/src/form/select/Select.ts +34 -66
- package/src/live/ContactChat.ts +56 -58
- package/src/store/flow-definition.d.ts +8 -2
- package/src/utils.ts +196 -0
- package/static/api/fields.json +93 -1208
- package/static/api/workspace.json +23 -0
- package/test/nodes/split_by_llm.test.ts +232 -0
- package/test/nodes/split_by_random.test.ts +0 -7
- package/test/temba-field-renderer.test.ts +26 -13
- package/test/utils.test.ts +20 -0
- package/test-assets/style.css +36 -234
- package/web-dev-server.config.mjs +28 -0
- package/web-test-runner.config.mjs +38 -1
- package/out-tsc/src/flow/actions/call_llm.js +0 -64
- package/out-tsc/src/flow/actions/call_llm.js.map +0 -1
- package/out-tsc/src/flow/actions/call_webhook.js +0 -131
- package/out-tsc/src/flow/actions/call_webhook.js.map +0 -1
- package/out-tsc/src/flow/actions/enter_flow.js +0 -14
- package/out-tsc/src/flow/actions/enter_flow.js.map +0 -1
- package/out-tsc/src/flow/actions/open_ticket.js +0 -73
- package/out-tsc/src/flow/actions/open_ticket.js.map +0 -1
- package/out-tsc/test/actions/call_llm.test.js +0 -103
- package/out-tsc/test/actions/call_llm.test.js.map +0 -1
- package/src/flow/actions/call_llm.ts +0 -66
- package/src/flow/actions/call_webhook.ts +0 -143
- package/src/flow/actions/enter_flow.ts +0 -15
- package/src/flow/actions/open_ticket.ts +0 -83
- package/test/actions/call_llm.test.ts +0 -137
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { COLORS } from '../types';
|
|
2
|
+
import { generateUUID, createSuccessFailureRouter } from '../../utils';
|
|
3
|
+
import { html } from 'lit';
|
|
4
|
+
export const split_by_llm = {
|
|
5
|
+
type: 'split_by_llm',
|
|
6
|
+
name: 'Call AI',
|
|
7
|
+
color: COLORS.call,
|
|
8
|
+
form: {
|
|
9
|
+
llm: {
|
|
10
|
+
type: 'select',
|
|
11
|
+
label: 'LLM',
|
|
12
|
+
required: true,
|
|
13
|
+
options: [],
|
|
14
|
+
endpoint: '/test-assets/select/llms.json',
|
|
15
|
+
searchable: true,
|
|
16
|
+
valueKey: 'uuid',
|
|
17
|
+
nameKey: 'name',
|
|
18
|
+
placeholder: 'Select an LLM...'
|
|
19
|
+
},
|
|
20
|
+
input: {
|
|
21
|
+
type: 'text',
|
|
22
|
+
label: 'Input',
|
|
23
|
+
helpText: 'The input the AI will process',
|
|
24
|
+
required: true,
|
|
25
|
+
evaluated: true,
|
|
26
|
+
placeholder: '@input'
|
|
27
|
+
},
|
|
28
|
+
instructions: {
|
|
29
|
+
type: 'textarea',
|
|
30
|
+
label: 'Instructions',
|
|
31
|
+
helpText: 'Tell the AI what to do with the input. The result can be referenced as **`@locals._llm_output`**',
|
|
32
|
+
required: true,
|
|
33
|
+
evaluated: true,
|
|
34
|
+
placeholder: 'Enter instructions for the AI model...',
|
|
35
|
+
minHeight: 130
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
layout: ['llm', 'input', 'instructions'],
|
|
39
|
+
render: (node) => {
|
|
40
|
+
var _a;
|
|
41
|
+
const callLlmAction = (_a = node.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'call_llm');
|
|
42
|
+
return html `
|
|
43
|
+
<div
|
|
44
|
+
class="body"
|
|
45
|
+
style="word-wrap: break-word; overflow-wrap: break-word; hyphens: auto; max-width: 180px; max-height: 90px; margin-bottom:10px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical;"
|
|
46
|
+
>
|
|
47
|
+
${(callLlmAction === null || callLlmAction === void 0 ? void 0 : callLlmAction.instructions) || 'Configure AI instructions'}
|
|
48
|
+
</div>
|
|
49
|
+
`;
|
|
50
|
+
},
|
|
51
|
+
toFormData: (node) => {
|
|
52
|
+
var _a;
|
|
53
|
+
// Extract data from the existing node structure
|
|
54
|
+
const callLlmAction = (_a = node.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'call_llm');
|
|
55
|
+
return {
|
|
56
|
+
uuid: node.uuid,
|
|
57
|
+
llm: (callLlmAction === null || callLlmAction === void 0 ? void 0 : callLlmAction.llm)
|
|
58
|
+
? [{ value: callLlmAction.llm.uuid, name: callLlmAction.llm.name }]
|
|
59
|
+
: [],
|
|
60
|
+
input: (callLlmAction === null || callLlmAction === void 0 ? void 0 : callLlmAction.input) || '@input',
|
|
61
|
+
instructions: (callLlmAction === null || callLlmAction === void 0 ? void 0 : callLlmAction.instructions) || ''
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
fromFormData: (formData, originalNode) => {
|
|
65
|
+
var _a, _b, _c;
|
|
66
|
+
// Get LLM selection
|
|
67
|
+
const llmSelection = Array.isArray(formData.llm) && formData.llm.length > 0
|
|
68
|
+
? formData.llm[0]
|
|
69
|
+
: null;
|
|
70
|
+
// Find existing call_llm action to preserve its UUID
|
|
71
|
+
const existingCallLlmAction = (_a = originalNode.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'call_llm');
|
|
72
|
+
const callLlmUuid = (existingCallLlmAction === null || existingCallLlmAction === void 0 ? void 0 : existingCallLlmAction.uuid) || generateUUID();
|
|
73
|
+
// Create call_llm action
|
|
74
|
+
const callLlmAction = {
|
|
75
|
+
type: 'call_llm',
|
|
76
|
+
uuid: callLlmUuid,
|
|
77
|
+
llm: llmSelection
|
|
78
|
+
? { uuid: llmSelection.value, name: llmSelection.name }
|
|
79
|
+
: { uuid: '', name: '' },
|
|
80
|
+
input: formData.input || '@input',
|
|
81
|
+
instructions: formData.instructions || '',
|
|
82
|
+
output_local: '_llm_output'
|
|
83
|
+
};
|
|
84
|
+
// Create categories and exits for Success and Failure
|
|
85
|
+
const existingCategories = ((_b = originalNode.router) === null || _b === void 0 ? void 0 : _b.categories) || [];
|
|
86
|
+
const existingExits = originalNode.exits || [];
|
|
87
|
+
const existingCases = ((_c = originalNode.router) === null || _c === void 0 ? void 0 : _c.cases) || [];
|
|
88
|
+
const { router, exits } = createSuccessFailureRouter('@locals._llm_output', {
|
|
89
|
+
type: 'has_text',
|
|
90
|
+
arguments: []
|
|
91
|
+
}, existingCategories, existingExits, existingCases);
|
|
92
|
+
// Return the complete node
|
|
93
|
+
return {
|
|
94
|
+
uuid: originalNode.uuid,
|
|
95
|
+
actions: [callLlmAction],
|
|
96
|
+
router: router,
|
|
97
|
+
exits: exits
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
//# sourceMappingURL=split_by_llm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split_by_llm.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_llm.ts"],"names":[],"mappings":"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","sourcesContent":["import { COLORS, NodeConfig } from '../types';\nimport { CallLLM, Node } from '../../store/flow-definition';\nimport { generateUUID, createSuccessFailureRouter } from '../../utils';\nimport { html } from 'lit';\n\nexport const split_by_llm: NodeConfig = {\n type: 'split_by_llm',\n name: 'Call AI',\n color: COLORS.call,\n form: {\n llm: {\n type: 'select',\n label: 'LLM',\n required: true,\n options: [],\n endpoint: '/test-assets/select/llms.json',\n searchable: true,\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Select an LLM...'\n },\n input: {\n type: 'text',\n label: 'Input',\n helpText: 'The input the AI will process',\n required: true,\n evaluated: true,\n placeholder: '@input'\n },\n instructions: {\n type: 'textarea',\n label: 'Instructions',\n helpText:\n 'Tell the AI what to do with the input. The result can be referenced as **`@locals._llm_output`**',\n required: true,\n evaluated: true,\n placeholder: 'Enter instructions for the AI model...',\n minHeight: 130\n }\n },\n layout: ['llm', 'input', 'instructions'],\n render: (node: Node) => {\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as CallLLM;\n return html`\n <div\n class=\"body\"\n style=\"word-wrap: break-word; overflow-wrap: break-word; hyphens: auto; max-width: 180px; max-height: 90px; margin-bottom:10px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical;\"\n >\n ${callLlmAction?.instructions || 'Configure AI instructions'}\n </div>\n `;\n },\n toFormData: (node: Node) => {\n // Extract data from the existing node structure\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as CallLLM;\n\n return {\n uuid: node.uuid,\n llm: callLlmAction?.llm\n ? [{ value: callLlmAction.llm.uuid, name: callLlmAction.llm.name }]\n : [],\n input: callLlmAction?.input || '@input',\n instructions: callLlmAction?.instructions || ''\n };\n },\n fromFormData: (formData: any, originalNode: Node): Node => {\n // Get LLM selection\n const llmSelection =\n Array.isArray(formData.llm) && formData.llm.length > 0\n ? formData.llm[0]\n : null;\n\n // Find existing call_llm action to preserve its UUID\n const existingCallLlmAction = originalNode.actions?.find(\n (action) => action.type === 'call_llm'\n );\n const callLlmUuid = existingCallLlmAction?.uuid || generateUUID();\n\n // Create call_llm action\n const callLlmAction: CallLLM = {\n type: 'call_llm',\n uuid: callLlmUuid,\n llm: llmSelection\n ? { uuid: llmSelection.value, name: llmSelection.name }\n : { uuid: '', name: '' },\n input: formData.input || '@input',\n instructions: formData.instructions || '',\n output_local: '_llm_output'\n };\n\n // Create categories and exits for Success and Failure\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const { router, exits } = createSuccessFailureRouter(\n '@locals._llm_output',\n {\n type: 'has_text',\n arguments: []\n },\n existingCategories,\n existingExits,\n existingCases\n );\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: [callLlmAction],\n router: router,\n exits: exits\n };\n }\n};\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { COLORS } from '../types';
|
|
2
|
-
import { generateUUID } from '../../utils';
|
|
2
|
+
import { generateUUID, createMultiCategoryRouter } from '../../utils';
|
|
3
3
|
import { html } from 'lit';
|
|
4
4
|
export const split_by_llm_categorize = {
|
|
5
5
|
type: 'split_by_llm_categorize',
|
|
@@ -123,98 +123,13 @@ export const split_by_llm_categorize = {
|
|
|
123
123
|
output_local: '_llm_output'
|
|
124
124
|
};
|
|
125
125
|
// Create categories and exits
|
|
126
|
-
const categories = [];
|
|
127
|
-
const exits = [];
|
|
128
|
-
const cases = [];
|
|
129
|
-
// Get existing categories from original node for UUID preservation
|
|
130
126
|
const existingCategories = ((_b = originalNode.router) === null || _b === void 0 ? void 0 : _b.categories) || [];
|
|
131
127
|
const existingExits = originalNode.exits || [];
|
|
132
128
|
const existingCases = ((_c = originalNode.router) === null || _c === void 0 ? void 0 : _c.cases) || [];
|
|
133
|
-
|
|
134
|
-
userCategories.forEach((categoryName) => {
|
|
135
|
-
// Check if this category already exists
|
|
136
|
-
const existingCategory = existingCategories.find((cat) => cat.name === categoryName);
|
|
137
|
-
const existingExit = existingCategory
|
|
138
|
-
? existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid)
|
|
139
|
-
: null;
|
|
140
|
-
const existingCase = existingCategory
|
|
141
|
-
? existingCases.find((case_) => case_.category_uuid === existingCategory.uuid)
|
|
142
|
-
: null;
|
|
143
|
-
// Use existing UUIDs if category name hasn't changed, otherwise generate new ones
|
|
144
|
-
const categoryUuid = (existingCategory === null || existingCategory === void 0 ? void 0 : existingCategory.uuid) || generateUUID();
|
|
145
|
-
const exitUuid = (existingExit === null || existingExit === void 0 ? void 0 : existingExit.uuid) || generateUUID();
|
|
146
|
-
const caseUuid = (existingCase === null || existingCase === void 0 ? void 0 : existingCase.uuid) || generateUUID();
|
|
147
|
-
categories.push({
|
|
148
|
-
uuid: categoryUuid,
|
|
149
|
-
name: categoryName,
|
|
150
|
-
exit_uuid: exitUuid
|
|
151
|
-
});
|
|
152
|
-
exits.push({
|
|
153
|
-
uuid: exitUuid,
|
|
154
|
-
destination_uuid: (existingExit === null || existingExit === void 0 ? void 0 : existingExit.destination_uuid) || null
|
|
155
|
-
});
|
|
156
|
-
cases.push({
|
|
157
|
-
uuid: caseUuid,
|
|
158
|
-
type: 'has_only_text',
|
|
159
|
-
arguments: [categoryName],
|
|
160
|
-
category_uuid: categoryUuid
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
// Add "Other" category (default)
|
|
164
|
-
const existingOtherCategory = existingCategories.find((cat) => cat.name === 'Other');
|
|
165
|
-
const existingOtherExit = existingOtherCategory
|
|
166
|
-
? existingExits.find((exit) => exit.uuid === existingOtherCategory.exit_uuid)
|
|
167
|
-
: null;
|
|
168
|
-
const otherCategoryUuid = (existingOtherCategory === null || existingOtherCategory === void 0 ? void 0 : existingOtherCategory.uuid) || generateUUID();
|
|
169
|
-
const otherExitUuid = (existingOtherExit === null || existingOtherExit === void 0 ? void 0 : existingOtherExit.uuid) || generateUUID();
|
|
170
|
-
categories.push({
|
|
171
|
-
uuid: otherCategoryUuid,
|
|
172
|
-
name: 'Other',
|
|
173
|
-
exit_uuid: otherExitUuid
|
|
174
|
-
});
|
|
175
|
-
exits.push({
|
|
176
|
-
uuid: otherExitUuid,
|
|
177
|
-
destination_uuid: (existingOtherExit === null || existingOtherExit === void 0 ? void 0 : existingOtherExit.destination_uuid) || null
|
|
178
|
-
});
|
|
179
|
-
// Add "Failure" category
|
|
180
|
-
const existingFailureCategory = existingCategories.find((cat) => cat.name === 'Failure');
|
|
181
|
-
const existingFailureExit = existingFailureCategory
|
|
182
|
-
? existingExits.find((exit) => exit.uuid === existingFailureCategory.exit_uuid)
|
|
183
|
-
: null;
|
|
184
|
-
const existingFailureCase = existingFailureCategory
|
|
185
|
-
? existingCases.find((case_) => {
|
|
186
|
-
var _a;
|
|
187
|
-
return case_.category_uuid === existingFailureCategory.uuid &&
|
|
188
|
-
((_a = case_.arguments) === null || _a === void 0 ? void 0 : _a[0]) === '<ERROR>';
|
|
189
|
-
})
|
|
190
|
-
: null;
|
|
191
|
-
const failureCategoryUuid = (existingFailureCategory === null || existingFailureCategory === void 0 ? void 0 : existingFailureCategory.uuid) || generateUUID();
|
|
192
|
-
const failureExitUuid = (existingFailureExit === null || existingFailureExit === void 0 ? void 0 : existingFailureExit.uuid) || generateUUID();
|
|
193
|
-
const failureCaseUuid = (existingFailureCase === null || existingFailureCase === void 0 ? void 0 : existingFailureCase.uuid) || generateUUID();
|
|
194
|
-
categories.push({
|
|
195
|
-
uuid: failureCategoryUuid,
|
|
196
|
-
name: 'Failure',
|
|
197
|
-
exit_uuid: failureExitUuid
|
|
198
|
-
});
|
|
199
|
-
exits.push({
|
|
200
|
-
uuid: failureExitUuid,
|
|
201
|
-
destination_uuid: (existingFailureExit === null || existingFailureExit === void 0 ? void 0 : existingFailureExit.destination_uuid) || null
|
|
202
|
-
});
|
|
203
|
-
// Add failure case for <ERROR>
|
|
204
|
-
cases.push({
|
|
205
|
-
uuid: failureCaseUuid,
|
|
129
|
+
const { router, exits } = createMultiCategoryRouter('@locals._llm_output', userCategories, (categoryName) => ({
|
|
206
130
|
type: 'has_only_text',
|
|
207
|
-
arguments: [
|
|
208
|
-
|
|
209
|
-
});
|
|
210
|
-
// Create the router
|
|
211
|
-
const router = {
|
|
212
|
-
type: 'switch',
|
|
213
|
-
categories: categories,
|
|
214
|
-
default_category_uuid: otherCategoryUuid,
|
|
215
|
-
operand: '@locals._llm_output',
|
|
216
|
-
cases: cases
|
|
217
|
-
};
|
|
131
|
+
arguments: [categoryName]
|
|
132
|
+
}), existingCategories, existingExits, existingCases);
|
|
218
133
|
// Return the complete node
|
|
219
134
|
return {
|
|
220
135
|
uuid: originalNode.uuid,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split_by_llm_categorize.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_llm_categorize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,UAAU,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAE3B,MAAM,CAAC,MAAM,uBAAuB,GAAe;IACjD,IAAI,EAAE,yBAAyB;IAC/B,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,MAAM,CAAC,IAAI;IAClB,IAAI,EAAE;QACJ,GAAG,EAAE;YACH,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,KAAK;YACZ,QAAQ,EAAE,0CAA0C;YACpD,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,+BAA+B;YACzC,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,MAAM;YACf,WAAW,EAAE,kBAAkB;SAChC;QACD,KAAK,EAAE;YACL,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,OAAO;YACd,QAAQ,EAAE,0CAA0C;YACpD,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,QAAQ;SACtB;QACD,UAAU,EAAE;YACV,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,YAAY;YACnB,QAAQ,EAAE,0CAA0C;YACpD,QAAQ,EAAE,IAAI;YACd,SAAS,EAAE,UAAU;YACrB,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,EAAE;YACZ,WAAW,EAAE,CAAC,IAAS,EAAE,EAAE;gBACzB,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;YAC/C,CAAC;YACD,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,MAAM;oBACZ,WAAW,EAAE,eAAe;oBAC5B,QAAQ,EAAE,IAAI;iBACf;aACF;SACF;KACF;IACD,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,YAAY,CAAC;IACtC,QAAQ,EAAE,CAAC,QAAa,EAAE,EAAE;QAC1B,MAAM,MAAM,GAA8B,EAAE,CAAC;QAE7C,qCAAqC;QACrC,IAAI,QAAQ,CAAC,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9D,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,CAC3C,CAAC,IAAS,EAAE,EAAE,CAAC,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,KAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CACrD,CAAC;YAEF,8DAA8D;YAC9D,MAAM,mBAAmB,GAAG,EAAE,CAAC;YAC/B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAE,CAAC;YAE/B,wDAAwD;YACxD,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;gBAC9B,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBACrD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBACjC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;gBAClC,CAAC;gBACD,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACzD,CAAC,CAAC,CAAC;YAEH,4DAA4D;YAC5D,YAAY,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,EAAE;gBACrC,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC7B,mBAAmB,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC,CAAC,CAAC;YAEH,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnC,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;gBAC3D,MAAM,CAAC,UAAU,GAAG,mCAAmC,gBAAgB,CAAC,IAAI,CAC1E,IAAI,CACL,EAAE,CAAC;YACN,CAAC;QACH,CAAC;QAED,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;YACvC,MAAM;SACP,CAAC;IACJ,CAAC;IACD,MAAM,EAAE,CAAC,IAAU,EAAE,EAAE;;QACrB,MAAM,aAAa,GAAG,MAAA,IAAI,CAAC,OAAO,0CAAE,IAAI,CACtC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,CAChC,CAAC;QACT,OAAO,IAAI,CAAA;0CAC2B,aAAa,CAAC,GAAG,CAAC,IAAI;KAC3D,CAAC;IACJ,CAAC;IACD,UAAU,EAAE,CAAC,IAAU,EAAE,EAAE;;QACzB,gDAAgD;QAChD,MAAM,aAAa,GAAG,MAAA,IAAI,CAAC,OAAO,0CAAE,IAAI,CACtC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,CAChC,CAAC;QACT,MAAM,UAAU,GACd,CAAA,MAAA,MAAA,IAAI,CAAC,MAAM,0CAAE,UAAU,0CACnB,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,OAAO,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAC/D,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAI,EAAE,CAAC;QAE9C,OAAO;YACL,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,GAAG,EAAE,CAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,GAAG;gBACrB,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;gBACnE,CAAC,CAAC,EAAE;YACN,KAAK,EAAE,CAAA,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,KAAK,KAAI,QAAQ;YACvC,UAAU,EAAE,UAAU;SACvB,CAAC;IACJ,CAAC;IACD,YAAY,EAAE,CAAC,QAAa,EAAE,YAAkB,EAAQ,EAAE;;QACxD,oBAAoB;QACpB,MAAM,YAAY,GAChB,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC;YACpD,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;YACjB,CAAC,CAAC,IAAI,CAAC;QAEX,sBAAsB;QACtB,MAAM,cAAc,GAAG,CAAC,QAAQ,CAAC,UAAU,IAAI,EAAE,CAAC;aAC/C,MAAM,CAAC,CAAC,IAAS,EAAE,EAAE,WAAC,OAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,IAAI,0CAAE,IAAI,EAAE,CAAA,EAAA,CAAC;aACzC,GAAG,CAAC,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAExC,qDAAqD;QACrD,MAAM,qBAAqB,GAAG,MAAA,YAAY,CAAC,OAAO,0CAAE,IAAI,CACtD,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU,CACvC,CAAC;QACF,MAAM,WAAW,GAAG,CAAA,qBAAqB,aAArB,qBAAqB,uBAArB,qBAAqB,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;QAElE,sEAAsE;QACtE,MAAM,aAAa,GAAQ;YACzB,IAAI,EAAE,UAAU;YAChB,IAAI,EAAE,WAAW;YACjB,GAAG,EAAE,YAAY;gBACf,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,CAAC,IAAI,EAAE;gBACvD,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;YAC1B,YAAY,EAAE,wDAAwD;YACtE,KAAK,EAAE,QAAQ,CAAC,KAAK,IAAI,QAAQ;YACjC,YAAY,EAAE,aAAa;SAC5B,CAAC;QAEF,8BAA8B;QAC9B,MAAM,UAAU,GAAG,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,EAAE,CAAC;QAEjB,mEAAmE;QACnE,MAAM,kBAAkB,GAAG,CAAA,MAAA,YAAY,CAAC,MAAM,0CAAE,UAAU,KAAI,EAAE,CAAC;QACjE,MAAM,aAAa,GAAG,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/C,MAAM,aAAa,GAAG,CAAA,MAAA,YAAY,CAAC,MAAM,0CAAE,KAAK,KAAI,EAAE,CAAC;QAEvD,sBAAsB;QACtB,cAAc,CAAC,OAAO,CAAC,CAAC,YAAoB,EAAE,EAAE;YAC9C,wCAAwC;YACxC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,IAAI,CAC9C,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,YAAY,CACnC,CAAC;YACF,MAAM,YAAY,GAAG,gBAAgB;gBACnC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB,CAAC,SAAS,CAAC;gBACxE,CAAC,CAAC,IAAI,CAAC;YACT,MAAM,YAAY,GAAG,gBAAgB;gBACnC,CAAC,CAAC,aAAa,CAAC,IAAI,CAChB,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,KAAK,gBAAgB,CAAC,IAAI,CACzD;gBACH,CAAC,CAAC,IAAI,CAAC;YAET,kFAAkF;YAClF,MAAM,YAAY,GAAG,CAAA,gBAAgB,aAAhB,gBAAgB,uBAAhB,gBAAgB,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;YAC9D,MAAM,QAAQ,GAAG,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;YACtD,MAAM,QAAQ,GAAG,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;YAEtD,UAAU,CAAC,IAAI,CAAC;gBACd,IAAI,EAAE,YAAY;gBAClB,IAAI,EAAE,YAAY;gBAClB,SAAS,EAAE,QAAQ;aACpB,CAAC,CAAC;YAEH,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,QAAQ;gBACd,gBAAgB,EAAE,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,gBAAgB,KAAI,IAAI;aACzD,CAAC,CAAC;YAEH,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,eAAe;gBACrB,SAAS,EAAE,CAAC,YAAY,CAAC;gBACzB,aAAa,EAAE,YAAY;aAC5B,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,iCAAiC;QACjC,MAAM,qBAAqB,GAAG,kBAAkB,CAAC,IAAI,CACnD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,OAAO,CAC9B,CAAC;QACF,MAAM,iBAAiB,GAAG,qBAAqB;YAC7C,CAAC,CAAC,aAAa,CAAC,IAAI,CAChB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,qBAAqB,CAAC,SAAS,CACxD;YACH,CAAC,CAAC,IAAI,CAAC;QAET,MAAM,iBAAiB,GAAG,CAAA,qBAAqB,aAArB,qBAAqB,uBAArB,qBAAqB,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;QACxE,MAAM,aAAa,GAAG,CAAA,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;QAEhE,UAAU,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,iBAAiB;YACvB,IAAI,EAAE,OAAO;YACb,SAAS,EAAE,aAAa;SACzB,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,aAAa;YACnB,gBAAgB,EAAE,CAAA,iBAAiB,aAAjB,iBAAiB,uBAAjB,iBAAiB,CAAE,gBAAgB,KAAI,IAAI;SAC9D,CAAC,CAAC;QAEH,yBAAyB;QACzB,MAAM,uBAAuB,GAAG,kBAAkB,CAAC,IAAI,CACrD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,SAAS,CAChC,CAAC;QACF,MAAM,mBAAmB,GAAG,uBAAuB;YACjD,CAAC,CAAC,aAAa,CAAC,IAAI,CAChB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,uBAAuB,CAAC,SAAS,CAC1D;YACH,CAAC,CAAC,IAAI,CAAC;QACT,MAAM,mBAAmB,GAAG,uBAAuB;YACjD,CAAC,CAAC,aAAa,CAAC,IAAI,CAChB,CAAC,KAAK,EAAE,EAAE;;gBACR,OAAA,KAAK,CAAC,aAAa,KAAK,uBAAuB,CAAC,IAAI;oBACpD,CAAA,MAAA,KAAK,CAAC,SAAS,0CAAG,CAAC,CAAC,MAAK,SAAS,CAAA;aAAA,CACrC;YACH,CAAC,CAAC,IAAI,CAAC;QAET,MAAM,mBAAmB,GAAG,CAAA,uBAAuB,aAAvB,uBAAuB,uBAAvB,uBAAuB,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;QAC5E,MAAM,eAAe,GAAG,CAAA,mBAAmB,aAAnB,mBAAmB,uBAAnB,mBAAmB,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;QACpE,MAAM,eAAe,GAAG,CAAA,mBAAmB,aAAnB,mBAAmB,uBAAnB,mBAAmB,CAAE,IAAI,KAAI,YAAY,EAAE,CAAC;QAEpE,UAAU,CAAC,IAAI,CAAC;YACd,IAAI,EAAE,mBAAmB;YACzB,IAAI,EAAE,SAAS;YACf,SAAS,EAAE,eAAe;SAC3B,CAAC,CAAC;QACH,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,eAAe;YACrB,gBAAgB,EAAE,CAAA,mBAAmB,aAAnB,mBAAmB,uBAAnB,mBAAmB,CAAE,gBAAgB,KAAI,IAAI;SAChE,CAAC,CAAC;QAEH,+BAA+B;QAC/B,KAAK,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,eAAe;YACrB,SAAS,EAAE,CAAC,SAAS,CAAC;YACtB,aAAa,EAAE,mBAAmB;SACnC,CAAC,CAAC;QAEH,oBAAoB;QACpB,MAAM,MAAM,GAAG;YACb,IAAI,EAAE,QAAiB;YACvB,UAAU,EAAE,UAAU;YACtB,qBAAqB,EAAE,iBAAiB;YACxC,OAAO,EAAE,qBAAqB;YAC9B,KAAK,EAAE,KAAK;SACb,CAAC;QAEF,2BAA2B;QAC3B,OAAO;YACL,IAAI,EAAE,YAAY,CAAC,IAAI;YACvB,OAAO,EAAE,CAAC,aAAa,CAAC;YACxB,MAAM,EAAE,MAAM;YACd,KAAK,EAAE,KAAK;SACb,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { COLORS, NodeConfig } from '../types';\nimport { Node } from '../../store/flow-definition';\nimport { generateUUID } from '../../utils';\nimport { html } from 'lit';\n\nexport const split_by_llm_categorize: NodeConfig = {\n type: 'split_by_llm_categorize',\n name: 'Split by AI',\n color: COLORS.call,\n form: {\n llm: {\n type: 'select',\n label: 'LLM',\n helpText: 'Select the LLM to use for categorization',\n required: true,\n endpoint: '/test-assets/select/llms.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Select an LLM...'\n },\n input: {\n type: 'text',\n label: 'Input',\n helpText: 'The input to categorize (usually @input)',\n required: true,\n evaluated: true,\n placeholder: '@input'\n },\n categories: {\n type: 'array',\n label: 'Categories',\n helpText: 'Define the categories for classification',\n required: true,\n itemLabel: 'Category',\n minItems: 1,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.name || item.name.trim() === '';\n },\n itemConfig: {\n name: {\n type: 'text',\n placeholder: 'Category name',\n required: true\n }\n }\n }\n },\n layout: ['llm', 'input', 'categories'],\n validate: (formData: any) => {\n const errors: { [key: string]: string } = {};\n\n // Check for duplicate category names\n if (formData.categories && Array.isArray(formData.categories)) {\n const categories = formData.categories.filter(\n (item: any) => item?.name && item.name.trim() !== ''\n );\n\n // Find all categories that have duplicates (case-insensitive)\n const duplicateCategories = [];\n const lowerCaseMap = new Map();\n\n // First pass: map lowercase names to all original cases\n categories.forEach((category) => {\n const lowerName = category.name.trim().toLowerCase();\n if (!lowerCaseMap.has(lowerName)) {\n lowerCaseMap.set(lowerName, []);\n }\n lowerCaseMap.get(lowerName).push(category.name.trim());\n });\n\n // Second pass: collect all names that appear more than once\n lowerCaseMap.forEach((originalNames) => {\n if (originalNames.length > 1) {\n duplicateCategories.push(...originalNames);\n }\n });\n\n if (duplicateCategories.length > 0) {\n const uniqueDuplicates = [...new Set(duplicateCategories)];\n errors.categories = `Duplicate category names found: ${uniqueDuplicates.join(\n ', '\n )}`;\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n render: (node: Node) => {\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as any;\n return html`\n <div class=\"body\">Categorize with ${callLlmAction.llm.name}</div>\n `;\n },\n toFormData: (node: Node) => {\n // Extract data from the existing node structure\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as any;\n const categories =\n node.router?.categories\n ?.filter((cat) => cat.name !== 'Other' && cat.name !== 'Failure')\n .map((cat) => ({ name: cat.name })) || [];\n\n return {\n uuid: node.uuid,\n llm: callLlmAction?.llm\n ? [{ value: callLlmAction.llm.uuid, name: callLlmAction.llm.name }]\n : [],\n input: callLlmAction?.input || '@input',\n categories: categories\n };\n },\n fromFormData: (formData: any, originalNode: Node): Node => {\n // Get LLM selection\n const llmSelection =\n Array.isArray(formData.llm) && formData.llm.length > 0\n ? formData.llm[0]\n : null;\n\n // Get user categories\n const userCategories = (formData.categories || [])\n .filter((item: any) => item?.name?.trim())\n .map((item: any) => item.name.trim());\n\n // Find existing call_llm action to preserve its UUID\n const existingCallLlmAction = originalNode.actions?.find(\n (action) => action.type === 'call_llm'\n );\n const callLlmUuid = existingCallLlmAction?.uuid || generateUUID();\n\n // Create call_llm action (using any type to match the example format)\n const callLlmAction: any = {\n type: 'call_llm',\n uuid: callLlmUuid,\n llm: llmSelection\n ? { uuid: llmSelection.value, name: llmSelection.name }\n : { uuid: '', name: '' },\n instructions: `@(prompt(\"categorize\", slice(node.categories, 0, -2)))`,\n input: formData.input || '@input',\n output_local: '_llm_output'\n };\n\n // Create categories and exits\n const categories = [];\n const exits = [];\n const cases = [];\n\n // Get existing categories from original node for UUID preservation\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n // Add user categories\n userCategories.forEach((categoryName: string) => {\n // Check if this category already exists\n const existingCategory = existingCategories.find(\n (cat) => cat.name === categoryName\n );\n const existingExit = existingCategory\n ? existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid)\n : null;\n const existingCase = existingCategory\n ? existingCases.find(\n (case_) => case_.category_uuid === existingCategory.uuid\n )\n : null;\n\n // Use existing UUIDs if category name hasn't changed, otherwise generate new ones\n const categoryUuid = existingCategory?.uuid || generateUUID();\n const exitUuid = existingExit?.uuid || generateUUID();\n const caseUuid = existingCase?.uuid || generateUUID();\n\n categories.push({\n uuid: categoryUuid,\n name: categoryName,\n exit_uuid: exitUuid\n });\n\n exits.push({\n uuid: exitUuid,\n destination_uuid: existingExit?.destination_uuid || null\n });\n\n cases.push({\n uuid: caseUuid,\n type: 'has_only_text',\n arguments: [categoryName],\n category_uuid: categoryUuid\n });\n });\n\n // Add \"Other\" category (default)\n const existingOtherCategory = existingCategories.find(\n (cat) => cat.name === 'Other'\n );\n const existingOtherExit = existingOtherCategory\n ? existingExits.find(\n (exit) => exit.uuid === existingOtherCategory.exit_uuid\n )\n : null;\n\n const otherCategoryUuid = existingOtherCategory?.uuid || generateUUID();\n const otherExitUuid = existingOtherExit?.uuid || generateUUID();\n\n categories.push({\n uuid: otherCategoryUuid,\n name: 'Other',\n exit_uuid: otherExitUuid\n });\n exits.push({\n uuid: otherExitUuid,\n destination_uuid: existingOtherExit?.destination_uuid || null\n });\n\n // Add \"Failure\" category\n const existingFailureCategory = existingCategories.find(\n (cat) => cat.name === 'Failure'\n );\n const existingFailureExit = existingFailureCategory\n ? existingExits.find(\n (exit) => exit.uuid === existingFailureCategory.exit_uuid\n )\n : null;\n const existingFailureCase = existingFailureCategory\n ? existingCases.find(\n (case_) =>\n case_.category_uuid === existingFailureCategory.uuid &&\n case_.arguments?.[0] === '<ERROR>'\n )\n : null;\n\n const failureCategoryUuid = existingFailureCategory?.uuid || generateUUID();\n const failureExitUuid = existingFailureExit?.uuid || generateUUID();\n const failureCaseUuid = existingFailureCase?.uuid || generateUUID();\n\n categories.push({\n uuid: failureCategoryUuid,\n name: 'Failure',\n exit_uuid: failureExitUuid\n });\n exits.push({\n uuid: failureExitUuid,\n destination_uuid: existingFailureExit?.destination_uuid || null\n });\n\n // Add failure case for <ERROR>\n cases.push({\n uuid: failureCaseUuid,\n type: 'has_only_text',\n arguments: ['<ERROR>'],\n category_uuid: failureCategoryUuid\n });\n\n // Create the router\n const router = {\n type: 'switch' as const,\n categories: categories,\n default_category_uuid: otherCategoryUuid,\n operand: '@locals._llm_output',\n cases: cases\n };\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: [callLlmAction],\n router: router,\n exits: exits\n };\n }\n};\n"]}
|
|
1
|
+
{"version":3,"file":"split_by_llm_categorize.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_llm_categorize.ts"],"names":[],"mappings":"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","sourcesContent":["import { COLORS, NodeConfig } from '../types';\nimport { CallLLM, Node } from '../../store/flow-definition';\nimport { generateUUID, createMultiCategoryRouter } from '../../utils';\nimport { html } from 'lit';\n\nexport const split_by_llm_categorize: NodeConfig = {\n type: 'split_by_llm_categorize',\n name: 'Split by AI',\n color: COLORS.call,\n form: {\n llm: {\n type: 'select',\n label: 'LLM',\n helpText: 'Select the LLM to use for categorization',\n required: true,\n endpoint: '/test-assets/select/llms.json',\n valueKey: 'uuid',\n nameKey: 'name',\n placeholder: 'Select an LLM...'\n },\n input: {\n type: 'text',\n label: 'Input',\n helpText: 'The input to categorize (usually @input)',\n required: true,\n evaluated: true,\n placeholder: '@input'\n },\n categories: {\n type: 'array',\n label: 'Categories',\n helpText: 'Define the categories for classification',\n required: true,\n itemLabel: 'Category',\n minItems: 1,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.name || item.name.trim() === '';\n },\n itemConfig: {\n name: {\n type: 'text',\n placeholder: 'Category name',\n required: true\n }\n }\n }\n },\n layout: ['llm', 'input', 'categories'],\n validate: (formData: any) => {\n const errors: { [key: string]: string } = {};\n\n // Check for duplicate category names\n if (formData.categories && Array.isArray(formData.categories)) {\n const categories = formData.categories.filter(\n (item: any) => item?.name && item.name.trim() !== ''\n );\n\n // Find all categories that have duplicates (case-insensitive)\n const duplicateCategories = [];\n const lowerCaseMap = new Map();\n\n // First pass: map lowercase names to all original cases\n categories.forEach((category) => {\n const lowerName = category.name.trim().toLowerCase();\n if (!lowerCaseMap.has(lowerName)) {\n lowerCaseMap.set(lowerName, []);\n }\n lowerCaseMap.get(lowerName).push(category.name.trim());\n });\n\n // Second pass: collect all names that appear more than once\n lowerCaseMap.forEach((originalNames) => {\n if (originalNames.length > 1) {\n duplicateCategories.push(...originalNames);\n }\n });\n\n if (duplicateCategories.length > 0) {\n const uniqueDuplicates = [...new Set(duplicateCategories)];\n errors.categories = `Duplicate category names found: ${uniqueDuplicates.join(\n ', '\n )}`;\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n render: (node: Node) => {\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as CallLLM;\n return html`\n <div class=\"body\">Categorize with ${callLlmAction.llm.name}</div>\n `;\n },\n toFormData: (node: Node) => {\n // Extract data from the existing node structure\n const callLlmAction = node.actions?.find(\n (action) => action.type === 'call_llm'\n ) as any;\n const categories =\n node.router?.categories\n ?.filter((cat) => cat.name !== 'Other' && cat.name !== 'Failure')\n .map((cat) => ({ name: cat.name })) || [];\n\n return {\n uuid: node.uuid,\n llm: callLlmAction?.llm\n ? [{ value: callLlmAction.llm.uuid, name: callLlmAction.llm.name }]\n : [],\n input: callLlmAction?.input || '@input',\n categories: categories\n };\n },\n fromFormData: (formData: any, originalNode: Node): Node => {\n // Get LLM selection\n const llmSelection =\n Array.isArray(formData.llm) && formData.llm.length > 0\n ? formData.llm[0]\n : null;\n\n // Get user categories\n const userCategories = (formData.categories || [])\n .filter((item: any) => item?.name?.trim())\n .map((item: any) => item.name.trim());\n\n // Find existing call_llm action to preserve its UUID\n const existingCallLlmAction = originalNode.actions?.find(\n (action) => action.type === 'call_llm'\n );\n const callLlmUuid = existingCallLlmAction?.uuid || generateUUID();\n\n // Create call_llm action (using any type to match the example format)\n const callLlmAction: CallLLM = {\n type: 'call_llm',\n uuid: callLlmUuid,\n llm: llmSelection\n ? { uuid: llmSelection.value, name: llmSelection.name }\n : { uuid: '', name: '' },\n instructions: `@(prompt(\"categorize\", slice(node.categories, 0, -2)))`,\n input: formData.input || '@input',\n output_local: '_llm_output'\n };\n\n // Create categories and exits\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n const { router, exits } = createMultiCategoryRouter(\n '@locals._llm_output',\n userCategories,\n (categoryName) => ({\n type: 'has_only_text',\n arguments: [categoryName]\n }),\n existingCategories,\n existingExits,\n existingCases\n );\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: [callLlmAction],\n router: router,\n exits: exits\n };\n }\n};\n"]}
|
|
@@ -1,8 +1,125 @@
|
|
|
1
1
|
import { COLORS } from '../types';
|
|
2
|
+
import { generateUUID } from '../../utils';
|
|
3
|
+
// Helper function to create a random router with categories
|
|
4
|
+
const createRandomRouter = (userCategories, existingCategories = [], existingExits = []) => {
|
|
5
|
+
const categories = [];
|
|
6
|
+
const exits = [];
|
|
7
|
+
// Create categories and exits for user-defined buckets
|
|
8
|
+
userCategories.forEach((categoryName) => {
|
|
9
|
+
// Try to find existing category by name
|
|
10
|
+
const existingCategory = existingCategories.find((cat) => cat.name === categoryName);
|
|
11
|
+
const existingExit = existingCategory
|
|
12
|
+
? existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid)
|
|
13
|
+
: null;
|
|
14
|
+
const exitUuid = (existingExit === null || existingExit === void 0 ? void 0 : existingExit.uuid) || generateUUID();
|
|
15
|
+
const categoryUuid = (existingCategory === null || existingCategory === void 0 ? void 0 : existingCategory.uuid) || generateUUID();
|
|
16
|
+
categories.push({
|
|
17
|
+
uuid: categoryUuid,
|
|
18
|
+
name: categoryName,
|
|
19
|
+
exit_uuid: exitUuid
|
|
20
|
+
});
|
|
21
|
+
exits.push({
|
|
22
|
+
uuid: exitUuid,
|
|
23
|
+
destination_uuid: (existingExit === null || existingExit === void 0 ? void 0 : existingExit.destination_uuid) || null
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
router: {
|
|
28
|
+
type: 'random',
|
|
29
|
+
categories: categories
|
|
30
|
+
},
|
|
31
|
+
exits: exits
|
|
32
|
+
};
|
|
33
|
+
};
|
|
2
34
|
export const split_by_random = {
|
|
3
35
|
type: 'split_by_random',
|
|
4
36
|
name: 'Split by Random',
|
|
5
37
|
color: COLORS.split,
|
|
38
|
+
form: {
|
|
39
|
+
categories: {
|
|
40
|
+
type: 'array',
|
|
41
|
+
label: 'Buckets',
|
|
42
|
+
helpText: 'Define the buckets to randomly split contacts into',
|
|
43
|
+
required: true,
|
|
44
|
+
itemLabel: 'Bucket',
|
|
45
|
+
minItems: 2,
|
|
46
|
+
maxItems: 10,
|
|
47
|
+
isEmptyItem: (item) => {
|
|
48
|
+
return !item.name || item.name.trim() === '';
|
|
49
|
+
},
|
|
50
|
+
itemConfig: {
|
|
51
|
+
name: {
|
|
52
|
+
type: 'text',
|
|
53
|
+
placeholder: 'Bucket name',
|
|
54
|
+
required: true
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
layout: ['categories'],
|
|
60
|
+
validate: (formData) => {
|
|
61
|
+
const errors = {};
|
|
62
|
+
// Check for duplicate category names
|
|
63
|
+
if (formData.categories && Array.isArray(formData.categories)) {
|
|
64
|
+
const categories = formData.categories.filter((item) => (item === null || item === void 0 ? void 0 : item.name) && item.name.trim() !== '');
|
|
65
|
+
// Ensure minimum buckets
|
|
66
|
+
if (categories.length < 2) {
|
|
67
|
+
errors.categories = 'At least 2 buckets are required for random split';
|
|
68
|
+
}
|
|
69
|
+
// Find all categories that have duplicates (case-insensitive)
|
|
70
|
+
const duplicateCategories = [];
|
|
71
|
+
const lowerCaseMap = new Map();
|
|
72
|
+
// First pass: map lowercase names to all original cases
|
|
73
|
+
categories.forEach((category) => {
|
|
74
|
+
const lowerName = category.name.trim().toLowerCase();
|
|
75
|
+
if (!lowerCaseMap.has(lowerName)) {
|
|
76
|
+
lowerCaseMap.set(lowerName, []);
|
|
77
|
+
}
|
|
78
|
+
lowerCaseMap.get(lowerName).push(category.name.trim());
|
|
79
|
+
});
|
|
80
|
+
// Second pass: collect all names that appear more than once
|
|
81
|
+
lowerCaseMap.forEach((originalNames) => {
|
|
82
|
+
if (originalNames.length > 1) {
|
|
83
|
+
duplicateCategories.push(...originalNames);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
if (duplicateCategories.length > 0) {
|
|
87
|
+
const uniqueDuplicates = [...new Set(duplicateCategories)];
|
|
88
|
+
errors.categories = `Duplicate bucket names found: ${uniqueDuplicates.join(', ')}`;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
valid: Object.keys(errors).length === 0,
|
|
93
|
+
errors
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
toFormData: (node) => {
|
|
97
|
+
var _a, _b;
|
|
98
|
+
// Extract categories from the existing node structure
|
|
99
|
+
const categories = ((_b = (_a = node.router) === null || _a === void 0 ? void 0 : _a.categories) === null || _b === void 0 ? void 0 : _b.map((cat) => ({ name: cat.name }))) || [];
|
|
100
|
+
return {
|
|
101
|
+
uuid: node.uuid,
|
|
102
|
+
categories: categories
|
|
103
|
+
};
|
|
104
|
+
},
|
|
105
|
+
fromFormData: (formData, originalNode) => {
|
|
106
|
+
var _a;
|
|
107
|
+
// Get user categories
|
|
108
|
+
const userCategories = (formData.categories || [])
|
|
109
|
+
.filter((item) => { var _a; return (_a = item === null || item === void 0 ? void 0 : item.name) === null || _a === void 0 ? void 0 : _a.trim(); })
|
|
110
|
+
.map((item) => item.name.trim());
|
|
111
|
+
// Create router and exits using existing data when possible
|
|
112
|
+
const existingCategories = ((_a = originalNode.router) === null || _a === void 0 ? void 0 : _a.categories) || [];
|
|
113
|
+
const existingExits = originalNode.exits || [];
|
|
114
|
+
const { router, exits } = createRandomRouter(userCategories, existingCategories, existingExits);
|
|
115
|
+
// Return the complete node
|
|
116
|
+
return {
|
|
117
|
+
uuid: originalNode.uuid,
|
|
118
|
+
actions: originalNode.actions || [],
|
|
119
|
+
router: router,
|
|
120
|
+
exits: exits
|
|
121
|
+
};
|
|
122
|
+
},
|
|
6
123
|
router: {
|
|
7
124
|
type: 'random'
|
|
8
125
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split_by_random.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_random.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,UAAU,CAAC;AAE9C,MAAM,CAAC,MAAM,eAAe,GAAe;IACzC,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE,iBAAiB;IACvB,KAAK,EAAE,MAAM,CAAC,KAAK;IACnB,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;KACf;CACF,CAAC","sourcesContent":["import { COLORS, NodeConfig } from '../types';\n\nexport const split_by_random: NodeConfig = {\n type: 'split_by_random',\n name: 'Split by Random',\n color: COLORS.split,\n router: {\n type: 'random'\n }\n};\n"]}
|
|
1
|
+
{"version":3,"file":"split_by_random.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_random.ts"],"names":[],"mappings":"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","sourcesContent":["import { COLORS, NodeConfig } from '../types';\nimport { Node, Category, Exit } from '../../store/flow-definition.d';\nimport { generateUUID } from '../../utils';\n\n// Helper function to create a random router with categories\nconst createRandomRouter = (\n userCategories: string[],\n existingCategories: Category[] = [],\n existingExits: Exit[] = []\n) => {\n const categories: Category[] = [];\n const exits: Exit[] = [];\n\n // Create categories and exits for user-defined buckets\n userCategories.forEach((categoryName) => {\n // Try to find existing category by name\n const existingCategory = existingCategories.find(\n (cat) => cat.name === categoryName\n );\n const existingExit = existingCategory\n ? existingExits.find((exit) => exit.uuid === existingCategory.exit_uuid)\n : null;\n\n const exitUuid = existingExit?.uuid || generateUUID();\n const categoryUuid = existingCategory?.uuid || generateUUID();\n\n categories.push({\n uuid: categoryUuid,\n name: categoryName,\n exit_uuid: exitUuid\n });\n\n exits.push({\n uuid: exitUuid,\n destination_uuid: existingExit?.destination_uuid || null\n });\n });\n\n return {\n router: {\n type: 'random' as const,\n categories: categories\n },\n exits: exits\n };\n};\n\nexport const split_by_random: NodeConfig = {\n type: 'split_by_random',\n name: 'Split by Random',\n color: COLORS.split,\n form: {\n categories: {\n type: 'array',\n label: 'Buckets',\n helpText: 'Define the buckets to randomly split contacts into',\n required: true,\n itemLabel: 'Bucket',\n minItems: 2,\n maxItems: 10,\n isEmptyItem: (item: any) => {\n return !item.name || item.name.trim() === '';\n },\n itemConfig: {\n name: {\n type: 'text',\n placeholder: 'Bucket name',\n required: true\n }\n }\n }\n },\n layout: ['categories'],\n validate: (formData: any) => {\n const errors: { [key: string]: string } = {};\n\n // Check for duplicate category names\n if (formData.categories && Array.isArray(formData.categories)) {\n const categories = formData.categories.filter(\n (item: any) => item?.name && item.name.trim() !== ''\n );\n\n // Ensure minimum buckets\n if (categories.length < 2) {\n errors.categories = 'At least 2 buckets are required for random split';\n }\n\n // Find all categories that have duplicates (case-insensitive)\n const duplicateCategories = [];\n const lowerCaseMap = new Map();\n\n // First pass: map lowercase names to all original cases\n categories.forEach((category) => {\n const lowerName = category.name.trim().toLowerCase();\n if (!lowerCaseMap.has(lowerName)) {\n lowerCaseMap.set(lowerName, []);\n }\n lowerCaseMap.get(lowerName).push(category.name.trim());\n });\n\n // Second pass: collect all names that appear more than once\n lowerCaseMap.forEach((originalNames) => {\n if (originalNames.length > 1) {\n duplicateCategories.push(...originalNames);\n }\n });\n\n if (duplicateCategories.length > 0) {\n const uniqueDuplicates = [...new Set(duplicateCategories)];\n errors.categories = `Duplicate bucket names found: ${uniqueDuplicates.join(\n ', '\n )}`;\n }\n }\n\n return {\n valid: Object.keys(errors).length === 0,\n errors\n };\n },\n toFormData: (node: Node) => {\n // Extract categories from the existing node structure\n const categories =\n node.router?.categories?.map((cat) => ({ name: cat.name })) || [];\n\n return {\n uuid: node.uuid,\n categories: categories\n };\n },\n fromFormData: (formData: any, originalNode: Node): Node => {\n // Get user categories\n const userCategories = (formData.categories || [])\n .filter((item: any) => item?.name?.trim())\n .map((item: any) => item.name.trim());\n\n // Create router and exits using existing data when possible\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n\n const { router, exits } = createRandomRouter(\n userCategories,\n existingCategories,\n existingExits\n );\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: originalNode.actions || [],\n router: router,\n exits: exits\n };\n },\n router: {\n type: 'random'\n }\n};\n"]}
|
|
@@ -1,9 +1,129 @@
|
|
|
1
|
-
import { enter_flow } from '../actions/enter_flow';
|
|
2
1
|
import { COLORS } from '../types';
|
|
2
|
+
import { generateUUID } from '../../utils';
|
|
3
|
+
import { html } from 'lit';
|
|
3
4
|
export const split_by_subflow = {
|
|
4
5
|
type: 'split_by_subflow',
|
|
5
|
-
name: '
|
|
6
|
+
name: 'Enter a Flow',
|
|
6
7
|
color: COLORS.execute,
|
|
7
|
-
|
|
8
|
+
form: {
|
|
9
|
+
flow: {
|
|
10
|
+
type: 'select',
|
|
11
|
+
required: true,
|
|
12
|
+
placeholder: 'Select a flow...',
|
|
13
|
+
helpText: 'Once the subflow is complete or expires, the contact will return here',
|
|
14
|
+
endpoint: '/api/v2/flows.json',
|
|
15
|
+
valueKey: 'uuid',
|
|
16
|
+
nameKey: 'name'
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
layout: ['flow'],
|
|
20
|
+
render: (node) => {
|
|
21
|
+
var _a, _b;
|
|
22
|
+
const enterFlowAction = (_a = node.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'enter_flow');
|
|
23
|
+
return html `
|
|
24
|
+
<div class="body">
|
|
25
|
+
${((_b = enterFlowAction === null || enterFlowAction === void 0 ? void 0 : enterFlowAction.flow) === null || _b === void 0 ? void 0 : _b.name) || 'Configure subflow'}
|
|
26
|
+
</div>
|
|
27
|
+
`;
|
|
28
|
+
},
|
|
29
|
+
toFormData: (node) => {
|
|
30
|
+
var _a;
|
|
31
|
+
// Extract data from the existing node structure
|
|
32
|
+
const enterFlowAction = (_a = node.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'enter_flow');
|
|
33
|
+
return {
|
|
34
|
+
uuid: node.uuid,
|
|
35
|
+
flow: (enterFlowAction === null || enterFlowAction === void 0 ? void 0 : enterFlowAction.flow)
|
|
36
|
+
? [{ uuid: enterFlowAction.flow.uuid, name: enterFlowAction.flow.name }]
|
|
37
|
+
: []
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
fromFormData: (formData, originalNode) => {
|
|
41
|
+
var _a, _b, _c;
|
|
42
|
+
// Get flow selection
|
|
43
|
+
const flowSelection = Array.isArray(formData.flow) && formData.flow.length > 0
|
|
44
|
+
? formData.flow[0]
|
|
45
|
+
: null;
|
|
46
|
+
// Find existing enter_flow action to preserve its UUID
|
|
47
|
+
const existingEnterFlowAction = (_a = originalNode.actions) === null || _a === void 0 ? void 0 : _a.find((action) => action.type === 'enter_flow');
|
|
48
|
+
const enterFlowUuid = (existingEnterFlowAction === null || existingEnterFlowAction === void 0 ? void 0 : existingEnterFlowAction.uuid) || generateUUID();
|
|
49
|
+
// Create enter_flow action
|
|
50
|
+
const enterFlowAction = {
|
|
51
|
+
type: 'enter_flow',
|
|
52
|
+
uuid: enterFlowUuid,
|
|
53
|
+
flow: flowSelection
|
|
54
|
+
? {
|
|
55
|
+
uuid: flowSelection.uuid || flowSelection.value,
|
|
56
|
+
name: flowSelection.name
|
|
57
|
+
}
|
|
58
|
+
: { uuid: '', name: '' }
|
|
59
|
+
};
|
|
60
|
+
// Create categories and exits for Complete and Expired
|
|
61
|
+
const existingCategories = ((_b = originalNode.router) === null || _b === void 0 ? void 0 : _b.categories) || [];
|
|
62
|
+
const existingExits = originalNode.exits || [];
|
|
63
|
+
const existingCases = ((_c = originalNode.router) === null || _c === void 0 ? void 0 : _c.cases) || [];
|
|
64
|
+
// Find existing Complete category
|
|
65
|
+
const existingCompleteCategory = existingCategories.find((cat) => cat.name === 'Complete');
|
|
66
|
+
const existingCompleteExit = existingCompleteCategory
|
|
67
|
+
? existingExits.find((exit) => exit.uuid === existingCompleteCategory.exit_uuid)
|
|
68
|
+
: null;
|
|
69
|
+
const existingCompleteCase = existingCompleteCategory
|
|
70
|
+
? existingCases.find((case_) => case_.category_uuid === existingCompleteCategory.uuid)
|
|
71
|
+
: null;
|
|
72
|
+
const completeCategoryUuid = (existingCompleteCategory === null || existingCompleteCategory === void 0 ? void 0 : existingCompleteCategory.uuid) || generateUUID();
|
|
73
|
+
const completeExitUuid = (existingCompleteExit === null || existingCompleteExit === void 0 ? void 0 : existingCompleteExit.uuid) || generateUUID();
|
|
74
|
+
const completeCaseUuid = (existingCompleteCase === null || existingCompleteCase === void 0 ? void 0 : existingCompleteCase.uuid) || generateUUID();
|
|
75
|
+
// Find existing Expired category
|
|
76
|
+
const existingExpiredCategory = existingCategories.find((cat) => cat.name === 'Expired');
|
|
77
|
+
const existingExpiredExit = existingExpiredCategory
|
|
78
|
+
? existingExits.find((exit) => exit.uuid === existingExpiredCategory.exit_uuid)
|
|
79
|
+
: null;
|
|
80
|
+
const expiredCategoryUuid = (existingExpiredCategory === null || existingExpiredCategory === void 0 ? void 0 : existingExpiredCategory.uuid) || generateUUID();
|
|
81
|
+
const expiredExitUuid = (existingExpiredExit === null || existingExpiredExit === void 0 ? void 0 : existingExpiredExit.uuid) || generateUUID();
|
|
82
|
+
const categories = [
|
|
83
|
+
{
|
|
84
|
+
uuid: completeCategoryUuid,
|
|
85
|
+
name: 'Complete',
|
|
86
|
+
exit_uuid: completeExitUuid
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
uuid: expiredCategoryUuid,
|
|
90
|
+
name: 'Expired',
|
|
91
|
+
exit_uuid: expiredExitUuid
|
|
92
|
+
}
|
|
93
|
+
];
|
|
94
|
+
const exits = [
|
|
95
|
+
{
|
|
96
|
+
uuid: completeExitUuid,
|
|
97
|
+
destination_uuid: (existingCompleteExit === null || existingCompleteExit === void 0 ? void 0 : existingCompleteExit.destination_uuid) || null
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
uuid: expiredExitUuid,
|
|
101
|
+
destination_uuid: (existingExpiredExit === null || existingExpiredExit === void 0 ? void 0 : existingExpiredExit.destination_uuid) || null
|
|
102
|
+
}
|
|
103
|
+
];
|
|
104
|
+
const cases = [
|
|
105
|
+
{
|
|
106
|
+
uuid: completeCaseUuid,
|
|
107
|
+
type: 'has_only_text',
|
|
108
|
+
arguments: ['completed'],
|
|
109
|
+
category_uuid: completeCategoryUuid
|
|
110
|
+
}
|
|
111
|
+
];
|
|
112
|
+
// Create the router
|
|
113
|
+
const router = {
|
|
114
|
+
type: 'switch',
|
|
115
|
+
categories: categories,
|
|
116
|
+
default_category_uuid: expiredCategoryUuid,
|
|
117
|
+
operand: '@child.status',
|
|
118
|
+
cases: cases
|
|
119
|
+
};
|
|
120
|
+
// Return the complete node
|
|
121
|
+
return {
|
|
122
|
+
uuid: originalNode.uuid,
|
|
123
|
+
actions: [enterFlowAction],
|
|
124
|
+
router: router,
|
|
125
|
+
exits: exits
|
|
126
|
+
};
|
|
127
|
+
}
|
|
8
128
|
};
|
|
9
129
|
//# sourceMappingURL=split_by_subflow.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"split_by_subflow.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_subflow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"split_by_subflow.js","sourceRoot":"","sources":["../../../../src/flow/nodes/split_by_subflow.ts"],"names":[],"mappings":"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","sourcesContent":["import { COLORS, NodeConfig } from '../types';\nimport { Node } from '../../store/flow-definition';\nimport { generateUUID } from '../../utils';\nimport { html } from 'lit';\n\nexport const split_by_subflow: NodeConfig = {\n type: 'split_by_subflow',\n name: 'Enter a Flow',\n color: COLORS.execute,\n form: {\n flow: {\n type: 'select',\n required: true,\n placeholder: 'Select a flow...',\n helpText:\n 'Once the subflow is complete or expires, the contact will return here',\n endpoint: '/api/v2/flows.json',\n valueKey: 'uuid',\n nameKey: 'name'\n }\n },\n layout: ['flow'],\n render: (node: Node) => {\n const enterFlowAction = node.actions?.find(\n (action) => action.type === 'enter_flow'\n ) as any;\n return html`\n <div class=\"body\">\n ${enterFlowAction?.flow?.name || 'Configure subflow'}\n </div>\n `;\n },\n toFormData: (node: Node) => {\n // Extract data from the existing node structure\n const enterFlowAction = node.actions?.find(\n (action) => action.type === 'enter_flow'\n ) as any;\n\n return {\n uuid: node.uuid,\n flow: enterFlowAction?.flow\n ? [{ uuid: enterFlowAction.flow.uuid, name: enterFlowAction.flow.name }]\n : []\n };\n },\n fromFormData: (formData: any, originalNode: Node): Node => {\n // Get flow selection\n const flowSelection =\n Array.isArray(formData.flow) && formData.flow.length > 0\n ? formData.flow[0]\n : null;\n\n // Find existing enter_flow action to preserve its UUID\n const existingEnterFlowAction = originalNode.actions?.find(\n (action) => action.type === 'enter_flow'\n );\n const enterFlowUuid = existingEnterFlowAction?.uuid || generateUUID();\n\n // Create enter_flow action\n const enterFlowAction: any = {\n type: 'enter_flow',\n uuid: enterFlowUuid,\n flow: flowSelection\n ? {\n uuid: flowSelection.uuid || flowSelection.value,\n name: flowSelection.name\n }\n : { uuid: '', name: '' }\n };\n\n // Create categories and exits for Complete and Expired\n const existingCategories = originalNode.router?.categories || [];\n const existingExits = originalNode.exits || [];\n const existingCases = originalNode.router?.cases || [];\n\n // Find existing Complete category\n const existingCompleteCategory = existingCategories.find(\n (cat) => cat.name === 'Complete'\n );\n const existingCompleteExit = existingCompleteCategory\n ? existingExits.find(\n (exit) => exit.uuid === existingCompleteCategory.exit_uuid\n )\n : null;\n const existingCompleteCase = existingCompleteCategory\n ? existingCases.find(\n (case_) => case_.category_uuid === existingCompleteCategory.uuid\n )\n : null;\n\n const completeCategoryUuid =\n existingCompleteCategory?.uuid || generateUUID();\n const completeExitUuid = existingCompleteExit?.uuid || generateUUID();\n const completeCaseUuid = existingCompleteCase?.uuid || generateUUID();\n\n // Find existing Expired category\n const existingExpiredCategory = existingCategories.find(\n (cat) => cat.name === 'Expired'\n );\n const existingExpiredExit = existingExpiredCategory\n ? existingExits.find(\n (exit) => exit.uuid === existingExpiredCategory.exit_uuid\n )\n : null;\n\n const expiredCategoryUuid = existingExpiredCategory?.uuid || generateUUID();\n const expiredExitUuid = existingExpiredExit?.uuid || generateUUID();\n\n const categories = [\n {\n uuid: completeCategoryUuid,\n name: 'Complete',\n exit_uuid: completeExitUuid\n },\n {\n uuid: expiredCategoryUuid,\n name: 'Expired',\n exit_uuid: expiredExitUuid\n }\n ];\n\n const exits = [\n {\n uuid: completeExitUuid,\n destination_uuid: existingCompleteExit?.destination_uuid || null\n },\n {\n uuid: expiredExitUuid,\n destination_uuid: existingExpiredExit?.destination_uuid || null\n }\n ];\n\n const cases = [\n {\n uuid: completeCaseUuid,\n type: 'has_only_text',\n arguments: ['completed'],\n category_uuid: completeCategoryUuid\n }\n ];\n\n // Create the router\n const router = {\n type: 'switch' as const,\n categories: categories,\n default_category_uuid: expiredCategoryUuid,\n operand: '@child.status',\n cases: cases\n };\n\n // Return the complete node\n return {\n uuid: originalNode.uuid,\n actions: [enterFlowAction],\n router: router,\n exits: exits\n };\n }\n};\n"]}
|