@nervur-org/dock 0.4.0 → 0.5.0
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 +9 -10
- package/package.json +4 -13
- package/GETTING_STARTED.md +0 -138
- package/GLOSSARY.md +0 -118
- package/WORLDS.md +0 -569
- package/quo-api.md +0 -196
- package/quo-app-bells.md +0 -280
- package/quo-dock.md +0 -1945
- package/quo-harbor.md +0 -874
- package/quo-human.md +0 -1042
- package/quo-mcp.md +0 -343
package/README.md
CHANGED
|
@@ -19,16 +19,15 @@ its Caddyfile, and a package file that depends on the dock and nothing
|
|
|
19
19
|
else. Add your beings to `droplet/classes/`, and your placement to the
|
|
20
20
|
routes and agents files.
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
and
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
theirs.
|
|
22
|
+
The documentation is at <https://nervur.org/docs>: the trunk of this
|
|
23
|
+
package, the human, model, api and harbor sides, the bells, what home,
|
|
24
|
+
presence and membership mean, and every word above the spec. This package
|
|
25
|
+
carries its code and this file, and nothing written for a reader lives
|
|
26
|
+
inside it, because a document and a release move at different speeds.
|
|
27
|
+
|
|
28
|
+
Quo itself is at <https://quo.systems>: the spec, the vectors a kit is
|
|
29
|
+
checked against, and the verifier that replays them. This package
|
|
30
|
+
implements it and never restates it.
|
|
32
31
|
|
|
33
32
|
## Versions
|
|
34
33
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nervur-org/dock",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "The dock: what every estate on Quo needs and nobody writes twice. A daemon and the nervur command, the front desk, the user being and the avatar, harbors on disk, in a tab and on the edge, the model sides and the screen.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"quo",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
}
|
|
80
80
|
},
|
|
81
81
|
"scripts": {
|
|
82
|
-
"build": "rm -rf dist && tsc -p tsconfig.build.json && node build/bundle.ts && chmod +x dist/cli/nervur.js && cp harbor/edge/platform.d.ts dist/harbor/edge/ && cp -R cli/estate dist/cli/
|
|
82
|
+
"build": "rm -rf dist && tsc -p tsconfig.build.json && node build/bundle.ts && chmod +x dist/cli/nervur.js && cp harbor/edge/platform.d.ts dist/harbor/edge/ && cp -R cli/estate dist/cli/",
|
|
83
83
|
"check": "node --test \"test/*.test.ts\"",
|
|
84
84
|
"deep": "node --test \"test/terrain/*.test.ts\"",
|
|
85
85
|
"prepublishOnly": "test \"$NERVUR_GATED\" = 1 || { echo 'publish from the root, gated once: npm run release:dock' >&2; exit 1; }"
|
|
@@ -92,8 +92,8 @@
|
|
|
92
92
|
"@capacitor/geolocation": "^8.2.2",
|
|
93
93
|
"@capacitor/local-notifications": "^8.3.1",
|
|
94
94
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
95
|
-
"nervur": "^0.
|
|
96
|
-
"@nervur-org/ui": "^0.
|
|
95
|
+
"nervur": "^0.18.0",
|
|
96
|
+
"@nervur-org/ui": "^0.4.0",
|
|
97
97
|
"ws": "^8.21.3"
|
|
98
98
|
},
|
|
99
99
|
"devDependencies": {
|
|
@@ -113,15 +113,6 @@
|
|
|
113
113
|
"mcp",
|
|
114
114
|
"human",
|
|
115
115
|
"api",
|
|
116
|
-
"quo-dock.md",
|
|
117
|
-
"quo-app-bells.md",
|
|
118
|
-
"quo-human.md",
|
|
119
|
-
"quo-mcp.md",
|
|
120
|
-
"quo-api.md",
|
|
121
|
-
"quo-harbor.md",
|
|
122
|
-
"GLOSSARY.md",
|
|
123
|
-
"WORLDS.md",
|
|
124
|
-
"GETTING_STARTED.md",
|
|
125
116
|
"README.md",
|
|
126
117
|
"LICENSE",
|
|
127
118
|
"NOTICE"
|
package/GETTING_STARTED.md
DELETED
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
# Getting started
|
|
2
|
-
|
|
3
|
-
Quo lets an object ask another object and get an answer, without knowing
|
|
4
|
-
whether that other object is in the same process, on the same device, or
|
|
5
|
-
on another planet. Three words: a harbor boots wards, a ward keeps beings
|
|
6
|
-
and judges its door, and a being is one ordinary object with one voice.
|
|
7
|
-
This is the shortest road from nothing to each of the three, for a
|
|
8
|
-
stranger with a terminal. `SPEC.md` is the truth behind every sentence
|
|
9
|
-
here and assumes nothing; `quo-dock.md` is the dock, the part a box runs.
|
|
10
|
-
|
|
11
|
-
Quo is the protocol and Nervur is this kit of it. Every name you install
|
|
12
|
-
and every command you type is Nervur's; `quo` stays on the wire, as the
|
|
13
|
-
`quo.` route a ward's door answers at.
|
|
14
|
-
|
|
15
|
-
Two packages, and you start with the one that fits what you have:
|
|
16
|
-
|
|
17
|
-
- `nervur`, the library. A harbor, a ward and a being in one
|
|
18
|
-
process, no wire, no files. For a program that wants Quo inside it.
|
|
19
|
-
- `@nervur-org/dock`, the dock. A daemon and one command, `nervur`, that
|
|
20
|
-
stand a box up: a person's world with a page, a model's side, an api, a
|
|
21
|
-
door on the wire. For a box that receives people and models.
|
|
22
|
-
|
|
23
|
-
The command is in the dock and not in the library, so `npm install nervur`
|
|
24
|
-
gives you something to import and no command, and the command arrives with
|
|
25
|
-
`npm install -g @nervur-org/dock`. That is how a kit of this shape is
|
|
26
|
-
always named: one unscoped headline name for the library, the parts under
|
|
27
|
-
the scope, and the CLI in the package that owns it.
|
|
28
|
-
|
|
29
|
-
## A being, in one process
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
npm install nervur
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
A being is a class with `asks`, the methods anyone may reach, each with
|
|
36
|
-
the JSON schema of its input. Everything else on the class is hers alone.
|
|
37
|
-
|
|
38
|
-
```js
|
|
39
|
-
import { Being } from 'nervur';
|
|
40
|
-
import { Ward } from 'nervur/ward';
|
|
41
|
-
import { MemoryHarbor } from 'nervur/harbor';
|
|
42
|
-
|
|
43
|
-
class Shop extends Being {
|
|
44
|
-
static asks = { price: { input: { type: 'object', properties: { item: { type: 'string' } } } } };
|
|
45
|
-
price({ item }) {
|
|
46
|
-
return { item, eur: 12 };
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
class Customer extends Being {
|
|
50
|
-
static asks = {};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const harbor = new MemoryHarbor();
|
|
54
|
-
const ward = await harbor.boot('acme', Ward, { Shop, Customer });
|
|
55
|
-
await ward.ask('boot', { key: 'shop', class: 'Shop' });
|
|
56
|
-
await ward.ask('boot', { key: 'ana', class: 'Customer' });
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
The harbor booted a ward named `acme` with two classes it may make beings
|
|
60
|
-
of, and the ward's owner, the process itself, booted one of each by key.
|
|
61
|
-
The ward's own asks are seven, `boot`, `public`, `invite`, `knock`,
|
|
62
|
-
`remove`, `unboot` and `ask`, and `ward.ask()` with no method is her
|
|
63
|
-
describe: those asks and her `notes`, the ward's `pk` and her beings.
|
|
64
|
-
|
|
65
|
-
Nobody reaches a being she has not invited. An invitation is minted on a
|
|
66
|
-
being for one id, the shop's for `ana`, and the customer knocks with it;
|
|
67
|
-
from then she holds a standing at the shop, under the name she took, and
|
|
68
|
-
the shop holds her as an occupant.
|
|
69
|
-
|
|
70
|
-
```js
|
|
71
|
-
const invitation = await ward.ask('invite', { being: 'shop', id: 'ana' });
|
|
72
|
-
const ana = harbor.objects.get(harbor.partitions.get('acme').beings.ana);
|
|
73
|
-
await ana.knock(invitation);
|
|
74
|
-
await ana.take('shop', invitation);
|
|
75
|
-
console.log(await ana.standings.shop.ask('price', { item: 'bread' }));
|
|
76
|
-
// { item: 'bread', eur: 12 }
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
That is the whole protocol: a standing on one side, an occupant on the
|
|
80
|
-
other, an ask that rides the relation and an answer that rides it back.
|
|
81
|
-
The two beings here share a process; the same lines hold when the shop is
|
|
82
|
-
on a box across the sea, because a standing is an address and a key, and
|
|
83
|
-
the harbor owns the wire. `harbor.objects` is the memory harbor's hand for
|
|
84
|
-
a test and a first program; a being on a real box is reached through her
|
|
85
|
-
ward, never held.
|
|
86
|
-
|
|
87
|
-
## A box
|
|
88
|
-
|
|
89
|
-
```bash
|
|
90
|
-
npm install @nervur-org/dock
|
|
91
|
-
npx nervur init --dir ~/.nervur --ward acme --user razvan --domain acme.com --default --show
|
|
92
|
-
npx nervur serve --dir ~/.nervur --http 8787
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
`init` mints the ward `acme`, boots razvan's user being, her doorbell and
|
|
96
|
-
the desk in it, marks it the default ward and shows it at the web route,
|
|
97
|
-
and writes `routes.json`, the four routes of a box, `mcp.`, `web.`, `quo.`
|
|
98
|
-
and `api.` under the domain, for a proxy to map onto the one loopback
|
|
99
|
-
port. Without `--domain`, write it yourself; on a Mac the four are paths
|
|
100
|
-
at one loopback address:
|
|
101
|
-
|
|
102
|
-
```json
|
|
103
|
-
{ "mcp": "http://127.0.0.1:8787/mcp", "web": "http://127.0.0.1:8787/web", "quo": "http://127.0.0.1:8787/quo", "api": "http://127.0.0.1:8787/api" }
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
`serve` is the daemon, the one process over that folder, and every other
|
|
107
|
-
command is its client. From a second terminal, a phone:
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
npx nervur invite --dir ~/.nervur '{"being":"razvan","id":"phone"}'
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
The answer carries `link`, the ward's page with the invitation in its
|
|
114
|
-
fragment. Opened on the phone, the tab boots a harbor of its own, joins as
|
|
115
|
-
that device, and is in: no account, nothing typed. What a model gets is
|
|
116
|
-
the same world as tools at `mcp.`, what a program gets is the same asks as
|
|
117
|
-
JSON at `api.`, and what another box gets is the door at `quo.`; a being
|
|
118
|
-
answers each the same, because each is an ask at her door.
|
|
119
|
-
|
|
120
|
-
The box's own doings are rows on the faculties of its dock ward, placed by
|
|
121
|
-
the root with `nervur ask --ward dock`: a socket held to another box, an
|
|
122
|
-
agent run for a ward, a schedule on the clock. A second box owns this one
|
|
123
|
-
across the wire with an invitation on the ward's own pk, knocked with
|
|
124
|
-
from there, and every owner command with `--via` from then on. Each of
|
|
125
|
-
those, the edge, and what an estate stands beyond the init, is the
|
|
126
|
-
"Getting started" chapter of `quo-dock.md`, proven cold on a Mac by
|
|
127
|
-
somebody with nothing else to read.
|
|
128
|
-
|
|
129
|
-
## Your own beings on a box
|
|
130
|
-
|
|
131
|
-
A box holds the dock's classes and yours. `classes/index.ts` beside the
|
|
132
|
-
wards exports each of yours by name, and `nervur boot '{"key":"shop",
|
|
133
|
-
"class":"Shop"}'` boots one; `nervur init --class Shop` makes the ward's home
|
|
134
|
-
being one of yours, an organisation's ward with the org as its being. A
|
|
135
|
-
being's asks may name who may reach them, `for`, over the record of the
|
|
136
|
-
occupant asking, and her `cells` are what she keeps between boots: the
|
|
137
|
-
whole of what a being is, in `SPEC.md`, and the words above the spec, a
|
|
138
|
-
world, a home, a membership, in `WORLDS.md` and `GLOSSARY.md`.
|
package/GLOSSARY.md
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
# GLOSSARY
|
|
2
|
-
|
|
3
|
-
Every word the papers above the spec use, in one place. The protocol's own
|
|
4
|
-
words, being, ward, harbor, standing, occupant, invitation, knock and the
|
|
5
|
-
rest, are in the glossary of `quo/SPEC.md`, which assumes nothing and
|
|
6
|
-
is not repeated here; what the library spells for itself is in
|
|
7
|
-
`papers/quo-kit.md`. A word here is a convention of the dock or of an
|
|
8
|
-
estate, and changes no word of the spec. `papers/WORLDS.md` is where the
|
|
9
|
-
first seven are reasoned; `papers/quo-dock.md` and the papers of its sides
|
|
10
|
-
are where the rest are built.
|
|
11
|
-
|
|
12
|
-
## A person and a world
|
|
13
|
-
|
|
14
|
-
- **org**: the unit every "you" names: a company, a family, a club, a
|
|
15
|
-
service, and at the smallest one human alone, an org of one. An org owns
|
|
16
|
-
wards, holds standings, trusts boxes and is trusted. Never an avatar, an
|
|
17
|
-
account or a user id; each of those is a thing an org holds.
|
|
18
|
-
- **world**: a ward, as a human sees it: one seed, one partition, one body
|
|
19
|
-
of code, one owner.
|
|
20
|
-
- **home**: the one ward an org owns on a harbor it trusts; the org's own
|
|
21
|
-
being is its being. Also that being's standing at the ward's own door as
|
|
22
|
-
an owner, `home`. One per org, and an org may have none yet.
|
|
23
|
-
- **org being**: home's own being, one per org, running day and night,
|
|
24
|
-
holding the org's standings and its members as occupants. An estate's
|
|
25
|
-
own class for an organisation; the user being for an org of one.
|
|
26
|
-
- **presence**: a ward a person owns on a harbor in her hand, one per world
|
|
27
|
-
reached from that device. The tab, the phone and the desk are presences
|
|
28
|
-
of the same shape, and nothing in a hand is a home.
|
|
29
|
-
- **presence being**: the being of a world who lives on a device, booted in
|
|
30
|
-
the presence ward when the world is joined. She lends every faculty the
|
|
31
|
-
box has at her birth and carries them, so a world reaches the device only
|
|
32
|
-
by asking her.
|
|
33
|
-
- **app**: a browser of worlds, one harbor and a presence ward per world,
|
|
34
|
-
the same shell on every terrain. It has no account and no person of its
|
|
35
|
-
own; which app a person uses is settled at home, and an adopter's app is
|
|
36
|
-
only the first one its member meets.
|
|
37
|
-
- **membership**: an id in a ward someone else owns. An employee id, a
|
|
38
|
-
member id, a customer id. Never a ward of hers.
|
|
39
|
-
- **hub**: home, as the one place every relation of hers meets.
|
|
40
|
-
- **rule**: home answering one standing by asking another.
|
|
41
|
-
- **device**: a harbor in her hand, with a ward of its own holding what that
|
|
42
|
-
box can do. One OS user is one harbor, and the app has no people of its
|
|
43
|
-
own.
|
|
44
|
-
|
|
45
|
-
## The dock
|
|
46
|
-
|
|
47
|
-
- **dock**: what every estate needs and nobody writes twice,
|
|
48
|
-
`packages/dock/`, published as `@nervur-org/dock`.
|
|
49
|
-
- **dock ward**: the ward a harbor boots and roots for itself, holding the
|
|
50
|
-
faculties that box lends. Never a home, and never migrated.
|
|
51
|
-
- **estate**: all of one owner's harbors, with what is theirs alone, in a
|
|
52
|
-
tree of the owner's own and never published.
|
|
53
|
-
- **daemon**: `nervur serve`, the one process on a device that holds a harbor.
|
|
54
|
-
- **route**: a hostname a reverse proxy sends to one process: `web.`,
|
|
55
|
-
`quo.`, `mcp.`, `api.`.
|
|
56
|
-
- **user being**: the org being of an org of one: a human's own, holding
|
|
57
|
-
all of her standings. The dock's `User` class, which also serves a
|
|
58
|
-
membership the desk makes in another org's ward.
|
|
59
|
-
- **front desk**: the being every fresh client meets; hands out invitations
|
|
60
|
-
minted by the ward's being, and is what `nervur init` marks public in a
|
|
61
|
-
fresh ward. Any ward may mark one being of any class public instead.
|
|
62
|
-
- **avatar**: a being that is someone's voice from outside Quo, one per
|
|
63
|
-
client identity.
|
|
64
|
-
- **side**: the interface an avatar speaks through to someone outside Quo:
|
|
65
|
-
a screen, an MCP server, a runner, an agent.
|
|
66
|
-
- **client identity**: what a credential exchange establishes; one avatar,
|
|
67
|
-
for life.
|
|
68
|
-
- **proof**: a vouch the front desk trades once for an invitation: the
|
|
69
|
-
daemon's nonce for a local side, or the link a world mailed to an address
|
|
70
|
-
it wants proof of. Everyone else arrives with an invitation.
|
|
71
|
-
- **way in**: a being who says who a proof of one kind is for, and who sends
|
|
72
|
-
the proof out to an address where the kind has one. The desk holds a
|
|
73
|
-
standing at each, under `way:<kind>`: the box's, lent by the dock ward,
|
|
74
|
-
and the world's own, in the world's ward.
|
|
75
|
-
- **carrier**: a being who shows her standings' asks as her own and
|
|
76
|
-
forwards. The user being and the device are two.
|
|
77
|
-
- **envoy**: a being of the org's standing in for a ward nobody here runs,
|
|
78
|
-
one being per vendor and one relation per account, on the base
|
|
79
|
-
`beings/envoy.ts`. Her asks out are the vendor's surface, narrowed; her
|
|
80
|
-
one ask in, `deliver`, is the owner's, the vendor's bytes reaching her
|
|
81
|
-
own body through the api route and never a door; her credential is in
|
|
82
|
-
her cells, placed by the owner and shown to nobody; and a delivery is one
|
|
83
|
-
ask on the way back her occupant handed her at the knock.
|
|
84
|
-
- **faculty**: a being of the dock ward, standing for one thing the box can
|
|
85
|
-
do: a timer, a line, a store, a vendor's API. Reached by `lend`, held as
|
|
86
|
-
an ordinary standing, and she wakes whoever invited her. She holds what
|
|
87
|
-
the device holds and begins holding it at birth.
|
|
88
|
-
- **ring**: one platform's way of waking a device by its token, held by the
|
|
89
|
-
push faculty: `web`, `apns`, `fcm`. It carries the banner sealed to that
|
|
90
|
-
device's banner key, and nothing else.
|
|
91
|
-
- **bell**: a ward that wakes devices, with a public being for a phone
|
|
92
|
-
nobody knows and one doorbell per device. `papers/quo-app-bells.md`.
|
|
93
|
-
- **doorbell**: one device's being at a bell. Its cells hold that device's
|
|
94
|
-
platform token, and its occupants are the worlds that device allowed to
|
|
95
|
-
wake it, one standing each.
|
|
96
|
-
- **porter**: a bell's public being, where a phone nobody knows arrives as
|
|
97
|
-
`{}` and comes away with a doorbell of its own.
|
|
98
|
-
- **banner key**: the pair a device keeps in the cells of its notifications
|
|
99
|
-
faculty. A world seals a notification to its public half; the secret half
|
|
100
|
-
opens banners and nothing else, and never the world.
|
|
101
|
-
- **timer**: the faculty that reads the box's clock, and the only thing on a
|
|
102
|
-
device that may. She wakes whoever invited her, every minute.
|
|
103
|
-
- **clock**: the being who wakes beings at a time, on standings the root
|
|
104
|
-
placed. She holds the schedules and invited the timer.
|
|
105
|
-
- **gate**: `for(occupant, asker)`; the whole permission model.
|
|
106
|
-
- **look**: how a being is presented, as values; one optional ask.
|
|
107
|
-
- **page**: a being's page as a tree of values in the screen's grammar; one
|
|
108
|
-
optional ask, read by a screen alone.
|
|
109
|
-
- **owner pilot**: `nervur pilot`, the model side over a ward's owner asks,
|
|
110
|
-
reaching the daemon's socket; with `--via`, a ward elsewhere through a
|
|
111
|
-
standing. Under cron, the estate's own agent.
|
|
112
|
-
|
|
113
|
-
## The model side
|
|
114
|
-
|
|
115
|
-
- **constitution**: the folder and instructions an autonomous agent runs
|
|
116
|
-
under; governance, never permission.
|
|
117
|
-
- **runner**: an inline MCP client for a model that speaks function
|
|
118
|
-
calling; it drives the loop the MCP client would, over one conversation.
|