Merge pull request #652 from kinode-dao/develop

Develop 0.10.0
This commit is contained in:
doria 2024-12-26 13:31:52 -05:00 committed by GitHub
commit 22700f4e97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 191 additions and 32 deletions

View File

@ -88,7 +88,6 @@ fn make_widget() -> String {
body {
overflow: hidden;
background: transparent;
}
#latest-apps {

View File

@ -163,6 +163,8 @@ fn init(our: Address) {
.bind_http_path("/order", http_config)
.expect("failed to bind /order");
kinode_process_lib::homepage::add_to_homepage("Clock", None, None, Some(&make_clock_widget()));
// load persisted app order
let mut persisted_app_order =
kinode_process_lib::get_typed_state(|bytes| serde_json::from_slice(bytes))
@ -194,7 +196,12 @@ fn init(our: Address) {
)),
),
"/version" => {
if app_data.len() >= 4 {
// hacky way to ensure that the homepage has populated itself before
// loading in after boot
if app_data.len() >= 4
&& app_data.values().filter(|app| app.widget.is_some()).count()
>= 3
{
(
server::HttpResponse::new(http::StatusCode::OK),
Some(LazyLoadBlob::new(
@ -381,3 +388,126 @@ fn version_from_cargo_toml() -> String {
.trim_matches('"')
.to_string()
}
fn make_clock_widget() -> String {
return format!(
r#"<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/kinode.css">
<style>
.clock {{
width: 200px;
height: 200px;
border: 8px solid var(--text);
border-radius: 50%;
position: relative;
margin: 20px auto;
}}
.hand {{
position: absolute;
bottom: 50%;
left: 50%;
transform-origin: bottom;
background-color: light-dark(var(--off-black), var(--off-white));
}}
.hour {{
width: 4px;
height: 60px;
margin-left: -2px;
}}
.minute {{
width: 3px;
height: 80px;
margin-left: -1.5px;
}}
.second {{
width: 2px;
height: 90px;
margin-left: -1px;
background-color: var(--orange);
}}
.center {{
width: 12px;
height: 12px;
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}}
.marker {{
position: absolute;
width: 2px;
height: 4px;
background: light-dark(var(--off-black), var(--off-white));
left: 50%;
margin-left: -1px;
transform-origin: 50% 100px;
}}
.marker.primary {{
width: 3px;
height: 8px;
margin-left: -1.5px;
}}
.digital-time {{
font-family: var(--font-family-main);
margin-top: 1em;
font-size: 0.7em;
color: light-dark(var(--off-black), var(--off-white));
position: absolute;
width:100%;
text-align: center;
bottom: 40px;
}}
</style>
</head>
<body style="margin: 0;">
<div class="clock">
<div class="marker primary" style="transform: rotate(0deg)"></div>
<div class="marker" style="transform: rotate(30deg)"></div>
<div class="marker" style="transform: rotate(60deg)"></div>
<div class="marker primary" style="transform: rotate(90deg)"></div>
<div class="marker" style="transform: rotate(120deg)"></div>
<div class="marker" style="transform: rotate(150deg)"></div>
<div class="marker primary" style="transform: rotate(180deg)"></div>
<div class="marker" style="transform: rotate(210deg)"></div>
<div class="marker" style="transform: rotate(240deg)"></div>
<div class="marker primary" style="transform: rotate(270deg)"></div>
<div class="marker" style="transform: rotate(300deg)"></div>
<div class="marker" style="transform: rotate(330deg)"></div>
<div class="hand hour" id="hour"></div>
<div class="hand minute" id="minute"></div>
<div class="hand second" id="second"></div>
<div class="center"></div>
</div>
<div class="digital-time" id="digital"></div>
<script>
function updateClock() {{
const now = new Date();
const hours = now.getHours() % 12;
const minutes = now.getMinutes();
const seconds = now.getSeconds();
const hourDeg = (hours * 30) + (minutes * 0.5);
const minuteDeg = minutes * 6;
const secondDeg = seconds * 6;
document.getElementById('hour').style.transform = `rotate(${{hourDeg}}deg)`;
document.getElementById('minute').style.transform = `rotate(${{minuteDeg}}deg)`;
document.getElementById('second').style.transform = `rotate(${{secondDeg}}deg)`;
// Update digital display
const displayHours = hours === 0 ? 12 : hours;
const displayMinutes = minutes.toString().padStart(2, '0');
document.getElementById('digital').textContent = `${{displayHours}}:${{displayMinutes}}`;
}}
setInterval(updateClock, 1000);
updateClock();
</script>
</body>
</html>"#
);
}

View File

@ -109,15 +109,11 @@ impl State {
impl From<net::KnsUpdate> for WitKnsUpdate {
fn from(k: net::KnsUpdate) -> Self {
WitKnsUpdate {
name: k.name.clone(),
public_key: k.public_key.clone(),
ips: k.ips.clone(),
ports: k
.ports
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect::<Vec<_>>(),
routers: k.routers.clone(),
name: k.name,
public_key: k.public_key,
ips: k.ips,
ports: k.ports.into_iter().map(|(k, v)| (k, v)).collect::<Vec<_>>(),
routers: k.routers,
}
}
}
@ -125,11 +121,11 @@ impl From<net::KnsUpdate> for WitKnsUpdate {
impl From<WitKnsUpdate> for net::KnsUpdate {
fn from(k: WitKnsUpdate) -> Self {
net::KnsUpdate {
name: k.name.clone(),
public_key: k.public_key.clone(),
ips: k.ips.clone(),
name: k.name,
public_key: k.public_key,
ips: k.ips,
ports: BTreeMap::from_iter(k.ports),
routers: k.routers.clone(),
routers: k.routers,
}
}
}
@ -138,19 +134,15 @@ impl From<State> for WitState {
fn from(s: State) -> Self {
let contract_address: [u8; 20] = s.contract_address.into();
WitState {
chain_id: s.chain_id.clone(),
chain_id: s.chain_id,
contract_address: contract_address.to_vec(),
names: s
.names
.iter()
.map(|(k, v)| (k.clone(), v.clone()))
.collect::<Vec<_>>(),
names: s.names.into_iter().map(|(k, v)| (k, v)).collect::<Vec<_>>(),
nodes: s
.nodes
.iter()
.map(|(k, v)| (k.clone(), v.clone().into()))
.into_iter()
.map(|(k, v)| (k, v.into()))
.collect::<Vec<_>>(),
last_block: s.last_checkpoint_block.clone(),
last_block: s.last_checkpoint_block,
}
}
}

View File

@ -369,6 +369,14 @@ async fn handle_kernel_request(
.expect("event loop: fatal: sender died");
None
}
t::KernelCommand::SetOnExit { target, on_exit } => {
if let Some(process) = process_map.get_mut(&target) {
process.on_exit = on_exit;
}
// persist state because it changed
persist_state(&send_to_loop, process_map).await;
None
}
//
// send 'run' message to a process that's already been initialized
//

View File

@ -497,11 +497,42 @@ impl StandardHost for process::ProcessWasiV1 {
// process management:
//
/// TODO critical: move to kernel logic to enable persistence of choice made here
async fn set_on_exit(&mut self, on_exit: wit::OnExit) -> Result<()> {
self.process.metadata.on_exit = t::OnExit::de_wit_v1(on_exit);
print_debug(&self.process, "set new on-exit behavior").await;
Ok(())
let on_exit = t::OnExit::de_wit_v1(on_exit);
self.process.metadata.on_exit = on_exit.clone();
match self
.process
.send_request_v1(
Some(t::Address {
node: self.process.metadata.our.node.clone(),
process: KERNEL_PROCESS_ID.clone(),
}),
wit::Address {
node: self.process.metadata.our.node.clone(),
process: KERNEL_PROCESS_ID.en_wit_v1(),
},
wit::Request {
inherit: false,
expects_response: None,
body: serde_json::to_vec(&t::KernelCommand::SetOnExit {
target: self.process.metadata.our.process.clone(),
on_exit,
})
.unwrap(),
metadata: None,
capabilities: vec![],
},
None,
None,
)
.await
{
Ok(_) => {
print_debug(&self.process, "set new on-exit behavior").await;
Ok(())
}
Err(e) => Err(e),
}
}
async fn get_on_exit(&mut self) -> Result<wit::OnExit> {

View File

@ -75,10 +75,7 @@ pub async fn load_state(
}
}
// bootstrap the distro processes into the node. TODO:
// once we manage userspace sys packages onchain, stop
// doing this and allow node operator to manually or auto-update
// all their own userspace packages.
// bootstrap the distro processes into the node
bootstrap(
&our_name,
keypair,

View File

@ -429,6 +429,8 @@ pub enum KernelCommand {
target: ProcessId,
capabilities: Vec<Capability>,
},
/// Set the on-exit behavior for a process.
SetOnExit { target: ProcessId, on_exit: OnExit },
/// Tell the kernel to run a process that has already been installed.
/// TODO: in the future, this command could be extended to allow for
/// resource provision.