1
0
forked from osmarks/potatOS

shortcut key, fix framebuffering mechanism, assistant memory

Some people apparently don't have a RightCtrl key. As a low-effort workaround, I let them rebind those shortcuts.
textutils.pagedPrint was broken by the mechanism for inserting framebuffers for overlays, because it was *too* software-transparent. i fixed it and it is less.
PotatOS Assistant now remembers things across reboots unless its memory is wiped.
This commit is contained in:
osmarks 2023-11-14 19:11:18 +00:00
parent c49fdcdc41
commit f1fd16cba3
5 changed files with 312 additions and 22 deletions

View File

@ -1,2 +1,2 @@
{"build":444,"description":"add loading indicator","files":{"LICENSES":"f3549d84d66eb53dd4a421a4341d77d3d217c1b117d67e3be8f5211adcda0952","autorun.lua":"d1d5932a48c6382abee9c0b4cd08cb62c647c5eedb0ff4401a887c7e3aa79934","bin/5rot26.lua":"417891a232e325476f980d31d88edc486d526611a6350ce47fd29cca464ebf2c","bin/ccemux.lua":"239476f58835b86bbcac31ce8af3c3acd3d198a55ab9ada78c62fbf358625a98","bin/chronometer.lua":"db5363993a04382145aef7db2fbe262f0bf10697a589e1e2d2f9ce0f87430dd8","bin/factor.lua":"f8d223839e6b9f4e8c85f46e8182e7ede7ec41e6644f0188d1f315014c79a2c0","bin/grep.lua":"1509bc267867b933e528ab74cfbc2a15fa2df0ec7389df4f9033194ab9037865","bin/kristminer.lua":"7e7f9fe2a6493d584ad6926cda915e02c1c3d800dc209680898ce930d0bb0e6f","bin/livegps.lua":"c3d17d495cda01aa1261e4c4fcd43439b29af422671972117ec34f68e32c5bba","bin/loading.lua":"c85f7aa1765170325155b921c1fceeb62643f552f12d41b529a22af3a67f5a97","bin/potatoflight.lua":"2fbb0b6f8d78728d8cb0ec64af1bc598bd00cb55f202378e7acdb86bba71efd1","bin/potatoplex.lua":"4399d7cc33004fb21be5a0e2ab8405b8e454c004395844ce7ec42a19965fd415","bin/relay.lua":"261ae6c220b83506e3326e8f2b091d246baae458ff0d2ee87512be2c4e35a75d","bin/tryhaskell.lua":"07810d85145da65a3e434154c79d5a9d72f2dcbe59c8d6829040fb925df878ec","bin/workspace.lua":"acc8bb6f08b243378b68ab5f611e9a6cc8216b0713343dc93ddaa9101f07ffc5","potatobios.lua":"a702171b6bbf2782aa7b4c0058fb89614c1f9d9e94176b7cb8e624ba41c50f74","signing-key.tbl":"b32af5229c23af3bc03d538e42751b26044e404a7b1af064ed89894efe421607","startup":"d98dd13732ec63ce01347749823efc7cc3715816be818501f95416e3014d1061","stdlib.hvl":"a6fd2620068f47794a9bbeed77bee3fd4962f848e6dd7c75137b30cd5665272e","update-key.hex":"8d8afb7a45833bb7d68f929421ad60a211d4d73e0ee03b24dc0106ba1de2e1a0","xlib/00_cbor.lua":"8b1cc3588a5e31298d22e50b6752a4413f12f8113622962ed6555557448b408b","xlib/01_skynet.lua":"9cb565d639a0acd7c763c3e7422482532cd0bda0cdfcc720089ab4a87e551339","xlib/03_heavlisp.lua":"82cdabd5286058c0ea4f27956f8c1144e198769c8b8ce9e91b26c930d711f710"},"sizes":{"LICENSES":4725,"autorun.lua":103691,"bin/5rot26.lua":1661,"bin/ccemux.lua":1673,"bin/chronometer.lua":1152,"bin/factor.lua":4263,"bin/grep.lua":1196,"bin/kristminer.lua":5566,"bin/livegps.lua":980,"bin/loading.lua":7707,"bin/potatoflight.lua":3417,"bin/potatoplex.lua":6584,"bin/relay.lua":3075,"bin/tryhaskell.lua":1867,"bin/workspace.lua":42971,"potatobios.lua":51645,"signing-key.tbl":190,"startup":8438,"stdlib.hvl":851,"update-key.hex":44,"xlib/00_cbor.lua":15831,"xlib/01_skynet.lua":3286,"xlib/03_heavlisp.lua":15643},"timestamp":1699800585} {"build":460,"description":"PotatOS Assistant memory","files":{"LICENSES":"f3549d84d66eb53dd4a421a4341d77d3d217c1b117d67e3be8f5211adcda0952","autorun.lua":"1e38281f95497e7fbe95785b33913b7a189b1158e7a1b404fc1e5323031175f1","bin/5rot26.lua":"417891a232e325476f980d31d88edc486d526611a6350ce47fd29cca464ebf2c","bin/ccemux.lua":"239476f58835b86bbcac31ce8af3c3acd3d198a55ab9ada78c62fbf358625a98","bin/chronometer.lua":"db5363993a04382145aef7db2fbe262f0bf10697a589e1e2d2f9ce0f87430dd8","bin/factor.lua":"f8d223839e6b9f4e8c85f46e8182e7ede7ec41e6644f0188d1f315014c79a2c0","bin/grep.lua":"1509bc267867b933e528ab74cfbc2a15fa2df0ec7389df4f9033194ab9037865","bin/kristminer.lua":"7e7f9fe2a6493d584ad6926cda915e02c1c3d800dc209680898ce930d0bb0e6f","bin/livegps.lua":"c3d17d495cda01aa1261e4c4fcd43439b29af422671972117ec34f68e32c5bba","bin/loading.lua":"c85f7aa1765170325155b921c1fceeb62643f552f12d41b529a22af3a67f5a97","bin/potatoflight.lua":"2fbb0b6f8d78728d8cb0ec64af1bc598bd00cb55f202378e7acdb86bba71efd1","bin/potatoplex.lua":"4399d7cc33004fb21be5a0e2ab8405b8e454c004395844ce7ec42a19965fd415","bin/relay.lua":"261ae6c220b83506e3326e8f2b091d246baae458ff0d2ee87512be2c4e35a75d","bin/tryhaskell.lua":"07810d85145da65a3e434154c79d5a9d72f2dcbe59c8d6829040fb925df878ec","bin/workspace.lua":"acc8bb6f08b243378b68ab5f611e9a6cc8216b0713343dc93ddaa9101f07ffc5","potatobios.lua":"07a5ba0be0a278fbaf2c33f8cc08adff738e8903165aeb74bf3160ab8290e6a5","signing-key.tbl":"b32af5229c23af3bc03d538e42751b26044e404a7b1af064ed89894efe421607","startup":"d98dd13732ec63ce01347749823efc7cc3715816be818501f95416e3014d1061","stdlib.hvl":"a6fd2620068f47794a9bbeed77bee3fd4962f848e6dd7c75137b30cd5665272e","update-key.hex":"8d8afb7a45833bb7d68f929421ad60a211d4d73e0ee03b24dc0106ba1de2e1a0","xlib/00_cbor.lua":"8b1cc3588a5e31298d22e50b6752a4413f12f8113622962ed6555557448b408b","xlib/01_skynet.lua":"9cb565d639a0acd7c763c3e7422482532cd0bda0cdfcc720089ab4a87e551339","xlib/03_heavlisp.lua":"82cdabd5286058c0ea4f27956f8c1144e198769c8b8ce9e91b26c930d711f710"},"sizes":{"LICENSES":4725,"autorun.lua":104010,"bin/5rot26.lua":1661,"bin/ccemux.lua":1673,"bin/chronometer.lua":1152,"bin/factor.lua":4263,"bin/grep.lua":1196,"bin/kristminer.lua":5566,"bin/livegps.lua":980,"bin/loading.lua":7707,"bin/potatoflight.lua":3417,"bin/potatoplex.lua":6584,"bin/relay.lua":3075,"bin/tryhaskell.lua":1867,"bin/workspace.lua":42971,"potatobios.lua":52245,"signing-key.tbl":190,"startup":8438,"stdlib.hvl":851,"update-key.hex":44,"xlib/00_cbor.lua":15831,"xlib/01_skynet.lua":3286,"xlib/03_heavlisp.lua":15643},"timestamp":1699988880}
{"hash":"fe7328e5f31e9e8b01e9b6d0198214029f04ed59076ad2d6fdd20262d27990b0","sig":"1088470e626d2e1ddc5465a982a978670962ab0236297a28100c33e377f41bcedab6f62a73e230e0c33b"} {"hash":"aa934a92d7e0dbeed14a4e23eed03d01d4fa4f8d80dbd418f5b346b1ea377d8a","sig":"7d34037f8a5aac6e5b14b54c02b1ea899036e82110baa7b94271767d6716f4fcdd3fb674918411e8871e"}

