Skip to content

Commit

Permalink
update the book for hackathon
Browse files Browse the repository at this point in the history
  • Loading branch information
nick1udwig committed Nov 15, 2024
1 parent a7387c9 commit 9d5ac5f
Show file tree
Hide file tree
Showing 46 changed files with 318 additions and 276 deletions.
6 changes: 3 additions & 3 deletions src/apis/frontend_development.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

Kinode can easily serve any webpage or web app developed with normal libraries and frameworks.

There are some specific endpoints, JS libraries, and process_lib functions that are helpful for doing frontend development.
There are some specific endpoints, JS libraries, and `process_lib` functions that are helpful for doing frontend development.

There are also some important considerations and "gotchas" that can happen when trying to do frontend development.

Kinode OS can serve a website or web app just like any HTTP webserver.
Kinode can serve a website or web app just like any HTTP webserver.
The preferred method is to upload your static assets on install by placing them in the `pkg` folder.
By convention, `kit` bundles these assets into a directory inside `pkg` called `ui`, but you can call it anything.
You **must** place your `index.html` in the top-level folder.
Expand Down Expand Up @@ -50,7 +50,7 @@ To make development easy, your setup should support a base URL and http proxying

### Base URL

All processes in Kinode OS are namespaced by process name in the standard format of `process:package:publisher`.
All processes on Kinode are namespaced by process name in the standard format of `process:package:publisher`.
So if your process is called `my-process:my-package:template.os`, then your process can only bind HTTP paths that start with `/my-process:my-package:template.os`.
Your UI should be developed and compiled with the base URL set to the appropriate process path.

Expand Down
2 changes: 1 addition & 1 deletion src/apis/http_authentication.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# HTTP API

In Kinode OS, incoming HTTP requests are handled by a Rust `warp` server in the core `http_server:distro:sys` process.
Incoming HTTP requests are handled by a Rust `warp` server in the core `http_server:distro:sys` process.
This process handles binding (registering) routes, simple JWT-based authentication, and serving a `/login` page if auth is missing.

## Binding (Registering) HTTP Paths
Expand Down
6 changes: 3 additions & 3 deletions src/apis/kinode_wit.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ WIT, or Wasm Interface Type, is a language for describing the types and function
In conjunction with the Component Model itself, WIT allows for the creation of WebAssembly modules that can be used as components in a larger system.
This standard has been under development for many years, and while still under construction, it's the perfect tool for building an operating-system-like environment for Wasm apps.

Kinode OS uses WIT to present a standard interface for Kinode processes.
Kinode uses WIT to present a standard interface for Kinode processes.
This interface is a set of types and functions that are available to all processes.
It also contains functions (well, just a single function: `init()`) that processes must implement in order to compile and run in Kinode OS.
It also contains functions (well, just a single function: `init()`) that processes must implement in order to compile and run on Kinode.
If one can generate WIT bindings in a language that compiles to Wasm, that language can be used to write Kinode processes.
So far, we've written Kinode processes in Rust, Javascript, Go, and Python.

To see exactly how to use WIT to write Kinode processes, see the [My First App](../my_first_app/chapter_1.md) chapter or the [Chess Tutorial](../chess_app/chess_engine.md).

