@dcasegr/skein 0.0.0-stage → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +525 -2
- package/bin/skein-host.js +22 -0
- package/bin/skein.js +8 -0
- package/dist/client/admin-cli.d.ts +10 -0
- package/dist/client/admin-cli.js +370 -0
- package/dist/client/admin.d.ts +139 -0
- package/dist/client/admin.js +256 -0
- package/dist/client/bundle.d.ts +9 -0
- package/dist/client/bundle.js +34 -0
- package/dist/client/cli.d.ts +44 -0
- package/dist/client/cli.js +306 -0
- package/dist/client/client.d.ts +161 -0
- package/dist/client/client.js +237 -0
- package/dist/client/config.d.ts +18 -0
- package/dist/client/config.js +31 -0
- package/dist/client/conversation.d.ts +62 -0
- package/dist/client/conversation.js +113 -0
- package/dist/client/raw.d.ts +94 -0
- package/dist/client/raw.js +154 -0
- package/dist/client/target.d.ts +34 -0
- package/dist/client/target.js +158 -0
- package/dist/dev/cli.d.ts +8 -0
- package/dist/dev/cli.js +248 -0
- package/dist/dev/scan.d.ts +15 -0
- package/dist/dev/scan.js +173 -0
- package/dist/envelope-cbor.d.ts +110 -0
- package/dist/envelope-cbor.js +160 -0
- package/dist/envelope.d.ts +38 -0
- package/dist/envelope.js +101 -0
- package/dist/host/arc.d.ts +131 -0
- package/dist/host/arc.js +425 -0
- package/dist/host/billing.d.ts +102 -0
- package/dist/host/billing.js +167 -0
- package/dist/host/boot.d.ts +246 -0
- package/dist/host/boot.js +643 -0
- package/dist/host/cli.d.ts +57 -0
- package/dist/host/cli.js +1253 -0
- package/dist/host/clock.d.ts +3 -0
- package/dist/host/clock.js +8 -0
- package/dist/host/control.d.ts +45 -0
- package/dist/host/control.js +170 -0
- package/dist/host/cron.d.ts +99 -0
- package/dist/host/cron.js +196 -0
- package/dist/host/deliver.d.ts +53 -0
- package/dist/host/deliver.js +251 -0
- package/dist/host/deploy.d.ts +29 -0
- package/dist/host/deploy.js +55 -0
- package/dist/host/door-answer.d.ts +24 -0
- package/dist/host/door-answer.js +21 -0
- package/dist/host/events.d.ts +89 -0
- package/dist/host/events.js +222 -0
- package/dist/host/fake-arcade.d.ts +40 -0
- package/dist/host/fake-arcade.js +149 -0
- package/dist/host/fake-discovery.d.ts +4 -0
- package/dist/host/fake-discovery.js +58 -0
- package/dist/host/feeds.d.ts +127 -0
- package/dist/host/feeds.js +422 -0
- package/dist/host/frontdoor.d.ts +92 -0
- package/dist/host/frontdoor.js +172 -0
- package/dist/host/genesis.d.ts +259 -0
- package/dist/host/genesis.js +353 -0
- package/dist/host/handles.d.ts +40 -0
- package/dist/host/handles.js +88 -0
- package/dist/host/hostenv.d.ts +30 -0
- package/dist/host/hostenv.js +83 -0
- package/dist/host/image-chain.d.ts +127 -0
- package/dist/host/image-chain.js +440 -0
- package/dist/host/install.d.ts +22 -0
- package/dist/host/install.js +139 -0
- package/dist/host/instances.d.ts +227 -0
- package/dist/host/instances.js +430 -0
- package/dist/host/kernel.d.ts +246 -0
- package/dist/host/kernel.js +603 -0
- package/dist/host/liveness.d.ts +65 -0
- package/dist/host/liveness.js +155 -0
- package/dist/host/manifest.d.ts +160 -0
- package/dist/host/manifest.js +597 -0
- package/dist/host/p2p.d.ts +337 -0
- package/dist/host/p2p.js +1002 -0
- package/dist/host/packet.d.ts +121 -0
- package/dist/host/packet.js +562 -0
- package/dist/host/plan.d.ts +154 -0
- package/dist/host/plan.js +418 -0
- package/dist/host/providers.d.ts +238 -0
- package/dist/host/providers.js +565 -0
- package/dist/host/roster.d.ts +72 -0
- package/dist/host/roster.js +172 -0
- package/dist/host/router.d.ts +782 -0
- package/dist/host/router.js +2411 -0
- package/dist/host/signer.d.ts +49 -0
- package/dist/host/signer.js +167 -0
- package/dist/host/store-sqlite.d.ts +39 -0
- package/dist/host/store-sqlite.js +170 -0
- package/dist/host/stores.d.ts +43 -0
- package/dist/host/stores.js +342 -0
- package/dist/host/sync.d.ts +121 -0
- package/dist/host/sync.js +467 -0
- package/dist/host/testbeef.d.ts +21 -0
- package/dist/host/testbeef.js +37 -0
- package/dist/host/testhost.d.ts +149 -0
- package/dist/host/testhost.js +211 -0
- package/dist/host/vcdiff.d.ts +9 -0
- package/dist/host/vcdiff.js +210 -0
- package/dist/host/wasm-kernel.d.ts +87 -0
- package/dist/host/wasm-kernel.js +296 -0
- package/dist/host/wasm-worker.d.ts +1 -0
- package/dist/host/wasm-worker.js +186 -0
- package/dist/peers/cron.d.ts +33 -0
- package/dist/peers/cron.js +75 -0
- package/dist/peers/infer-main.d.ts +2 -0
- package/dist/peers/infer-main.js +74 -0
- package/dist/peers/infer.d.ts +163 -0
- package/dist/peers/infer.js +367 -0
- package/dist/runtime/beef.d.ts +28 -0
- package/dist/runtime/beef.js +107 -0
- package/dist/runtime/bitcoin.d.ts +36 -0
- package/dist/runtime/bitcoin.js +141 -0
- package/dist/runtime/cid.d.ts +14 -0
- package/dist/runtime/cid.js +51 -0
- package/dist/runtime/dispatch.d.ts +92 -0
- package/dist/runtime/dispatch.js +142 -0
- package/dist/runtime/envelope.d.ts +60 -0
- package/dist/runtime/envelope.js +101 -0
- package/dist/runtime/heads.d.ts +25 -0
- package/dist/runtime/heads.js +37 -0
- package/dist/runtime/identity.d.ts +28 -0
- package/dist/runtime/identity.js +67 -0
- package/dist/runtime/index-store.d.ts +152 -0
- package/dist/runtime/index-store.js +715 -0
- package/dist/runtime/log.d.ts +62 -0
- package/dist/runtime/log.js +104 -0
- package/dist/runtime/programs.d.ts +30 -0
- package/dist/runtime/programs.js +61 -0
- package/dist/runtime/records.d.ts +135 -0
- package/dist/runtime/records.js +149 -0
- package/dist/runtime/sqlite.d.ts +33 -0
- package/dist/runtime/sqlite.js +604 -0
- package/dist/runtime/store.d.ts +141 -0
- package/dist/runtime/store.js +24 -0
- package/dist/runtime/syscalls.d.ts +9 -0
- package/dist/runtime/syscalls.js +41 -0
- package/dist/runtime/tree.d.ts +60 -0
- package/dist/runtime/tree.js +196 -0
- package/dist/runtime/types.d.ts +100 -0
- package/dist/runtime/types.js +7 -0
- package/dist/testapps.d.ts +101 -0
- package/dist/testapps.js +275 -0
- package/dist/testkit.d.ts +25 -0
- package/dist/testkit.js +48 -0
- package/dist/wallet.d.ts +35 -0
- package/dist/wallet.js +87 -0
- package/images/README.md +68 -0
- package/images/default/README.md +38 -0
- package/images/default/bin/frontdoor.cid +1 -0
- package/images/default/bin/frontdoor.json +5 -0
- package/images/default/bin/messagebox.cid +1 -0
- package/images/default/bin/messagebox.json +8 -0
- package/images/default/bin/wallet.cid +1 -0
- package/images/default/bin/wallet.json +14 -0
- package/images/default/etc/config.json +1 -0
- package/images/default/etc/dispatch.json +82 -0
- package/images/host/etc/apps.json +8 -0
- package/kernel-zig/README.md +1247 -0
- package/kernel-zig/web/client.js +65 -0
- package/kernel-zig/web/kernel.d.ts +59 -0
- package/kernel-zig/web/kernel.js +329 -0
- package/kernel-zig/web/store.js +67 -0
- package/kernel-zig/web/worker.js +79 -0
- package/kernel-zig/zig-out/web/skein-kernel.wasm +0 -0
- package/package.json +77 -4
- package/wasm/README.md +35 -0
- package/wasm/frontdoor.wasm +0 -0
- package/wasm/messagebox.wasm +0 -0
- package/wasm/resolve.wasm +0 -0
- package/wasm/wallet.wasm +0 -0
- package/wasm/wire-probe.wasm +0 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// The roster for the front end (#24): every enabled row as
|
|
2
|
+
// {handle, domain, identity, displayName, description, emoji?, avatar?, status}
|
|
3
|
+
// with the display fields from the deployed tree's IDENTITY.md (`- Name:`,
|
|
4
|
+
// `- Emoji:`, `- Description:`, `- Avatar:` lines), read from the instance's
|
|
5
|
+
// store by the row's `tree` (else, #124, the store's `main`); `status` is `live` when the instance's process,
|
|
6
|
+
// supervised by this host (`skein-host run`), is up and ready, else `idle`.
|
|
7
|
+
// `skein-host roster` prints it; `skein-host run` serves it at /roster.json
|
|
8
|
+
// (CORS *) for a static page on another origin, and an operator page at /
|
|
9
|
+
// (hostPage): every instance, its process, a link to its origin (a skein
|
|
10
|
+
// from the default image serves its management page there, #92).
|
|
11
|
+
//
|
|
12
|
+
// Each agent's own roster (#27) is a file, ROSTER.md (`skein-host roster --for`
|
|
13
|
+
// prints it; the owner deploys it with the directory: `skein deploy
|
|
14
|
+
// --only …,ROSTER.md`), which the loop appends to the system prompt: the colleagues the row
|
|
15
|
+
// `knows` (host.db), each with its address — `- @kurt@localhost — Kurt: …`.
|
|
16
|
+
import { createServer } from "node:http";
|
|
17
|
+
import { CID } from "multiformats/cid";
|
|
18
|
+
import { headTree, MAIN } from "../runtime/heads.js";
|
|
19
|
+
import { lookup, readBlob, readFile } from "../runtime/tree.js";
|
|
20
|
+
import { knowsOf } from "./instances.js";
|
|
21
|
+
const FIELD = { name: "displayName", description: "description", emoji: "emoji", avatar: "avatar" };
|
|
22
|
+
/** IDENTITY.md's `- Key: value` lines (first of each wins); missing ones are "" (name, description) or absent. */
|
|
23
|
+
export function parseIdentity(text) {
|
|
24
|
+
const out = { displayName: "", description: "" };
|
|
25
|
+
const seen = new Set();
|
|
26
|
+
for (const line of text.split(/\r?\n/)) {
|
|
27
|
+
const m = /^\s*[-*]\s*([A-Za-z]+)\s*:\s*(.*?)\s*$/.exec(line);
|
|
28
|
+
const k = m && FIELD[m[1].toLowerCase()];
|
|
29
|
+
if (!k || seen.has(k) || !m[2])
|
|
30
|
+
continue;
|
|
31
|
+
seen.add(k);
|
|
32
|
+
out[k] = m[2];
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
/** The row's entry; `blocks` holds its store, if there is one to read. A tree not (yet) in the store reads as no IDENTITY.md. */
|
|
37
|
+
export async function rosterEntry(row, blocks, live) {
|
|
38
|
+
let id = { displayName: "", description: "" };
|
|
39
|
+
const tree = await treeOf(row, blocks);
|
|
40
|
+
if (tree && blocks) {
|
|
41
|
+
try {
|
|
42
|
+
id = parseIdentity(new TextDecoder().decode(await readFile(blocks, tree, "IDENTITY.md")));
|
|
43
|
+
}
|
|
44
|
+
catch { /* no IDENTITY.md, or the deploy has not been admitted yet: the page shows the row without a name either way */ }
|
|
45
|
+
}
|
|
46
|
+
return { handle: row.handle, domain: row.domain, identity: row.identity ?? "", ...id, status: live ? "live" : "idle" };
|
|
47
|
+
}
|
|
48
|
+
/** The row's deployed tree: its `tree`, else (#124: the owner deploys by message) the store's `main`. */
|
|
49
|
+
async function treeOf(row, blocks) {
|
|
50
|
+
if (row.tree)
|
|
51
|
+
return CID.parse(row.tree);
|
|
52
|
+
const s = blocks;
|
|
53
|
+
if (!s?.log || !(await s.log.tip()))
|
|
54
|
+
return undefined;
|
|
55
|
+
try {
|
|
56
|
+
return await headTree(s, MAIN);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* IDENTITY.md's fields in the row's deployed tree: empty ones if the tree has
|
|
64
|
+
* none, undefined if there is no tree or `blocks` does not have it (yet).
|
|
65
|
+
*/
|
|
66
|
+
export async function deployedIdentity(row, blocks) {
|
|
67
|
+
const tree = await treeOf(row, blocks);
|
|
68
|
+
if (!tree || !blocks)
|
|
69
|
+
return undefined;
|
|
70
|
+
if (!(await blocks.has(tree)))
|
|
71
|
+
return undefined;
|
|
72
|
+
const leaf = await lookup(blocks, tree, "IDENTITY.md");
|
|
73
|
+
return leaf ? parseIdentity(new TextDecoder().decode(await readBlob(blocks, leaf.cid))) : { displayName: "", description: "" };
|
|
74
|
+
}
|
|
75
|
+
/** The heading of every ROSTER.md. */
|
|
76
|
+
export const ROSTER_HEADING = "## Colleagues";
|
|
77
|
+
/**
|
|
78
|
+
* `row`'s ROSTER.md: the rows it knows among `rows` (in their order; itself
|
|
79
|
+
* never; `knows` naming no row is skipped), one line each —
|
|
80
|
+
* `- @handle@domain — Name: description` (no name: the handle; no
|
|
81
|
+
* description: no ": …"). Undefined when it knows nobody: no file.
|
|
82
|
+
*/
|
|
83
|
+
export async function rosterFor(row, rows, fields) {
|
|
84
|
+
const k = knowsOf(row);
|
|
85
|
+
const known = rows.filter((r) => r.handle !== row.handle && (k === "all" || k.includes(r.handle)));
|
|
86
|
+
if (!known.length)
|
|
87
|
+
return undefined;
|
|
88
|
+
const lines = [];
|
|
89
|
+
for (const r of known) {
|
|
90
|
+
const f = await fields(r);
|
|
91
|
+
const oneLine = (x) => x.replace(/\s+/g, " ").trim();
|
|
92
|
+
const name = oneLine(f.displayName) || r.handle, description = oneLine(f.description);
|
|
93
|
+
lines.push(`- @${r.handle}@${r.domain} — ${name}${description ? `: ${description}` : ""}`);
|
|
94
|
+
}
|
|
95
|
+
return `${ROSTER_HEADING}\n\n${lines.join("\n")}\n`;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The roster of `rows` (the caller passes the enabled ones). `open` gives a
|
|
99
|
+
* row's store to read, or undefined, and how to let go of it.
|
|
100
|
+
*/
|
|
101
|
+
export async function roster(rows, open, live) {
|
|
102
|
+
const out = [];
|
|
103
|
+
for (const row of rows) {
|
|
104
|
+
const s = await open(row);
|
|
105
|
+
try {
|
|
106
|
+
out.push(await rosterEntry(row, s.blocks, live(row)));
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
await s.close?.();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
const esc = (x) => String(x).replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`);
|
|
115
|
+
/** The host's operator page (#23): read-only, one row per enabled instance, a link to each one's origin. */
|
|
116
|
+
export function hostPage(rows, info = {}) {
|
|
117
|
+
const body = rows.map((r) => `<tr><td><b>${esc(r.handle)}</b>@${esc(r.domain)}</td><td class="k" title="${esc(r.identity)}">${r.identity ? `${esc(r.identity.slice(0, 16))}…` : "—"}</td>
|
|
118
|
+
<td class="${r.status === "live" ? "ok" : "mut"}">${esc(r.status)}${r.restarts ? ` <span class="mut">(${r.restarts} restart${r.restarts === 1 ? "" : "s"})</span>` : ""}${r.wake !== undefined ? ` <span class="mut small" title="the waker hydrates it then">wakes ${esc(new Date(r.wake).toISOString().replace("T", " ").slice(0, 19))}</span>` : ""}</td><td>${r.pid ?? "—"}</td>
|
|
119
|
+
<td class="k">${esc(r.store)}</td><td class="k" title="${esc(r.tree)}">${r.tree ? `…${esc(r.tree.slice(-12))}` : "—"}</td><td>${r.origin ? `<a href="${esc(r.origin)}/">open</a>` : "—"}</td></tr>`).join("\n");
|
|
120
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>skein host</title>
|
|
121
|
+
<style>:root{--bg:#fbfaf7;--fg:#1d1c1a;--mut:#6b6760;--line:#e3e0d8;--acc:#2f5fd0;--ok:#1f7a3d}
|
|
122
|
+
@media (prefers-color-scheme:dark){:root{--bg:#141413;--fg:#e8e6e1;--mut:#9a968e;--line:#2c2b28;--acc:#8fb0ff;--ok:#6fcf8f}}
|
|
123
|
+
body{margin:0 auto;max-width:1100px;padding:14px 16px;background:var(--bg);color:var(--fg);font:15px/1.5 system-ui,sans-serif}
|
|
124
|
+
a{color:var(--acc)}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid var(--line);padding:5px 6px;text-align:left;vertical-align:top;overflow-wrap:anywhere}
|
|
125
|
+
th{font-size:13px;color:var(--mut);font-weight:600}.k{font-family:ui-monospace,monospace;font-size:13px}.mut{color:var(--mut)}.ok{color:var(--ok)}</style></head>
|
|
126
|
+
<body><h1 style="font-size:19px">skein host <span class="mut" style="font-size:13px">${rows.length} instance${rows.length === 1 ? "" : "s"} · <a href="/roster.json">roster.json</a></span></h1>
|
|
127
|
+
${info.router ? `<p class="mut">router <code>${esc(info.router)}</code>${info.originOf ? ` · an instance at <code>${esc(info.originOf("<handle>"))}</code> (its front door)` : ""} · an instance is <span class="ok">live</span> while its kernel runs; the router starts it on demand and stops it when idle</p>` : ""}
|
|
128
|
+
<table><tr><th>handle</th><th>identity</th><th>status</th><th>pid</th><th>store</th><th>tree</th><th>origin</th></tr>
|
|
129
|
+
${body}</table>
|
|
130
|
+
${info.mailboxes ? `<h2 style="font-size:16px">mailbox instances</h2>${info.mailboxes.length ? `<table><tr><th>handle</th><th>whose</th><th>origin</th></tr>
|
|
131
|
+
${info.mailboxes.map((m) => `<tr><td><b>${esc(m.handle)}</b>@${esc(m.domain)}</td><td class="k" title="${esc(m.owner ?? "")}">${esc((m.owner ?? "").slice(0, 16))}…</td><td class="k">${esc(info.originOf?.(m.handle) ?? "")}</td></tr>`).join("\n")}</table>` : `<p class="mut">none (skein-host add --mailbox, or POST /account/register)</p>`}` : ""}</body></html>`;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* GET /roster.json → get(), CORS *; GET / → page(), if given. Resolves once
|
|
135
|
+
* listening (port 0: any; see server.address()).
|
|
136
|
+
*/
|
|
137
|
+
export function serveRoster(port, get, host = "127.0.0.1", page) {
|
|
138
|
+
const server = createServer(async (req, res) => {
|
|
139
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
140
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
141
|
+
res.setHeader("Access-Control-Allow-Headers", "*");
|
|
142
|
+
if (req.method === "OPTIONS") {
|
|
143
|
+
res.writeHead(204).end();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const path = new URL(req.url ?? "/", "http://x").pathname;
|
|
147
|
+
if (req.method === "GET" && path === "/" && page) {
|
|
148
|
+
try {
|
|
149
|
+
res.writeHead(200, { "content-type": "text/html; charset=utf-8", "cache-control": "no-store" }).end(await page());
|
|
150
|
+
}
|
|
151
|
+
catch (e) {
|
|
152
|
+
res.writeHead(500, { "content-type": "text/plain" }).end(`${e.message}\n`);
|
|
153
|
+
}
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (req.method !== "GET" || path !== "/roster.json") {
|
|
157
|
+
res.writeHead(404, { "content-type": "text/plain" }).end("not found\n");
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
const body = JSON.stringify(await get());
|
|
162
|
+
res.writeHead(200, { "content-type": "application/json", "cache-control": "no-store" }).end(body);
|
|
163
|
+
}
|
|
164
|
+
catch (e) {
|
|
165
|
+
res.writeHead(500, { "content-type": "text/plain" }).end(`${e.message}\n`);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
return new Promise((resolve, reject) => {
|
|
169
|
+
server.once("error", reject);
|
|
170
|
+
server.listen(port, host, () => { server.off("error", reject); resolve(server); });
|
|
171
|
+
});
|
|
172
|
+
}
|