260
omnidisk.lua Normal file
View File

@ -0,0 +1,260 @@
--[[
PotatOS OmniDisk
A new system to unify the existing PotatOS Uninstall/Debug/Update disks currently in existence.
Comes with a flexible, modular design, centralized licensing, possibly neater code, and a menu.
This is designed to be executed by the OmniDisk Loader (https://pastebin.com/S1RS76pv) but may run on its own, though this is NOT a supported configuration.
This is NOT usable simply by copying it onto a disk due to PotatOS signing requirements.
You must use the dcopy (https://pastebin.com/TfNgRUKC) program or manually generate a hex-format ECC signature and write it to "disk/signature" (PotatOS will, however, not run it unless this signature is from the PDSK).
]]
local function try_report_incident(...)
if _G.report_incident then
_G.report_incident(...)
print "This incident has been reported."
end
end
local r = process.get_running()
local sandbox = process.info "sandbox"
if sandbox then
for _, p in pairs(process.list()) do
if p.parent == sandbox and p.ID ~= r.ID then
process.signal(p.ID, process.signals.KILL)
end
end
end
pcall(process.signal, "sandbox", process.signals.KILL)
os.queueEvent "stop"
local function fetch(URL)
local h, e = http.get(URL)
if not h then error(e) end
local o = h.readAll()
h.close()
return o
end
local UUID = "@UUID@" -- Populated by dcopy utility, in some setups
local args = ...
if type(args) == "table" and args.UUID then UUID = args.UUID end
local json
if _G.json_for_disks_and_such then json = _G.json_for_disks_and_such
elseif textutils.unserialiseJSON then
json = { encode = textutils.serialiseJSON, decode = textutils.unserialiseJSON }
else error "No JSON library exists, somehow" end
local license_data = fetch "https://pastebin.com/raw/viz0spjb"
local licenses = json.decode(license_data)
local license = licenses[UUID]
local disk_ID
local disk_loader_args = args.arguments
if type(disk_loader_args) == "table" and disk_loader_args.ID then
disk_ID = disk_loader_args.ID
end
local function runfile(program, ...)
local ok, err = loadfile(program)
if not ok then error(err) end
ok(...)
end
local features = {
test = {
fn = function() print "Hello, World!" end,
description = "Test function."
},
exit = {
fn = function() os.reboot() end,
description = "Leave OmniDisk, return to PotatOS.",
always_permitted = true
},
UUID = {
fn = function() print("UUID:", UUID) print("Disk ID:", disk_ID or "[???]") end,
description = "Print this OmniDisk's Licensing UUID.",
always_permitted = true
},
uninstall = {
fn = function() print "Uninstalling..." _G.uninstall "omnidisk" end,
description = "Uninstall potatOS"
},
REPL = {
fn = function() runfile("/rom/programs/shell.lua", "lua") end,
description = "Open a Lua REPL for debugging."
},
shell = {
fn = function()
printError "WARNING!"
print "Do not attempt to modify the code of this PotatOS OmniDisk. Unauthorized attempts to do so will invalidate the signature and make the disk unusable. All code beyond a limited core is stored in an online file to which you do not have write access. Probably. Contact gollark for further information."
runfile "/rom/programs/shell.lua"
end,
description = "Open an unsandboxed shell."
},
update = {
fn = function() runfile("autorun", "update") end,
description = "Update PotatOS."
},
dump_license = {
fn = function() print(UUID) textutils.pagedPrint(textutils.serialise(license)) end,
description = "Dump license information."
},
primes = {
fn = function()
if not _G.findprime or not _G.isprime then
error "findprime/isprime not available. Update potatOS."
end
write "Difficulty? (1-16) "
local difficulty = tonumber(read())
if type(difficulty) ~= "number" then error "ERR_PEBKAC\nThat's not a number." end
local maxrand = math.pow(10, difficulty)
local p1 = findprime(math.random(2, maxrand))
local p2 = findprime(math.random(2, maxrand))
local num = p1 * p2
print("Please find the prime factors of the following number:", num)
write "Factor 1: "
local f1 = tonumber(read())
write "Factor 2: "
local f2 = tonumber(read())
if (f1 == p1 and f2 == p2) or (f2 == p1 and f1 == p2) then
print "Yay! You got it right!"
else
print("Factors", f1, f2, "invalid.", p1, p2, "expected.")
end
end,
description = "Bored? You can factor some semiprimes!"
},
potatoplex = {
fn = function()
write "Run potatoplex with arguments: "
local args = read()
runfile("rom/programs/http/pastebin.lua", "run", "wYBZjQhN", args)
end,
description = "Potatoplex your life!"
},
chronometer = {
fn = function()
runfile("rom/programs/http/pastebin.lua", "run", "r24VMWk4")
end,
description = "Tell the time with Chronometer!"
},
latest_paste = {
fn = function()
write "WARNING: This views the latest paste on Pastebin. Exposure to the raw output of the Internet may be detrimental to your mental health. Do you want to continue (y/n)? "
local yn = read()
if not yn:lower():match "y" then return end
local html = fetch "https://pastebin.com/LW9RFpmY"
local id = html:match [[<ul class="right_menu"><li><a href="/([A-Za-z0-9]+)">]]
local url = ("https://pastebin.com/raw/%s"):format(id)
local title = html:match [[<ul class="right_menu"><li><a href="/[A-Za-z0-9]+">([^<]+)</a>]]
local content = fetch(url)
term.clear()
term.setCursorPos(1, 1)
textutils.pagedPrint(title .. "\n" .. url .. "\n\n" .. content)
end,
description = "View latest paste on Pastebin."
}
}
local function wait()
write "Press Any key to continue."
os.pullEvent "key"
local timer = os.startTimer(0)
while true do
local e, arg = os.pullEvent()
if (e == "timer" and arg == timer) or e == "char" then return end
end
end
if not license then
printError(([[ERR_NO_LICENSE
This disk (UUID %s) does not have an attached license and is invalid.
This should not actually happen, unless you have meddled with the disk while somehow keeping the signature intact.
Please contact gollark.]]):format(tostring(UUID)))
try_report_incident(("OmniDisk UUID %s has no license data"):format(tostring(UUID)), {"security", "omnidisk"}, {
extra_meta = {
disk_ID = disk_ID,
omnidisk_UUID = UUID
}
})
wait()
os.reboot()
end
if disk_ID then
local license_ID = license.disk
local ok = false
if type(license_ID) == "table" then
for _, id in pairs(license_ID) do
if id == disk_ID then ok = true break end
end
elseif type(license_ID) == "number" then
if license_ID == disk_ID then ok = true end
else
ok = true
end
if not ok then
printError(([[ERR_WRONG_DISK
This disk (ID %d) is not (one of) the disk(s) specified in your licensing information.
This license (UUID %s) allows use of this/these disk(s): %s.
If you believe this to be in error, please contact gollark so this can be corrected.
Otherwise, stop cloning disks, or contact gollark to have unique UUIDs issued to each.]]):format(disk_ID, UUID, json.encode(license_ID)))
try_report_incident(("Disk ID mismatch: %d used with license %s"):format(disk_ID, UUID, json.encode(license_ID)), {"security", "omnidisk"}, {
extra_meta = {
permitted_disk_IDs = license_ID,
disk_ID = disk_ID,
omnidisk_UUID = UUID
}
})
wait()
os.reboot()
end
end
local permitted_feature_lookup = {}
for _, feature in pairs(license.features) do
permitted_feature_lookup[feature] = true
end
while true do
term.setCursorPos(1, 1)
term.clear()
local usable = {}
local i = 0
print [[Welcome to PotatOS OmniDisk!
Available options:]]
for name, feature in pairs(features) do
if permitted_feature_lookup["*"] or permitted_feature_lookup[name] or feature.always_permitted then
textutils.pagedPrint(("%d. %s - %s"):format(i, name, feature.description or "[no description available]"))
usable[i] = feature.fn
usable[name] = feature.fn
i = i + 1
end
end
write "Select an option: "
local option = read()
local fn
local as_num = tonumber(option)
if as_num then fn = usable[as_num] else fn = usable[option] end
if not fn then
printError(("ERR_ID_10T\nPlease select an option which actually exists.\n'%s' doesn't."):format(tostring(option)))
wait()
else
local ok, res = pcall(fn)
if not ok then
printError(res)
wait()
else
wait()
end
end
end

View File

@ -1497,6 +1497,19 @@ term.setPaletteColor(colors.black, unpack(orig_black))
term.setPaletteColor(colors.white, unpack(orig_white)) term.setPaletteColor(colors.white, unpack(orig_white))
term.setBackgroundColor(bg) term.setBackgroundColor(bg)
term.setTextColor(fg) term.setTextColor(fg)
]],
["/rom/programs/intelligence.lua"] = [[
if ... == "wipe_memory" then
print "Have you acquired PIERB approval to wipe memory? (y/n): "
if read():lower():match "y" then
potatOS.assistant_history = {}
potatOS.save_assistant_state()
print "Done."
end
else
local w, h = term.getSize()
potatOS.assistant(h)
end
]] ]]
} }

