feat: merged demo into dev #43
@@ -67,10 +67,36 @@ function StepReduce(planElement: PlanElement, _nodes: Node[]) : Record<string, u
|
|||||||
* @param plan: the plan to check
|
* @param plan: the plan to check
|
||||||
* @returns: a boolean
|
* @returns: a boolean
|
||||||
*/
|
*/
|
||||||
export function DoesPlanIterate(plan?: Plan) : boolean {
|
export function DoesPlanIterate( _nodes: Node[], plan?: Plan,) : boolean {
|
||||||
// TODO: should recursively check plans that have goals (and thus more plans) in them.
|
// TODO: should recursively check plans that have goals (and thus more plans) in them.
|
||||||
if (!plan) return false
|
if (!plan) return false
|
||||||
return plan.steps.filter((step) => step.type == "llm").length > 0;
|
return plan.steps.filter((step) => step.type == "llm").length > 0 ||
|
||||||
|
(
|
||||||
|
// Find the goal node of this step
|
||||||
|
plan.steps.filter((step) => step.type == "goal").map((goalStep) => {
|
||||||
|
const goalId = goalStep.id;
|
||||||
|
const goalNode = _nodes.find((x) => x.id === goalId);
|
||||||
|
// In case we don't find any valid plan, this node doesn't iterate
|
||||||
|
if (!goalNode || !goalNode.data.plan) return false;
|
||||||
|
// Otherwise, check if this node can fail - if so, we should have the option to iterate
|
||||||
|
return (goalNode && goalNode.data.plan && goalNode.data.can_fail)
|
||||||
|
})
|
||||||
|
).includes(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if any of the plan's goal steps has its can_fail value set to true.
|
||||||
|
* @param plan: plan to check
|
||||||
|
* @param _nodes: nodes in flow store.
|
||||||
|
*/
|
||||||
|
export function HasCheckingSubGoal(plan: Plan, _nodes: Node[]) {
|
||||||
|
const goalSteps = plan.steps.filter((x) => x.type == "goal");
|
||||||
|
return goalSteps.map((goalStep) => {
|
||||||
|
// Find the goal node and check its can_fail data boolean.
|
||||||
|
const goalId = goalStep.id;
|
||||||
|
const goalNode = _nodes.find((x) => x.id === goalId);
|
||||||
|
return (goalNode && goalNode.data.can_fail)
|
||||||
|
}).includes(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export default function PlanEditorDialog({
|
|||||||
const [newActionType, setNewActionType] = useState<ActionTypes>("speech");
|
const [newActionType, setNewActionType] = useState<ActionTypes>("speech");
|
||||||
const [newActionGestureType, setNewActionGestureType] = useState<boolean>(true);
|
const [newActionGestureType, setNewActionGestureType] = useState<boolean>(true);
|
||||||
const [newActionValue, setNewActionValue] = useState("");
|
const [newActionValue, setNewActionValue] = useState("");
|
||||||
|
const [hasInteractedWithPlan, setHasInteractedWithPlan] = useState<boolean>(false)
|
||||||
const { setScrollable } = useFlowStore();
|
const { setScrollable } = useFlowStore();
|
||||||
const nodes = useFlowStore().nodes;
|
const nodes = useFlowStore().nodes;
|
||||||
|
|
||||||
@@ -56,6 +57,7 @@ export default function PlanEditorDialog({
|
|||||||
|
|
||||||
const buildAction = (): Action => {
|
const buildAction = (): Action => {
|
||||||
const id = crypto.randomUUID();
|
const id = crypto.randomUUID();
|
||||||
|
setHasInteractedWithPlan(true)
|
||||||
switch (newActionType) {
|
switch (newActionType) {
|
||||||
case "speech":
|
case "speech":
|
||||||
return { id, text: newActionValue, type: "speech" };
|
return { id, text: newActionValue, type: "speech" };
|
||||||
@@ -103,7 +105,7 @@ export default function PlanEditorDialog({
|
|||||||
<div className={styles.planEditorLeft}>
|
<div className={styles.planEditorLeft}>
|
||||||
{/* Left Side (Action Adder) */}
|
{/* Left Side (Action Adder) */}
|
||||||
<h4>Add Action</h4>
|
<h4>Add Action</h4>
|
||||||
{(!plan && description && draftPlan.steps.length === 0) && (<div className={styles.stepSuggestion}>
|
{(!plan && description && draftPlan.steps.length === 0 && !hasInteractedWithPlan) && (<div className={styles.stepSuggestion}>
|
||||||
<label> Filled in as a suggestion! </label>
|
<label> Filled in as a suggestion! </label>
|
||||||
<label> Feel free to change! </label>
|
<label> Feel free to change! </label>
|
||||||
</div>)}
|
</div>)}
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ export default function BasicBeliefNode(props: NodeProps<BasicBeliefNode>) {
|
|||||||
wrapping = '"'
|
wrapping = '"'
|
||||||
break;
|
break;
|
||||||
case ("semantic"):
|
case ("semantic"):
|
||||||
placeholder = "description..."
|
placeholder = "short description..."
|
||||||
wrapping = '"'
|
wrapping = '"'
|
||||||
break;
|
break;
|
||||||
case ("object"):
|
case ("object"):
|
||||||
@@ -180,7 +180,7 @@ export default function BasicBeliefNode(props: NodeProps<BasicBeliefNode>) {
|
|||||||
<MultilineTextField
|
<MultilineTextField
|
||||||
value={data.belief.description}
|
value={data.belief.description}
|
||||||
setValue={setBeliefDescription}
|
setValue={setBeliefDescription}
|
||||||
placeholder={"Describe the desciption of this LLM belief..."}
|
placeholder={"Describe a detailed desciption of this LLM belief..."}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { TextField } from '../../../../components/TextField';
|
|||||||
import {MultiConnectionHandle} from "../components/RuleBasedHandle.tsx";
|
import {MultiConnectionHandle} from "../components/RuleBasedHandle.tsx";
|
||||||
import {allowOnlyConnectionsFromHandle, allowOnlyConnectionsFromType} from "../HandleRules.ts";
|
import {allowOnlyConnectionsFromHandle, allowOnlyConnectionsFromType} from "../HandleRules.ts";
|
||||||
import useFlowStore from '../VisProgStores';
|
import useFlowStore from '../VisProgStores';
|
||||||
import {DoesPlanIterate, PlanReduce, type Plan } from '../components/Plan';
|
import {DoesPlanIterate, HasCheckingSubGoal, PlanReduce, type Plan } from '../components/Plan';
|
||||||
import PlanEditorDialog from '../components/PlanEditor';
|
import PlanEditorDialog from '../components/PlanEditor';
|
||||||
import { MultilineTextField } from '../../../../components/MultilineTextField';
|
import { MultilineTextField } from '../../../../components/MultilineTextField';
|
||||||
import { defaultPlan } from '../components/Plan.default.ts';
|
import { defaultPlan } from '../components/Plan.default.ts';
|
||||||
@@ -45,10 +45,12 @@ export type GoalNode = Node<GoalNodeData>
|
|||||||
*/
|
*/
|
||||||
export default function GoalNode({id, data}: NodeProps<GoalNode>) {
|
export default function GoalNode({id, data}: NodeProps<GoalNode>) {
|
||||||
const {updateNodeData} = useFlowStore();
|
const {updateNodeData} = useFlowStore();
|
||||||
|
const _nodes = useFlowStore().nodes;
|
||||||
|
|
||||||
const text_input_id = `goal_${id}_text_input`;
|
const text_input_id = `goal_${id}_text_input`;
|
||||||
const checkbox_id = `goal_${id}_checkbox`;
|
const checkbox_id = `goal_${id}_checkbox`;
|
||||||
const planIterate = DoesPlanIterate(data.plan);
|
const planIterate = DoesPlanIterate(_nodes, data.plan);
|
||||||
|
const hasCheckSubGoal = data.plan !== undefined && HasCheckingSubGoal(data.plan, _nodes)
|
||||||
|
|
||||||
const setDescription = (value: string) => {
|
const setDescription = (value: string) => {
|
||||||
updateNodeData(id, {...data, description: value});
|
updateNodeData(id, {...data, description: value});
|
||||||
@@ -75,7 +77,7 @@ export default function GoalNode({id, data}: NodeProps<GoalNode>) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{data.can_fail && (<div>
|
{(data.can_fail || hasCheckSubGoal) && (<div>
|
||||||
<label htmlFor={text_input_id}>Description/ Condition of goal:</label>
|
<label htmlFor={text_input_id}>Description/ Condition of goal:</label>
|
||||||
<div className={"flex-wrap"}>
|
<div className={"flex-wrap"}>
|
||||||
<MultilineTextField
|
<MultilineTextField
|
||||||
@@ -95,8 +97,8 @@ export default function GoalNode({id, data}: NodeProps<GoalNode>) {
|
|||||||
<input
|
<input
|
||||||
id={checkbox_id}
|
id={checkbox_id}
|
||||||
type={"checkbox"}
|
type={"checkbox"}
|
||||||
disabled={!planIterate}
|
disabled={!planIterate || (data.plan && HasCheckingSubGoal(data.plan, _nodes))}
|
||||||
checked={!planIterate || data.can_fail}
|
checked={!planIterate || data.can_fail || (data.plan && HasCheckingSubGoal(data.plan, _nodes))}
|
||||||
onChange={(e) => planIterate ? setFailable(e.target.checked) : setFailable(false)}
|
onChange={(e) => planIterate ? setFailable(e.target.checked) : setFailable(false)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -137,7 +139,7 @@ export function GoalReduce(node: Node, _nodes: Node[]) {
|
|||||||
id: node.id,
|
id: node.id,
|
||||||
name: data.name,
|
name: data.name,
|
||||||
description: data.description,
|
description: data.description,
|
||||||
can_fail: data.can_fail,
|
can_fail: data.can_fail || (data.plan && HasCheckingSubGoal(data.plan, _nodes)),
|
||||||
plan: data.plan ? PlanReduce(_nodes, data.plan) : "",
|
plan: data.plan ? PlanReduce(_nodes, data.plan) : "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user