Merge pull request #313 from kinode-dao/dr/settings-page

Add settings page app
This commit is contained in:
doria 2024-05-02 04:04:38 +09:00 committed by GitHub
commit 76d0adf795
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 1815 additions and 49 deletions

37
Cargo.lock generated
View File

@ -3081,6 +3081,28 @@ dependencies = [
"wit-bindgen", "wit-bindgen",
] ]
[[package]]
name = "kinode_process_lib"
version = "0.6.1"
source = "git+https://github.com/kinode-dao/process_lib?tag=v0.6.1#37a20b0249dc2c86ae6c2c69cfb199fb177f1520"
dependencies = [
"alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=6f8ebb4)",
"alloy-primitives 0.6.4",
"alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=6f8ebb4)",
"alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=6f8ebb4)",
"anyhow",
"bincode",
"http 1.1.0",
"mime_guess",
"rand 0.8.5",
"rmp-serde",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]] [[package]]
name = "kinode_process_lib" name = "kinode_process_lib"
version = "0.7.0" version = "0.7.0"
@ -4812,6 +4834,21 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "settings"
version = "0.1.0"
dependencies = [
"anyhow",
"base64 0.22.0",
"bincode",
"kinode_process_lib 0.6.1",
"rmp-serde",
"serde",
"serde_json",
"url",
"wit-bindgen",
]
[[package]] [[package]]
name = "sha1" name = "sha1"
version = "0.10.6" version = "0.10.6"

View File

