Update from main, add proper error returns
| 
		 Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB  | 
| 
		 Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB  | 
| 
		 Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB  | 
| 
		 Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB  | 
@ -405,7 +405,6 @@ const ToolbarItemTooltip = memo(function ToolbarItemContents({
 | 
			
		||||
      position="bottom"
 | 
			
		||||
      wrapperClassName={'!p-4 !pointer-events-auto ' + wrapperClassName}
 | 
			
		||||
      contentClassName={contentClassName}
 | 
			
		||||
      delay={0}
 | 
			
		||||
    >
 | 
			
		||||
      {children}
 | 
			
		||||
    </Tooltip>
 | 
			
		||||
 | 
			
		||||
@ -123,6 +123,8 @@ import { Node } from '@rust/kcl-lib/bindings/Node'
 | 
			
		||||
import { radToDeg } from 'three/src/math/MathUtils'
 | 
			
		||||
import toast from 'react-hot-toast'
 | 
			
		||||
import { getArtifactFromRange, codeRefFromRange } from 'lang/std/artifactGraph'
 | 
			
		||||
import { updateModelingState } from 'lang/modelingWorkflows'
 | 
			
		||||
import { EXECUTION_TYPE_MOCK } from 'lib/constants'
 | 
			
		||||
 | 
			
		||||
type DraftSegment = 'line' | 'tangentialArcTo'
 | 
			
		||||
 | 
			
		||||
@ -1075,7 +1077,11 @@ export class SceneEntities {
 | 
			
		||||
          return
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await kclManager.executeAstMock(modifiedAst)
 | 
			
		||||
        await updateModelingState(modifiedAst, EXECUTION_TYPE_MOCK, {
 | 
			
		||||
          kclManager,
 | 
			
		||||
          editorManager,
 | 
			
		||||
          codeManager,
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        if (intersectsProfileStart) {
 | 
			
		||||
          sceneInfra.modelingSend({ type: 'Close sketch' })
 | 
			
		||||
@ -1090,8 +1096,6 @@ export class SceneEntities {
 | 
			
		||||
            segmentName
 | 
			
		||||
          )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await codeManager.updateEditorWithAstAndWriteToFile(modifiedAst)
 | 
			
		||||
      },
 | 
			
		||||
      onMove: (args) => {
 | 
			
		||||
        const expressionIndex = Number(sketchEntryNodePath[1][0])
 | 
			
		||||
@ -1303,13 +1307,16 @@ export class SceneEntities {
 | 
			
		||||
        _ast = pResult.program
 | 
			
		||||
 | 
			
		||||
        // Update the primary AST and unequip the rectangle tool
 | 
			
		||||
        await kclManager.executeAstMock(_ast)
 | 
			
		||||
        sceneInfra.modelingSend({ type: 'Finish rectangle' })
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // lee: I had this at the bottom of the function, but it's
 | 
			
		||||
        // possible sketchFromKclValue "fails" when sketching on a face,
 | 
			
		||||
        // and this couldn't wouldn't run.
 | 
			
		||||
        await codeManager.updateEditorWithAstAndWriteToFile(_ast)
 | 
			
		||||
        await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
 | 
			
		||||
          kclManager,
 | 
			
		||||
          editorManager,
 | 
			
		||||
          codeManager,
 | 
			
		||||
        })
 | 
			
		||||
        sceneInfra.modelingSend({ type: 'Finish rectangle' })
 | 
			
		||||
      },
 | 
			
		||||
    })
 | 
			
		||||
    return {
 | 
			
		||||
@ -1493,13 +1500,16 @@ export class SceneEntities {
 | 
			
		||||
          _ast = pResult.program
 | 
			
		||||
 | 
			
		||||
          // Update the primary AST and unequip the rectangle tool
 | 
			
		||||
          await kclManager.executeAstMock(_ast)
 | 
			
		||||
          sceneInfra.modelingSend({ type: 'Finish center rectangle' })
 | 
			
		||||
 | 
			
		||||
          //
 | 
			
		||||
          // lee: I had this at the bottom of the function, but it's
 | 
			
		||||
          // possible sketchFromKclValue "fails" when sketching on a face,
 | 
			
		||||
          // and this couldn't wouldn't run.
 | 
			
		||||
          await codeManager.updateEditorWithAstAndWriteToFile(_ast)
 | 
			
		||||
          await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
 | 
			
		||||
            kclManager,
 | 
			
		||||
            editorManager,
 | 
			
		||||
            codeManager,
 | 
			
		||||
          })
 | 
			
		||||
          sceneInfra.modelingSend({ type: 'Finish center rectangle' })
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    })
 | 
			
		||||
@ -1678,9 +1688,12 @@ export class SceneEntities {
 | 
			
		||||
          _ast = pResult.program
 | 
			
		||||
 | 
			
		||||
          // Update the primary AST and unequip the rectangle tool
 | 
			
		||||
          await kclManager.executeAstMock(_ast)
 | 
			
		||||
          await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
 | 
			
		||||
            kclManager,
 | 
			
		||||
            editorManager,
 | 
			
		||||
            codeManager,
 | 
			
		||||
          })
 | 
			
		||||
          sceneInfra.modelingSend({ type: 'Finish circle three point' })
 | 
			
		||||
          await codeManager.updateEditorWithAstAndWriteToFile(_ast)
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    })
 | 
			
		||||
@ -1912,9 +1925,12 @@ export class SceneEntities {
 | 
			
		||||
          _ast = pResult.program
 | 
			
		||||
 | 
			
		||||
          // Update the primary AST and unequip the arc tool
 | 
			
		||||
          await kclManager.executeAstMock(_ast)
 | 
			
		||||
          await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
 | 
			
		||||
            kclManager,
 | 
			
		||||
            editorManager,
 | 
			
		||||
            codeManager,
 | 
			
		||||
          })
 | 
			
		||||
          sceneInfra.modelingSend({ type: 'Finish arc' })
 | 
			
		||||
          await codeManager.updateEditorWithAstAndWriteToFile(_ast)
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    })
 | 
			
		||||
@ -2166,13 +2182,16 @@ export class SceneEntities {
 | 
			
		||||
          _ast = pResult.program
 | 
			
		||||
 | 
			
		||||
          // Update the primary AST and unequip the arc tool
 | 
			
		||||
          await kclManager.executeAstMock(_ast)
 | 
			
		||||
          await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
 | 
			
		||||
            kclManager,
 | 
			
		||||
            editorManager,
 | 
			
		||||
            codeManager,
 | 
			
		||||
          })
 | 
			
		||||
          if (intersectsProfileStart) {
 | 
			
		||||
            sceneInfra.modelingSend({ type: 'Close sketch' })
 | 
			
		||||
          } else {
 | 
			
		||||
            sceneInfra.modelingSend({ type: 'Finish arc' })
 | 
			
		||||
          }
 | 
			
		||||
          await codeManager.updateEditorWithAstAndWriteToFile(_ast)
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    })
 | 
			
		||||
