ChatCraft week 8: Successful refactoring PR!
Tags: chatgpt, chatcraft, typescript, opensource
Published: 2024-03-09 05:28:17

---
series: Collaborating on ChatCraft
---

# Sheriff Duty

This week on [ChatCraft](https://chatcraft.org), I am the designated Sheriff for our project team. This means that I lead the weekly team meeting, [took notes](https://github.com/humphd/osd700-winter-2024/wiki/Meeting-Minutes-%E2%80%90-Milestone-1.4), and I was the point of contact person when issues arise. I also monitored the to-do items for this weeks release and pushed a new [release](https://github.com/tarasglek/chatcraft.org/releases/tag/v1.4.0) to GitHub today since it is the end of the week!

# Largest Pull Request Yet

This release marked my largest merged [pull request](https://github.com/tarasglek/chatcraft.org/pull/479) to date with a whopping 15 file changes!

[![large_pr](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nq7v2wa47vnfa4b0y8tz.png)](https://github.com/tarasglek/chatcraft.org/pull/479)

In this PR I worked with React use states, use effects and use context. ChatCraft uses React Context to provide access to and store the data in localStorage. The api key and api url used to be stored in `settings.apiKey` and `settings.apiUrl` respectively. 

However, since I have recently introduced a `ChatCraftProvider` class which holds all the information about a provider such as name, key, url, some refactoring of the project is needed. I also introduced two child classes called `OpenAiProvider` and `OpenRouterProvider`. The goal is to establish another new provider in the coming weeks.

I replaced `settings.apiUrl` and `settings.apiKey` with `settings.currentProvider`. I also had to deal with the deserialization of `currentProvider` in the `deserializer` function of [`settings.ts`](https://github.com/tarasglek/chatcraft.org/blob/main/src/lib/settings.ts). I parsed the JSON of `currentProvider` into a `ChatCraftProvider` object.

I also implemented the migration of current ChatCraft users who still have `apiKey` and `apiUrl` values in their localStorage. I migrated those values to `currentProvider` and removed those fields.

```
export const deserializer = (value: string): Settings => {
  const settings = JSON.parse(value);
  if (!settings.model) {
    settings.model = defaults.model;
  }

  if (typeof settings.model === "string") {
    settings.model = new ChatCraftModel(settings.model);
  }

  if (settings.currentProvider) {
    // Handle deserialization of currentProvider
    settings.currentProvider = providerFromJSON(settings.currentProvider);
  } else {
    // No current provider, check if we need to handle migration of deprecated apiKey, apiUrl
    if (settings.apiKey && settings.apiUrl) {
      const newProvider = providerFromUrl(settings.apiUrl, settings.apiKey);
      settings.currentProvider = newProvider;
      settings.providers = { ...settings.providers, [newProvider.apiUrl]: newProvider };
      delete settings.apiKey;
      delete settings.apiUrl;
      console.warn("Migrated deprecated apiKey, apiUrl");
    }
  }

  return { ...defaults, ...settings };
};
```

# Code Changes after Review

At first I was using dynamic imports in `ChatCraftProvider` to circumvent a circular dependency issue. But after speaking to Dave I realized it would be better to simply move the code out of that class and into another file, providers/index.ts.

This made my code a lot simpler since without the dynamic imports, I wouldn't have to deal with the functions being `async`. This allowed me to move my deserialization code and migration code into the `deserializer` function of `settings.ts`. This was the best place for it, but I previously could not place it there due to the `deserializer` function only allowing asynchronous calls.

# My Reviews on Team's PR

{% github https://github.com/tarasglek/chatcraft.org/pull/485 %}

I [reviewed](https://github.com/tarasglek/chatcraft.org/pull/485#pullrequestreview-1924071095) this very cool PR this week and I urge you to check it out. My teammate [Yumei](https://dev.to/wanggithub0) has made it possible for users to run Python code in ChatCraft! If you ask for or give ChatCraft some Python code, there is now a run icon you can click to execute the code!

I tested this and the only problem I saw with it was that it cannot run any code that requires input from the user. Not yet anyways :)

So apparently she was able to get this working using [python-wasi](https://github.com/tarasglek/chatcraft.org/issues/312#issuecomment-1962128589) 

# More about Python WASI

Imagine you want to run Python code, but instead of running it on your computer directly, you want to run it in a web browser. python-wasi is a version of Python that's been modified to run in a web environment using WebAssembly.

WebAssembly (often abbreviated as WASM) is a technology that lets you run code written in languages other than JavaScript (like Python, in this case) right in your web browser, at near-native speed.