@ -19,6 +19,7 @@ members = [
"kinode/packages/chess/chess", "kinode/packages/chess/chess",
"kinode/packages/homepage/homepage", "kinode/packages/homepage/homepage",
"kinode/packages/kns_indexer/kns_indexer", "kinode/packages/kns_indexer/get_block", "kinode/packages/kns_indexer/state", "kinode/packages/kns_indexer/kns_indexer", "kinode/packages/kns_indexer/get_block", "kinode/packages/kns_indexer/state",
"kinode/packages/settings/settings",
"kinode/packages/terminal/terminal", "kinode/packages/terminal/terminal",
"kinode/packages/terminal/alias", "kinode/packages/terminal/cat", "kinode/packages/terminal/echo", "kinode/packages/terminal/hi", "kinode/packages/terminal/m", "kinode/packages/terminal/top", "kinode/packages/terminal/alias", "kinode/packages/terminal/cat", "kinode/packages/terminal/echo", "kinode/packages/terminal/hi", "kinode/packages/terminal/m", "kinode/packages/terminal/top",
"kinode/packages/terminal/namehash_to_name", "kinode/packages/terminal/net_diagnostics", "kinode/packages/terminal/peer", "kinode/packages/terminal/peers", "kinode/packages/terminal/namehash_to_name", "kinode/packages/terminal/net_diagnostics", "kinode/packages/terminal/peer", "kinode/packages/terminal/peers",

View File

@ -5,10 +5,10 @@ use kinode_process_lib::{
bind_http_path, bind_http_static_path, send_response, serve_ui, HttpServerError, bind_http_path, bind_http_static_path, send_response, serve_ui, HttpServerError,
HttpServerRequest, StatusCode, HttpServerRequest, StatusCode,
}, },
println, Address, Message, ProcessId, println, Address, Message,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::BTreeMap;
/// The request format to add or remove an app from the homepage. You must have messaging /// The request format to add or remove an app from the homepage. You must have messaging
/// access to `homepage:homepage:sys` in order to perform this. Serialize using serde_json. /// access to `homepage:homepage:sys` in order to perform this. Serialize using serde_json.
@ -40,7 +40,7 @@ wit_bindgen::generate!({
call_init!(init); call_init!(init);
fn init(our: Address) { fn init(our: Address) {
let mut app_data: HashMap<ProcessId, HomepageApp> = HashMap::new(); let mut app_data: BTreeMap<ProcessId, HomepageApp> = BTreeMap::new();
serve_ui(&our, "ui", true, false, vec!["/"]).expect("failed to serve ui"); serve_ui(&our, "ui", true, false, vec!["/"]).expect("failed to serve ui");
@ -86,7 +86,7 @@ fn init(our: Address) {
match request { match request {
HomepageRequest::Add { label, icon, path } => { HomepageRequest::Add { label, icon, path } => {
app_data.insert( app_data.insert(
message.source().process.clone(), message.source().process.to_string(),
HomepageApp { HomepageApp {
package_name: message.source().clone().package().to_string(), package_name: message.source().clone().package().to_string(),
path: format!( path: format!(
@ -113,7 +113,7 @@ fn init(our: Address) {
if path == "/apps" { if path == "/apps" {
send_response( send_response(
StatusCode::OK, StatusCode::OK,
Some(HashMap::from([( Some(std::collections::HashMap::from([(
"Content-Type".to_string(), "Content-Type".to_string(),
"application/json".to_string(), "application/json".to_string(),
)])), )])),

View File

@ -0,0 +1,16 @@
{
"name": "System Settings",
"description": "A program for managing key system settings, including onchain identity.",
"image": "",
"properties": {
"package_name": "settings",
"current_version": "0.1.0",
"publisher": "sys",
"mirrors": [],
"code_hashes": {
"0.1.0": ""
}
},
"external_url": "https://kinode.org",
"animation_url": ""
}

View File

@ -0,0 +1,30 @@
[
{
"process_name": "settings",
"process_wasm_path": "/settings.wasm",
"on_exit": "Restart",
"request_networking": true,
"request_capabilities": [
"eth:distro:sys",
{
"process": "eth:distro:sys",
"params": {
"root": true
}
},
"homepage:homepage:sys",
"http_server:distro:sys",
"kernel:distro:sys",
"net:distro:sys",
"vfs:distro:sys"
],
"grant_capabilities": [
"eth:distro:sys",
"http_server:distro:sys",
"kernel:distro:sys",
"net:distro:sys",
"vfs:distro:sys"
],
"public": false
}
]

View File

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Kinode Settings</title>
<link rel="stylesheet" href="/settings:settings:sys/style.css">
</head>
<body>
<h1>system diagnostics & settings</h1>
<main>
<article id="node-info">
<p>node info</p>
<p id="node-name"></p>
<p id="net-key"></p>
<p id="ip-ports"></p>
<p id="routers"></p>
<button>reset networking key</button>
<button>adjust networking info</button>
<button id="shutdown">shut down node</button>
</article>
<article id="net-diagnostics">
<p>networking diagnostics</p>
<p id="diagnostics"></p>
</article>
<article id="pings">
<p>fetch PKI data</p>
<form id="get-peer-pki">
<input type="text" name="peer" placeholder="peer-name.os">
<button type="submit">get peer info</button>
</form>
<p id="peer-pki-response"></p>
<p>ping a node</p>
<form id="ping-peer">
<input type="text" name="peer" placeholder="peer-name.os">
<input type="text" name="content" placeholder="message">
<label><input type="number" name="timeout">timeout (seconds)</label>
<button type="submit">ping</button>
</form>
<p id="peer-ping-response"></p>
</article>
<article id="eth-rpc-providers">
<p>ETH RPC providers</p>
<ul id="providers"></ul>
</article>
<article id="eth-rpc-settings">
<p>ETH RPC settings</p>
<p id="public"></p>
<div>
<p>nodes allowed to connect:</p>
<ul id="allowed-nodes"></ul>
</div>
<div>
<p>nodes banned from connecting:</p>
<ul id="denied-nodes"></ul>
</div>
</article>
<article id="kernel">
<p>running processes:</p>
<p>(TODO)</p>
<ul></ul>
</article>
<script src="/settings:settings:sys/script.js"></script>
</main>
</body>
</html>

View File

@ -0,0 +1,167 @@
const APP_PATH = '/settings:settings:sys/ask';
// Fetch initial data and populate the UI
function init() {
fetch('/our')
.then(response => response.text())
.then(data => {
const our = data + '@settings:settings:sys';
fetch(APP_PATH)
.then(response => response.json())
.then(data => {
console.log(data);
populate(data);
});
});
}
function api_call(body) {
fetch(APP_PATH, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
}
function shutdown() {
api_call("Shutdown");
}
function populate(data) {
populate_node_info(data.identity);
populate_net_diagnostics(data.diagnostics);
populate_eth_rpc_providers(data.eth_rpc_providers);
populate_eth_rpc_settings(data.eth_rpc_access_settings);
// populate_kernel()
}
function populate_node_info(identity) {
document.getElementById('node-name').innerText = identity.name;
document.getElementById('net-key').innerText = identity.networking_key;
if (identity.ws_routing) {
document.getElementById('ip-ports').innerText = identity.ws_routing;
} else {
document.getElementById('ip-ports').style.display = 'none';
}
if (identity.routers) {
document.getElementById('routers').innerText = identity.routers;
} else {
document.getElementById('routers').style.display = 'none';
}
}
function populate_net_diagnostics(diagnostics) {
document.getElementById('diagnostics').innerText = diagnostics;
}
function populate_eth_rpc_providers(providers) {
const ul = document.getElementById('providers');
ul.innerHTML = '';
providers.forEach(provider => {
const li = document.createElement('li');
li.innerHTML = `<li>${JSON.stringify(provider)}</li>`;
ul.appendChild(li);
});
}
function populate_eth_rpc_settings(settings) {
if (settings.public) {
document.getElementById('public').innerText = 'public';
document.getElementById('allowed-nodes').style.display = 'none';
} else {
document.getElementById('public').innerText = 'private';
const ul = document.getElementById('allowed-nodes');
ul.innerHTML = '';
if (settings.allow.length === 0) {
const li = document.createElement('li');
li.innerHTML = `<li>(none)</li>`;
ul.appendChild(li);
} else {
settings.allow.forEach(allowed_node => {
const li = document.createElement('li');
li.innerHTML = `<li>${allowed_node}</li>`;
ul.appendChild(li);
});
}
}
const ul = document.getElementById('denied-nodes');
ul.innerHTML = '';
if (settings.deny.length === 0) {
const li = document.createElement('li');
li.innerHTML = `<li>(none)</li>`;
ul.appendChild(li);
} else {
settings.deny.forEach(denied_node => {
const li = document.createElement('li');
li.innerHTML = `<li>${denied_node}</li>`;
ul.appendChild(li);
});
}
}
// Call init to start the application
init();
// Setup event listeners
document.getElementById('shutdown').addEventListener('click', shutdown);
document.getElementById('get-peer-pki').addEventListener('submit', (e) => {
e.preventDefault();
const data = new FormData(e.target);
const body = {
"PeerId": data.get('peer'),
};
fetch(APP_PATH, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
}).then(response => response.json())
.then(data => {
if (data === null) {
document.getElementById('peer-pki-response').innerText = "no pki data for peer";
} else {
document.getElementById('peer-pki-response').innerText = JSON.stringify(data);
}
});
})
document.getElementById('ping-peer').addEventListener('submit', (e) => {
e.preventDefault();
const data = new FormData(e.target);
const body = {
"Hi": {
node: data.get('peer'),
content: data.get('content'),
timeout: Number(data.get('timeout')),
}
};
fetch(APP_PATH, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
}).then(response => response.json())
.then(data => {
if (data === null) {
document.getElementById('peer-ping-response').innerText = "ping successful!";
} else if (data === "HiTimeout") {
document.getElementById('peer-ping-response').innerText = "node timed out";
} else if (data === "HiOffline") {
document.getElementById('peer-ping-response').innerText = "node is offline";
}
});
})
// Setup WebSocket connection
const ws = new WebSocket("ws://" + location.host + "/settings:settings:sys/");
ws.onmessage = event => {
const data = JSON.parse(event.data);
console.log(data);
populate(data);
};

View File

@ -0,0 +1,181 @@
/* CSS Reset from https://www.joshwcomeau.com/css/custom-css-reset/ */
/*
1. Use a more-intuitive box-sizing model.
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
/*
2. Remove default margin
*/
* {
margin: 0;
}
/*
Typographic tweaks!
3. Add accessible line-height
4. Improve text rendering
*/
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
/*
5. Improve media defaults
*/
img,
picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
}
/*
6. Remove built-in form typography styles
*/
input,
button,
textarea,
select {
font: inherit;
}
/*
7. Avoid text overflows
*/
p,
h1,
h2,
h3,
h4,
h5,
h6 {
overflow-wrap: break-word;
}
/*
8. Create a root stacking context
*/
#root,
#__next {
isolation: isolate;
}
/* Actual styles */
body {
font-family: 'Courier New', Courier, monospace;
background-color: #1a1a1a;
color: #f0f0f0;
}
h1 {
padding: 20px;
}
main {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
padding: 20px;
max-width: 1200px;
min-width: 300px;
}
article {
background-color: #333;
border: 1px solid #444;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
max-height: 600px;
overflow-y: auto;
}
/* Custom scrollbar styles */
article::-webkit-scrollbar {
width: 8px;
}
article::-webkit-scrollbar-track {
background: #2c2c2c;
}
article::-webkit-scrollbar-thumb {
background-color: #444;
border-radius: 4px;
}
button {
background-color: #4CAF50;
color: white;
border: none;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
transition-duration: 0.4s;
cursor: pointer;
border-radius: 4px;
}
button:hover {
background-color: white;
color: #4CAF50;
}
input[type="text"],
input[type="number"],
select,
textarea {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
input[type="submit"] {
background-color: #f44336;
color: white;
border: none;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
transition-duration: 0.4s;
cursor: pointer;
border-radius: 4px;
}
input[type="submit"]:hover {
background-color: white;
color: #f44336;
}
ul {
list-style-type: none;
padding: 0;
}
li {
padding: 8px;
margin-bottom: 6px;
background-color: #2c2c2c;
border-radius: 4px;
word-wrap: break-word;
}

View File

@ -0,0 +1,835 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
[[package]]
name = "autocfg"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78"
dependencies = [
"autocfg 1.1.0",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "bincode"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
dependencies = [
"serde",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "bytes"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chess"
version = "0.2.0"
dependencies = [
"anyhow",
"base64",
"bincode",
"kinode_process_lib",
"pleco",
"serde",
"serde_json",
"url",
"wit-bindgen",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]]
name = "either"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "form_urlencoded"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
dependencies = [
"percent-encoding",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "getrandom"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f"
[[package]]
name = "http"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "id-arena"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
[[package]]
name = "idna"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b"
dependencies = [
"equivalent",
"hashbrown",
"serde",
]
[[package]]
name = "itoa"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "kinode_process_lib"
<<<<<<< HEAD:modules/chess/chess/Cargo.lock
version = "0.5.7"
source = "git+https://github.com/kinode-dao/process_lib?tag=v0.5.9-alpha#c1ac7227951fbd8cabf6568704f0ce11e8558c8a"
=======
version = "0.5.6"
source = "git+https://github.com/kinode-dao/process_lib?rev=fccb6a0#fccb6a0c07ebda3e385bff7f76e4984b741f01c7"
>>>>>>> develop:kinode/packages/chess/chess/Cargo.lock
dependencies = [
"anyhow",
"bincode",
"http",
"mime_guess",
"rand 0.8.5",
"serde",
"serde_json",
"thiserror",
"url",
"wit-bindgen",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "leb128"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]]
name = "libc"
version = "0.2.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
[[package]]
name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mime_guess"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "mucow"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c55d0c9dc43dedfd2414deb74ade67687749ef88b1d3482024d4c81d901a7a83"
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pleco"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28a8c8ab569c544644c468a63f4fe4b33c0706b1472bebb517fabb75ec0f688e"
dependencies = [
"bitflags 1.3.2",
"lazy_static",
"mucow",
"num_cpus",
"rand 0.6.5",
"rayon",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.8",
"libc",
"rand_chacha 0.1.1",
"rand_core 0.4.2",
"rand_hc",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg",
"rand_xorshift",
"winapi",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.3.1",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.4",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg 0.1.8",
"rand_core 0.4.2",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rayon"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "ryu"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "semver"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
[[package]]
name = "serde"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.113"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "smallvec"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
[[package]]
name = "spdx"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bde1398b09b9f93fc2fc9b9da86e362693e999d3a54a8ac47a99a5a73f638b"
dependencies = [
"smallvec",
]
[[package]]
name = "syn"
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "unicase"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"version_check",
]
[[package]]
name = "unicode-bidi"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "url"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
]
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-encoder"
version = "0.38.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ad2b51884de9c7f4fe2fd1043fccb8dcad4b1e29558146ee57a144d15779f3f"
dependencies = [
"leb128",
]
[[package]]
name = "wasm-encoder"
version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e09bca7d6388637d27fb5edbeab11f56bfabcef8743c55ae34370e1e5030a071"
dependencies = [
"leb128",
]
[[package]]
name = "wasm-metadata"
version = "0.10.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c853d3809fc9fccf3bc0ad63f4f51d8eefad0bacf88f957aa991c1d9b88b016e"
dependencies = [
"anyhow",
"indexmap",
"serde",
"serde_derive",
"serde_json",
"spdx",
"wasm-encoder 0.41.0",
"wasmparser 0.121.0",
]
[[package]]
name = "wasmparser"
version = "0.118.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ee9723b928e735d53000dec9eae7b07a60e490c85ab54abb66659fc61bfcd9"
dependencies = [
"indexmap",
"semver",
]
[[package]]
name = "wasmparser"
version = "0.121.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953cf6a7606ab31382cb1caa5ae403e77ba70c7f8e12eeda167e7040d42bfda8"
dependencies = [
"bitflags 2.4.2",
"indexmap",
"semver",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "wit-bindgen"
version = "0.16.0"
source = "git+https://github.com/bytecodealliance/wit-bindgen?rev=efcc759#efcc7592cf3277bcb9be1034e48569c6d822b322"
dependencies = [
"bitflags 2.4.2",
"wit-bindgen-rust-macro",
]
[[package]]
name = "wit-bindgen-core"
version = "0.16.0"
source = "git+https://github.com/bytecodealliance/wit-bindgen?rev=efcc759#efcc7592cf3277bcb9be1034e48569c6d822b322"
dependencies = [
"anyhow",
"wit-component",
"wit-parser",
]
[[package]]
name = "wit-bindgen-rust"
version = "0.16.0"
source = "git+https://github.com/bytecodealliance/wit-bindgen?rev=efcc759#efcc7592cf3277bcb9be1034e48569c6d822b322"
dependencies = [
"anyhow",
"heck",
"wasm-metadata",
"wit-bindgen-core",
"wit-component",
]
[[package]]
name = "wit-bindgen-rust-macro"
version = "0.16.0"
source = "git+https://github.com/bytecodealliance/wit-bindgen?rev=efcc759#efcc7592cf3277bcb9be1034e48569c6d822b322"
dependencies = [
"anyhow",
"proc-macro2",
"quote",
"syn",
"wit-bindgen-core",
"wit-bindgen-rust",
"wit-component",
]
[[package]]
name = "wit-component"
version = "0.18.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b8a35a2a9992898c9d27f1664001860595a4bc99d32dd3599d547412e17d7e2"
dependencies = [
"anyhow",
"bitflags 2.4.2",
"indexmap",
"log",
"serde",
"serde_derive",
"serde_json",
"wasm-encoder 0.38.1",
"wasm-metadata",
"wasmparser 0.118.1",
"wit-parser",
]
[[package]]
name = "wit-parser"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df4913a2219096373fd6512adead1fb77ecdaa59d7fc517972a7d30b12f625be"
dependencies = [
"anyhow",
"id-arena",
"indexmap",
"log",
"semver",
"serde",
"serde_derive",
"serde_json",
"unicode-xid",
]

View File

@ -0,0 +1,24 @@
[package]
name = "settings"
version = "0.1.0"
edition = "2021"
[features]
simulation-mode = []
[dependencies]
anyhow = "1.0"
base64 = "0.22.0"
bincode = "1.3.3"
kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", tag = "v0.6.1" }
rmp-serde = "1.2.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
url = "*"
wit-bindgen = "0.24.0"
[lib]
crate-type = ["cdylib"]
[package.metadata.component]
package = "kinode:process"

View File

@ -0,0 +1 @@
data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIiA/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHZlcnNpb249IjEuMSIgd2lkdGg9IjEwODAiIGhlaWdodD0iMTA4MCIgdmlld0JveD0iMCAwIDEwODAgMTA4MCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxkZXNjPkNyZWF0ZWQgd2l0aCBGYWJyaWMuanMgNS4yLjQ8L2Rlc2M+CjxkZWZzPgo8L2RlZnM+CjxnIHRyYW5zZm9ybT0ibWF0cml4KDEgMCAwIDEgNTQwIDU0MCkiIGlkPSI0MDhjZjk5Ni0xN2M1LTQxOTctYmVhMy1jNTQwZGJhYTlhZGUiICA+CjxyZWN0IHN0eWxlPSJzdHJva2U6IG5vbmU7IHN0cm9rZS13aWR0aDogMTsgc3Ryb2tlLWRhc2hhcnJheTogbm9uZTsgc3Ryb2tlLWxpbmVjYXA6IGJ1dHQ7IHN0cm9rZS1kYXNob2Zmc2V0OiAwOyBzdHJva2UtbGluZWpvaW46IG1pdGVyOyBzdHJva2UtbWl0ZXJsaW1pdDogNDsgZmlsbDogcmdiKDI1NSwyNTUsMjU1KTsgZmlsbC1ydWxlOiBub256ZXJvOyBvcGFjaXR5OiAxOyB2aXNpYmlsaXR5OiBoaWRkZW47IiB2ZWN0b3ItZWZmZWN0PSJub24tc2NhbGluZy1zdHJva2UiICB4PSItNTQwIiB5PSItNTQwIiByeD0iMCIgcnk9IjAiIHdpZHRoPSIxMDgwIiBoZWlnaHQ9IjEwODAiIC8+CjwvZz4KPGcgdHJhbnNmb3JtPSJtYXRyaXgoMSAwIDAgMSA1NDAgNTQwKSIgaWQ9ImM1MzhkOTdkLWFhNjAtNGRmNi05NzM1LTE4N2FlOGU3ODQwYyIgID4KPC9nPgo8ZyB0cmFuc2Zvcm09Im1hdHJpeChOYU4gTmFOIE5hTiBOYU4gMCAwKSIgID4KPGcgc3R5bGU9IiIgICA+CjwvZz4KPC9nPgo8ZyB0cmFuc2Zvcm09Im1hdHJpeCgyLjExIDAgMCAyLjExIDU0MCA1NDApIiAgPgo8cGF0aCBzdHlsZT0ic3Ryb2tlOiByZ2IoMCwwLDApOyBzdHJva2Utd2lkdGg6IDA7IHN0cm9rZS1kYXNoYXJyYXk6IG5vbmU7IHN0cm9rZS1saW5lY2FwOiBidXR0OyBzdHJva2UtZGFzaG9mZnNldDogMDsgc3Ryb2tlLWxpbmVqb2luOiBtaXRlcjsgc3Ryb2tlLW1pdGVybGltaXQ6IDQ7IGZpbGw6IHJnYigwLDAsMCk7IGZpbGwtcnVsZTogbm9uemVybzsgb3BhY2l0eTogMTsiICB0cmFuc2Zvcm09IiB0cmFuc2xhdGUoLTI1NiwgLTI1NikiIGQ9Ik0gNDEzLjk2NyAyNzYuOCBDIDQxNS4wMjcgMjcwLjU2NSA0MTUuMDI3IDI2My4yODIwMDAwMDAwMDAwNCA0MTUuMDI3IDI1NiBDIDQxNS4wMjcgMjQ4LjcxNzk5OTk5OTk5OTk2IDQxMy45NjcgMjQyLjQ4MiA0MTMuOTY3IDIzNS4yIEwgNDU4LjYzNCAyMDAuODgyIEMgNDYyLjg5NCAxOTcuNzY0IDQ2My45NTMwMDAwMDAwMDAwMyAxOTIuNTY1IDQ2MC43NjQgMTg3LjM2NCBMIDQxOC4yMTUgMTE1LjYgQyA0MTYuMDg1OTk5OTk5OTk5OTYgMTExLjQzNTk5OTk5OTk5OTk5IDQwOS43MDc5OTk5OTk5OTk5NyAxMDkuMzY1IDQwNS40NDggMTExLjQzNTk5OTk5OTk5OTk5IEwgMzUyLjI2MiAxMzIuMjM3IEMgMzQxLjYyNCAxMjMuOTE5IDMyOC44NjggMTE2LjYzNiAzMTYuMTAyIDExMS40MzU5OTk5OTk5OTk5OSBMIDMwOC42NTQgNTYuMzE4OTk5OTk5OTk5OTk2IEMgMzA3LjU5NCA1Mi4xNjQ5OTk5OTk5OTk5OSAzMDMuMzM1IDQ4LjAwMSAyOTguMDE2IDQ4LjAwMSBMIDIxMi45MTggNDguMDAxIEMgMjA3LjYgNDguMDAxIDIwMy4zNDEgNTIuMTY1IDIwMi4yODEgNTYuMzE4OTk5OTk5OTk5OTk2IEwgMTkzLjc3MyAxMTEuNDM1OTk5OTk5OTk5OTkgQyAxODEuMDA2IDExNi42MzYgMTY5LjMwOSAxMjMuOTE3OTk5OTk5OTk5OTkgMTU3LjYwMiAxMzIuMjM3IEwgMTA0LjQxNiAxMTEuNDM1OTk5OTk5OTk5OTkgQyA5OS4wOTcgMTA5LjM2NSA5My43Nzc5OTk5OTk5OTk5OSAxMTEuNDM1OTk5OTk5OTk5OTkgOTEuNjQ5IDExNS42IEwgNDkuMSAxODcuMzY1IEMgNDYuOTgxIDE5MS41MTggNDguMDM5IDE5Ny43NjQgNTEuMjI5IDIwMC44ODMgTCA5Ni45NyAyMzUuMiBDIDk2Ljk3IDI0Mi40ODIgOTUuOTEgMjQ4LjcxOCA5NS45MSAyNTYgQyA5NS45MSAyNjMuMjgyMDAwMDAwMDAwMDQgOTYuOTcgMjY5LjUxODAwMDAwMDAwMDAzIDk2Ljk3IDI3Ni44IEwgNTIuMzAyIDMxMS4xMTggQyA0OC4wNDIgMzE0LjIzNiA0Ni45ODQgMzE5LjQzNSA1MC4xNzIgMzI0LjYzNTk5OTk5OTk5OTk3IEwgOTIuNzIxIDM5Ni40IEMgOTQuODUxIDQwMC41NjM5OTk5OTk5OTk5NiAxMDEuMjI5IDQwMi42MzUgMTA1LjQ4OCA0MDAuNTYzOTk5OTk5OTk5OTYgTCAxNTguNjc1IDM3OS43NjMgQyAxNjkuMzEyIDM4OC4wODA5OTk5OTk5OTk5NiAxODIuMDY5MDAwMDAwMDAwMDIgMzk1LjM2NCAxOTQuODM1IDQwMC41NjM5OTk5OTk5OTk5NiBMIDIwMy4zNDMwMDAwMDAwMDAwMiA0NTUuNjgxIEMgMjA0LjQxMiA0NjAuODgxIDIwOC42NjEwMDAwMDAwMDAwMyA0NjMuOTk4OTk5OTk5OTk5OTcgMjEzLjk4MDAwMDAwMDAwMDAyIDQ2My45OTg5OTk5OTk5OTk5NyBMIDI5OS4wNzgwMDAwMDAwMDAwMyA0NjMuOTk4OTk5OTk5OTk5OTcgQyAzMDQuMzk3MDAwMDAwMDAwMDUgNDYzLjk5ODk5OTk5OTk5OTk3IDMwOC42NTYgNDU5LjgzNSAzMDkuNzE2IDQ1NS42ODEgTCAzMTguMjM0MDAwMDAwMDAwMDQgNDAwLjU2Mzk5OTk5OTk5OTk2IEMgMzMwLjk5MTAwMDAwMDAwMDA0IDM5NS4zNjQgMzQyLjY5ODAwMDAwMDAwMDA0IDM4OC4wODIgMzU0LjM5NCAzNzkuNzYzIEwgNDA3LjU4MSA0MDAuNTYzOTk5OTk5OTk5OTYgQyA0MTIuODk5IDQwMi42MzUgNDE4LjIxOCA0MDAuNTYzOTk5OTk5OTk5OTYgNDIwLjM0OCAzOTYuNCBMIDQ2Mi44OTcgMzI0LjYzNSBDIDQ2NS4wMjYgMzIwLjQ4MTk5OTk5OTk5OTk3IDQ2My45NTcgMzE0LjIzNiA0NjAuNzY3IDMxMS4xMTY5OTk5OTk5OTk5NiBMIDQxMy45NjcgMjc2Ljc5OTk5OTk5OTk5OTk1IHogTSAyNTUuNDY4IDMyOC44IEMgMjEzLjk3ODk5OTk5OTk5OTk4IDMyOC44IDE4MS4wMDc5OTk5OTk5OTk5OCAyOTYuNTY1IDE4MS4wMDc5OTk5OTk5OTk5OCAyNTYgQyAxODEuMDA3OTk5OTk5OTk5OTggMjE1LjQzNSAyMTMuOTc4OTk5OTk5OTk5OTggMTgzLjIgMjU1LjQ2Nzk5OTk5OTk5OTk2IDE4My4yIEMgMjk2Ljk1Njk5OTk5OTk5OTk0IDE4My4yIDMyOS45MjkgMjE1LjQzNSAzMjkuOTI5IDI1NiBDIDMyOS45MjkgMjk2LjU2NSAyOTYuOTU3IDMyOC44IDI1NS40Njc5OTk5OTk5OTk5NiAzMjguOCB6IiBzdHJva2UtbGluZWNhcD0icm91bmQiIC8+CjwvZz4KPC9zdmc+

View File

@ -0,0 +1,389 @@
use kinode_process_lib::{println, *};
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
extern crate base64;
const ICON: &str = include_str!("icon");
#[derive(Debug, Serialize, Deserialize)]
enum SettingsRequest {
Hi {
node: NodeId,
content: String,
timeout: u64,
},
PeerId(NodeId),
EthConfig(eth::EthConfigAction),
Shutdown,
KillProcess(ProcessId),
}
type SettingsResponse = Result<Option<SettingsData>, SettingsError>;
#[derive(Debug, Serialize, Deserialize)]
enum SettingsData {
PeerId(net::Identity),
}
#[derive(Debug, Serialize, Deserialize)]
enum SettingsError {
HiTimeout,
HiOffline,
KernelNonresponsive,
MalformedRequest,
StateFetchFailed,
}
/// never gets persisted
#[derive(Debug, Serialize, Deserialize)]
struct SettingsState {
pub our: Address,
pub ws_clients: HashSet<u32>,
pub identity: Option<net::Identity>,
pub diagnostics: Option<String>,
pub eth_rpc_providers: Option<eth::SavedConfigs>,
pub eth_rpc_access_settings: Option<eth::AccessSettings>,
}
impl SettingsState {
fn new(our: Address) -> Self {
Self {
our,
ws_clients: HashSet::new(),
identity: None,
diagnostics: None,
eth_rpc_providers: None,
eth_rpc_access_settings: None,
}
}
fn ws_update(&self) {
for channel in &self.ws_clients {
http::send_ws_push(
*channel,
http::WsMessageType::Text,
LazyLoadBlob {
mime: Some("application/json".to_string()),
bytes: serde_json::to_vec(self).unwrap(),
},
);
}
}
/// get data that the settings page presents to user
/// - get Identity struct from net:distro:sys
/// - get ETH RPC providers from eth:distro:sys
/// - get ETH RPC access settings from eth:distro:sys
/// - get running processes from kernel:distro:sys
fn fetch(&mut self) -> anyhow::Result<()> {
// identity
let Ok(Ok(Message::Response { body, .. })) = Request::to(("our", "net", "distro", "sys"))
.body(rmp_serde::to_vec(&net::NetAction::GetPeer(self.our.node.clone())).unwrap())
.send_and_await_response(5)
else {
return Err(anyhow::anyhow!("failed to get identity from net"));
};
let Ok(net::NetResponse::Peer(Some(identity))) = rmp_serde::from_slice(&body) else {
return Err(anyhow::anyhow!("got malformed response from net"));
};
self.identity = Some(identity);
// diagnostics string
let Ok(Ok(Message::Response { body, .. })) = Request::to(("our", "net", "distro", "sys"))
.body(rmp_serde::to_vec(&net::NetAction::GetDiagnostics).unwrap())
.send_and_await_response(5)
else {
return Err(anyhow::anyhow!("failed to get diagnostics from net"));
};
let Ok(net::NetResponse::Diagnostics(diagnostics_string)) = rmp_serde::from_slice(&body)
else {
return Err(anyhow::anyhow!("got malformed response from net"));
};
self.diagnostics = Some(diagnostics_string);
// eth rpc providers
let Ok(Ok(Message::Response { body, .. })) = Request::to(("our", "eth", "distro", "sys"))
.body(serde_json::to_vec(&eth::EthConfigAction::GetProviders).unwrap())
.send_and_await_response(5)
else {
return Err(anyhow::anyhow!("failed to get providers from eth"));
};
let Ok(eth::EthConfigResponse::Providers(providers)) = serde_json::from_slice(&body) else {
return Err(anyhow::anyhow!("got malformed response from eth"));
};
self.eth_rpc_providers = Some(providers);
// eth rpc access settings
let Ok(Ok(Message::Response { body, .. })) = Request::to(("our", "eth", "distro", "sys"))
.body(serde_json::to_vec(&eth::EthConfigAction::GetAccessSettings).unwrap())
.send_and_await_response(5)
else {
return Err(anyhow::anyhow!("failed to get access settings from eth"));
};
let Ok(eth::EthConfigResponse::AccessSettings(access_settings)) =
serde_json::from_slice(&body)
else {
return Err(anyhow::anyhow!("got malformed response from eth"));
};
self.eth_rpc_access_settings = Some(access_settings);
// TODO: running processes
Ok(())
}
}
wit_bindgen::generate!({
path: "wit",
world: "process",
});
call_init!(initialize);
fn initialize(our: Address) {
// add ourselves to the homepage
Request::to(("our", "homepage", "homepage", "sys"))
.body(
serde_json::json!({
"Add": {
"label": "Settings",
"icon": ICON,
"path": "/", // just our root
}
})
.to_string()
.as_bytes()
.to_vec(),
)
.send()
.unwrap();
// Serve the index.html and other UI files found in pkg/ui at the root path.
http::serve_ui(&our, "ui", true, false, vec!["/"]).unwrap();
http::bind_http_path("/ask", true, false).unwrap();
http::bind_ws_path("/", true, false).unwrap();
// Grab our state, then enter the main event loop.
let mut state: SettingsState = SettingsState::new(our);
match state.fetch() {
Ok(()) => {}
Err(e) => {
println!("failed to fetch initial state: {e}");
}
}
main_loop(&mut state);
}
fn main_loop(state: &mut SettingsState) {
loop {
match await_message() {
Err(send_error) => {
println!("got send error: {send_error:?}");
continue;
}
Ok(Message::Request {
source,
body,
expects_response,
..
}) => {
if source.node() != state.our.node {
continue; // ignore messages from other nodes
}
let response = handle_request(&source, &body, state);
if expects_response.is_some() {
Response::new()
.body(serde_json::to_vec(&response).unwrap())
.send()
.unwrap();
}
}
_ => continue, // ignore responses
}
}
}
fn handle_request(source: &Address, body: &[u8], state: &mut SettingsState) -> SettingsResponse {
// source node is ALWAYS ourselves since networking is disabled
if source.process == "http_server:distro:sys" {
// receive HTTP requests and websocket connection messages from our server
match serde_json::from_slice::<http::HttpServerRequest>(body)
.map_err(|_| SettingsError::MalformedRequest)?
{
http::HttpServerRequest::Http(ref incoming) => {
match handle_http_request(state, incoming) {
Ok(()) => Ok(None),
Err(e) => {
println!("error handling HTTP request: {e}");
http::send_response(
http::StatusCode::INTERNAL_SERVER_ERROR,
None,
"Service Unavailable".to_string().as_bytes().to_vec(),
);
Ok(None)
}
}
}
http::HttpServerRequest::WebSocketOpen { channel_id, .. } => {
state.ws_clients.insert(channel_id);
Ok(None)
}
http::HttpServerRequest::WebSocketClose(channel_id) => {
// client frontend closed a websocket
state.ws_clients.remove(&channel_id);
Ok(None)
}
http::HttpServerRequest::WebSocketPush { .. } => {
// client frontend sent a websocket message
// we don't expect this! we only use websockets to push updates
Ok(None)
}
}
} else {
let settings_request = serde_json::from_slice::<SettingsRequest>(body)
.map_err(|_| SettingsError::MalformedRequest)?;
handle_settings_request(state, settings_request)
}
}
/// Handle HTTP requests from our own frontend.
fn handle_http_request(
state: &mut SettingsState,
http_request: &http::IncomingHttpRequest,
) -> anyhow::Result<()> {
match http_request.method()?.as_str() {
"GET" => Ok(http::send_response(
http::StatusCode::OK,
Some(HashMap::from([(
String::from("Content-Type"),
String::from("application/json"),
)])),
serde_json::to_vec(&state)?,
)),
"POST" => {
let Some(blob) = get_blob() else {
return Ok(http::send_response(
http::StatusCode::BAD_REQUEST,
None,
vec![],
));
};
let request = serde_json::from_slice::<SettingsRequest>(&blob.bytes)?;
let response = handle_settings_request(state, request);
state.ws_update();
Ok(http::send_response(
http::StatusCode::OK,
None,
match response {
Ok(Some(data)) => serde_json::to_vec(&data)?,
Ok(None) => "null".as_bytes().to_vec(),
Err(e) => serde_json::to_vec(&e)?,
},
))
}
// Any other method will be rejected.
_ => Ok(http::send_response(
http::StatusCode::METHOD_NOT_ALLOWED,
None,
vec![],
)),
}
}
fn handle_settings_request(
state: &mut SettingsState,
request: SettingsRequest,
) -> SettingsResponse {
match request {
SettingsRequest::Hi {
node,
content,
timeout,
} => {
if let Err(SendError { kind, .. }) = Request::to((&node, "net", "distro", "sys"))
.body(content.into_bytes())
.send_and_await_response(timeout)
.unwrap()
{
match kind {
SendErrorKind::Timeout => {
println!("message to {node} timed out");
return Err(SettingsError::HiTimeout);
}
SendErrorKind::Offline => {
println!("{node} is offline or does not exist");
return Err(SettingsError::HiOffline);
}
}
} else {
return Ok(None);
}
}
SettingsRequest::PeerId(node) => {
// get peer info
match Request::to(("our", "net", "distro", "sys"))
.body(rmp_serde::to_vec(&net::NetAction::GetPeer(node)).unwrap())
.send_and_await_response(30)
.unwrap()
{
Ok(msg) => match rmp_serde::from_slice::<net::NetResponse>(msg.body()) {
Ok(net::NetResponse::Peer(Some(peer))) => {
println!("got peer info: {peer:?}");
return Ok(Some(SettingsData::PeerId(peer)));
}
Ok(net::NetResponse::Peer(None)) => {
println!("peer not found");
return Ok(None);
}
_ => {
return Err(SettingsError::KernelNonresponsive);
}
},
Err(_) => {
return Err(SettingsError::KernelNonresponsive);
}
}
}
SettingsRequest::EthConfig(action) => {
match Request::to(("our", "eth", "distro", "sys"))
.body(serde_json::to_vec(&action).unwrap())
.send_and_await_response(30)
.unwrap()
{
Ok(msg) => match serde_json::from_slice::<eth::EthConfigResponse>(msg.body()) {
Ok(eth::EthConfigResponse::PermissionDenied) => {
return Err(SettingsError::KernelNonresponsive);
}
Ok(other) => {
println!("eth config action succeeded: {other:?}");
}
Err(_) => {
return Err(SettingsError::KernelNonresponsive);
}
},
Err(_) => {
return Err(SettingsError::KernelNonresponsive);
}
}
}
SettingsRequest::Shutdown => {
// shutdown the node IMMEDIATELY!
Request::to(("our", "kernel", "distro", "sys"))
.body(serde_json::to_vec(&kernel_types::KernelCommand::Shutdown).unwrap())
.send()
.unwrap();
}
SettingsRequest::KillProcess(pid) => {
// kill a process
if let Err(_) = Request::to(("our", "kernel", "distro", "sys"))
.body(serde_json::to_vec(&kernel_types::KernelCommand::KillProcess(pid)).unwrap())
.send_and_await_response(30)
.unwrap()
{
return SettingsResponse::Err(SettingsError::KernelNonresponsive);
}
}
}
state.fetch().map_err(|_| SettingsError::StateFetchFailed)?;
state.ws_update();
SettingsResponse::Ok(None)
}

View File

@ -75,6 +75,7 @@ async fn persist_state(
} }
/// handle commands inside messages sent directly to kernel. source is always our own node. /// handle commands inside messages sent directly to kernel. source is always our own node.
/// returns Some(()) if the kernel should shut down.
async fn handle_kernel_request( async fn handle_kernel_request(
our_name: String, our_name: String,
keypair: Arc<signature::Ed25519KeyPair>, keypair: Arc<signature::Ed25519KeyPair>,
@ -88,9 +89,9 @@ async fn handle_kernel_request(
caps_oracle: t::CapMessageSender, caps_oracle: t::CapMessageSender,
engine: &Engine, engine: &Engine,
home_directory_path: &str, home_directory_path: &str,
) { ) -> Option<()> {
let t::Message::Request(request) = km.message else { let t::Message::Request(request) = km.message else {
return; return None;
}; };
let command: t::KernelCommand = match serde_json::from_slice(&request.body) { let command: t::KernelCommand = match serde_json::from_slice(&request.body) {
Err(e) => { Err(e) => {
@ -100,7 +101,7 @@ async fn handle_kernel_request(
content: format!("kernel: couldn't parse command: {:?}", e), content: format!("kernel: couldn't parse command: {:?}", e),
}) })
.await; .await;
return; return None;
} }
Ok(c) => c, Ok(c) => c,
}; };
@ -138,6 +139,7 @@ async fn handle_kernel_request(
for handle in process_handles.values() { for handle in process_handles.values() {
handle.abort(); handle.abort();
} }
return Some(());
} }
// //
// initialize a new process. this is the only way to create a new process. // initialize a new process. this is the only way to create a new process.
@ -183,7 +185,7 @@ async fn handle_kernel_request(
}) })
.await .await
.expect("event loop: fatal: sender died"); .expect("event loop: fatal: sender died");
return; return None;
}; };
// check cap sigs & transform valid to unsigned to be plugged into procs // check cap sigs & transform valid to unsigned to be plugged into procs
@ -321,7 +323,7 @@ async fn handle_kernel_request(
), ),
}) })
.await; .await;
return; return None;
}; };
let signed_caps: Vec<(t::Capability, Vec<u8>)> = capabilities let signed_caps: Vec<(t::Capability, Vec<u8>)> = capabilities
.iter() .iter()
@ -361,7 +363,7 @@ async fn handle_kernel_request(
), ),
}) })
.await; .await;
return; return None;
}; };
for cap in capabilities { for cap in capabilities {
entry.capabilities.remove(&cap); entry.capabilities.remove(&cap);
@ -465,7 +467,7 @@ async fn handle_kernel_request(
content: format!("kernel: no such process {process_id} to kill"), content: format!("kernel: no such process {process_id} to kill"),
}) })
.await; .await;
return; return None;
} }
}; };
process_handle.abort(); process_handle.abort();
@ -484,7 +486,7 @@ async fn handle_kernel_request(
content: format!("killing process {process_id}"), content: format!("killing process {process_id}"),
}) })
.await; .await;
return; return None;
} }
let _ = send_to_terminal let _ = send_to_terminal
.send(t::Printout { .send(t::Printout {
@ -537,7 +539,7 @@ async fn handle_kernel_request(
content: format!("kernel: no such running process {}", process_id), content: format!("kernel: no such running process {}", process_id),
}) })
.await; .await;
return; return None;
}; };
let _ = send_to_terminal let _ = send_to_terminal
.send(t::Printout { .send(t::Printout {
@ -563,6 +565,7 @@ async fn handle_kernel_request(
} }
}, },
} }
None
} }
/// spawn a process loop and insert the process in the relevant kernel state maps /// spawn a process loop and insert the process in the relevant kernel state maps
@ -1064,7 +1067,7 @@ pub async fn kernel(
if our.name != kernel_message.source.node { if our.name != kernel_message.source.node {
continue; continue;
} }
handle_kernel_request( if let Some(()) = handle_kernel_request(
our.name.clone(), our.name.clone(),
keypair.clone(), keypair.clone(),
kernel_message, kernel_message,
@ -1077,7 +1080,10 @@ pub async fn kernel(
caps_oracle_sender.clone(), caps_oracle_sender.clone(),
&engine, &engine,
&home_directory_path, &home_directory_path,
).await; ).await {
// shut down the node
return Ok(());
}
} else { } else {
// pass message to appropriate runtime module or process // pass message to appropriate runtime module or process
match senders.get(&kernel_message.target.process) { match senders.get(&kernel_message.target.process) {

View File

@ -457,12 +457,15 @@ async fn main() {
// if a runtime task exits, try to recover it, // if a runtime task exits, try to recover it,
// unless it was terminal signaling a quit // unless it was terminal signaling a quit
// or a SIG* was intercepted // or a SIG* was intercepted
let mut quit_msg: String = tokio::select! { let quit_msg: String = tokio::select! {
Some(Ok(res)) = tasks.join_next() => { Some(Ok(res)) = tasks.join_next() => {
format!( match res {
"uh oh, a kernel process crashed -- this should never happen: {:?}", Ok(_) => "graceful exit".into(),
res Err(e) => format!(
) "uh oh, a kernel process crashed -- this should never happen: {e:?}"
),
}
} }
quit = terminal::terminal( quit = terminal::terminal(
our.clone(), our.clone(),
@ -476,39 +479,39 @@ async fn main() {
verbose_mode, verbose_mode,
) => { ) => {
match quit { match quit {
Ok(_) => "graceful exit".into(), Ok(_) => match kernel_message_sender
.send(KernelMessage {
id: rand::random(),
source: Address {
node: our.name.clone(),
process: KERNEL_PROCESS_ID.clone(),
},
target: Address {
node: our.name.clone(),
process: KERNEL_PROCESS_ID.clone(),
},
rsvp: None,
message: Message::Request(Request {
inherit: false,
expects_response: None,
body: serde_json::to_vec(&KernelCommand::Shutdown).unwrap(),
metadata: None,
capabilities: vec![],
}),
lazy_load_blob: None,
})
.await
{
Ok(()) => "graceful exit".into(),
Err(_) => {
"failed to gracefully shut down kernel".into()
}
},
Err(e) => e.to_string(), Err(e) => e.to_string(),
} }
} }
}; };
// gracefully abort all running processes in kernel
if let Err(_) = kernel_message_sender
.send(KernelMessage {
id: rand::random(),
source: Address {
node: our.name.clone(),
process: KERNEL_PROCESS_ID.clone(),
},
target: Address {
node: our.name.clone(),
process: KERNEL_PROCESS_ID.clone(),
},
rsvp: None,
message: Message::Request(Request {
inherit: false,
expects_response: None,
body: serde_json::to_vec(&KernelCommand::Shutdown).unwrap(),
metadata: None,
capabilities: vec![],
}),
lazy_load_blob: None,
})
.await
{
quit_msg = "failed to gracefully shut down kernel".into();
}
// abort all remaining tasks // abort all remaining tasks
tasks.shutdown().await; tasks.shutdown().await;
let stdout = std::io::stdout(); let stdout = std::io::stdout();