windmill-components 1.531.1 → 1.532.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/package/components/ArgInput.svelte +44 -1
- package/package/components/EditableSchemaForm.svelte +27 -18
- package/package/components/EditableSchemaForm.svelte.d.ts +1 -0
- package/package/components/Editor.svelte +2 -2
- package/package/components/Editor.svelte.d.ts +1 -0
- package/package/components/EditorBar.svelte +2 -2
- package/package/components/EditorBar.svelte.d.ts +1 -0
- package/package/components/FieldHeader.svelte +1 -1
- package/package/components/ModuleTest.svelte +4 -1
- package/package/components/ResourceEditor.svelte +4 -0
- package/package/components/ScriptEditor.svelte +1 -0
- package/package/components/StringTypeNarrowing.svelte.d.ts +1 -1
- package/package/components/copilot/FlowInlineScriptAIButton.svelte +4 -2
- package/package/components/copilot/FlowInlineScriptAIButton.svelte.d.ts +4 -1
- package/package/components/copilot/autocomplete/Autocompletor.js +0 -2
- package/package/components/copilot/chat/AIChat.svelte +2 -4
- package/package/components/copilot/chat/AIChatInput.svelte +4 -3
- package/package/components/copilot/chat/AIChatManager.svelte.js +21 -9
- package/package/components/copilot/chat/AvailableContextList.svelte +115 -24
- package/package/components/copilot/chat/AvailableContextList.svelte.d.ts +1 -0
- package/package/components/copilot/chat/ContextElementBadge.svelte +31 -15
- package/package/components/copilot/chat/ContextElementBadge.svelte.d.ts +5 -20
- package/package/components/copilot/chat/ContextManager.svelte.d.ts +15 -2
- package/package/components/copilot/chat/ContextManager.svelte.js +102 -15
- package/package/components/copilot/chat/ContextTextarea.svelte +1 -1
- package/package/components/copilot/chat/context.d.ts +14 -1
- package/package/components/copilot/chat/context.js +1 -0
- package/package/components/copilot/chat/flow/FlowAIChat.svelte +1 -1
- package/package/components/copilot/chat/flow/core.d.ts +2 -1
- package/package/components/copilot/chat/flow/core.js +52 -18
- package/package/components/copilot/chat/script/core.d.ts +2 -2
- package/package/components/copilot/chat/script/core.js +51 -122
- package/package/components/copilot/chat/shared.d.ts +13 -2
- package/package/components/copilot/chat/shared.js +155 -4
- package/package/components/flows/FlowEditor.svelte +12 -0
- package/package/components/flows/FlowModuleIcon.svelte +39 -0
- package/package/components/flows/FlowModuleIcon.svelte.d.ts +10 -0
- package/package/components/flows/content/FlowModuleComponent.svelte +2 -0
- package/package/components/flows/map/MapItem.svelte +8 -39
- package/package/components/schema/FlowPropertyEditor.svelte +75 -17
- package/package/components/schema/PropertyEditor.svelte.d.ts +1 -1
- package/package/components/schema/jsonSchemaResource.svelte.d.ts +2 -0
- package/package/components/schema/jsonSchemaResource.svelte.js +40 -0
- package/package/utils.d.ts +1 -1
- package/package.json +13 -13
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">import { preventDefault, stopPropagation, createBubbler } from 'svelte/legacy';
|
|
2
2
|
const bubble = createBubbler();
|
|
3
|
-
import { setInputCat as computeInputCat, debounce, emptyString, getSchemaFromProperties } from '../utils';
|
|
3
|
+
import { setInputCat as computeInputCat, debounce, emptySchema, emptyString, getSchemaFromProperties } from '../utils';
|
|
4
4
|
import { DollarSign, Plus, X, Check, Loader2, ExternalLink } from 'lucide-svelte';
|
|
5
5
|
import { createEventDispatcher, onDestroy, onMount, tick, untrack } from 'svelte';
|
|
6
6
|
import { fade } from 'svelte/transition';
|
|
@@ -28,6 +28,8 @@ import MultiSelect from './select/MultiSelect.svelte';
|
|
|
28
28
|
import { safeSelectItems } from './select/utils.svelte';
|
|
29
29
|
import S3ArgInput from './common/fileUpload/S3ArgInput.svelte';
|
|
30
30
|
import { base } from '../base';
|
|
31
|
+
import { workspaceStore } from '../stores';
|
|
32
|
+
import { getJsonSchemaFromResource } from './schema/jsonSchemaResource.svelte';
|
|
31
33
|
let { label = '', value = $bindable(), defaultValue = $bindable(undefined), description = $bindable(undefined), format = $bindable(undefined), contentEncoding = undefined, type = undefined, oneOf = $bindable(undefined), required = false, pattern = $bindable(undefined), valid = $bindable(undefined), enum_ = $bindable(undefined), disabled = false, itemsType = $bindable(undefined), displayHeader = true, properties = $bindable(undefined), nestedRequired = undefined, autofocus = null, compact = false, password = false, pickForField = $bindable(undefined), variableEditor = undefined, itemPicker = undefined, noMargin = false, extra = {}, minW = true, prettifyHeader = false, resourceTypes, disablePortal = false, showSchemaExplorer = false, simpleTooltip = undefined, customErrorMessage = undefined, onlyMaskPassword = false, nullable = false, title = $bindable(undefined), placeholder = $bindable(undefined), order = $bindable(undefined), editor = $bindable(undefined), orderEditable = false, shouldDispatchChanges = false, noDefaultOnSelectFirst = false, helperScript = undefined, otherArgs = {}, lightHeader = false, diffStatus = undefined, hideNested = false, nestedParent = undefined, nestedClasses = '', displayType = true, css = undefined, appPath = undefined, computeS3ForceViewerPolicies = undefined, workspace = undefined, actions } = $props();
|
|
32
34
|
$effect(() => {
|
|
33
35
|
if (description == undefined) {
|
|
@@ -488,6 +490,47 @@ onDestroy(() => {
|
|
|
488
490
|
{appPath}
|
|
489
491
|
{computeS3ForceViewerPolicies}
|
|
490
492
|
/>
|
|
493
|
+
{:else if inputCat == 'object' && format == 'json-schema'}
|
|
494
|
+
{#await import('./EditableSchemaForm.svelte')}
|
|
495
|
+
<Loader2 class="animate-spin" />
|
|
496
|
+
{:then Module}
|
|
497
|
+
<Module.default
|
|
498
|
+
bind:schema={
|
|
499
|
+
() =>
|
|
500
|
+
value && typeof value === 'object' && !Array.isArray(value) ? value : emptySchema(),
|
|
501
|
+
(v) => {
|
|
502
|
+
value = v
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
isFlowInput
|
|
506
|
+
editTab="inputEditor"
|
|
507
|
+
noPreview
|
|
508
|
+
addPropertyInEditorTab
|
|
509
|
+
/>
|
|
510
|
+
{/await}
|
|
511
|
+
{:else if inputCat == 'object' && format?.startsWith('jsonschema-')}
|
|
512
|
+
{#await getJsonSchemaFromResource(format.substring('jsonschema-'.length), workspace ?? $workspaceStore ?? '')}
|
|
513
|
+
<Loader2 class="animate-spin" />
|
|
514
|
+
{:then schema}
|
|
515
|
+
{#if !schema || !schema.properties}
|
|
516
|
+
{#await import('./JsonEditor.svelte')}
|
|
517
|
+
<Loader2 class="animate-spin" />
|
|
518
|
+
{:then Module}
|
|
519
|
+
<Module.default code={JSON.stringify(value, null, 2)} bind:value />
|
|
520
|
+
{/await}
|
|
521
|
+
{:else}
|
|
522
|
+
<div class="py-4 pr-2 pl-6 border rounded-md w-full">
|
|
523
|
+
<SchemaForm
|
|
524
|
+
{onlyMaskPassword}
|
|
525
|
+
{disablePortal}
|
|
526
|
+
{disabled}
|
|
527
|
+
{prettifyHeader}
|
|
528
|
+
{schema}
|
|
529
|
+
bind:args={value}
|
|
530
|
+
/>
|
|
531
|
+
</div>
|
|
532
|
+
{/if}
|
|
533
|
+
{/await}
|
|
491
534
|
{:else if inputCat == 'list' && !isListJson}
|
|
492
535
|
<div class="w-full flex gap-4">
|
|
493
536
|
<div class="w-full">
|
|
@@ -24,9 +24,10 @@ import { deepEqual } from 'fast-equals';
|
|
|
24
24
|
import { tweened } from 'svelte/motion';
|
|
25
25
|
import Section from './Section.svelte';
|
|
26
26
|
import Editor from './Editor.svelte';
|
|
27
|
+
import AddPropertyV2 from './schema/AddPropertyV2.svelte';
|
|
27
28
|
// export let openEditTab: () => void = () => {}
|
|
28
29
|
const dispatch = createEventDispatcher();
|
|
29
|
-
let { schema = $bindable(), hiddenArgs = [], args = $bindable(undefined), shouldHideNoInputs = false, noVariablePicker = false, flexWrap = false, uiOnly = false, isFlowInput = false, noPreview = false, jsonEnabled = true, isAppInput = false, displayWebhookWarning = false, onlyMaskPassword = false, dndType = undefined, editTab, previewSchema = undefined, editPanelInitialSize = undefined, editPanelSize = $bindable(0), diff = {}, disableDnd = false, shouldDispatchChanges = false, isValid = $bindable(true), customUi = undefined, pannelExtraButtonWidth = 0, class: clazz = '', dynSelectCode = $bindable(), dynSelectLang = $bindable(), showDynSelectOpt = false, openEditTab, addProperty, runButton, extraTab } = $props();
|
|
30
|
+
let { schema = $bindable(), hiddenArgs = [], args = $bindable(undefined), shouldHideNoInputs = false, noVariablePicker = false, flexWrap = false, uiOnly = false, isFlowInput = false, noPreview = false, jsonEnabled = true, isAppInput = false, displayWebhookWarning = false, onlyMaskPassword = false, dndType = undefined, editTab, previewSchema = undefined, editPanelInitialSize = undefined, editPanelSize = $bindable(0), diff = {}, disableDnd = false, shouldDispatchChanges = false, isValid = $bindable(true), customUi = undefined, pannelExtraButtonWidth = 0, class: clazz = '', dynSelectCode = $bindable(), dynSelectLang = $bindable(), showDynSelectOpt = false, addPropertyInEditorTab = false, openEditTab, addProperty, runButton, extraTab } = $props();
|
|
30
31
|
$effect.pre(() => {
|
|
31
32
|
if (args == undefined) {
|
|
32
33
|
args = {};
|
|
@@ -390,22 +391,31 @@ function updateDynSelectCode(functionName, lang = 'bun') {
|
|
|
390
391
|
{:else}
|
|
391
392
|
<!-- WIP -->
|
|
392
393
|
{#if jsonEnabled && customUi?.jsonOnly != true}
|
|
393
|
-
<div class="w-full p-3 flex justify-end">
|
|
394
|
-
|
|
395
|
-
bind:
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
394
|
+
<div class="w-full p-3 flex gap-4 justify-end items-center">
|
|
395
|
+
{#if addPropertyInEditorTab}
|
|
396
|
+
<AddPropertyV2 bind:schema on:change>
|
|
397
|
+
{#snippet trigger()}
|
|
398
|
+
<Button color="light" size="xs" iconOnly startIcon={{ icon: Plus }} />
|
|
399
|
+
{/snippet}
|
|
400
|
+
</AddPropertyV2>
|
|
401
|
+
{/if}
|
|
402
|
+
<div class="shrink-0">
|
|
403
|
+
<Toggle
|
|
404
|
+
bind:checked={jsonView}
|
|
405
|
+
label="JSON View"
|
|
406
|
+
size="xs"
|
|
407
|
+
options={{
|
|
408
|
+
right: 'JSON editor',
|
|
409
|
+
rightTooltip:
|
|
410
|
+
'Arguments can be edited either using the wizard, or by editing their JSON Schema.'
|
|
411
|
+
}}
|
|
412
|
+
lightMode
|
|
413
|
+
on:change={() => {
|
|
414
|
+
schemaString = JSON.stringify(schema, null, '\t')
|
|
415
|
+
editor?.setCode(schemaString)
|
|
416
|
+
}}
|
|
417
|
+
/>
|
|
418
|
+
</div>
|
|
409
419
|
</div>
|
|
410
420
|
{/if}
|
|
411
421
|
|
|
@@ -536,7 +546,6 @@ function updateDynSelectCode(functionName, lang = 'bun') {
|
|
|
536
546
|
const isS3 = v == 'S3'
|
|
537
547
|
const isOneOf = v == 'oneOf'
|
|
538
548
|
const isDynSelect = v == 'dynselect'
|
|
539
|
-
|
|
540
549
|
const emptyProperty = {
|
|
541
550
|
contentEncoding: undefined,
|
|
542
551
|
enum_: undefined,
|
|
@@ -31,6 +31,7 @@ interface Props {
|
|
|
31
31
|
dynSelectCode?: string | undefined;
|
|
32
32
|
dynSelectLang?: ScriptLang | undefined;
|
|
33
33
|
showDynSelectOpt?: boolean;
|
|
34
|
+
addPropertyInEditorTab?: boolean;
|
|
34
35
|
openEditTab?: import('svelte').Snippet;
|
|
35
36
|
addProperty?: import('svelte').Snippet;
|
|
36
37
|
runButton?: import('svelte').Snippet;
|
|
@@ -114,7 +114,7 @@ import { getDbSchemas } from './apps/components/display/dbtable/utils';
|
|
|
114
114
|
// import EditorTheme from './EditorTheme.svelte'
|
|
115
115
|
let divEl = $state(null);
|
|
116
116
|
let editor = $state(null);
|
|
117
|
-
let { code = $bindable(), cmdEnterAction = undefined, formatAction = undefined, automaticLayout = true, websocketAlive = $bindable(), shouldBindKey = true, fixedOverflowWidgets = true, path = undefined, yContent = undefined, awareness = undefined, folding = false, args = undefined, useWebsockets = true, small = false, scriptLang, disabled = false, lineNumbersMinChars = 3, files = {}, extraLib = undefined, changeTimeout = 500, loadAsync = false, key = undefined, class: clazz = undefined } = $props();
|
|
117
|
+
let { code = $bindable(), cmdEnterAction = undefined, formatAction = undefined, automaticLayout = true, websocketAlive = $bindable(), shouldBindKey = true, fixedOverflowWidgets = true, path = undefined, yContent = undefined, awareness = undefined, folding = false, args = undefined, useWebsockets = true, small = false, scriptLang, disabled = false, lineNumbersMinChars = 3, files = {}, extraLib = undefined, changeTimeout = 500, loadAsync = false, key = undefined, class: clazz = undefined, moduleId = undefined } = $props();
|
|
118
118
|
$effect.pre(() => {
|
|
119
119
|
if (websocketAlive == undefined) {
|
|
120
120
|
websocketAlive = {
|
|
@@ -1077,7 +1077,7 @@ async function loadMonaco() {
|
|
|
1077
1077
|
(selection.startLineNumber !== selection.endLineNumber ||
|
|
1078
1078
|
selection.startColumn !== selection.endColumn);
|
|
1079
1079
|
if (hasSelection && selectedLines) {
|
|
1080
|
-
aiChatManager.addSelectedLinesToContext(selectedLines, selection.startLineNumber, selection.endLineNumber);
|
|
1080
|
+
aiChatManager.addSelectedLinesToContext(selectedLines, selection.startLineNumber, selection.endLineNumber, moduleId);
|
|
1081
1081
|
}
|
|
1082
1082
|
else {
|
|
1083
1083
|
aiChatManager.toggleOpen();
|
|
@@ -31,6 +31,7 @@ interface Props {
|
|
|
31
31
|
loadAsync?: boolean;
|
|
32
32
|
key?: string | undefined;
|
|
33
33
|
class?: string | undefined;
|
|
34
|
+
moduleId?: string;
|
|
34
35
|
}
|
|
35
36
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
36
37
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
@@ -31,7 +31,7 @@ import S3FilePicker from './S3FilePicker.svelte';
|
|
|
31
31
|
import DucklakeIcon from './icons/DucklakeIcon.svelte';
|
|
32
32
|
import FlowInlineScriptAiButton from './copilot/FlowInlineScriptAIButton.svelte';
|
|
33
33
|
import ScriptGen from './copilot/ScriptGen.svelte';
|
|
34
|
-
let { lang, editor, websocketAlive, iconOnly = false, validCode = true, kind = 'script', template = 'script', collabMode = false, collabLive = false, collabUsers = [], scriptPath = undefined, diffEditor = undefined, args, noHistory = false, saveToWorkspace = false, customUi = {}, lastDeployedCode = undefined, diffMode = false, showHistoryDrawer = $bindable(false), right, openAiChat = false } = $props();
|
|
34
|
+
let { lang, editor, websocketAlive, iconOnly = false, validCode = true, kind = 'script', template = 'script', collabMode = false, collabLive = false, collabUsers = [], scriptPath = undefined, diffEditor = undefined, args, noHistory = false, saveToWorkspace = false, customUi = {}, lastDeployedCode = undefined, diffMode = false, showHistoryDrawer = $bindable(false), right, openAiChat = false, moduleId = undefined } = $props();
|
|
35
35
|
let contextualVariablePicker = $state();
|
|
36
36
|
let variablePicker = $state();
|
|
37
37
|
let resourcePicker = $state();
|
|
@@ -870,7 +870,7 @@ JsonNode ${windmillPathToCamelCaseName(path)} = JsonNode.Parse(await client.GetS
|
|
|
870
870
|
|
|
871
871
|
{#if customUi?.aiGen != false}
|
|
872
872
|
{#if openAiChat}
|
|
873
|
-
<FlowInlineScriptAiButton />
|
|
873
|
+
<FlowInlineScriptAiButton {moduleId} />
|
|
874
874
|
{:else}
|
|
875
875
|
<ScriptGen {editor} {diffEditor} {lang} {iconOnly} {args} />
|
|
876
876
|
{/if}
|
|
@@ -33,6 +33,7 @@ interface Props {
|
|
|
33
33
|
showHistoryDrawer?: boolean;
|
|
34
34
|
right?: import('svelte').Snippet;
|
|
35
35
|
openAiChat?: boolean;
|
|
36
|
+
moduleId?: string;
|
|
36
37
|
}
|
|
37
38
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
38
39
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
@@ -38,7 +38,7 @@ export let simpleTooltipIconClass = '';
|
|
|
38
38
|
{/if}
|
|
39
39
|
|
|
40
40
|
{#if displayType}
|
|
41
|
-
{#if format && !format.startsWith('resource')}
|
|
41
|
+
{#if format && !format.startsWith('resource') && !format.startsWith('jsonschema-')}
|
|
42
42
|
<span class="text-xs italic ml-2 text-tertiary dark:text-indigo-400">
|
|
43
43
|
{format}
|
|
44
44
|
</span>
|
|
@@ -129,7 +129,10 @@ modulesTestStates.states[mod.id] = {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
|
-
bind:job={
|
|
132
|
+
bind:job={
|
|
133
|
+
() => modulesTestStates.states[mod.id]?.testJob,
|
|
134
|
+
(v) => modulesTestStates.states[mod.id] && (modulesTestStates.states[mod.id].testJob = v)
|
|
135
|
+
}
|
|
133
136
|
loadPlaceholderJobOnStart={{
|
|
134
137
|
type: 'QueuedJob',
|
|
135
138
|
id: '',
|
|
@@ -18,6 +18,7 @@ import GfmMarkdown from './GfmMarkdown.svelte';
|
|
|
18
18
|
import TestTriggerConnection from './triggers/TestTriggerConnection.svelte';
|
|
19
19
|
import GitHubAppIntegration from './GitHubAppIntegration.svelte';
|
|
20
20
|
import Button from './common/button/Button.svelte';
|
|
21
|
+
import { clearJsonSchemaResourceCache } from './schema/jsonSchemaResource.svelte';
|
|
21
22
|
let { canSave = $bindable(true), resource_type = $bindable(undefined), path = $bindable(''), newResource = false, hidePath = false, onChange, defaultValues = undefined } = $props();
|
|
22
23
|
let isValid = $state(true);
|
|
23
24
|
let jsonError = $state('');
|
|
@@ -64,6 +65,9 @@ export async function editResource() {
|
|
|
64
65
|
path: resourceToEdit.path,
|
|
65
66
|
requestBody: { path, value: args, description }
|
|
66
67
|
});
|
|
68
|
+
if (resourceToEdit.resource_type === 'json_schema') {
|
|
69
|
+
clearJsonSchemaResourceCache(resourceToEdit.path, $workspaceStore);
|
|
70
|
+
}
|
|
67
71
|
sendUserToast(`Updated resource at ${path}`);
|
|
68
72
|
dispatch('refresh', path);
|
|
69
73
|
}
|
|
@@ -15,6 +15,6 @@ interface Props {
|
|
|
15
15
|
overrideAllowKindChange?: boolean;
|
|
16
16
|
originalType?: string | undefined;
|
|
17
17
|
}
|
|
18
|
-
declare const StringTypeNarrowing: import("svelte").Component<Props, {}, "password" | "disableCreate" | "pattern" | "format" | "enum_" | "enumLabels" | "contentEncoding" | "customErrorMessage" | "
|
|
18
|
+
declare const StringTypeNarrowing: import("svelte").Component<Props, {}, "password" | "disableCreate" | "pattern" | "format" | "enum_" | "enumLabels" | "contentEncoding" | "customErrorMessage" | "minRows" | "disableVariablePicker" | "dateFormat">;
|
|
19
19
|
type StringTypeNarrowing = ReturnType<typeof StringTypeNarrowing>;
|
|
20
20
|
export default StringTypeNarrowing;
|
|
@@ -6,6 +6,7 @@ import { ExternalLink, WandSparkles } from 'lucide-svelte';
|
|
|
6
6
|
import { base } from '../../base';
|
|
7
7
|
import { twMerge } from 'tailwind-merge';
|
|
8
8
|
import { aiChatManager, AIMode } from './chat/AIChatManager.svelte';
|
|
9
|
+
const { moduleId } = $props();
|
|
9
10
|
const aiChatScriptModeClasses = $derived(aiChatManager.mode === AIMode.SCRIPT && aiChatManager.isOpen
|
|
10
11
|
? 'dark:bg-violet-900 bg-violet-100'
|
|
11
12
|
: '');
|
|
@@ -18,7 +19,7 @@ const aiChatScriptModeClasses = $derived(aiChatManager.mode === AIMode.SCRIPT &&
|
|
|
18
19
|
btnClasses={twMerge('!px-2', aiChatScriptModeClasses)}
|
|
19
20
|
{onClick}
|
|
20
21
|
iconOnly
|
|
21
|
-
title="Open AI chat
|
|
22
|
+
title="Open AI chat"
|
|
22
23
|
startIcon={{ icon: WandSparkles, classes: 'text-violet-800 dark:text-violet-400' }}
|
|
23
24
|
/>
|
|
24
25
|
{/snippet}
|
|
@@ -26,7 +27,8 @@ const aiChatScriptModeClasses = $derived(aiChatManager.mode === AIMode.SCRIPT &&
|
|
|
26
27
|
{#if $copilotInfo.enabled}
|
|
27
28
|
{@render button(() => {
|
|
28
29
|
aiChatManager.openChat()
|
|
29
|
-
aiChatManager.
|
|
30
|
+
const availableContext = aiChatManager.contextManager.getAvailableContext()
|
|
31
|
+
aiChatManager.contextManager.setSelectedModuleContext(moduleId, availableContext)
|
|
30
32
|
})}
|
|
31
33
|
{:else}
|
|
32
34
|
<Popover
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
interface Props {
|
|
2
|
+
moduleId?: string;
|
|
3
|
+
}
|
|
4
|
+
declare const FlowInlineScriptAiButton: import("svelte").Component<Props, {}, "">;
|
|
2
5
|
type FlowInlineScriptAiButton = ReturnType<typeof FlowInlineScriptAiButton>;
|
|
3
6
|
export default FlowInlineScriptAiButton;
|
|
@@ -128,9 +128,7 @@ export class Autocompletor {
|
|
|
128
128
|
]
|
|
129
129
|
};
|
|
130
130
|
},
|
|
131
|
-
// @ts-ignore
|
|
132
131
|
disposeInlineCompletions: () => { },
|
|
133
|
-
freeInlineCompletions: () => { }
|
|
134
132
|
});
|
|
135
133
|
this.#cursorDisposable = editor.onDidChangeCursorPosition(async (e) => {
|
|
136
134
|
deletionsCues.clear();
|
|
@@ -47,7 +47,7 @@ $effect(() => {
|
|
|
47
47
|
aiChatManager.listenForDbSchemasChanges($dbSchemas);
|
|
48
48
|
});
|
|
49
49
|
$effect(() => {
|
|
50
|
-
aiChatManager.
|
|
50
|
+
aiChatManager.listenForContextChange($dbSchemas, $workspaceStore, $copilotSessionModel);
|
|
51
51
|
});
|
|
52
52
|
$effect(() => {
|
|
53
53
|
aiChatManager.updateMode(untrack(() => aiChatManager.mode));
|
|
@@ -80,9 +80,7 @@ $effect(() => {
|
|
|
80
80
|
pastChats={historyManager.getPastChats()}
|
|
81
81
|
bind:selectedContext={
|
|
82
82
|
() => aiChatManager.contextManager.getSelectedContext(),
|
|
83
|
-
(sc) =>
|
|
84
|
-
aiChatManager.scriptEditorOptions && aiChatManager.contextManager.setSelectedContext(sc)
|
|
85
|
-
}
|
|
83
|
+
(sc) => aiChatManager.contextManager.setSelectedContext(sc)
|
|
86
84
|
}
|
|
87
85
|
availableContext={aiChatManager.contextManager.getAvailableContext()}
|
|
88
86
|
messages={aiChatManager.currentReply
|
|
@@ -33,7 +33,7 @@ let contextTextareaComponent = $state();
|
|
|
33
33
|
let instructionsTextareaComponent = $state();
|
|
34
34
|
let instructions = $state(initialInstructions);
|
|
35
35
|
export function focusInput() {
|
|
36
|
-
if (aiChatManager.mode === AIMode.SCRIPT) {
|
|
36
|
+
if (aiChatManager.mode === AIMode.SCRIPT || aiChatManager.mode === AIMode.FLOW) {
|
|
37
37
|
contextTextareaComponent?.focus();
|
|
38
38
|
}
|
|
39
39
|
else {
|
|
@@ -82,7 +82,7 @@ $effect(() => {
|
|
|
82
82
|
</script>
|
|
83
83
|
|
|
84
84
|
<div use:clickOutside class="relative">
|
|
85
|
-
{#if aiChatManager.mode === AIMode.SCRIPT}
|
|
85
|
+
{#if aiChatManager.mode === AIMode.SCRIPT || aiChatManager.mode === AIMode.FLOW}
|
|
86
86
|
{#if showContext}
|
|
87
87
|
<div class="flex flex-row gap-1 mb-1 overflow-scroll pt-2 no-scrollbar">
|
|
88
88
|
<Popover>
|
|
@@ -100,6 +100,7 @@ $effect(() => {
|
|
|
100
100
|
addContextToSelection(element)
|
|
101
101
|
close()
|
|
102
102
|
}}
|
|
103
|
+
categorize
|
|
103
104
|
/>
|
|
104
105
|
</svelte:fragment>
|
|
105
106
|
</Popover>
|
|
@@ -107,7 +108,7 @@ $effect(() => {
|
|
|
107
108
|
<ContextElementBadge
|
|
108
109
|
contextElement={element}
|
|
109
110
|
deletable
|
|
110
|
-
|
|
111
|
+
onDelete={() => {
|
|
111
112
|
selectedContext = selectedContext?.filter(
|
|
112
113
|
(c) => c.type !== element.type || c.title !== element.title
|
|
113
114
|
)
|
|
@@ -53,6 +53,7 @@ class AIChatManager {
|
|
|
53
53
|
tools = $state([]);
|
|
54
54
|
helpers = $state(undefined);
|
|
55
55
|
scriptEditorOptions = $state(undefined);
|
|
56
|
+
flowOptions = $state(undefined);
|
|
56
57
|
scriptEditorApplyCode = $state(undefined);
|
|
57
58
|
scriptEditorShowDiffMode = $state(undefined);
|
|
58
59
|
flowAiChatHelpers = $state(undefined);
|
|
@@ -61,7 +62,7 @@ class AIChatManager {
|
|
|
61
62
|
aiChatInput = $state(null);
|
|
62
63
|
confirmationCallback = $state(undefined);
|
|
63
64
|
allowedModes = $derived({
|
|
64
|
-
script: this.scriptEditorOptions !== undefined,
|
|
65
|
+
script: this.flowAiChatHelpers === undefined && this.scriptEditorOptions !== undefined,
|
|
65
66
|
flow: this.flowAiChatHelpers !== undefined,
|
|
66
67
|
navigator: true,
|
|
67
68
|
ask: true,
|
|
@@ -507,7 +508,7 @@ class AIChatManager {
|
|
|
507
508
|
}
|
|
508
509
|
try {
|
|
509
510
|
const oldSelectedContext = this.contextManager?.getSelectedContext() ?? [];
|
|
510
|
-
if (this.mode === AIMode.SCRIPT) {
|
|
511
|
+
if (this.mode === AIMode.SCRIPT || this.mode === AIMode.FLOW) {
|
|
511
512
|
this.contextManager?.updateContextOnRequest(options);
|
|
512
513
|
}
|
|
513
514
|
this.loading = true;
|
|
@@ -527,7 +528,9 @@ class AIChatManager {
|
|
|
527
528
|
{
|
|
528
529
|
role: 'user',
|
|
529
530
|
content: this.instructions,
|
|
530
|
-
contextElements: this.mode === AIMode.SCRIPT
|
|
531
|
+
contextElements: this.mode === AIMode.SCRIPT || this.mode === AIMode.FLOW
|
|
532
|
+
? oldSelectedContext
|
|
533
|
+
: undefined,
|
|
531
534
|
snapshot,
|
|
532
535
|
index: this.messages.length // matching with actual messages index. not -1 because it's not yet added to the messages array
|
|
533
536
|
}
|
|
@@ -545,7 +548,7 @@ class AIChatManager {
|
|
|
545
548
|
};
|
|
546
549
|
switch (this.mode) {
|
|
547
550
|
case AIMode.FLOW:
|
|
548
|
-
userMessage = prepareFlowUserMessage(oldInstructions, this.flowAiChatHelpers.getFlowAndSelectedId());
|
|
551
|
+
userMessage = prepareFlowUserMessage(oldInstructions, this.flowAiChatHelpers.getFlowAndSelectedId(), oldSelectedContext);
|
|
549
552
|
break;
|
|
550
553
|
case AIMode.NAVIGATOR:
|
|
551
554
|
userMessage = prepareNavigatorUserMessage(oldInstructions);
|
|
@@ -672,12 +675,14 @@ class AIChatManager {
|
|
|
672
675
|
this.contextManager?.setFixContext();
|
|
673
676
|
this.sendRequest();
|
|
674
677
|
};
|
|
675
|
-
addSelectedLinesToContext = (lines, startLine, endLine) => {
|
|
678
|
+
addSelectedLinesToContext = (lines, startLine, endLine, moduleId) => {
|
|
676
679
|
if (!this.open) {
|
|
677
680
|
this.toggleOpen();
|
|
678
681
|
}
|
|
679
|
-
|
|
680
|
-
|
|
682
|
+
if (!moduleId) {
|
|
683
|
+
this.changeMode(AIMode.SCRIPT);
|
|
684
|
+
}
|
|
685
|
+
this.contextManager?.addSelectedLinesToContext(lines, startLine, endLine, moduleId);
|
|
681
686
|
this.focusInput();
|
|
682
687
|
};
|
|
683
688
|
saveAndClear = async () => {
|
|
@@ -712,10 +717,16 @@ class AIChatManager {
|
|
|
712
717
|
isPreprocessor: moduleId === 'preprocessor'
|
|
713
718
|
});
|
|
714
719
|
};
|
|
715
|
-
|
|
716
|
-
if (this.scriptEditorOptions) {
|
|
720
|
+
listenForContextChange = (dbSchemas, workspaceStore, copilotSessionModel) => {
|
|
721
|
+
if (this.mode === AIMode.SCRIPT && this.scriptEditorOptions) {
|
|
717
722
|
this.contextManager.updateAvailableContext(this.scriptEditorOptions, dbSchemas, workspaceStore ?? '', !copilotSessionModel?.model.endsWith('/thinking'), untrack(() => this.contextManager.getSelectedContext()));
|
|
718
723
|
}
|
|
724
|
+
else if (this.mode === AIMode.FLOW && this.flowOptions) {
|
|
725
|
+
this.contextManager.updateAvailableContextForFlow(this.flowOptions, dbSchemas, workspaceStore ?? '', !copilotSessionModel?.model.endsWith('/thinking'), untrack(() => this.contextManager.getSelectedContext()));
|
|
726
|
+
}
|
|
727
|
+
if (this.scriptEditorOptions) {
|
|
728
|
+
this.contextManager.setScriptOptions(this.scriptEditorOptions);
|
|
729
|
+
}
|
|
719
730
|
};
|
|
720
731
|
listenForDbSchemasChanges = (dbSchemas) => {
|
|
721
732
|
this.displayMessages = ContextManager.updateDisplayMessages(untrack(() => this.displayMessages), dbSchemas);
|
|
@@ -792,6 +803,7 @@ class AIChatManager {
|
|
|
792
803
|
else {
|
|
793
804
|
this.scriptEditorOptions = undefined;
|
|
794
805
|
}
|
|
806
|
+
untrack(() => this.contextManager?.setSelectedModuleContext(selectedId, untrack(() => this.contextManager.getAvailableContext())));
|
|
795
807
|
return () => {
|
|
796
808
|
this.scriptEditorOptions = undefined;
|
|
797
809
|
};
|
|
@@ -1,39 +1,130 @@
|
|
|
1
|
-
<script lang="ts">import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
<script lang="ts">import FlowModuleIcon from '../../flows/FlowModuleIcon.svelte';
|
|
2
|
+
import BarsStaggered from '../../icons/BarsStaggered.svelte';
|
|
3
|
+
import { ContextIconMap } from './context';
|
|
4
|
+
import { ArrowLeft, Diff, Database, Code, ChevronRight } from 'lucide-svelte';
|
|
5
|
+
const { availableContext, selectedContext, onSelect, showAllAvailable = false, stringSearch = '', selectedIndex = 0, categorize = false } = $props();
|
|
6
|
+
// Current view state: 'categories' or specific category type
|
|
7
|
+
let currentView = $state('categories');
|
|
8
|
+
// Category definitions
|
|
9
|
+
const categories = [
|
|
10
|
+
{ id: 'diffs', label: 'Diffs', icon: Diff },
|
|
11
|
+
{ id: 'modules', label: 'Modules', icon: BarsStaggered },
|
|
12
|
+
{ id: 'databases', label: 'Databases', icon: Database },
|
|
13
|
+
{ id: 'code', label: 'Code', icon: Code }
|
|
14
|
+
];
|
|
15
|
+
const filteredAvailableContext = $derived(availableContext.filter((context) => {
|
|
16
|
+
const filtered = (showAllAvailable ||
|
|
17
|
+
!selectedContext.some((sc) => sc.type === context.type && sc.title === context.title)) &&
|
|
18
|
+
(!stringSearch || context.title.toLowerCase().includes(stringSearch.toLowerCase()));
|
|
19
|
+
return filtered;
|
|
17
20
|
}));
|
|
21
|
+
// Group context by category
|
|
22
|
+
const contextByCategory = $derived.by(() => {
|
|
23
|
+
const grouped = {
|
|
24
|
+
diffs: [],
|
|
25
|
+
modules: [],
|
|
26
|
+
databases: [],
|
|
27
|
+
code: []
|
|
28
|
+
};
|
|
29
|
+
filteredAvailableContext.forEach((context) => {
|
|
30
|
+
if (context.type === 'diff')
|
|
31
|
+
grouped.diffs.push(context);
|
|
32
|
+
else if (context.type === 'flow_module')
|
|
33
|
+
grouped.modules.push(context);
|
|
34
|
+
else if (context.type === 'db')
|
|
35
|
+
grouped.databases.push(context);
|
|
36
|
+
else if (context.type === 'code')
|
|
37
|
+
grouped.code.push(context);
|
|
38
|
+
});
|
|
39
|
+
return grouped;
|
|
40
|
+
});
|
|
41
|
+
const currentCategoryItems = $derived(currentView !== 'categories' ? contextByCategory[currentView] : []);
|
|
42
|
+
function handleCategoryClick(categoryId) {
|
|
43
|
+
currentView = categoryId;
|
|
44
|
+
}
|
|
45
|
+
function handleBackClick() {
|
|
46
|
+
currentView = 'categories';
|
|
47
|
+
}
|
|
18
48
|
</script>
|
|
19
49
|
|
|
20
|
-
<div class="flex flex-col gap-1 text-tertiary text-xs p-1 min-w-24 max-h-48 overflow-y-scroll">
|
|
21
|
-
{#if
|
|
22
|
-
|
|
50
|
+
<div class="flex flex-col gap-1 text-tertiary text-xs p-1 pr-0 min-w-24 max-h-48 overflow-y-scroll">
|
|
51
|
+
{#if categorize}
|
|
52
|
+
{#if currentView === 'categories'}
|
|
53
|
+
{#each categories as category}
|
|
54
|
+
{@const itemCount = contextByCategory[category.id].length}
|
|
55
|
+
{@const Icon = category.icon}
|
|
56
|
+
{#if itemCount > 0}
|
|
57
|
+
<button
|
|
58
|
+
class="hover:bg-surface-hover rounded-md p-1 pr-0 text-left flex flex-row gap-1 items-center font-normal transition-colors"
|
|
59
|
+
onclick={() => handleCategoryClick(category.id)}
|
|
60
|
+
>
|
|
61
|
+
<Icon size={16} />
|
|
62
|
+
<span class="flex-1">{category.label}</span>
|
|
63
|
+
<ChevronRight size={16} />
|
|
64
|
+
</button>
|
|
65
|
+
{/if}
|
|
66
|
+
{/each}
|
|
67
|
+
{#if categories.every((cat) => contextByCategory[cat.id].length === 0)}
|
|
68
|
+
<div class="text-center text-tertiary text-xs py-2">No available context</div>
|
|
69
|
+
{/if}
|
|
70
|
+
{:else}
|
|
71
|
+
<!-- Category items view -->
|
|
72
|
+
<button
|
|
73
|
+
class="hover:bg-surface-hover rounded-md text-left flex flex-row gap-1 items-center font-normal transition-colors mb-1"
|
|
74
|
+
onclick={handleBackClick}
|
|
75
|
+
>
|
|
76
|
+
<ArrowLeft size={12} />
|
|
77
|
+
<span class="text-xs">Go back</span>
|
|
78
|
+
</button>
|
|
79
|
+
|
|
80
|
+
{#if currentCategoryItems.length === 0}
|
|
81
|
+
<div class="text-center text-tertiary text-xs py-2">No items in this category</div>
|
|
82
|
+
{:else}
|
|
83
|
+
{#each currentCategoryItems as element}
|
|
84
|
+
{@const Icon = ContextIconMap[element.type]}
|
|
85
|
+
<button
|
|
86
|
+
class="hover:bg-surface-hover rounded-md p-1 text-left flex flex-row gap-1 items-center font-normal transition-colors"
|
|
87
|
+
onclick={() => {
|
|
88
|
+
onSelect(element)
|
|
89
|
+
currentView = 'categories' // Go back to categories after selection
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
{#if element.type === 'flow_module'}
|
|
93
|
+
<FlowModuleIcon module={element as FlowModule} size={16} />
|
|
94
|
+
{:else if Icon}
|
|
95
|
+
<Icon size={16} />
|
|
96
|
+
{/if}
|
|
97
|
+
<span class="truncate">
|
|
98
|
+
{element.type === 'diff' || element.type === 'flow_module'
|
|
99
|
+
? element.title.replace(/_/g, ' ')
|
|
100
|
+
: element.title}
|
|
101
|
+
</span>
|
|
102
|
+
</button>
|
|
103
|
+
{/each}
|
|
104
|
+
{/if}
|
|
105
|
+
{/if}
|
|
23
106
|
{:else}
|
|
24
|
-
{#each
|
|
107
|
+
{#each filteredAvailableContext as element, i}
|
|
25
108
|
{@const Icon = ContextIconMap[element.type]}
|
|
26
109
|
<button
|
|
27
|
-
class="hover:bg-surface-hover rounded-md p-1 text-left flex flex-row gap-1 items-center font-normal {i ===
|
|
110
|
+
class="hover:bg-surface-hover rounded-md p-1 text-left flex flex-row gap-1 items-center font-normal transition-colors {i ===
|
|
28
111
|
selectedIndex
|
|
29
112
|
? 'bg-surface-hover'
|
|
30
113
|
: ''}"
|
|
31
|
-
onclick={() =>
|
|
114
|
+
onclick={() => {
|
|
115
|
+
onSelect(element)
|
|
116
|
+
}}
|
|
32
117
|
>
|
|
33
|
-
{#if
|
|
118
|
+
{#if element.type === 'flow_module'}
|
|
119
|
+
<FlowModuleIcon module={element as FlowModule} size={16} />
|
|
120
|
+
{:else if Icon}
|
|
34
121
|
<Icon size={16} />
|
|
35
122
|
{/if}
|
|
36
|
-
|
|
123
|
+
<span class="truncate">
|
|
124
|
+
{element.type === 'diff' || element.type === 'flow_module'
|
|
125
|
+
? element.title.replace(/_/g, ' ')
|
|
126
|
+
: element.title}
|
|
127
|
+
</span>
|
|
37
128
|
</button>
|
|
38
129
|
{/each}
|
|
39
130
|
{/if}
|
|
@@ -6,6 +6,7 @@ interface Props {
|
|
|
6
6
|
showAllAvailable?: boolean;
|
|
7
7
|
stringSearch?: string;
|
|
8
8
|
selectedIndex?: number;
|
|
9
|
+
categorize?: boolean;
|
|
9
10
|
}
|
|
10
11
|
declare const AvailableContextList: import("svelte").Component<Props, {}, "">;
|
|
11
12
|
type AvailableContextList = ReturnType<typeof AvailableContextList>;
|