diff --git a/packages/toolkit/src/components/ReferenceHintTag.tsx b/packages/toolkit/src/components/ReferenceHintTag.tsx
new file mode 100644
index 0000000000..d7895248e8
--- /dev/null
+++ b/packages/toolkit/src/components/ReferenceHintTag.tsx
@@ -0,0 +1,62 @@
+import cn from "clsx";
+import * as React from "react";
+import { Icons } from "@instill-ai/design-system";
+
+export const ReferenceHintTagRoot = ({
+ children,
+ className,
+}: {
+ children: React.ReactNode;
+ className?: string;
+}) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export const ReferenceHintTagIcon = ({
+ type,
+ className,
+}: {
+ type: "x" | "check";
+ className?: string;
+}) => {
+ return type === "x" ? (
+
+ ) : (
+
+ );
+};
+export const ReferenceHintTagLabel = ({
+ children,
+ className,
+}: {
+ children: React.ReactNode;
+ className?: string;
+}) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export const ReferenceHintTag = {
+ Root: ReferenceHintTagRoot,
+ Icon: ReferenceHintTagIcon,
+ Label: ReferenceHintTagLabel,
+};
diff --git a/packages/toolkit/src/components/index.ts b/packages/toolkit/src/components/index.ts
index 9c0a89edb2..bb193d5282 100644
--- a/packages/toolkit/src/components/index.ts
+++ b/packages/toolkit/src/components/index.ts
@@ -25,6 +25,7 @@ export * from "./ObjectViewer";
export * from "./PageBase";
export * from "./PageHead";
export * from "./PageTitle";
+export * from "./ReferenceHintTag";
export * from "./cells";
export * from "./TableError";
export * from "./UserProfileCard";
diff --git a/packages/toolkit/src/lib/use-instill-form/components/component-output-reference-hints/ListField.tsx b/packages/toolkit/src/lib/use-instill-form/components/component-output-reference-hints/ListField.tsx
new file mode 100644
index 0000000000..ad5338e707
--- /dev/null
+++ b/packages/toolkit/src/lib/use-instill-form/components/component-output-reference-hints/ListField.tsx
@@ -0,0 +1,35 @@
+import { ReferenceHintTag } from "../../../../components";
+
+export const ListField = ({
+ componentID,
+ path,
+ title,
+ instillFormat,
+ description,
+}: {
+ componentID?: string;
+ path: string;
+ title: string;
+ instillFormat: string;
+ description?: string;
+}) => {
+ return (
+
+
+ {`${title} [${instillFormat}]`}
+
+
+
+
+ {componentID ? `${componentID}.` + path : path}
+
+
+
+ {description ? (
+
+ {description}
+
+ ) : null}
+
+ );
+};
diff --git a/packages/toolkit/src/lib/use-instill-form/components/component-output-reference-hints/ObjectArrayField.tsx b/packages/toolkit/src/lib/use-instill-form/components/component-output-reference-hints/ObjectArrayField.tsx
new file mode 100644
index 0000000000..2a26d2fceb
--- /dev/null
+++ b/packages/toolkit/src/lib/use-instill-form/components/component-output-reference-hints/ObjectArrayField.tsx
@@ -0,0 +1,43 @@
+import { ComponentOutputReferenceHints } from ".";
+import { ComponentOutoutReferenceHint } from "../../type";
+
+export const ObjectArrayField = ({
+ hints,
+ parentPath,
+ componentID,
+}: {
+ hints: ComponentOutoutReferenceHint[];
+ parentPath: string;
+ componentID?: string;
+}) => {
+ return (
+
+
+ {`${parentPath} [array]`}
+
+
+
+ {"The "}
+ {parentPath}
+
+ {
+ " is an array with this object, you need to add the index to correctly reference its value"
+ }
+
+
+ {hints.map((hint) => {
+ return (
+
+ );
+ })}
+
+
+ );
+};
diff --git a/packages/toolkit/src/lib/use-instill-form/components/component-output-reference-hints/index.ts b/packages/toolkit/src/lib/use-instill-form/components/component-output-reference-hints/index.ts
new file mode 100644
index 0000000000..f7739d4a6c
--- /dev/null
+++ b/packages/toolkit/src/lib/use-instill-form/components/component-output-reference-hints/index.ts
@@ -0,0 +1,7 @@
+import { ListField } from "./ListField";
+import { ObjectArrayField } from "./ObjectArrayField";
+
+export const ComponentOutputReferenceHints = {
+ ListField,
+ ObjectArrayField,
+};
diff --git a/packages/toolkit/src/lib/use-instill-form/index.ts b/packages/toolkit/src/lib/use-instill-form/index.ts
index cd6c4b8cd9..a327974d02 100644
--- a/packages/toolkit/src/lib/use-instill-form/index.ts
+++ b/packages/toolkit/src/lib/use-instill-form/index.ts
@@ -2,3 +2,4 @@ export * from "./type";
export * from "./useComponentOutputFields";
export * from "./useInstillForm";
export * from "./useStartOperatorTriggerPipelineForm";
+export * from "./useComponentOutputReferenceHintFields";
diff --git a/packages/toolkit/src/lib/use-instill-form/pick/pickComponentOutputFieldsFromInstillFormTree.tsx b/packages/toolkit/src/lib/use-instill-form/pick/pickComponentOutputFieldsFromInstillFormTree.tsx
index b710af89a0..151d7f7d39 100644
--- a/packages/toolkit/src/lib/use-instill-form/pick/pickComponentOutputFieldsFromInstillFormTree.tsx
+++ b/packages/toolkit/src/lib/use-instill-form/pick/pickComponentOutputFieldsFromInstillFormTree.tsx
@@ -93,7 +93,7 @@ export function pickComponentOutputFieldsFromInstillFormTree(
}
// Process objectArray
- // Becase we don't know the index of the output objectArray, we need to user
+ // Becase we don't know the index of the output objectArray, we need to use
// the data as a hint here
if (tree._type === "objectArray") {
diff --git a/packages/toolkit/src/lib/use-instill-form/pick/pickComponentsFromReferenceHints.tsx b/packages/toolkit/src/lib/use-instill-form/pick/pickComponentsFromReferenceHints.tsx
new file mode 100644
index 0000000000..3b53a22db7
--- /dev/null
+++ b/packages/toolkit/src/lib/use-instill-form/pick/pickComponentsFromReferenceHints.tsx
@@ -0,0 +1,58 @@
+import { groupBy } from "../../utility";
+import { ComponentOutputReferenceHints } from "../components/component-output-reference-hints";
+import { ComponentOutoutReferenceHint } from "../type";
+
+export type PickComponentsFromReferenceHintsOptions = {
+ mode?: "groupByFormat" | "list";
+ componentID?: string;
+};
+
+export function pickComponentsFromReferenceHints(
+ hints: ComponentOutoutReferenceHint[],
+ options?: PickComponentsFromReferenceHintsOptions
+) {
+ const mode = options?.mode ?? "list";
+ const componentID = options?.componentID ?? undefined;
+ const fields: React.ReactNode[] = [];
+
+ if (mode === "list") {
+ const nonObjectArrayHints: ComponentOutoutReferenceHint[] = [];
+ const objectArrayHints: ComponentOutoutReferenceHint[] = [];
+
+ hints.forEach((hint) => {
+ if (hint.isObjectArrayChild) {
+ objectArrayHints.push(hint);
+ } else {
+ nonObjectArrayHints.push(hint);
+ }
+ });
+
+ const groupedObjectArrayHints = groupBy(objectArrayHints, (hint) =>
+ hint.isObjectArrayChild ? hint.objectArrayParentPath : ""
+ );
+
+ nonObjectArrayHints.forEach((hint) => {
+ fields.push(
+
+ );
+ });
+
+ Object.entries(groupedObjectArrayHints).forEach(([parentPath, hints]) => {
+ fields.push(
+
+ );
+ });
+ }
+
+ return fields;
+}
diff --git a/packages/toolkit/src/lib/use-instill-form/transform/transformInstillFormTreeToReferenceHints.ts b/packages/toolkit/src/lib/use-instill-form/transform/transformInstillFormTreeToReferenceHints.ts
new file mode 100644
index 0000000000..b75b09b2c7
--- /dev/null
+++ b/packages/toolkit/src/lib/use-instill-form/transform/transformInstillFormTreeToReferenceHints.ts
@@ -0,0 +1,83 @@
+import { ComponentOutoutReferenceHint, InstillFormTree } from "../type";
+
+export function transformInstillFormTreeToReferenceHints(
+ tree: InstillFormTree,
+ isObjectArrayChild?: boolean,
+ objectArrayParentPath?: string
+): ComponentOutoutReferenceHint[] {
+ // 1. Preprocess
+ const title = tree.title ?? tree.fieldKey;
+ let referenceHints: ComponentOutoutReferenceHint[] = [];
+
+ // Normall a objectArray child will be a formGroup with the same
+ // path, so we only need to pass the isObjectArrayChild flag and
+ // objectArrayParentPath to the children
+
+ // 2. Process
+
+ if (tree._type === "formGroup") {
+ for (const property of tree.properties) {
+ const hints = transformInstillFormTreeToReferenceHints(
+ property,
+ isObjectArrayChild,
+ objectArrayParentPath
+ );
+ referenceHints = [...referenceHints, ...hints];
+ }
+ return referenceHints;
+ }
+
+ // The component output don't have formCondition
+ if (tree._type === "formCondition") {
+ return referenceHints;
+ }
+
+ if (tree._type === "objectArray") {
+ // ObjectArray need to have the path (by instill protocol the top level won't be the
+ // objectArray, so we can safely assume that the path is not null)
+ if (tree.path) {
+ const hints = transformInstillFormTreeToReferenceHints(
+ tree.properties,
+ true,
+ tree.path
+ );
+ referenceHints = [...referenceHints, ...hints];
+ }
+ return referenceHints;
+ }
+
+ // Process const field
+ if (tree.const || !tree.path) {
+ return referenceHints;
+ }
+
+ // We don't need to hint a field that is lacking instillFormat
+ if (!tree.instillFormat) {
+ return referenceHints;
+ }
+
+ // We don't need to hint a field that is lacking title and key
+ if (!title) {
+ return referenceHints;
+ }
+
+ // Process a normal field
+
+ const hint: ComponentOutoutReferenceHint =
+ isObjectArrayChild && objectArrayParentPath
+ ? {
+ title,
+ path: tree.path,
+ instillFormat: tree.instillFormat,
+ isObjectArrayChild: isObjectArrayChild ?? false,
+ objectArrayParentPath,
+ }
+ : {
+ title,
+ path: tree.path,
+ instillFormat: tree.instillFormat,
+ isObjectArrayChild: false,
+ };
+
+ return [...referenceHints, hint];
+}
diff --git a/packages/toolkit/src/lib/use-instill-form/type.ts b/packages/toolkit/src/lib/use-instill-form/type.ts
index 9bffc21dd9..915742e4c5 100644
--- a/packages/toolkit/src/lib/use-instill-form/type.ts
+++ b/packages/toolkit/src/lib/use-instill-form/type.ts
@@ -161,3 +161,20 @@ export type StartOperatorFreeFormFieldBaseProps = {
disabledFieldControl?: boolean;
disabledReferenceHint?: boolean;
};
+
+export type ComponentOutoutReferenceHint =
+ | {
+ instillFormat: string;
+ path: string;
+ title: string;
+ description?: string;
+ isObjectArrayChild: false;
+ }
+ | {
+ instillFormat: string;
+ path: string;
+ title: string;
+ description?: string;
+ isObjectArrayChild: true;
+ objectArrayParentPath: string;
+ };
diff --git a/packages/toolkit/src/lib/use-instill-form/useComponentOutputFields.tsx b/packages/toolkit/src/lib/use-instill-form/useComponentOutputFields.tsx
index dd037ea5b8..4b6612f387 100644
--- a/packages/toolkit/src/lib/use-instill-form/useComponentOutputFields.tsx
+++ b/packages/toolkit/src/lib/use-instill-form/useComponentOutputFields.tsx
@@ -23,6 +23,8 @@ export function useComponentOutputFields(props: UseComponentOutputFieldsProps) {
const outputFormTree = transformInstillJSONSchemaToFormTree(props.schema);
+ console.log(outputFormTree);
+
const fields = pickComponentOutputFieldsFromInstillFormTree({
...props,
tree: outputFormTree,
diff --git a/packages/toolkit/src/lib/use-instill-form/useComponentOutputReferenceHintFields.tsx b/packages/toolkit/src/lib/use-instill-form/useComponentOutputReferenceHintFields.tsx
new file mode 100644
index 0000000000..710928c938
--- /dev/null
+++ b/packages/toolkit/src/lib/use-instill-form/useComponentOutputReferenceHintFields.tsx
@@ -0,0 +1,32 @@
+import * as React from "react";
+
+import { InstillJSONSchema } from "./type";
+import { Nullable } from "../type";
+import { transformInstillJSONSchemaToFormTree } from "./transform";
+import { pickComponentsFromReferenceHints } from "./pick/pickComponentsFromReferenceHints";
+import { transformInstillFormTreeToReferenceHints } from "./transform/transformInstillFormTreeToReferenceHints";
+
+export type UseComponentOutputReferenceHintFieldsOptions = {
+ componentID: string;
+};
+
+export function useComponentOutputReferenceHintFields(
+ schema: Nullable,
+ options?: UseComponentOutputReferenceHintFieldsOptions
+) {
+ const componentID = options?.componentID ?? undefined;
+
+ const fields = React.useMemo(() => {
+ if (!schema) {
+ return [];
+ }
+
+ const outputFormTree = transformInstillJSONSchemaToFormTree(schema);
+ const hints = transformInstillFormTreeToReferenceHints(outputFormTree);
+ const fields = pickComponentsFromReferenceHints(hints, { componentID });
+
+ return fields;
+ }, [schema, componentID]);
+
+ return fields;
+}
diff --git a/packages/toolkit/src/lib/use-instill-form/useInstillForm.test.tsx b/packages/toolkit/src/lib/use-instill-form/useInstillForm.test.tsx
index 16fe9f0051..a1e150855a 100644
--- a/packages/toolkit/src/lib/use-instill-form/useInstillForm.test.tsx
+++ b/packages/toolkit/src/lib/use-instill-form/useInstillForm.test.tsx
@@ -9,7 +9,6 @@ import {
import { useInstillForm } from "./useInstillForm";
import { InstillJSONSchema } from "./type";
import { Form } from "@instill-ai/design-system";
-import exp from "constants";
const SimpleFormSchema: InstillJSONSchema = {
title: "Simple Form JSON",
diff --git a/packages/toolkit/src/lib/vdp-sdk/connector/actions.ts b/packages/toolkit/src/lib/vdp-sdk/connector/actions.ts
index 7e4837b291..307091a28c 100644
--- a/packages/toolkit/src/lib/vdp-sdk/connector/actions.ts
+++ b/packages/toolkit/src/lib/vdp-sdk/connector/actions.ts
@@ -1,6 +1,6 @@
import { Nullable } from "../../type";
import { createInstillAxiosClient } from "../helper";
-import { Connector, ConnectorState, ConnectorWithDefinition } from "./types";
+import { ConnectorState, ConnectorWithDefinition } from "./types";
export type TestUserConnectorConnectionResponse = {
state: ConnectorState;
diff --git a/packages/toolkit/src/view/model/CreateModelForm.tsx b/packages/toolkit/src/view/model/CreateModelForm.tsx
index fc547fca1e..2d65188523 100644
--- a/packages/toolkit/src/view/model/CreateModelForm.tsx
+++ b/packages/toolkit/src/view/model/CreateModelForm.tsx
@@ -20,7 +20,6 @@ import {
type Model,
type Nullable,
type CreateResourceFormStore,
- useAmplitudeCtx,
sendAmplitudeData,
useCreateResourceFormStore,
getInstillApiErrorMessage,
@@ -85,7 +84,6 @@ export const CreateModelForm = (props: CreateModelFormProps) => {
* Initialize form state
* -----------------------------------------------------------------------*/
- const { amplitudeIsInit } = useAmplitudeCtx();
const queryClient = useQueryClient();
const {
@@ -233,7 +231,7 @@ export const CreateModelForm = (props: CreateModelFormProps) => {
model_definition_name: modelDefinitionName,
});
},
- [amplitudeIsInit, accessToken, queryClient, setFieldValue]
+ [accessToken, queryClient, setFieldValue]
);
const deployUserModel = useDeployUserModel();
diff --git a/packages/toolkit/src/view/pipeline-builder/components/ComponentOutputReferenceHints.tsx b/packages/toolkit/src/view/pipeline-builder/components/ComponentOutputReferenceHints.tsx
new file mode 100644
index 0000000000..ba0f850545
--- /dev/null
+++ b/packages/toolkit/src/view/pipeline-builder/components/ComponentOutputReferenceHints.tsx
@@ -0,0 +1,47 @@
+import { ScrollArea } from "@instill-ai/design-system";
+import {
+ InstillJSONSchema,
+ Nullable,
+ useComponentOutputReferenceHintFields,
+} from "../../../lib";
+import { ReferenceHintTag } from "../../../components";
+
+export const ComponentOutputReferenceHints = ({
+ componentID,
+ outputSchema,
+}: {
+ componentID: string;
+ outputSchema: Nullable;
+}) => {
+ const hintFields = useComponentOutputReferenceHintFields(outputSchema, {
+ componentID,
+ });
+
+ return (
+
+
+ Output
+
+
+
+
+
+
+
+
+ references
+
+
+
+
{hintFields}
+
+
+
+ );
+};
diff --git a/packages/toolkit/src/view/pipeline-builder/components/ComponentOutputs.tsx b/packages/toolkit/src/view/pipeline-builder/components/ComponentOutputs.tsx
index 612117b946..4b626d0103 100644
--- a/packages/toolkit/src/view/pipeline-builder/components/ComponentOutputs.tsx
+++ b/packages/toolkit/src/view/pipeline-builder/components/ComponentOutputs.tsx
@@ -58,7 +58,9 @@ export const ComponentOutputs = ({
return (
{nodeType === "connector" ? (
-
output
+
+ Output
+
) : null}
({
selectedConnectorNodeId: store.selectedConnectorNodeId,
@@ -295,7 +295,11 @@ export const ConnectorNode = ({ data, id }: NodeProps) => {
(e) => e.name === data.component.definition_name
) ?? null
);
- }, [connectorDefinitions.isSuccess, connectorDefinitions.data]);
+ }, [
+ connectorDefinitions.isSuccess,
+ connectorDefinitions.data,
+ data.component,
+ ]);
return (
) => {
{!resourceNotCreated && !enableEdit ? (
-
+
) : null}
diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/operator-node/OperatorNode.tsx b/packages/toolkit/src/view/pipeline-builder/components/nodes/operator-node/OperatorNode.tsx
index 4d8b11cba1..eadaaa1e75 100644
--- a/packages/toolkit/src/view/pipeline-builder/components/nodes/operator-node/OperatorNode.tsx
+++ b/packages/toolkit/src/view/pipeline-builder/components/nodes/operator-node/OperatorNode.tsx
@@ -19,7 +19,6 @@ import { ImageWithFallback, ObjectViewer } from "../../../../../components";
import { useShallow } from "zustand/react/shallow";
import { ConnectorOperatorControlPanel } from "../control-panel";
import { OpenAdvancedConfigurationButton } from "../../OpenAdvancedConfigurationButton";
-import { ComponentOutputs } from "../../ComponentOutputs";
import { getOperatorInputOutputSchema } from "../../../lib/getOperatorInputOutputSchema";
import { useCheckIsHidden } from "../../useCheckIsHidden";
import { useUpdaterOnNode } from "../../useUpdaterOnNode";
@@ -31,6 +30,7 @@ import {
NodeWrapper,
useNodeIDEditorForm,
} from "../common";
+import { ComponentOutputReferenceHints } from "../../ComponentOutputReferenceHints";
const selector = (store: InstillStore) => ({
selectedConnectorNodeId: store.selectedConnectorNodeId,
@@ -339,12 +339,9 @@ export const OperatorNode = ({ data, id }: NodeProps) => {
/>
-
>
)}
diff --git a/packages/toolkit/src/view/pipeline-builder/components/nodes/start-operator-node/StartOperatorNode.tsx b/packages/toolkit/src/view/pipeline-builder/components/nodes/start-operator-node/StartOperatorNode.tsx
index 4f45211081..535aaeb93f 100644
--- a/packages/toolkit/src/view/pipeline-builder/components/nodes/start-operator-node/StartOperatorNode.tsx
+++ b/packages/toolkit/src/view/pipeline-builder/components/nodes/start-operator-node/StartOperatorNode.tsx
@@ -30,7 +30,6 @@ import {
import { pickSelectedTypeFromInstillFormat } from "./pickSelectedTypeFromInstillFormat";
import { arrayMove } from "@dnd-kit/sortable";
-import { constructFieldKey } from "./constructFieldKey";
import { StartEndOperatorControlPanel } from "../control-panel";
import { NodeHead, NodeSortableFieldWrapper, NodeWrapper } from "../common";
import { VerticalSortableWrapper } from "../../VerticalSortableWrapper";
diff --git a/packages/toolkit/src/view/pipeline-builder/lib/getReferencesFromString.ts b/packages/toolkit/src/view/pipeline-builder/lib/getReferencesFromString.ts
index 1253ee4de7..1fa17dba82 100644
--- a/packages/toolkit/src/view/pipeline-builder/lib/getReferencesFromString.ts
+++ b/packages/toolkit/src/view/pipeline-builder/lib/getReferencesFromString.ts
@@ -1,4 +1,4 @@
-import { InstillReference, ReferenceValueSet } from "../type";
+import { InstillReference } from "../type";
export function getReferencesFromString(value: string): InstillReference[] {
const dollarBraceReferences: InstillReference[] = [];
diff --git a/packages/toolkit/src/view/pipeline/view-pipelines/CreatePipelineDialog.tsx b/packages/toolkit/src/view/pipeline/view-pipelines/CreatePipelineDialog.tsx
index 306924ec4a..5cacdec977 100644
--- a/packages/toolkit/src/view/pipeline/view-pipelines/CreatePipelineDialog.tsx
+++ b/packages/toolkit/src/view/pipeline/view-pipelines/CreatePipelineDialog.tsx
@@ -68,7 +68,6 @@ export const CreatePipelineDialog = ({ className }: { className?: string }) => {
const [permission, setPermission] =
React.useState>("private");
const router = useRouter();
- const { entity } = router.query;
const { toast } = useToast();
@@ -101,7 +100,13 @@ export const CreatePipelineDialog = ({ className }: { className?: string }) => {
});
}
return orgsAndUserList;
- }, [organizations.isSuccess, entityObject.isSuccess]);
+ }, [
+ organizations.isSuccess,
+ organizations.data,
+ entityObject.isSuccess,
+ entityObject.entity,
+ entityObject.entityName,
+ ]);
const createPipeline = useCreateUserPipeline();
async function onSubmit(data: z.infer) {
diff --git a/packages/toolkit/src/view/pipeline/view-pipelines/ViewPipelines.tsx b/packages/toolkit/src/view/pipeline/view-pipelines/ViewPipelines.tsx
index 1ee048a31d..8f808ec7af 100644
--- a/packages/toolkit/src/view/pipeline/view-pipelines/ViewPipelines.tsx
+++ b/packages/toolkit/src/view/pipeline/view-pipelines/ViewPipelines.tsx
@@ -73,7 +73,7 @@ export const ViewPipelines = ({
}
return all;
- }, [pipelines.data, pipelines.isSuccess, searchCode]);
+ }, [pipelines.data, pipelines.isSuccess]);
return (