@ -2364,9 +2383,12 @@ export class SceneEntities {
 | 
			
		||||
          _ast = pResult.program
 | 
			
		||||
 | 
			
		||||
          // Update the primary AST and unequip the rectangle tool
 | 
			
		||||
          await kclManager.executeAstMock(_ast)
 | 
			
		||||
          await updateModelingState(_ast, EXECUTION_TYPE_MOCK, {
 | 
			
		||||
            kclManager,
 | 
			
		||||
            editorManager,
 | 
			
		||||
            codeManager,
 | 
			
		||||
          })
 | 
			
		||||
          sceneInfra.modelingSend({ type: 'Finish circle' })
 | 
			
		||||
          await codeManager.updateEditorWithAstAndWriteToFile(_ast)
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
@ -48,7 +48,6 @@ export function ActionButtonDropdown({
 | 
			
		||||
              {props.name ? props.name + ': ' : ''}open menu
 | 
			
		||||
            </span>
 | 
			
		||||
            <Tooltip
 | 
			
		||||
              delay={0}
 | 
			
		||||
              position="bottom"
 | 
			
		||||
              hoverOnly
 | 
			
		||||
              wrapperClassName="ui-open:!hidden"
 | 
			
		||||
 | 
			
		||||
@ -136,7 +136,7 @@ export const CommandBar = () => {
 | 
			
		||||
                  name="close"
 | 
			
		||||
                  className="w-5 h-5 rounded-sm bg-destroy-10 text-destroy-80 dark:bg-destroy-80 dark:text-destroy-10 group-hover:brightness-110"
 | 
			
		||||
                />
 | 
			
		||||
                <Tooltip position="bottom" delay={500}>
 | 
			
		||||
                <Tooltip position="bottom">
 | 
			
		||||
                  Cancel{' '}
 | 
			
		||||
                  <kbd className="hotkey ml-4 dark:!bg-chalkboard-80">esc</kbd>
 | 
			
		||||
                </Tooltip>
 | 
			
		||||
@ -144,7 +144,7 @@ export const CommandBar = () => {
 | 
			
		||||
              {!commandBarState.matches('Selecting command') && (
 | 
			
		||||
                <button onClick={stepBack} className="m-0 p-0 border-none">
 | 
			
		||||
                  <CustomIcon name="arrowLeft" className="w-5 h-5 rounded-sm" />
 | 
			
		||||
                  <Tooltip position="bottom" delay={500}>
 | 
			
		||||
                  <Tooltip position="bottom">
 | 
			
		||||
                    Step back{' '}
 | 
			
		||||
                    <kbd className="hotkey ml-4 dark:!bg-chalkboard-80">
 | 
			
		||||
                      Shift
 | 
			
		||||
 | 
			
		||||
@ -547,9 +547,7 @@ export const FileTreeMenu = ({
 | 
			
		||||
        className="!p-0 !bg-transparent hover:text-primary border-transparent hover:border-primary !outline-none"
 | 
			
		||||
        onClick={onCreateFile}
 | 
			
		||||
      >
 | 
			
		||||
        <Tooltip position="bottom-right" delay={750}>
 | 
			
		||||
          Create file
 | 
			
		||||
        </Tooltip>
 | 
			
		||||
        <Tooltip position="bottom-right">Create file</Tooltip>
 | 
			
		||||
      </ActionButton>
 | 
			
		||||
 | 
			
		||||
      <ActionButton
 | 
			
		||||
@ -563,9 +561,7 @@ export const FileTreeMenu = ({
 | 
			
		||||
        className="!p-0 !bg-transparent hover:text-primary border-transparent hover:border-primary !outline-none"
 | 
			
		||||
        onClick={onCreateFolder}
 | 
			
		||||
      >
 | 
			
		||||
        <Tooltip position="bottom-right" delay={750}>
 | 
			
		||||
          Create folder
 | 
			
		||||
        </Tooltip>
 | 
			
		||||
        <Tooltip position="bottom-right">Create folder</Tooltip>
 | 
			
		||||
      </ActionButton>
 | 
			
		||||
    </>
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
@ -119,6 +119,8 @@ import { EXPORT_TOAST_MESSAGES, MAKE_TOAST_MESSAGES } from 'lib/constants'
 | 
			
		||||
import { exportMake } from 'lib/exportMake'
 | 
			
		||||
import { exportSave } from 'lib/exportSave'
 | 
			
		||||
import { Plane } from '@rust/kcl-lib/bindings/Plane'
 | 
			
		||||
import { updateModelingState } from 'lang/modelingWorkflows'
 | 
			
		||||
import { EXECUTION_TYPE_MOCK } from 'lib/constants'
 | 
			
		||||
 | 
			
		||||
export const ModelingMachineContext = createContext(
 | 
			
		||||
  {} as {
 | 
			
		||||
@ -148,7 +150,6 @@ export const ModelingMachineProvider = ({
 | 
			
		||||
      enableSSAO,
 | 
			
		||||
    },
 | 
			
		||||
  } = useSettings()
 | 
			
		||||
  const previousAllowOrbitInSketchMode = useRef(allowOrbitInSketchMode.current)
 | 
			
		||||
  const navigate = useNavigate()
 | 
			
		||||
  const { context, send: fileMachineSend } = useFileContext()
 | 
			
		||||
  const { file } = useLoaderData() as IndexLoaderData
 | 
			
		||||
@ -1661,7 +1662,7 @@ export const ModelingMachineProvider = ({
 | 
			
		||||
              sketchDetails.sketchEntryNodePath
 | 
			
		||||
            )
 | 
			
		||||
            if (err(doesNeedSplitting)) return reject(doesNeedSplitting)
 | 
			
		||||
            let moddedAst: Program = structuredClone(kclManager.ast)
 | 
			
		||||
            let moddedAst: Node<Program> = structuredClone(kclManager.ast)
 | 
			
		||||
            let pathToProfile = sketchDetails.sketchEntryNodePath
 | 
			
		||||
            let updatedSketchNodePaths = sketchDetails.sketchNodePaths
 | 
			
		||||
            if (doesNeedSplitting) {
 | 
			
		||||
@ -1723,8 +1724,11 @@ export const ModelingMachineProvider = ({
 | 
			
		||||
              indexToDelete >= 0 ||
 | 
			
		||||
              isLastInPipeThreePointArc
 | 
			
		||||
            ) {
 | 
			
		||||
              await kclManager.executeAstMock(moddedAst)
 | 
			
		||||
              await codeManager.updateEditorWithAstAndWriteToFile(moddedAst)
 | 
			
		||||
              await updateModelingState(moddedAst, EXECUTION_TYPE_MOCK, {
 | 
			
		||||
                kclManager,
 | 
			
		||||
                editorManager,
 | 
			
		||||
                codeManager,
 | 
			
		||||
              })
 | 
			
		||||
            }
 | 
			
		||||
            return {
 | 
			
		||||
              updatedEntryNodePath: pathToProfile,
 | 
			
		||||
@ -1841,14 +1845,6 @@ export const ModelingMachineProvider = ({
 | 
			
		||||
  }, [engineCommandManager.engineConnection, modelingSend])
 | 
			
		||||
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    // Only trigger this if the state actually changes, if it stays the same do not reload the camera
 | 
			
		||||
    if (
 | 
			
		||||
      previousAllowOrbitInSketchMode.current === allowOrbitInSketchMode.current
 | 
			
		||||
    ) {
 | 
			
		||||
      //no op
 | 
			
		||||
      previousAllowOrbitInSketchMode.current = allowOrbitInSketchMode.current
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    const inSketchMode = modelingState.matches('Sketch')
 | 
			
		||||
 | 
			
		||||
    // If you are in sketch mode and you disable the orbit, return back to the normal view to the target
 | 
			
		||||
@ -1871,9 +1867,7 @@ export const ModelingMachineProvider = ({
 | 
			
		||||
    if (inSketchMode) {
 | 
			
		||||
      sceneInfra.camControls.enableRotate = allowOrbitInSketchMode.current
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    previousAllowOrbitInSketchMode.current = allowOrbitInSketchMode.current
 | 
			
		||||
  }, [allowOrbitInSketchMode])
 | 
			
		||||
  }, [allowOrbitInSketchMode.current])
 | 
			
		||||
 | 
			
		||||
  // Allow using the delete key to delete solids. Backspace only on macOS as Windows and Linux have dedicated Delete
 | 
			
		||||
  // `navigator.platform` is deprecated, but the alternative `navigator.userAgentData.platform` is not reliable
 | 
			
		||||
 | 
			
		||||
@ -51,9 +51,7 @@ export const ModelingPaneHeader = ({
 | 
			
		||||
        className="!p-0 !bg-transparent hover:text-primary border-transparent dark:!border-transparent hover:!border-primary dark:hover:!border-chalkboard-70 !outline-none"
 | 
			
		||||
        onClick={() => onClose()}
 | 
			
		||||
      >
 | 
			
		||||
        <Tooltip position="bottom-right" delay={750}>
 | 
			
		||||
          Close
 | 
			
		||||
        </Tooltip>
 | 
			
		||||
        <Tooltip position="bottom-right">Close</Tooltip>
 | 
			
		||||
      </ActionButton>
 | 
			
		||||
    </div>
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
@ -40,9 +40,7 @@ export const MemoryPaneMenu = () => {
 | 
			
		||||
        className="!p-0 !bg-transparent hover:text-primary border-transparent hover:border-primary !outline-none"
 | 
			
		||||
        onClick={copyProgramMemoryToClipboard}
 | 
			
		||||
      >
 | 
			
		||||
        <Tooltip position="bottom-right" delay={750}>
 | 
			
		||||
          Copy to clipboard
 | 
			
		||||
        </Tooltip>
 | 
			
		||||
        <Tooltip position="bottom-right">Copy to clipboard</Tooltip>
 | 
			
		||||
      </ActionButton>
 | 
			
		||||
    </>
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
@ -169,9 +169,7 @@ function ProjectCard({
 | 
			
		||||
            }}
 | 
			
		||||
            className="!p-0"
 | 
			
		||||
          >
 | 
			
		||||
            <Tooltip position="top-right" delay={1000}>
 | 
			
		||||
              Rename project
 | 
			
		||||
            </Tooltip>
 | 
			
		||||
            <Tooltip position="top-right">Rename project</Tooltip>
 | 
			
		||||
          </ActionButton>
 | 
			
		||||
          <ActionButton
 | 
			
		||||
            disabled={!project.readWriteAccess}
 | 
			
		||||
@ -188,9 +186,7 @@ function ProjectCard({
 | 
			
		||||
              setIsConfirmingDelete(true)
 | 
			
		||||
            }}
 | 
			
		||||
          >
 | 
			
		||||
            <Tooltip position="top-right" delay={1000}>
 | 
			
		||||
              Delete project
 | 
			
		||||
            </Tooltip>
 | 
			
		||||
            <Tooltip position="top-right">Delete project</Tooltip>
 | 
			
		||||
          </ActionButton>
 | 
			
		||||
        </div>
 | 
			
		||||
      )}
 | 
			
		||||
 | 
			
		||||
@ -43,9 +43,7 @@ export const ProjectCardRenameForm = forwardRef(
 | 
			
		||||
            }}
 | 
			
		||||
            className="!p-0"
 | 
			
		||||
          >
 | 
			
		||||
            <Tooltip position="left" delay={1000}>
 | 
			
		||||
              Rename project
 | 
			
		||||
            </Tooltip>
 | 
			
		||||
            <Tooltip position="left">Rename project</Tooltip>
 | 
			
		||||
          </ActionButton>
 | 
			
		||||
          <ActionButton
 | 
			
		||||
            Element="button"
 | 
			
		||||
@ -57,9 +55,7 @@ export const ProjectCardRenameForm = forwardRef(
 | 
			
		||||
            className="!p-0"
 | 
			
		||||
            onClick={onDismiss}
 | 
			
		||||
          >
 | 
			
		||||
            <Tooltip position="left" delay={1000}>
 | 
			
		||||
              Cancel
 | 
			
		||||
            </Tooltip>
 | 
			
		||||
            <Tooltip position="left">Cancel</Tooltip>
 | 
			
		||||
          </ActionButton>
 | 
			
		||||
        </div>
 | 
			
		||||
      </form>
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,7 @@ export default function Tooltip({
 | 
			
		||||
  wrapperClassName: className,
 | 
			
		||||
  contentClassName,
 | 
			
		||||
  wrapperStyle = {},
 | 
			
		||||
  delay = 200,
 | 
			
		||||
  delay = 0,
 | 
			
		||||
  hoverOnly = false,
 | 
			
		||||
  inert = true,
 | 
			
		||||
}: TooltipProps) {
 | 
			
		||||
 | 
			
		||||
@ -193,7 +193,7 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
 | 
			
		||||
            className="w-4 h-4 text-chalkboard-70 dark:text-chalkboard-40 ui-open:rotate-180"
 | 
			
		||||
          />
 | 
			
		||||
        </div>
 | 
			
		||||
        <Tooltip position="bottom-right" delay={1000} hoverOnly>
 | 
			
		||||
        <Tooltip position="bottom-right" hoverOnly>
 | 
			
		||||
          User menu
 | 
			
		||||
        </Tooltip>
 | 
			
		||||
      </Popover.Button>
 | 
			
		||||
 | 
			
		||||
@ -2,12 +2,12 @@ import { executeAst, executeAstMock, lintAst } from 'lang/langHelpers'
 | 
			
		||||
import { handleSelectionBatch, Selections } from 'lib/selections'
 | 
			
		||||
import {
 | 
			
		||||
  KCLError,
 | 
			
		||||
  complilationErrorsToDiagnostics,
 | 
			
		||||
  compilationErrorsToDiagnostics,
 | 
			
		||||
  kclErrorsToDiagnostics,
 | 
			
		||||
} from './errors'
 | 
			
		||||
import { uuidv4 } from 'lib/utils'
 | 
			
		||||
import { EngineCommandManager } from './std/engineConnection'
 | 
			
		||||
import { err } from 'lib/trap'
 | 
			
		||||
import { err, reportRejection } from 'lib/trap'
 | 
			
		||||
import { EXECUTE_AST_INTERRUPT_ERROR_MESSAGE } from 'lib/constants'
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
@ -295,8 +295,8 @@ export class KclManager {
 | 
			
		||||
    this._astParseFailed = false
 | 
			
		||||
 | 
			
		||||
    if (err(result)) {
 | 
			
		||||
      const kclerror: KCLError = result as KCLError
 | 
			
		||||
      this.diagnostics = kclErrorsToDiagnostics([kclerror])
 | 
			
		||||
      const kclError: KCLError = result as KCLError
 | 
			
		||||
      this.diagnostics = kclErrorsToDiagnostics([kclError])
 | 
			
		||||
      this._astParseFailed = true
 | 
			
		||||
 | 
			
		||||
      await this.checkIfSwitchedFilesShouldClear()
 | 
			
		||||
@ -310,8 +310,8 @@ export class KclManager {
 | 
			
		||||
    this._kclErrorsCallBack([])
 | 
			
		||||
    this._logsCallBack([])
 | 
			
		||||
 | 
			
		||||
    this.addDiagnostics(complilationErrorsToDiagnostics(result.errors))
 | 
			
		||||
    this.addDiagnostics(complilationErrorsToDiagnostics(result.warnings))
 | 
			
		||||
    this.addDiagnostics(compilationErrorsToDiagnostics(result.errors))
 | 
			
		||||
    this.addDiagnostics(compilationErrorsToDiagnostics(result.warnings))
 | 
			
		||||
    if (result.errors.length > 0) {
 | 
			
		||||
      this._astParseFailed = true
 | 
			
		||||
 | 
			
		||||
@ -337,8 +337,8 @@ export class KclManager {
 | 
			
		||||
  private _cancelTokens: Map<number, boolean> = new Map()
 | 
			
		||||
 | 
			
		||||
  // This NEVER updates the code, if you want to update the code DO NOT add to
 | 
			
		||||
  // this function, too many other things that don't want it exist.
 | 
			
		||||
  // just call to codeManager from wherever you want in other files.
 | 
			
		||||
  // this function, too many other things that don't want it exist. For that,
 | 
			
		||||
  // use updateModelingState().
 | 
			
		||||
  async executeAst(args: ExecuteArgs = {}): Promise<void> {
 | 
			
		||||
    if (this.isExecuting) {
 | 
			
		||||
      this.executeIsStale = args
 | 
			
		||||
@ -420,7 +420,7 @@ export class KclManager {
 | 
			
		||||
    this.addDiagnostics(isInterrupted ? [] : kclErrorsToDiagnostics(errors))
 | 
			
		||||
    // Add warnings and non-fatal errors
 | 
			
		||||
    this.addDiagnostics(
 | 
			
		||||
      isInterrupted ? [] : complilationErrorsToDiagnostics(execState.errors)
 | 
			
		||||
      isInterrupted ? [] : compilationErrorsToDiagnostics(execState.errors)
 | 
			
		||||
    )
 | 
			
		||||
    this.execState = execState
 | 
			
		||||
    if (!errors.length) {
 | 
			
		||||
@ -460,7 +460,6 @@ export class KclManager {
 | 
			
		||||
    markOnce('code/endExecuteAst')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // NOTE: this always updates the code state and editor.
 | 
			
		||||
  // DO NOT CALL THIS from codemirror ever.
 | 
			
		||||
  async executeAstMock(ast: Program) {
 | 
			
		||||
    await this.ensureWasmInit()
 | 
			
		||||
@ -472,7 +471,7 @@ export class KclManager {
 | 
			
		||||
    }
 | 
			
		||||
    const newAst = await this.safeParse(newCode)
 | 
			
		||||
    if (!newAst) {
 | 
			
		||||
      // By clearning the AST we indicate to our callers that there was an issue with execution and
 | 
			
		||||
      // By clearing the AST we indicate to our callers that there was an issue with execution and
 | 
			
		||||
      // the pre-execution state should be restored.
 | 
			
		||||
      this.clearAst()
 | 
			
		||||
      return
 | 
			
		||||
@ -501,7 +500,7 @@ export class KclManager {
 | 
			
		||||
    const ast = await this.safeParse(codeManager.code)
 | 
			
		||||
 | 
			
		||||
    if (!ast) {
 | 
			
		||||
      // By clearning the AST we indicate to our callers that there was an issue with execution and
 | 
			
		||||
      // By clearing the AST we indicate to our callers that there was an issue with execution and
 | 
			
		||||
      // the pre-execution state should be restored.
 | 
			
		||||
      this.clearAst()
 | 
			
		||||
      return
 | 
			
		||||
@ -516,8 +515,8 @@ export class KclManager {
 | 
			
		||||
   * This will override the zoom to fit to zoom into the model if the previous AST was empty.
 | 
			
		||||
   * Workflows this improves,
 | 
			
		||||
   *  When someone comments the entire file then uncomments the entire file it zooms to the model
 | 
			
		||||
   *  When someone CRTL+A and deletes the code then adds the code back it zooms to the model
 | 
			
		||||
   *  When someone CRTL+A and copies new code into the editor it zooms to the model
 | 
			
		||||
   *  When someone CTRL+A and deletes the code then adds the code back it zooms to the model
 | 
			
		||||
   *  When someone CTRL+A and copies new code into the editor it zooms to the model
 | 
			
		||||
   */
 | 
			
		||||
  tryToZoomToFitOnCodeUpdate(
 | 
			
		||||
    ast: Node<Program>,
 | 
			
		||||
@ -555,12 +554,16 @@ export class KclManager {
 | 
			
		||||
    codeManager.updateCodeStateEditor(code)
 | 
			
		||||
 | 
			
		||||
    // Write back to the file system.
 | 
			
		||||
    void codeManager.writeToFile().then(() => this.executeCode())
 | 
			
		||||
    void codeManager
 | 
			
		||||
      .writeToFile()
 | 
			
		||||
      .then(() => this.executeCode())
 | 
			
		||||
      .catch(reportRejection)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // There's overlapping responsibility between updateAst and executeAst.
 | 
			
		||||
  // updateAst was added as it was used a lot before xState migration so makes the port easier.
 | 
			
		||||
  // but should probably have think about which of the function to keep
 | 
			
		||||
  // This always updates the code state and editor and writes to the file system.
 | 
			
		||||
  // This never updates the code state or editor and doesn't write to the file system.
 | 
			
		||||
  async updateAst(
 | 
			
		||||
    ast: Node<Program>,
 | 
			
		||||
    execute: boolean,
 | 
			
		||||
@ -627,7 +630,6 @@ export class KclManager {
 | 
			
		||||
      // When we don't re-execute, we still want to update the program
 | 
			
		||||
      // memory with the new ast. So we will hit the mock executor
 | 
			
		||||
      // instead..
 | 
			
		||||
      // Execute ast mock will update the code state and editor.
 | 
			
		||||
      await this.executeAstMock(astWithUpdatedSource)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -165,10 +165,11 @@ export default class CodeManager {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async updateEditorWithAstAndWriteToFile(ast: Program) {
 | 
			
		||||
    // We clear the AST when there it cannot be parsed, so if we are trying to write an empty AST, its
 | 
			
		||||
    // probably because of an earlier error. That's a bad state to be in and it's not going to be
 | 
			
		||||
    // pretty, but at the least, lets not permanently delete the user's code.
 | 
			
		||||
    // If you want to clear the scene, call updateCodeStateEditor directly.
 | 
			
		||||
    // We clear the AST when it cannot be parsed. If we are trying to write an
 | 
			
		||||
    // empty AST, it's probably because of an earlier error. That's a bad state
 | 
			
		||||
    // to be in, and it's not going to be pretty, but at the least, let's not
 | 
			
		||||
    // permanently delete the user's code. If you want to clear the scene, call
 | 
			
		||||
    // updateCodeStateEditor directly.
 | 
			
		||||
    if (ast.body.length === 0) return
 | 
			
		||||
    const newCode = recast(ast)
 | 
			
		||||
    if (err(newCode)) return
 | 
			
		||||
 | 
			
		||||
@ -320,7 +320,7 @@ export function kclErrorsToDiagnostics(
 | 
			
		||||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function complilationErrorsToDiagnostics(
 | 
			
		||||
export function compilationErrorsToDiagnostics(
 | 
			
		||||
  errors: CompilationError[]
 | 
			
		||||
): CodeMirrorDiagnostic[] {
 | 
			
		||||
  return errors
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,12 @@
 | 
			
		||||
 | 
			
		||||
import { Node } from '@rust/kcl-lib/bindings/Node'
 | 
			
		||||
import { KclManager } from 'lang/KclSingleton'
 | 
			
		||||
import { ExecutionType } from 'lib/constants'
 | 
			
		||||
import {
 | 
			
		||||
  EXECUTION_TYPE_MOCK,
 | 
			
		||||
  EXECUTION_TYPE_NONE,
 | 
			
		||||
  EXECUTION_TYPE_REAL,
 | 
			
		||||
} from 'lib/constants'
 | 
			
		||||
import { PathToNode, Program, SourceRange } from 'lang/wasm'
 | 
			
		||||
import EditorManager from 'editor/manager'
 | 
			
		||||
import CodeManager from 'lang/codeManager'
 | 
			
		||||
@ -32,12 +38,13 @@ import CodeManager from 'lang/codeManager'
 | 
			
		||||
 * regardless of geometric validity issues.
 | 
			
		||||
 *
 | 
			
		||||
 * @param ast - AST to commit
 | 
			
		||||
 * @param executionType - How to execute the AST
 | 
			
		||||
 * @param dependencies - Required system components
 | 
			
		||||
 * @param options - Optional parameters for focus, zoom, etc.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export async function updateModelingState(
 | 
			
		||||
  ast: Node<Program>,
 | 
			
		||||
  executionType: ExecutionType,
 | 
			
		||||
  dependencies: {
 | 
			
		||||
    kclManager: KclManager
 | 
			
		||||
    editorManager: EditorManager
 | 
			
		||||
@ -55,6 +62,7 @@ export async function updateModelingState(
 | 
			
		||||
  // Step 1: Update AST without executing (prepare selections)
 | 
			
		||||
  const updatedAst = await dependencies.kclManager.updateAst(
 | 
			
		||||
    ast,
 | 
			
		||||
    // false == mock execution. Is this what we want?
 | 
			
		||||
    false, // Execution handled separately for error resilience
 | 
			
		||||
    options
 | 
			
		||||
  )
 | 
			
		||||
@ -69,14 +77,20 @@ export async function updateModelingState(
 | 
			
		||||
    dependencies.editorManager.selectRange(updatedAst.selections)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Step 4: Try to execute the new code in the engine
 | 
			
		||||
  // Step 4: Try to execute the new code
 | 
			
		||||
  // and continue regardless of errors
 | 
			
		||||
  try {
 | 
			
		||||
    await dependencies.kclManager.executeAst({
 | 
			
		||||
      ast: updatedAst.newAst,
 | 
			
		||||
      zoomToFit: options?.zoomToFit,
 | 
			
		||||
      zoomOnRangeAndType: options?.zoomOnRangeAndType,
 | 
			
		||||
    })
 | 
			
		||||
    if (executionType === EXECUTION_TYPE_REAL) {
 | 
			
		||||
      await dependencies.kclManager.executeAst({
 | 
			
		||||
        ast: updatedAst.newAst,
 | 
			
		||||
        zoomToFit: options?.zoomToFit,
 | 
			
		||||
        zoomOnRangeAndType: options?.zoomOnRangeAndType,
 | 
			
		||||
      })
 | 
			
		||||
    } else if (executionType === EXECUTION_TYPE_MOCK) {
 | 
			
		||||
      await dependencies.kclManager.executeAstMock(updatedAst.newAst)
 | 
			
		||||
    } else if (executionType === EXECUTION_TYPE_NONE) {
 | 
			
		||||
      // No execution.
 | 
			
		||||
    }
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    console.error('Engine execution error (UI is still updated):', e)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -673,7 +673,7 @@ export function sketchOnExtrudedFace(
 | 
			
		||||
  sketchPathToNode: PathToNode,
 | 
			
		||||
  extrudePathToNode: PathToNode,
 | 
			
		||||
  info: ExtrudeFacePlane['faceInfo'] = { type: 'wall' }
 | 
			
		||||
): { modifiedAst: Program; pathToNode: PathToNode } | Error {
 | 
			
		||||
): { modifiedAst: Node<Program>; pathToNode: PathToNode } | Error {
 | 
			
		||||
  let _node = { ...node }
 | 
			
		||||
  const newSketchName = findUniqueName(
 | 
			
		||||
    node,
 | 
			
		||||
@ -1375,7 +1375,7 @@ export function moveValueIntoNewVariablePath(
 | 
			
		||||
  pathToNode: PathToNode,
 | 
			
		||||
  variableName: string
 | 
			
		||||
): {
 | 
			
		||||
  modifiedAst: Program
 | 
			
		||||
  modifiedAst: Node<Program>
 | 
			
		||||
  pathToReplacedNode?: PathToNode
 | 
			
		||||
} {
 | 
			
		||||
  const meta = isNodeSafeToReplacePath(ast, pathToNode)
 | 
			
		||||
@ -1975,11 +1975,11 @@ making it safe for later code that uses part001 (the extrude in this example)
 | 
			
		||||
 * 
 | 
			
		||||
 */
 | 
			
		||||
export function splitPipedProfile(
 | 
			
		||||
  ast: Program,
 | 
			
		||||
  ast: Node<Program>,
 | 
			
		||||
  pathToPipe: PathToNode
 | 
			
		||||
):
 | 
			
		||||
  | {
 | 
			
		||||
      modifiedAst: Program
 | 
			
		||||
      modifiedAst: Node<Program>
 | 
			
		||||
      pathToProfile: PathToNode
 | 
			
		||||
      pathToPlane: PathToNode
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -39,6 +39,7 @@ import { Artifact, getSweepArtifactFromSelection } from 'lang/std/artifactGraph'
 | 
			
		||||
import { Node } from '@rust/kcl-lib/bindings/Node'
 | 
			
		||||
import { findKwArg } from 'lang/util'
 | 
			
		||||
import { KclManager } from 'lang/KclSingleton'
 | 
			
		||||
import { EXECUTION_TYPE_REAL } from 'lib/constants'
 | 
			
		||||
import { EngineCommandManager } from 'lang/std/engineConnection'
 | 
			
		||||
import EditorManager from 'editor/manager'
 | 
			
		||||
import CodeManager from 'lang/codeManager'
 | 
			
		||||
@ -86,6 +87,7 @@ export async function applyEdgeTreatmentToSelection(
 | 
			
		||||
  // 2. update ast
 | 
			
		||||
  await updateModelingState(
 | 
			
		||||
    modifiedAst,
 | 
			
		||||
    EXECUTION_TYPE_REAL,
 | 
			
		||||
    {
 | 
			
		||||
      kclManager: dependencies.kclManager,
 | 
			
		||||
      editorManager: dependencies.editorManager,
 | 
			
		||||
 | 
			
		||||
@ -3,12 +3,15 @@ import { getFaceDetails } from 'clientSideScene/sceneEntities'
 | 
			
		||||
import { deleteFromSelection } from 'lang/modifyAst'
 | 
			
		||||
import {
 | 
			
		||||
  codeManager,
 | 
			
		||||
  editorManager,
 | 
			
		||||
  engineCommandManager,
 | 
			
		||||
  kclManager,
 | 
			
		||||
  rustContext,
 | 
			
		||||
} from 'lib/singletons'
 | 
			
		||||
import { err } from 'lib/trap'
 | 
			
		||||
import { executeAstMock } from 'lang/langHelpers'
 | 
			
		||||
import { updateModelingState } from 'lang/modelingWorkflows'
 | 
			
		||||
import { EXECUTION_TYPE_REAL } from 'lib/constants'
 | 
			
		||||
 | 
			
		||||
export const deletionErrorMessage =
 | 
			
		||||
  'Unable to delete selection. Please edit manually in code pane.'
 | 
			
		||||
@ -36,7 +39,9 @@ export async function deleteSelectionPromise(
 | 
			
		||||
  if (testExecute.errors.length) {
 | 
			
		||||
    return new Error(deletionErrorMessage)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  await kclManager.updateAst(modifiedAst, true)
 | 
			
		||||
  await codeManager.updateEditorWithAstAndWriteToFile(modifiedAst)
 | 
			
		||||
  await updateModelingState(modifiedAst, EXECUTION_TYPE_REAL, {
 | 
			
		||||
    kclManager,
 | 
			
		||||
    editorManager,
 | 
			
		||||
    codeManager,
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -167,3 +167,17 @@ export const ZOO_STUDIO_PROTOCOL = 'zoo-studio'
 | 
			
		||||
 * to "open in desktop app" when present in the URL
 | 
			
		||||
 */
 | 
			
		||||
export const ASK_TO_OPEN_QUERY_PARAM = 'ask-open-desktop'
 | 
			
		||||
 | 
			
		||||
/** Real execution. */
 | 
			
		||||
export const EXECUTION_TYPE_REAL = 'real' as const
 | 
			
		||||
/** Mock execution. */
 | 
			
		||||
export const EXECUTION_TYPE_MOCK = 'mock' as const
 | 
			
		||||
/** No execution. */
 | 
			
		||||
export const EXECUTION_TYPE_NONE = 'none' as const
 | 
			
		||||
/**
 | 
			
		||||
 * Enum of engine execution kinds.
 | 
			
		||||
 */
 | 
			
		||||
export type ExecutionType =
 | 
			
		||||
  | typeof EXECUTION_TYPE_REAL
 | 
			
		||||
  | typeof EXECUTION_TYPE_MOCK
 | 
			
		||||
  | typeof EXECUTION_TYPE_NONE
 | 
			
		||||
 | 
			
		||||
@ -28,52 +28,25 @@ sketch001 = startSketchOn(XZ)
 | 
			
		||||
  |> xLine(length = thickness, tag = $seg05)
 | 
			
		||||
  |> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg06)
 | 
			
		||||
  |> close()
 | 
			
		||||
  |> extrude(%, length = width)
 | 
			
		||||
  |> fillet(
 | 
			
		||||
       radius = extFilletRadius,
 | 
			
		||||
       tags = [getNextAdjacentEdge(seg03)],
 | 
			
		||||
     )
 | 
			
		||||
  |> fillet(
 | 
			
		||||
       radius = filletRadius,
 | 
			
		||||
       tags = [getNextAdjacentEdge(seg06)],
 | 
			
		||||
     )
 | 
			
		||||
  |> fillet(
 | 
			
		||||
      radius = filletRadius,
 | 
			
		||||
      tags = [seg02, getOppositeEdge(seg02)],
 | 
			
		||||
    )
 | 
			
		||||
  |> fillet(
 | 
			
		||||
      radius = filletRadius,
 | 
			
		||||
      tags = [seg05, getOppositeEdge(seg05)],
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
sketch002 = startSketchOn(sketch001, seg03)
 | 
			
		||||
  |> circle(
 | 
			
		||||
    center = [-1.25, 1],
 | 
			
		||||
    radius = mountingHoleDiameter / 2,
 | 
			
		||||
  )
 | 
			
		||||
  |> patternLinear2d(
 | 
			
		||||
    instances = 2,
 | 
			
		||||
    distance = 2.5,
 | 
			
		||||
    axis = [-1, 0],
 | 
			
		||||
  )
 | 
			
		||||
  |> patternLinear2d(
 | 
			
		||||
    instances = 2,
 | 
			
		||||
    distance = 4,
 | 
			
		||||
    axis = [0, 1],
 | 
			
		||||
  )
 | 
			
		||||
  |> extrude(%, length = -thickness-.01)
 | 
			
		||||
extrude001 = extrude(sketch001, length = width)
 | 
			
		||||
  |> fillet(radius = extFilletRadius, tags = [getNextAdjacentEdge(seg03)])
 | 
			
		||||
  |> fillet(radius = filletRadius, tags = [getNextAdjacentEdge(seg06)])
 | 
			
		||||
  |> fillet(radius = filletRadius, tags = [seg02, getOppositeEdge(seg02)])
 | 
			
		||||
  |> fillet(radius = filletRadius, tags = [seg05, getOppositeEdge(seg05)])
 | 
			
		||||
 | 
			
		||||
sketch003 = startSketchOn(sketch001, seg04)
 | 
			
		||||
  |> circle(
 | 
			
		||||
    center = [1, -1],
 | 
			
		||||
    radius = mountingHoleDiameter / 2,
 | 
			
		||||
  )
 | 
			
		||||
  |> patternLinear2d(
 | 
			
		||||
    instances = 2,
 | 
			
		||||
    distance = 4,
 | 
			
		||||
    axis = [1, 0],
 | 
			
		||||
  )
 | 
			
		||||
  |> extrude(%, length = -thickness-0.1)
 | 
			
		||||
sketch002 = startSketchOn(extrude001, seg03)
 | 
			
		||||
  |> circle(center = [-1.25, 1], radius = mountingHoleDiameter / 2)
 | 
			
		||||
  |> patternLinear2d(instances = 2, distance = 2.5, axis = [-1, 0])
 | 
			
		||||
  |> patternLinear2d(instances = 2, distance = 4, axis = [0, 1])
 | 
			
		||||
  
 | 
			
		||||
extrude002 = extrude(sketch002, length = -thickness - .01)
 | 
			
		||||
 | 
			
		||||
sketch003 = startSketchOn(extrude002, seg04)
 | 
			
		||||
  |> circle(center = [1, -1], radius = mountingHoleDiameter / 2)
 | 
			
		||||
  |> patternLinear2d(instances = 2, distance = 4, axis = [1, 0])
 | 
			
		||||
 | 
			
		||||
extrude003 = extrude(sketch003, length = -thickness - 0.1)
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
@ -642,11 +642,11 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
 | 
			
		||||
    operation.type !== 'StdLibCall' ||
 | 
			
		||||
    !operation.labeledArgs
 | 
			
		||||
  ) {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
    return { reason: 'Wrong operation type or artifact' }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // We have to go a little roundabout to get from the original artifact
 | 
			
		||||
  // to the solid2DId that we need to pass to the Extrude command.
 | 
			
		||||
  // to the solid2DId that we need to pass to the command.
 | 
			
		||||
  const pathArtifact = getArtifactOfTypes(
 | 
			
		||||
    {
 | 
			
		||||
      key: artifact.pathId,
 | 
			
		||||
@ -658,8 +658,10 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
 | 
			
		||||
    err(pathArtifact) ||
 | 
			
		||||
    pathArtifact.type !== 'path' ||
 | 
			
		||||
    !pathArtifact.solid2dId
 | 
			
		||||
  )
 | 
			
		||||
    return baseCommand
 | 
			
		||||
  ) {
 | 
			
		||||
    return { reason: "Couldn't find related path artifact" }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const solid2DArtifact = getArtifactOfTypes(
 | 
			
		||||
    {
 | 
			
		||||
      key: pathArtifact.solid2dId,
 | 
			
		||||
@ -668,7 +670,7 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
 | 
			
		||||
    engineCommandManager.artifactGraph
 | 
			
		||||
  )
 | 
			
		||||
  if (err(solid2DArtifact) || solid2DArtifact.type !== 'solid2d') {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
    return { reason: "Couldn't find related solid2d artifact" }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const selection = {
 | 
			
		||||
@ -683,7 +685,7 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
 | 
			
		||||
 | 
			
		||||
  // axis options string arg
 | 
			
		||||
  if (!('axis' in operation.labeledArgs) || !operation.labeledArgs.axis) {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
    return { reason: "Couldn't find axis argument" }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const axisValue = operation.labeledArgs.axis.value
 | 
			
		||||
@ -705,7 +707,7 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
 | 
			
		||||
      engineCommandManager.artifactGraph
 | 
			
		||||
    )
 | 
			
		||||
    if (err(artifact)) {
 | 
			
		||||
      return baseCommand
 | 
			
		||||
      return { reason: "Couldn't find related edge artifact" }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    edge = {
 | 
			
		||||
@ -728,7 +730,7 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
 | 
			
		||||
      engineCommandManager.artifactGraph
 | 
			
		||||
    )
 | 
			
		||||
    if (err(artifact)) {
 | 
			
		||||
      return baseCommand
 | 
			
		||||
      return { reason: "Couldn't find related edge artifact" }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const codeRef = getSweepEdgeCodeRef(
 | 
			
		||||
@ -736,7 +738,7 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
 | 
			
		||||
      engineCommandManager.artifactGraph
 | 
			
		||||
    )
 | 
			
		||||
    if (err(codeRef)) {
 | 
			
		||||
      return baseCommand
 | 
			
		||||
      return { reason: "Couldn't find related edge code ref" }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    edge = {
 | 
			
		||||
@ -749,12 +751,12 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
 | 
			
		||||
      otherSelections: [],
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
    return { reason: 'The type of the axis argument is unsupported' }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // angle kcl arg
 | 
			
		||||
  if (!('angle' in operation.labeledArgs) || !operation.labeledArgs.angle) {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
    return { reason: "Couldn't find angle argument" }
 | 
			
		||||
  }
 | 
			
		||||
  const angle = await stringToKclExpression(
 | 
			
		||||
    codeManager.code.slice(
 | 
			
		||||
@ -763,7 +765,7 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
 | 
			
		||||
    )
 | 
			
		||||
  )
 | 
			
		||||
  if (err(angle) || 'errors' in angle) {
 | 
			
		||||
    return baseCommand
 | 
			
		||||
    return { reason: 'Error in angle argument retrieval' }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Assemble the default argument values for the Offset Plane command,
 | 
			
		||||
@ -780,8 +782,6 @@ const prepareToEditRevolve: PrepareToEditCallback = async ({
 | 
			
		||||
      sourceRangeFromRust(operation.sourceRange)
 | 
			
		||||
    ),
 | 
			
		||||
  }
 | 
			
		||||
  console.log(argDefaultValues)
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    ...baseCommand,
 | 
			
		||||
    argDefaultValues,
 | 
			
		||||
 | 
			
		||||
@ -102,6 +102,7 @@ import { setAppearance } from 'lang/modifyAst/setAppearance'
 | 
			
		||||
import { DRAFT_DASHED_LINE } from 'clientSideScene/sceneEntities'
 | 
			
		||||
import { Node } from '@rust/kcl-lib/bindings/Node'
 | 
			
		||||
import { updateModelingState } from 'lang/modelingWorkflows'
 | 
			
		||||
import { EXECUTION_TYPE_REAL } from 'lib/constants'
 | 
			
		||||
 | 
			
		||||
export const MODELING_PERSIST_KEY = 'MODELING_PERSIST_KEY'
 | 
			
		||||
 | 
			
		||||
@ -1744,20 +1745,23 @@ export const modelingMachine = setup({
 | 
			
		||||
        pathToExtrudeArg[1][0]++
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const updatedAst = await kclManager.updateAst(modifiedAst, true, {
 | 
			
		||||
        focusPath: [pathToExtrudeArg],
 | 
			
		||||
        zoomToFit: true,
 | 
			
		||||
        zoomOnRangeAndType: {
 | 
			
		||||
          range: selection.graphSelections[0]?.codeRef.range,
 | 
			
		||||
          type: 'path',
 | 
			
		||||
      await updateModelingState(
 | 
			
		||||
        modifiedAst,
 | 
			
		||||
        EXECUTION_TYPE_REAL,
 | 
			
		||||
        {
 | 
			
		||||
          kclManager,
 | 
			
		||||
          editorManager,
 | 
			
		||||
          codeManager,
 | 
			
		||||
        },
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      await codeManager.updateEditorWithAstAndWriteToFile(updatedAst.newAst)
 | 
			
		||||
 | 
			
		||||
      if (updatedAst?.selections) {
 | 
			
		||||
        editorManager.selectRange(updatedAst?.selections)
 | 
			
		||||
      }
 | 
			
		||||
        {
 | 
			
		||||
          focusPath: [pathToExtrudeArg],
 | 
			
		||||
          zoomToFit: true,
 | 
			
		||||
          zoomOnRangeAndType: {
 | 
			
		||||
            range: selection.graphSelections[0]?.codeRef.range,
 | 
			
		||||
            type: 'path',
 | 
			
		||||
          },
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
    }),
 | 
			
		||||
    revolveAstMod: fromPromise<
 | 
			
		||||
      unknown,
 | 
			
		||||
@ -1819,6 +1823,7 @@ export const modelingMachine = setup({
 | 
			
		||||
      const { modifiedAst, pathToRevolveArg } = revolveSketchRes
 | 
			
		||||
      await updateModelingState(
 | 
			
		||||
        modifiedAst,
 | 
			
		||||
        EXECUTION_TYPE_REAL,
 | 
			
		||||
        {
 | 
			
		||||
          kclManager,
 | 
			
		||||
          editorManager,
 | 
			
		||||
@ -1826,6 +1831,11 @@ export const modelingMachine = setup({
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          focusPath: [pathToRevolveArg],
 | 
			
		||||
          zoomToFit: true,
 | 
			
		||||
          zoomOnRangeAndType: {
 | 
			
		||||
            range: selection.graphSelections[0]?.codeRef.range,
 | 
			
		||||
            type: 'path',
 | 
			
		||||
          },
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
    }),
 | 
			
		||||
@ -1897,21 +1907,18 @@ export const modelingMachine = setup({
 | 
			
		||||
          offsetPlaneResult.pathToNode[1][0]++
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const updateAstResult = await kclManager.updateAst(
 | 
			
		||||
        await updateModelingState(
 | 
			
		||||
          offsetPlaneResult.modifiedAst,
 | 
			
		||||
          true,
 | 
			
		||||
          EXECUTION_TYPE_REAL,
 | 
			
		||||
          {
 | 
			
		||||
            kclManager,
 | 
			
		||||
            editorManager,
 | 
			
		||||
            codeManager,
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            focusPath: [offsetPlaneResult.pathToNode],
 | 
			
		||||
          }
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        await codeManager.updateEditorWithAstAndWriteToFile(
 | 
			
		||||
          updateAstResult.newAst
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        if (updateAstResult?.selections) {
 | 
			
		||||
          editorManager.selectRange(updateAstResult?.selections)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ),
 | 
			
		||||
    helixAstMod: fromPromise(
 | 
			
		||||
@ -2012,6 +2019,7 @@ export const modelingMachine = setup({
 | 
			
		||||
        })
 | 
			
		||||
        await updateModelingState(
 | 
			
		||||
          modifiedAst,
 | 
			
		||||
          EXECUTION_TYPE_REAL,
 | 
			
		||||
          {
 | 
			
		||||
            kclManager,
 | 
			
		||||
            editorManager,
 | 
			
		||||
@ -2105,6 +2113,7 @@ export const modelingMachine = setup({
 | 
			
		||||
        })
 | 
			
		||||
        await updateModelingState(
 | 
			
		||||
          modifiedAst,
 | 
			
		||||
          EXECUTION_TYPE_REAL,
 | 
			
		||||
          {
 | 
			
		||||
            kclManager,
 | 
			
		||||
            editorManager,
 | 
			
		||||
@ -2143,21 +2152,18 @@ export const modelingMachine = setup({
 | 
			
		||||
 | 
			
		||||
        // Perform the loft
 | 
			
		||||
        const loftSketchesRes = loftSketches(ast, declarators)
 | 
			
		||||
        const updateAstResult = await kclManager.updateAst(
 | 
			
		||||
        await updateModelingState(
 | 
			
		||||
          loftSketchesRes.modifiedAst,
 | 
			
		||||
          true,
 | 
			
		||||
          EXECUTION_TYPE_REAL,
 | 
			
		||||
          {
 | 
			
		||||
            kclManager,
 | 
			
		||||
            editorManager,
 | 
			
		||||
            codeManager,
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            focusPath: [loftSketchesRes.pathToNode],
 | 
			
		||||
          }
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        await codeManager.updateEditorWithAstAndWriteToFile(
 | 
			
		||||
          updateAstResult.newAst
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        if (updateAstResult?.selections) {
 | 
			
		||||
          editorManager.selectRange(updateAstResult?.selections)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ),
 | 
			
		||||
    shellAstMod: fromPromise(
 | 
			
		||||
@ -2323,21 +2329,18 @@ export const modelingMachine = setup({
 | 
			
		||||
          addResult.pathToNode[1][0]++
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const updateAstResult = await kclManager.updateAst(
 | 
			
		||||
        await updateModelingState(
 | 
			
		||||
          addResult.modifiedAst,
 | 
			
		||||
          true,
 | 
			
		||||
          EXECUTION_TYPE_REAL,
 | 
			
		||||
          {
 | 
			
		||||
            kclManager,
 | 
			
		||||
            editorManager,
 | 
			
		||||
            codeManager,
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            focusPath: [addResult.pathToNode],
 | 
			
		||||
          }
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        await codeManager.updateEditorWithAstAndWriteToFile(
 | 
			
		||||
          updateAstResult.newAst
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        if (updateAstResult?.selections) {
 | 
			
		||||
          editorManager.selectRange(updateAstResult?.selections)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ),
 | 
			
		||||
    filletAstMod: fromPromise(
 | 
			
		||||
@ -2389,15 +2392,11 @@ export const modelingMachine = setup({
 | 
			
		||||
          node: kclManager.ast,
 | 
			
		||||
          newExpression: value,
 | 
			
		||||
        })
 | 
			
		||||
        const updateAstResult = await kclManager.updateAst(newAst, true)
 | 
			
		||||
 | 
			
		||||
        await codeManager.updateEditorWithAstAndWriteToFile(
 | 
			
		||||
          updateAstResult.newAst
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        if (updateAstResult?.selections) {
 | 
			
		||||
          editorManager.selectRange(updateAstResult?.selections)
 | 
			
		||||
        }
 | 
			
		||||
        await updateModelingState(newAst, EXECUTION_TYPE_REAL, {
 | 
			
		||||
          kclManager,
 | 
			
		||||
          editorManager,
 | 
			
		||||
          codeManager,
 | 
			
		||||
        })
 | 
			
		||||
      }
 | 
			
		||||
    ),
 | 
			
		||||
    'actor.parameter.edit': fromPromise(
 | 
			
		||||
@ -2426,7 +2425,7 @@ export const modelingMachine = setup({
 | 
			
		||||
        // Mutate the variable's value
 | 
			
		||||
        variableNode.node.init = value.valueAst
 | 
			
		||||
 | 
			
		||||
        await updateModelingState(newAst, {
 | 
			
		||||
        await updateModelingState(newAst, EXECUTION_TYPE_REAL, {
 | 
			
		||||
          codeManager,
 | 
			
		||||
          editorManager,
 | 
			
		||||
          kclManager,
 | 
			
		||||
@ -2592,21 +2591,18 @@ export const modelingMachine = setup({
 | 
			
		||||
          return err(result)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const updateAstResult = await kclManager.updateAst(
 | 
			
		||||
        await updateModelingState(
 | 
			
		||||
          result.modifiedAst,
 | 
			
		||||
          true,
 | 
			
		||||
          EXECUTION_TYPE_REAL,
 | 
			
		||||
          {
 | 
			
		||||
            kclManager,
 | 
			
		||||
            editorManager,
 | 
			
		||||
            codeManager,
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            focusPath: [result.pathToNode],
 | 
			
		||||
          }
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        await codeManager.updateEditorWithAstAndWriteToFile(
 | 
			
		||||
          updateAstResult.newAst
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        if (updateAstResult?.selections) {
 | 
			
		||||
          editorManager.selectRange(updateAstResult?.selections)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ),
 | 
			
		||||
    exportFromEngine: fromPromise(
 | 
			
		||||
 | 
			
		||||
@ -193,7 +193,7 @@ export function OnboardingButtons({
 | 
			
		||||
          name="close"
 | 
			
		||||
          className="w-5 h-5 rounded-sm bg-destroy-10 text-destroy-80 dark:bg-destroy-80 dark:text-destroy-10 group-hover:brightness-110"
 | 
			
		||||
        />
 | 
			
		||||
        <Tooltip position="bottom" delay={500}>
 | 
			
		||||
        <Tooltip position="bottom">
 | 
			
		||||
          Dismiss <kbd className="hotkey ml-4 dark:!bg-chalkboard-80">esc</kbd>
 | 
			
		||||
        </Tooltip>
 | 
			
		||||
      </button>
 | 
			
		||||
 | 
			
		||||