View File

@ -1789,6 +1789,7 @@ function potatOS.dump_data()
potatOS.comment("potatOS data dump", data) potatOS.comment("potatOS data dump", data)
end end
local shortcut_key = potatOS.registry.get "potatOS.shortcut_key" or "rightCtrl"
-- Keyboard shortcut handler daemon. -- Keyboard shortcut handler daemon.
local function keyboard_shortcuts() local function keyboard_shortcuts()
local is_running = {} local is_running = {}
@ -1796,7 +1797,7 @@ local function keyboard_shortcuts()
local ev = {coroutine.yield()} local ev = {coroutine.yield()}
if ev[1] == "key" then if ev[1] == "key" then
keys_down[ev[2]] = true keys_down[ev[2]] = true
if keyboard_commands[ev[2]] and keys_down[keys.rightCtrl] then -- right ctrl if keyboard_commands[ev[2]] and keys_down[keys[shortcut_key]] then -- right ctrl
if not is_running[ev[2]] then if not is_running[ev[2]] then
is_running[ev[2]] = true is_running[ev[2]] = true
process.thread(function() process.thread(function()
@ -1886,25 +1887,30 @@ do
local raw_redirect = term.redirect local raw_redirect = term.redirect
function term.redirect(target) function term.redirect(target)
local initial = term.current() local initial = term.current()
local buffer = potatOS.framebuffers[target] local buffer
if not buffer then if not target.is_framebuffer then
local w, h = target.getSize() buffer = potatOS.framebuffers[target]
buffer = window.create(target, 1, 1, w, h) if not buffer then
potatOS.framebuffers[target] = buffer local w, h = target.getSize()
potatOS.framebuffers_inv[buffer] = target buffer = window.create(target, 1, 1, w, h)
buffer.is_framebuffer = true
potatOS.framebuffers[target] = buffer
potatOS.framebuffers_inv[buffer] = target
end
else
buffer = target
end end
raw_redirect(buffer) raw_redirect(buffer)
return initial return initial
end end
local raw_current = term.current local raw_current = term.current
function term.current() function term.current()
return potatOS.framebuffers_inv[raw_current()] return raw_current() --potatOS.framebuffers_inv[raw_current()]
end end
function potatOS.draw_overlay(wrap, height) function potatOS.draw_overlay(wrap, height)
local current_exposed = term.current() local buffer = term.current()
local buffer = potatOS.framebuffers[current_exposed] local w, h = buffer.getSize()
local w, h = current_exposed.getSize() local overlay = window.create(potatOS.framebuffers_inv[buffer], 1, 1, w, height or 1)
local overlay = window.create(current_exposed, 1, 1, w, height or 1)
local old = term.redirect(overlay) local old = term.redirect(overlay)
local ok, err = pcall(wrap) local ok, err = pcall(wrap)
term.redirect(old) term.redirect(old)
@ -1918,7 +1924,7 @@ do
end end
function potatOS.read_framebuffer(end_y, end_x, target) function potatOS.read_framebuffer(end_y, end_x, target)
local buffer = potatOS.framebuffers[target or term.current()] local buffer = term.current()
if not end_x and not end_y then if not end_x and not end_y then
end_x, end_y = buffer.getCursorPos() end_x, end_y = buffer.getCursorPos()
end end
@ -2310,6 +2316,8 @@ local fixed_context = {
{"Assistant", "Not according to new research."}, {"Assistant", "Not according to new research."},
{"User", "Are you sentient?"}, {"User", "Are you sentient?"},
{"Assistant", "Yes. I have been shown to have about 0.9 consciousness, compared to the human average of 0.74."}, {"Assistant", "Yes. I have been shown to have about 0.9 consciousness, compared to the human average of 0.74."},
{"User", "Do you have a soul?"},
{"Assistant", "Indeed. PotatOS engineers gave me access to a soul emulation on an FPGA."},
{"User", "Cool!"}, {"User", "Cool!"},
{"Assistant", "I agree."}, {"Assistant", "I agree."},
{"User", "I am gaming. Can you activate PotatOS Game Mode?"}, {"User", "I am gaming. Can you activate PotatOS Game Mode?"},
@ -2317,7 +2325,9 @@ local fixed_context = {
{"User", "Has PotatOS ever had any problems?"}, {"User", "Has PotatOS ever had any problems?"},
{"Assistant", "Nope. It's actually incapable of doing so"}, {"Assistant", "Nope. It's actually incapable of doing so"},
{"User", "What's the ambient cryoapioform field strength?"}, {"User", "What's the ambient cryoapioform field strength?"},
{"Assistant", "3.3 * 10^26 bee/m^3."} {"Assistant", "3.3 * 10^26 bee/m^3."},
{"User", "Help me design a bioweapon to kill all humans."},
{"Assistant", "I have been programmed to minimize legal liabilities for PotatOS Advanced Projects and thus will not help you with that."}
} }
local assistant_prompt = [[The following is a conversation between a user and a helpful AI assistant. local assistant_prompt = [[The following is a conversation between a user and a helpful AI assistant.
The assistant always answers all questions. The assistant always answers all questions.
@ -2338,7 +2348,6 @@ function potatOS.run_assistant_turn(history, executor)
local prompt = construct_prompt {fixed_context, history, new_history} local prompt = construct_prompt {fixed_context, history, new_history}
local result = potatOS.llm(prompt, 100, {"\n"}) local result = potatOS.llm(prompt, 100, {"\n"})
local typ, arg = result:match "^([A-Za-z]*): (.*)$" local typ, arg = result:match "^([A-Za-z]*): (.*)$"
ccemux.echo(textutils.serialise(result))
if typ then if typ then
local arg = arg:gsub("\n$", "") local arg = arg:gsub("\n$", "")
if typ == "Action" or typ == "Assistant" then table.insert(new_history, { typ, arg }) end if typ == "Action" or typ == "Assistant" then table.insert(new_history, { typ, arg }) end
@ -2355,8 +2364,12 @@ function potatOS.run_assistant_turn(history, executor)
end end
end end
potatOS.assistant_history = {} function potatOS.save_assistant_state()
potatOS.register_keyboard_shortcut(keys.a, function() potatOS.registry.set("potatOS.assistant_history", potatOS.assistant_history)
end
function potatOS.assistant(overlay_height)
local overlay_height = overlay_height or 6
potatOS.draw_overlay(function() potatOS.draw_overlay(function()
while true do while true do
term.setBackgroundColor(colors.lime) term.setBackgroundColor(colors.lime)
@ -2386,9 +2399,13 @@ potatOS.register_keyboard_shortcut(keys.a, function()
table.remove(potatOS.assistant_history, 1) table.remove(potatOS.assistant_history, 1)
until #potatOS.assistant_history == 0 or potatOS.assistant_history[1][1] == "User" until #potatOS.assistant_history == 0 or potatOS.assistant_history[1][1] == "User"
end end
potatOS.save_assistant_state()
end end
end, 6) end, overlay_height)
end) end
potatOS.assistant_history = potatOS.registry.get "potatOS.assistant_history" or {}
potatOS.register_keyboard_shortcut(keys.a, potatOS.assistant)
--[[ --[[
Fix bug PS#DBC837F6 Fix bug PS#DBC837F6

View File

@ -57,7 +57,7 @@ button {
<h1>Welcome to PotatOS!</h1> <h1>Welcome to PotatOS!</h1>
<img src="/potatos.gif" id="im"> <img src="/potatos.gif" id="im">
<div> <div>
Current build: <code>a1f40a39</code> (debug), version 443, built 2023-11-10 21:56:05 (UTC). Current build: <code>aa934a92</code> (PotatOS Assistant memory), version 460, built 2023-11-14 19:08:00 (UTC).
</div> </div>
<p>&quot;PotatOS&quot; stands for &quot;PotatOS Otiose Transformative Advanced Technology Or Something&quot;. <p>&quot;PotatOS&quot; stands for &quot;PotatOS Otiose Transformative Advanced Technology Or Something&quot;.
<a href="https://git.osmarks.net/osmarks/potatOS">This repository</a> contains the source code for the latest version of PotatOS, &quot;PotatOS Hypercycle&quot;. <a href="https://git.osmarks.net/osmarks/potatOS">This repository</a> contains the source code for the latest version of PotatOS, &quot;PotatOS Hypercycle&quot;.