From d1ea4262caf7834cb204473e39cecae7154e7df6 Mon Sep 17 00:00:00 2001 From: satoshi toyama Date: Tue, 22 Oct 2024 10:12:14 +0900 Subject: [PATCH 1/6] add isFinal type --- .../beta-proto/giselle-node/types.ts | 1 + scripts/20241022-db-patch-node-is-final.ts | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 scripts/20241022-db-patch-node-is-final.ts diff --git a/app/(playground)/p/[agentId]/beta-proto/giselle-node/types.ts b/app/(playground)/p/[agentId]/beta-proto/giselle-node/types.ts index dc632508..b2feb8d6 100644 --- a/app/(playground)/p/[agentId]/beta-proto/giselle-node/types.ts +++ b/app/(playground)/p/[agentId]/beta-proto/giselle-node/types.ts @@ -64,6 +64,7 @@ export type GiselleNode = { resultPortLabel: string; properties: Record; output: unknown; + isFinal: boolean; }; export type GiselleNodeArtifactElement = { diff --git a/scripts/20241022-db-patch-node-is-final.ts b/scripts/20241022-db-patch-node-is-final.ts new file mode 100644 index 00000000..89be8e69 --- /dev/null +++ b/scripts/20241022-db-patch-node-is-final.ts @@ -0,0 +1,43 @@ +import { agents, db } from "@/drizzle"; +import { eq } from "drizzle-orm"; + +function chunkArray(array: T[], chunkSize: number): T[][] { + const chunks: T[][] = []; + for (let i = 0; i < array.length; i += chunkSize) { + chunks.push(array.slice(i, i + chunkSize)); + } + return chunks; +} + +console.log("Add 'isFinal' to the all of the nodes..."); +const listOfAgents = await db + .select() + .from(agents) + .where(eq(agents.id, "agnt_a23elgoizppud3e8bygx39ea")); +console.log(`Updating ${listOfAgents.length} agents...`); + +const agentChunks = chunkArray(listOfAgents, 10); + +for (let i = 0; i < agentChunks.length; i++) { + const chunk = agentChunks[i]; + console.log( + ` ├ Processing chunk ${i + 1}/${agentChunks.length} (${chunk.length} agents)`, + ); + + await Promise.all( + chunk.map(async (agent) => { + await db.update(agents).set({ + graphv2: { + ...agent.graphv2, + nodes: agent.graphv2.nodes.map((node) => ({ + ...node, + isFinal: false, + })), + }, + }); + }), + ); + + console.log(` │ └ Completed chunk ${i + 1}/${i + 1}`); +} +console.log("All agents have been updated!"); From 3312a58cec582b45439095c7d57f65cca5b6b306 Mon Sep 17 00:00:00 2001 From: satoshi toyama Date: Tue, 22 Oct 2024 13:19:43 +0900 Subject: [PATCH 2/6] show final node label --- .../p/[agentId]/beta-proto/giselle-node/components.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/(playground)/p/[agentId]/beta-proto/giselle-node/components.tsx b/app/(playground)/p/[agentId]/beta-proto/giselle-node/components.tsx index 10be0a68..1bf31cf8 100644 --- a/app/(playground)/p/[agentId]/beta-proto/giselle-node/components.tsx +++ b/app/(playground)/p/[agentId]/beta-proto/giselle-node/components.tsx @@ -132,7 +132,8 @@ export function GiselleNode(props: GiselleNodeProps) { )} /> {props.object === "node" && ( -
+
+ {props.isFinal && Final} {props.name}
)} @@ -214,6 +215,7 @@ export function GiselleNode(props: GiselleNodeProps) {
outgoing: {props.outgoingConnections?.length ?? 0}
property: {JSON.stringify(props.properties, null, 2)}
ui: {JSON.stringify(props.ui, null, 2)}
+
isFinal: {JSON.stringify(props.isFinal)}
)} From ef44fff9a53da8aeb118b11a95693e1446244809 Mon Sep 17 00:00:00 2001 From: satoshi toyama Date: Tue, 22 Oct 2024 13:19:48 +0900 Subject: [PATCH 3/6] set final node --- .../p/[agentId]/beta-proto/graph/actions.ts | 64 +++++++++++++++++-- .../p/[agentId]/beta-proto/graph/reducer.ts | 10 +++ .../p/[agentId]/beta-proto/graph/v2/node.ts | 49 ++++++++++++++ 3 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 app/(playground)/p/[agentId]/beta-proto/graph/v2/node.ts diff --git a/app/(playground)/p/[agentId]/beta-proto/graph/actions.ts b/app/(playground)/p/[agentId]/beta-proto/graph/actions.ts index 2b3a43c8..a2f5842a 100644 --- a/app/(playground)/p/[agentId]/beta-proto/graph/actions.ts +++ b/app/(playground)/p/[agentId]/beta-proto/graph/actions.ts @@ -56,6 +56,7 @@ import { parseFile, uploadFile, } from "./server-actions"; +import { type V2NodeAction, updateNode } from "./v2/node"; export type AddNodeAction = { type: "addNode"; @@ -68,6 +69,7 @@ type AddNodeArgs = { node: GiselleNodeBlueprint; position: XYPosition; name: string; + isFinal?: boolean; properties?: Record; }; @@ -92,6 +94,7 @@ export const addNode = (args: AddNodeArgs): AddNodeAction => { ui: { position: args.position }, properties: args.properties ?? {}, state: giselleNodeState.idle, + isFinal: args.isFinal ?? false, output: "", }, }, @@ -168,6 +171,8 @@ export const addNodesAndConnect = ( args: AddNodesAndConnectArgs, ): ThunkAction => { return (dispatch, getState) => { + const state = getState(); + const hasFinalNode = state.graph.nodes.some((node) => node.isFinal); const currentNodes = getState().graph.nodes; const addSourceNode = addNode({ ...args.sourceNode, @@ -176,6 +181,7 @@ export const addNodesAndConnect = ( dispatch(addSourceNode); const addTargetNode = addNode({ ...args.targetNode, + isFinal: !hasFinalNode, name: `Untitled node - ${currentNodes.length + 2}`, }); dispatch(addTargetNode); @@ -810,18 +816,20 @@ export function addSourceToPromptNode( ): ThunkAction { return async (dispatch, getState) => { const state = getState(); - const updateNode = state.graph.nodes.find( + const targetPromptNode = state.graph.nodes.find( (node) => node.id === args.promptNode.id, ); - if (updateNode === undefined) { + if (targetPromptNode === undefined) { return; } - if (updateNode.archetype !== giselleNodeArchetypes.prompt) { + if (targetPromptNode.archetype !== giselleNodeArchetypes.prompt) { return; } - const currentSources = updateNode.properties.sources ?? []; + const currentSources = targetPromptNode.properties.sources ?? []; if (!Array.isArray(currentSources)) { - throw new Error(`${updateNode.id}'s sources property is not an array`); + throw new Error( + `${targetPromptNode.id}'s sources property is not an array`, + ); } dispatch( updateNodeProperty({ @@ -885,6 +893,28 @@ export function addSourceToPromptNode( }, }), ); + + const artifactGeneratorNode = state.graph.nodes.find( + (node) => node.id === artifact?.generatorNode.id, + ); + if (artifactGeneratorNode?.isFinal) { + dispatch( + updateNode({ + input: { + id: artifact.generatorNode.id, + isFinal: false, + }, + }), + ); + dispatch( + updateNode({ + input: { + id: outgoingNode.id, + isFinal: true, + }, + }), + ); + } } } else if (args.source.object === "file") { if (args.source.status === fileStatuses.uploading) { @@ -986,6 +1016,27 @@ export function addSourceToPromptNode( }, }), ); + const webSearchGeneratorNode = state.graph.nodes.find( + (node) => node.id === webSearch.generatorNode.id, + ); + if (webSearchGeneratorNode?.isFinal) { + dispatch( + updateNode({ + input: { + id: webSearchGeneratorNode.id, + isFinal: false, + }, + }), + ); + dispatch( + updateNode({ + input: { + id: outgoingNode.id, + isFinal: true, + }, + }), + ); + } } } }; @@ -1253,4 +1304,5 @@ export type GraphAction = | RemoveArtifactAction | AddParameterToNodeAction | RemoveParameterFromNodeAction - | UpsertWebSearchAction; + | UpsertWebSearchAction + | V2NodeAction; diff --git a/app/(playground)/p/[agentId]/beta-proto/graph/reducer.ts b/app/(playground)/p/[agentId]/beta-proto/graph/reducer.ts index fc3780df..41238563 100644 --- a/app/(playground)/p/[agentId]/beta-proto/graph/reducer.ts +++ b/app/(playground)/p/[agentId]/beta-proto/graph/reducer.ts @@ -1,10 +1,20 @@ import type { GraphAction } from "./actions"; import type { GraphState } from "./types"; +import { isV2NodeAction, v2NodeReducer } from "./v2/node"; export const graphReducer = ( state: GraphState, action: GraphAction, ): GraphState => { + if (isV2NodeAction(action)) { + return { + ...state, + graph: { + ...state.graph, + nodes: v2NodeReducer(state.graph.nodes, action), + }, + }; + } switch (action.type) { case "addNode": return { diff --git a/app/(playground)/p/[agentId]/beta-proto/graph/v2/node.ts b/app/(playground)/p/[agentId]/beta-proto/graph/v2/node.ts new file mode 100644 index 00000000..400df53c --- /dev/null +++ b/app/(playground)/p/[agentId]/beta-proto/graph/v2/node.ts @@ -0,0 +1,49 @@ +import type { GiselleNode, GiselleNodeId } from "../../giselle-node/types"; + +const v2NodeActionTypes = { + updateNode: "v2.updateNode", +} as const; +type V2NodeActionType = + (typeof v2NodeActionTypes)[keyof typeof v2NodeActionTypes]; +export function isV2NodeAction(action: unknown): action is V2NodeAction { + return Object.values(v2NodeActionTypes).includes( + (action as V2NodeAction).type, + ); +} +interface UpdateNodeAction { + type: Extract; + input: UpdateNodeInput; +} +interface UpdateNodeInput { + id: GiselleNodeId; + isFinal?: boolean; +} +export function updateNode({ + input, +}: { input: UpdateNodeInput }): UpdateNodeAction { + return { + type: v2NodeActionTypes.updateNode, + input, + }; +} + +export type V2NodeAction = UpdateNodeAction; + +export function v2NodeReducer( + nodes: GiselleNode[], + action: V2NodeAction, +): GiselleNode[] { + switch (action.type) { + case v2NodeActionTypes.updateNode: + return nodes.map((node) => { + if (node.id === action.input.id) { + return { + ...node, + isFinal: action.input.isFinal ?? false, + }; + } + return node; + }); + } + return nodes; +} From d0c589913ea960adb2ade36b46fee0fb959b1eb8 Mon Sep 17 00:00:00 2001 From: satoshi toyama Date: Tue, 22 Oct 2024 14:06:06 +0900 Subject: [PATCH 4/6] remove --- .../p/[agentId]/beta-proto/graph/actions.ts | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/app/(playground)/p/[agentId]/beta-proto/graph/actions.ts b/app/(playground)/p/[agentId]/beta-proto/graph/actions.ts index a2f5842a..d5deca08 100644 --- a/app/(playground)/p/[agentId]/beta-proto/graph/actions.ts +++ b/app/(playground)/p/[agentId]/beta-proto/graph/actions.ts @@ -1128,6 +1128,24 @@ export function removeSourceFromPromptNode( }, }), ); + if (outgoingNode?.isFinal) { + dispatch( + updateNode({ + input: { + id: outgoingNode.id, + isFinal: false, + }, + }), + ); + dispatch( + updateNode({ + input: { + id: artifact.generatorNode.id, + isFinal: true, + }, + }), + ); + } } } else if (args.source.object === "webSearch") { const artifact = state.graph.artifacts.find( @@ -1172,6 +1190,24 @@ export function removeSourceFromPromptNode( }, }), ); + if (outgoingNode?.isFinal) { + dispatch( + updateNode({ + input: { + id: outgoingNode.id, + isFinal: false, + }, + }), + ); + dispatch( + updateNode({ + input: { + id: artifact.generatorNode.id, + isFinal: true, + }, + }), + ); + } } } }; From 6959715b687624a5b6f0558ca6c6c071be64c2da Mon Sep 17 00:00:00 2001 From: satoshi toyama Date: Tue, 22 Oct 2024 14:21:22 +0900 Subject: [PATCH 5/6] tweak --- .../p/[agentId]/beta-proto/graph/actions.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/(playground)/p/[agentId]/beta-proto/graph/actions.ts b/app/(playground)/p/[agentId]/beta-proto/graph/actions.ts index d5deca08..6630aaa7 100644 --- a/app/(playground)/p/[agentId]/beta-proto/graph/actions.ts +++ b/app/(playground)/p/[agentId]/beta-proto/graph/actions.ts @@ -1148,10 +1148,10 @@ export function removeSourceFromPromptNode( } } } else if (args.source.object === "webSearch") { - const artifact = state.graph.artifacts.find( - (artifact) => artifact.id === args.source.id, + const webSearch = state.graph.webSearches.find( + (webSearch) => webSearch.id === args.source.id, ); - if (artifact === undefined) { + if (webSearch === undefined) { return; } const outgoingConnectors = state.graph.connectors.filter( @@ -1168,7 +1168,7 @@ export function removeSourceFromPromptNode( state.graph.connectors.find( (connector) => connector.target === outgoingNode.id && - connector.source === artifact.generatorNode.id, + connector.source === webSearch.generatorNode.id, ); if (artifactCreatorNodeToOutgoingNodeConnector === undefined) { continue; @@ -1202,7 +1202,7 @@ export function removeSourceFromPromptNode( dispatch( updateNode({ input: { - id: artifact.generatorNode.id, + id: webSearch.generatorNode.id, isFinal: true, }, }), From f8a324bf31ef3ebd721839d25d1994e0324cec9d Mon Sep 17 00:00:00 2001 From: satoshi toyama Date: Tue, 22 Oct 2024 14:50:51 +0900 Subject: [PATCH 6/6] fix migrate script --- scripts/20241022-db-patch-node-is-final.ts | 39 ++++++++++++++-------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/scripts/20241022-db-patch-node-is-final.ts b/scripts/20241022-db-patch-node-is-final.ts index 89be8e69..2eb13fbf 100644 --- a/scripts/20241022-db-patch-node-is-final.ts +++ b/scripts/20241022-db-patch-node-is-final.ts @@ -1,3 +1,4 @@ +import { giselleNodeCategories } from "@/app/(playground)/p/[agentId]/beta-proto/giselle-node/types"; import { agents, db } from "@/drizzle"; import { eq } from "drizzle-orm"; @@ -10,10 +11,7 @@ function chunkArray(array: T[], chunkSize: number): T[][] { } console.log("Add 'isFinal' to the all of the nodes..."); -const listOfAgents = await db - .select() - .from(agents) - .where(eq(agents.id, "agnt_a23elgoizppud3e8bygx39ea")); +const listOfAgents = await db.select().from(agents); console.log(`Updating ${listOfAgents.length} agents...`); const agentChunks = chunkArray(listOfAgents, 10); @@ -26,15 +24,30 @@ for (let i = 0; i < agentChunks.length; i++) { await Promise.all( chunk.map(async (agent) => { - await db.update(agents).set({ - graphv2: { - ...agent.graphv2, - nodes: agent.graphv2.nodes.map((node) => ({ - ...node, - isFinal: false, - })), - }, - }); + const instructionNodes = agent.graphv2.nodes.filter( + (node) => node.category === giselleNodeCategories.instruction, + ); + const actionNodes = agent.graphv2.nodes.filter( + (node) => node.category === giselleNodeCategories.action, + ); + await db + .update(agents) + .set({ + graphv2: { + ...agent.graphv2, + nodes: [ + ...instructionNodes.map((node) => ({ + ...node, + isFinal: false, + })), + ...actionNodes.map((node, index) => ({ + ...node, + isFinal: index === actionNodes.length - 1, + })), + ], + }, + }) + .where(eq(agents.id, agent.id)); }), );