To see `kinode.wit` for itself, see the [file in the GitHub repo](https://github.com/kinode-dao/kinode-wit/blob/master/kinode.wit).
Since this interface applies to all processes, it's one of the places in the OS where breaking changes are most likely to make an impact.
To that end, the version of the WIT file that a process uses must be compatible with the version of Kinode OS on which it runs.
To that end, the version of the WIT file that a process uses must be compatible with the version of Kinode on which it runs.
Kinode intends to achieve perfect backwards compatibility upon first major release (1.0.0) of the OS and the WIT file.
After that point, since processes signal the version of the WIT file they use, subsequent updates can be made without breaking existing processes or needing to change the version they use.

Expand Down
2 changes: 1 addition & 1 deletion src/apis/terminal.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ For documentation on using, writing, publishing, and composing scripts, see the
The Kinode terminal is broken up into two segments: a Wasm app, called `terminal:terminal:sys`, and a runtime module called `terminal:distro:sys`.
The Wasm app is the central area where terminal logic and authority live.
It parses `Requests` by attempting to read the `body` field as a UTF-8 string, then parsing that string into various commands to perform.
The runtime module exists in order to actually use this app from the terminal which is launched by starting Kinode OS.
The runtime module exists in order to actually use this app from the terminal which is launched by starting Kinode.
It manages the raw input and presents an interface with features such as command history, text manipulation, and shortcuts.

To "use" the terminal as an API, one simply needs the capability to message `terminal:terminal:sys`.
Expand Down
2 changes: 1 addition & 1 deletion src/apis/timer.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Timer API

The Timer API allows processes to manage time-based operations within Kinode OS.
The Timer API allows processes to manage time-based operations within Kinode.
This API provides a simple yet powerful mechanism for scheduling actions to be executed after a specified delay.
The entire API is just the `TimerAction`:

Expand Down
2 changes: 1 addition & 1 deletion src/apis/websocket.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# WebSocket API

In Kinode OS, WebSocket connects are made with a Rust `warp` server in the core `http_server:distro:sys` process.
WebSocket connections are made with a Rust `warp` server in the core `http_server:distro:sys` process.
Each connection is assigned a `channel_id` that can be bound to a given process using a `WsRegister` message.
The process receives the `channel_id` for pushing data into the WebSocket, and any subsequent messages from that client will be forwarded to the bound process.

Expand Down
Binary file added src/assets/register-confirm-wallet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/assets/register-connect-wallet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed src/assets/register-have-wallet.png
Binary file not shown.
Binary file modified src/assets/register-homepage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/register-metamask.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/register-mint.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed src/assets/register-need-wallet.png
Binary file not shown.
Binary file added src/assets/register-precommitting.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/assets/register-select-name.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed src/assets/register-set-password.png
Binary file not shown.
Binary file added src/assets/register-start.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed src/assets/register-wallet-prompt.png
Binary file not shown.
2 changes: 1 addition & 1 deletion src/chess_app/putting_everything_together.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ If you're interested in learning more about how to write Kinode processes, there
- Consider what another app might look like that uses the chess engine as a library.
Alter the process to serve this use case, or add another process that can be spawned to do such a thing.

There are also extensions to this tutorial which dive into specific use cases which make the most of Kinode OS:
There are also extensions to this tutorial which dive into specific use cases which make the most of Kinode:

- [Chat](./chat.md)
- [more coming soon](#)
Expand Down
50 changes: 25 additions & 25 deletions src/cookbook/file_transfer.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
# File Transfer

This recipe looks at the `file_transfer` package, a template included with `kit` and also copied [here](https://github.com/kinode-dao/kinode-book/tree/main/code/file-transfer).
This recipe looks at the `file-transfer` package, a template included with `kit` and also copied [here](https://github.com/kinode-dao/kinode-book/tree/main/code/file-transfer).
To create the template use
```
kit n file_transfer -t file_transfer
kit n file-transfer -t file-transfer
```

The `file_transfer` package shows off a few parts of Kinode userspace:
The `file-transfer` package shows off a few parts of Kinode userspace:
1. It makes use of the [VFS](../apis/vfs.md) to store files on disk.
2. It uses a manager-worker pattern (see conceptual discussion [here](../system/process/processes.md#awaiting-a-response) and [here](../system/process/processes.md#spawning-child-processes)) to enable multiple concurrent uploads/downloads without sacrificing code readability.
3. It exports its [WIT API](../system/process/wit_apis.md) so that other packages can easily build in file transfer functionality in a library-like manner, as demonstrated in [another recipe](./package_apis_workers.md).

## Protocol

The main `file_transfer` process is a thin wrapper over the `file_transfer_worker_api`.
The main `file-transfer` process is a thin wrapper over the `file-transfer-worker-api`.
The main process manages transfers and exposes a `ListFiles` Request variant that, when requested, returns the files that are available for download.

The `file_transfer_worker_api` makes calling the `file_transfer_worker` ergonomic.
The `file-transfer-worker-api` makes calling the `file-transfer-worker` ergonomic.
Specifically, it provides a function, `start_download()`, which spins up a worker to download a file from a given node.
When called on the node serving the file, it spins up a worker to upload the requested file to the requestor.

Downloading a file proceeds as follows:
1. Requestor [calls](https://github.com/kinode-dao/kinode-book/blob/main/code/file-transfer/file-transfer/src/lib.rs#L94) [`start_download()`](https://github.com/kinode-dao/kinode-book/blob/main/src/code/file-transfer/file-transfer-worker-api/src/lib.rs#L14-L55), which:
1. `spawn()`s a `file_transfer_worker`.
2. Passes `file_transfer_worker` a `Download` Request variant.
3. `file_transfer_worker` [forwards a modified `Download` Request variant to the `target`](https://github.com/kinode-dao/kinode-book/blob/main/src/code/file-transfer/file-transfer-worker/src/lib.rs#L70-L79).
1. `spawn()`s a `file-transfer-worker`.
2. Passes `file-transfer-worker` a `Download` Request variant.
3. `file-transfer-worker` [forwards a modified `Download` Request variant to the `target`](https://github.com/kinode-dao/kinode-book/blob/main/src/code/file-transfer/file-transfer-worker/src/lib.rs#L70-L79).
2. Provider receives `Download` Request variant, calls `start_download()`, which:
1. `spawn()`s a `file_transfer_worker`.
2. Passes `file_transfer_worker` the `Download` Request variant.
3. [Sends chunks of file to the requestor's `file_transfer_worker`](https://github.com/kinode-dao/kinode-book/blob/main/src/code/file-transfer/file-transfer-worker/src/lib.rs#L81-L110).
1. `spawn()`s a `file-transfer-worker`.
2. Passes `file-transfer-worker` the `Download` Request variant.
3. [Sends chunks of file to the requestor's `file-transfer-worker`](https://github.com/kinode-dao/kinode-book/blob/main/src/code/file-transfer/file-transfer-worker/src/lib.rs#L81-L110).

Thus, a worker is responsible for downloading/uploading a single file, and then exits.
All longer-term state and functionality is the responsibility of the main process, here, `file_transfer`.
All longer-term state and functionality is the responsibility of the main process, here, `file-transfer`.

Files are transferred from and to the `file_transfer:template.os/files` drive.
If you use the `file_transfer_worker` or `file_transfer_worker_api` in your own package, replace that first part of the path with your package's package id.
Files are transferred from and to the `file-transfer:template.os/files` drive.
If you use the `file-transfer-worker` or `file-transfer-worker-api` in your own package, replace that first part of the path with your package's package id.

## WIT API

Expand Down Expand Up @@ -69,28 +69,28 @@ If you use the `file_transfer_worker` or `file_transfer_worker_api` in your own
kit f
kit f -o /tmp/kinode-fake-node-2 -p 8081 -f fake2.dev
# Create & build file_transfer.
# Create & build file-transfer.
## The `-a` adds the worker Wasm file to the API so it can be exported properly.
kit n file_transfer -t file_transfer
kit b file_transfer -a file_transfer/pkg/file_transfer_worker.wasm
kit n file-transfer -t file-transfer
kit b file-transfer -a file-transfer/pkg/file-transfer-worker.wasm
# Start file_transfer on fake nodes.
kit s file_transfer
kit s file_transfer -p 8081
# Start file-transfer on fake nodes.
kit s file-transfer
kit s file-transfer -p 8081
```

### Usage

```
# First, put a file into `/tmp/kinode-fake-node-2/vfs/file_transfer:template.os/files/`, e.g.:
echo 'hello world' > /tmp/kinode-fake-node-2/vfs/file_transfer:template.os/files/my_file.txt
# First, put a file into `/tmp/kinode-fake-node-2/vfs/file-transfer:template.os/files/`, e.g.:
echo 'hello world' > /tmp/kinode-fake-node-2/vfs/file-transfer:template.os/files/my_file.txt
# In fake.dev terminal, check if file exists.
list_files:file_transfer:template.os fake2.dev
list-files:file-transfer:template.os fake2.dev
# In fake.dev terminal, download the file.
download:file_transfer:template.os my_file.txt fake2.dev
download:file-transfer:template.os my_file.txt fake2.dev
# Confirm file was downloaded:
cat /tmp/kinode-fake-node/vfs/file_transfer:template.os/files/my_file.txt
cat /tmp/kinode-fake-node/vfs/file-transfer:template.os/files/my_file.txt
```
3 changes: 3 additions & 0 deletions src/cookbook/file_transfer_ui.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Kino Files (File Transfer + UI)

**Warning: This document is known to be out-of-date as of November 14, 2024.
Proceed with caution.**

This entry will teach you to add a simple UI to the [file transfer app](./file_transfer.md), using [`kit`](../kit/kit-dev-toolkit.md)'s built-in UI template.

This guide assumes a basic understanding of Kinode process building, some familiarity with [`kit`](../kit/kit-dev-toolkit.md), requests and responses, and some knowledge of Rust syntax.
Expand Down
2 changes: 1 addition & 1 deletion src/cookbook/manage_child_processes.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Spawning and Managing Child Processes

In Kinode OS, a "parent" process can create additional processes, known as "children" (also discussed [here](../system/process/processes.md#spawning-child-processes)).
A "parent" process can create additional processes, known as "children" (also discussed [here](../system/process/processes.md#spawning-child-processes)).
These child processes are particularly useful for handling intensive tasks (referred to as "workers") that require long computation times without hindering the performance of the main application.
They are also beneficial for segregating distinct logical components.
Each process is its own subdirectory within the package.
Expand Down
82 changes: 26 additions & 56 deletions src/cookbook/publish_to_web.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,68 +18,38 @@ my-package

## Serving Static Assets

The simplest way to serve a UI is using the `serve_ui` function from `process_lib`:
The simplest way to serve a UI is using the [`http::HttpServer::serve_ui()`](https://docs.rs/kinode_process_lib/latest/kinode_process_lib/http/server/struct.HttpServer.html#method.serve_ui) method from `process_lib`:

```rs
serve_ui(&our, "ui", true, false, vec!["/"]).unwrap();
let mut server = http::server::HttpServer::new(5);
server
.serve_ui(
&our,
"ui",
vec!["/"],
http::server::HttpBindingConfig::new(true, false, false, None),
)
.unwrap();
```

This will serve the `index.html` in the specified folder at the home path of your process.
If your process is called `main:my-package:myusername.os` and your Kinode is running locally on port 8080,
then the UI will be served at `http://localhost:8080/main:my-package:myusername.os`.

`serve_ui` takes five arguments: the process' `&Address`, the name of the folder inside `pkg` that contains the `index.html` and other associated UI files, whether the UI requires authentication, whether the UI is local-only, and the path(s) on which to serve the UI (usually `["/"]`).
By convention, this is the `ui` directory inside of the `pkg` directory that will be uploaded when you install the process.
There must be an `index.html` in the `"ui"` directory (or whatever your top-level directory is called).

Under the hood, `serve_ui` uses `http_bind_static_path` which caches files in memory with `http_server` to respond to HTTP requests more quickly.
The signature for `http_bind_static_path` is below:

```rs
pub fn bind_http_static_path<T>(
path: T,
authenticated: bool,
local_only: bool,
content_type: Option<String>,
content: Vec<u8>,
) -> anyhow::Result<()>
```

If your process is called `main:my-package:myusername.os` and your Kinode is running locally on port 8080, then the UI will be served at `http://localhost:8080/main:my-package:myusername.os`.

`serve_ui` takes four arguments:
1. The process' `&Address`
2. The name of the folder inside `pkg` that contains the `index.html` and other associated UI files.
By convention, this is the `ui` directory inside of the `pkg` directory that will be uploaded when you install the process.
There must be an `index.html` in the `"ui"` directory (or whatever your top-level directory is called).
3. The path(s) on which to serve the UI (usually `["/"]`)
4. The configuration for the binding:
- Whether the UI requires authentication
- Whether the UI is local-only
- Whether the content is static (not relevant here)
- Whether to serve as a secure subdomain

Under the hood, `serve_ui` uses [`bind_http_static_path`](https://docs.rs/kinode_process_lib/latest/kinode_process_lib/http/server/struct.HttpServer.html#method.bind_http_static_path) which caches files in memory with `http_server` to respond to HTTP requests more quickly.
The two additional parameters are the `content_type` (an optional String) and the `content` (bytes).
The content will be served at the named route with the `Content-Type` header set appropriately.

Note that `serve_ui` caches all files in `http_server`, so if your website or web app has hundreds of MBs of asset files (like high-res images), then you will want to use a different method to serve content.
In this case, you would bind the `index.html` file to your main route, and then bind a given HTTP route to serve all of your assets like so:

```rs
serve_index_html(&our, "ui", true, false, vec!["/"]).unwrap();
bind_http_path("/assets/*", true, false).unwrap();
```

Then in your request handler, you can use `handle_ui_asset_request` to get the file whose path matches the HTTP route of the request:

```rs
let body = message.body();
if let Ok(http_request) = serde_json::from_slice::<HttpServerRequest>(body) {
match http_request {
HttpServerRequest::Http(IncomingHttpRequest { url, .. }) => {
if url.contains(&format!("/{}/assets/", our.process.to_string())) {
return handle_ui_asset_request(our, "ui", &url);
}
}
_ => {}
}
}
```

`handle_ui_asset_request` takes our (&Address), the top-level directory that contains the files, and the `url` of the incoming request.
In this case, the `/assets` directory must be in the `/ui` directory which must be uploaded from `pkg` when the process is installed.
So your project would look like this:

```
my-package
└── pkg
└── ui
├── assets
└── index.html
```
For example, see the [`docs:docs:nick.kino` application](https://github.com/nick1udwig/docs/blob/master/docs/src/lib.rs).
2 changes: 1 addition & 1 deletion src/cookbook/reading_data_from_eth.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,4 @@ There are a few important things to note when subscribing to contract events and

4. If a subscription fails, it makes sense to try resubscribing, but keep in mind that events might occur between the failure and the resubscribe. A good strategy is to fetch logs for this time period.

For a full example of an app that uses the ETH Provider in a critical use-case, check out the [kns_indexer](https://github.com/kinode-dao/kinode/blob/main/kinode/packages/kns_indexer/kns_indexer/src/lib.rs) in the Kinode OS repo.
For a full example of an app that uses the ETH Provider in a critical use-case, check out the [kns_indexer](https://github.com/kinode-dao/kinode/blob/main/kinode/packages/kns_indexer/kns_indexer/src/lib.rs) in the Kinode repo.
3 changes: 2 additions & 1 deletion src/cookbook/save_state.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ It can be retrieved later only by `get_state`, and only the original process tha
Processes frequently use this feature to maintain key state between restarts, which can happen at any time as a result of crashes, package updates, or node reboots.
It is considered good practice to save state any time the process mutates it.

**Keep in mind that every state set/get incurs an asynchronous disk read/write for the entire state object. If storing large amounts of data, consider using the [`vfs`, `sqlite`, and/or `kv` modules](../system/databases.md)!**
**Keep in mind that every state set/get incurs an asynchronous disk read/write for the entire state object.
If storing large amounts of data, consider using the [`vfs`, `sqlite`, and/or `kv` modules](../system/databases.md)!**

Here's an example of a process that saves and loads state:

Expand Down
Loading

0 comments on commit 9d5ac5f

Please sign in to comment.