nervur 0.15.0 → 0.17.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.
Files changed (116) hide show
  1. package/GETTING_STARTED.md +138 -0
  2. package/LICENSE +2 -1
  3. package/NOTICE +6 -0
  4. package/README.md +119 -151
  5. package/dist/being/being.d.ts +24 -0
  6. package/dist/being/being.js +109 -0
  7. package/dist/being/digest.d.ts +3 -0
  8. package/dist/being/digest.js +37 -0
  9. package/dist/being/index.d.ts +5 -0
  10. package/dist/being/index.js +6 -0
  11. package/dist/being/silence.d.ts +12 -0
  12. package/dist/being/silence.js +41 -0
  13. package/dist/being/types.d.ts +89 -0
  14. package/dist/being/types.js +58 -0
  15. package/dist/conformance/assert.d.ts +11 -0
  16. package/dist/conformance/assert.js +106 -0
  17. package/dist/conformance/beings.d.ts +198 -0
  18. package/dist/conformance/beings.js +183 -0
  19. package/dist/conformance/estate.d.ts +5 -0
  20. package/dist/conformance/estate.js +388 -0
  21. package/dist/conformance/index.d.ts +81 -0
  22. package/dist/conformance/index.js +816 -0
  23. package/dist/conformance/reach.d.ts +10 -0
  24. package/dist/conformance/reach.js +72 -0
  25. package/dist/conformance/store.d.ts +5 -0
  26. package/dist/conformance/store.js +123 -0
  27. package/dist/harbor/core.d.ts +53 -0
  28. package/dist/harbor/core.js +621 -0
  29. package/dist/harbor/dial.d.ts +9 -0
  30. package/dist/harbor/dial.js +81 -0
  31. package/dist/harbor/index.d.ts +8 -0
  32. package/dist/harbor/index.js +16 -0
  33. package/dist/harbor/memory.d.ts +25 -0
  34. package/dist/harbor/memory.js +72 -0
  35. package/dist/harbor/reach.d.ts +36 -0
  36. package/dist/harbor/reach.js +191 -0
  37. package/dist/harbor/store.d.ts +40 -0
  38. package/dist/harbor/store.js +70 -0
  39. package/dist/vector/cases.d.ts +41 -0
  40. package/dist/vector/cases.js +195 -0
  41. package/dist/vector/index.d.ts +6 -0
  42. package/dist/vector/index.js +8 -0
  43. package/dist/vector/stand.d.ts +9 -0
  44. package/dist/vector/stand.js +76 -0
  45. package/dist/vector/world.d.ts +143 -0
  46. package/dist/vector/world.js +198 -0
  47. package/dist/ward/allowance.d.ts +10 -0
  48. package/dist/ward/allowance.js +71 -0
  49. package/dist/ward/arithmetic.d.ts +31 -0
  50. package/dist/ward/arithmetic.js +245 -0
  51. package/dist/ward/cells.d.ts +7 -0
  52. package/dist/ward/cells.js +186 -0
  53. package/dist/ward/door.d.ts +18 -0
  54. package/dist/ward/door.js +186 -0
  55. package/dist/ward/ground.d.ts +23 -0
  56. package/dist/ward/ground.js +38 -0
  57. package/dist/ward/heirs.d.ts +13 -0
  58. package/dist/ward/heirs.js +115 -0
  59. package/dist/ward/index.d.ts +9 -0
  60. package/dist/ward/index.js +13 -0
  61. package/dist/ward/owner.d.ts +13 -0
  62. package/dist/ward/owner.js +220 -0
  63. package/dist/ward/partition.d.ts +65 -0
  64. package/dist/ward/partition.js +295 -0
  65. package/dist/ward/seal.d.ts +52 -0
  66. package/dist/ward/seal.js +145 -0
  67. package/dist/ward/stance.d.ts +25 -0
  68. package/dist/ward/stance.js +413 -0
  69. package/dist/ward/ward.d.ts +12 -0
  70. package/dist/ward/ward.js +361 -0
  71. package/package.json +51 -11
  72. package/protocol/SPEC.md +1843 -0
  73. package/protocol/vectors/arithmetic.json +117 -0
  74. package/protocol/vectors/door.json +345 -0
  75. package/protocol/vectors/framing.json +92 -0
  76. package/protocol/vectors/wire.json +48 -0
  77. package/quo-kit.md +652 -0
  78. package/src/being/being.ts +123 -0
  79. package/src/being/digest.ts +46 -0
  80. package/src/being/index.ts +7 -0
  81. package/src/being/silence.ts +46 -0
  82. package/src/being/types.ts +170 -0
  83. package/src/conformance/assert.ts +100 -0
  84. package/src/conformance/beings.ts +183 -0
  85. package/src/conformance/estate.ts +412 -0
  86. package/src/conformance/index.ts +962 -0
  87. package/src/conformance/reach.ts +83 -0
  88. package/src/conformance/store.ts +136 -0
  89. package/src/harbor/core.ts +660 -0
  90. package/src/harbor/dial.ts +112 -0
  91. package/src/harbor/index.ts +17 -0
  92. package/src/harbor/memory.ts +83 -0
  93. package/src/harbor/reach.ts +215 -0
  94. package/src/harbor/store.ts +101 -0
  95. package/src/vector/cases.ts +229 -0
  96. package/src/vector/index.ts +11 -0
  97. package/src/vector/stand.ts +75 -0
  98. package/src/vector/world.ts +220 -0
  99. package/src/ward/allowance.ts +85 -0
  100. package/src/ward/arithmetic.ts +247 -0
  101. package/src/ward/cells.ts +190 -0
  102. package/src/ward/door.ts +186 -0
  103. package/src/ward/ground.ts +160 -0
  104. package/src/ward/heirs.ts +114 -0
  105. package/src/ward/index.ts +17 -0
  106. package/src/ward/owner.ts +214 -0
  107. package/src/ward/partition.ts +353 -0
  108. package/src/ward/seal.ts +174 -0
  109. package/src/ward/stance.ts +433 -0
  110. package/src/ward/ward.ts +378 -0
  111. package/src/being.js +0 -125
  112. package/src/contract.js +0 -161
  113. package/src/ground.js +0 -273
  114. package/src/index.js +0 -5
  115. package/src/program.js +0 -74
  116. package/src/projection.js +0 -102
@@ -0,0 +1,41 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Silence is one distinguished value. Null is an answer. Silence is no answer.
3
+ //
4
+ // The ward's words are the other distinguished values: what her ward tells
5
+ // her when no object came back and it knows why. Each is one frozen object
6
+ // under one symbol key, so a being cannot make one by accident, none of them
7
+ // crosses an edge as a value, and a being who compares against them needs
8
+ // no fourth shape. `unreached` is one of them.
9
+ import { WORD_KEY } from './types.js';
10
+ export const silence = Symbol.for('quo.silence');
11
+ export const isSilence = (x) => x === silence;
12
+ // The words a door says to a key it has bound, and no other. They ride on
13
+ // the wire as `{ quo: word }`, so a reply is checked against this list.
14
+ export const DOOR_WORDS = ['removed', 'absent', 'unannounced', 'repeated', 'threw'];
15
+ export const isDoorWord = (s) => typeof s === 'string' && DOOR_WORDS.includes(s);
16
+ const WORDS = new Map();
17
+ export const word = (name) => {
18
+ let w = WORDS.get(name);
19
+ if (!w)
20
+ WORDS.set(name, (w = Object.freeze({ [WORD_KEY]: name })));
21
+ return w;
22
+ };
23
+ export const isWord = (x) => x !== null && typeof x === 'object' && typeof x[WORD_KEY] === 'string';
24
+ export const wordOf = (x) => x[WORD_KEY];
25
+ // What came back is an answer and not one of the two things that are not
26
+ // answers. A being who only wants the object writes one test instead of
27
+ // three, and the three shapes stay three shapes: silence is no answer, a word
28
+ // is her ward telling her why there is none.
29
+ export const answered = (x) => !isSilence(x) && !isWord(x);
30
+ // What she was told, with a word given its name and everything else left
31
+ // exactly as it came. One value to compare against, so asking which word came
32
+ // back is one test and not two joined by an and: `told(out) === 'late'` says
33
+ // what `isWord(out) && wordOf(out) === 'late'` says, and says which answer
34
+ // arrived instead when it is wrong, where the pair collapses to false and
35
+ // names nothing. Silence stays the symbol it is, and an object stays itself.
36
+ export const told = (x) => (isWord(x) ? wordOf(x) : x);
37
+ // Unreached: no far door was reached. Nothing is known to have been
38
+ // delivered, so asking again is safe. A being cannot produce it: a ward that
39
+ // sees a word come out of a being reads it as her having thrown.
40
+ export const unreached = () => word('unreached');
41
+ export const isUnreached = (x) => isWord(x) && wordOf(x) === 'unreached';
@@ -0,0 +1,89 @@
1
+ import type { silence } from './silence.ts';
2
+ export type Json = null | boolean | number | string | Json[] | {
3
+ [key: string]: Json;
4
+ };
5
+ export type JsonObject = {
6
+ [key: string]: Json;
7
+ };
8
+ export type Asker = {
9
+ id: string;
10
+ } | {
11
+ id?: undefined;
12
+ };
13
+ export declare const OWNER = "OWNER";
14
+ export declare const PUBLIC = "PUBLIC";
15
+ export declare const RESERVED_IDS: readonly string[];
16
+ export type Invitation = {
17
+ ward: string;
18
+ heir?: string;
19
+ secret?: string;
20
+ };
21
+ export declare const invitationArgs: (inv: Invitation) => JsonObject;
22
+ export declare const isInvitation: (v: unknown) => v is Invitation;
23
+ export type Schema = JsonObject;
24
+ export type Ask = {
25
+ name: string;
26
+ description?: string;
27
+ input: Schema;
28
+ output?: Schema;
29
+ };
30
+ export type Blueprint = {
31
+ asks: Ask[];
32
+ notes: Json;
33
+ };
34
+ export declare const isBlueprint: (v: unknown) => v is Blueprint;
35
+ export type StandingRecord = {
36
+ id: string;
37
+ digest: string | null;
38
+ blueprint: Blueprint | null;
39
+ seen: string | null;
40
+ };
41
+ export type OccupantRecord = {
42
+ id: string;
43
+ notes: JsonObject;
44
+ };
45
+ export type Cells = {
46
+ standings: Record<string, StandingRecord>;
47
+ occupants: Record<string, OccupantRecord>;
48
+ [hers: string]: Json;
49
+ };
50
+ export type Silence = typeof silence;
51
+ export type DoorWord = 'removed' | 'absent' | 'unannounced' | 'repeated' | 'threw';
52
+ export type WardWord = 'unreached' | 'late' | 'invitation' | 'dropped';
53
+ export type WordName = DoorWord | WardWord;
54
+ export declare const WORD_KEY: unique symbol;
55
+ export type Word<W extends WordName = WordName> = {
56
+ readonly [K in typeof WORD_KEY]: W;
57
+ };
58
+ export type Unreached = Word<'unreached'>;
59
+ export type Answer = Json | Silence | Word;
60
+ export type Reply = Json | Silence;
61
+ export type Wanted = {
62
+ time?: number;
63
+ };
64
+ export type Standing = {
65
+ readonly id: string;
66
+ ask(method?: string, args?: JsonObject, wanted?: Wanted): Promise<Answer>;
67
+ };
68
+ export type Standings = {
69
+ knock(invitation: Invitation, method?: string, args?: JsonObject, wanted?: Wanted): Promise<Answer>;
70
+ take(id: string, invitation: Invitation): Promise<string | null>;
71
+ remove(id: string): void;
72
+ } & {
73
+ readonly [id: string]: Standing | undefined;
74
+ };
75
+ export type Occupants = {
76
+ invite(id: string, notes?: JsonObject): Promise<Invitation | null>;
77
+ remove(id: string): void;
78
+ };
79
+ export type Stance = {
80
+ readonly cells: Cells;
81
+ readonly occupants: Occupants;
82
+ readonly standings: Standings;
83
+ lend(name: string, id: string): Promise<string | null>;
84
+ boot(className: string, key: string, id?: string): Promise<string | null>;
85
+ };
86
+ export interface BeingLike {
87
+ answer(asker: Asker, method?: string, args?: JsonObject): Reply | Promise<Reply>;
88
+ }
89
+ export type BeingClass = new (stance: Stance) => BeingLike;
@@ -0,0 +1,58 @@
1
+ // The ids the ward speaks under, and no being may mint. An asker id is hers:
2
+ // she chooses the strings, and the ward has no business in her namespace. But
3
+ // the ward must sometimes stand at her door itself — its describe asks every
4
+ // being under OWNER — and an id it shares with one of her occupants is two
5
+ // different parties wearing one name. She could not tell them apart, and the
6
+ // ward would shape its describe through an occupant's gate.
7
+ //
8
+ // So the ward's words are shouted, and refused at the mint. A word can only
9
+ // be reserved before anyone has used it: a partition already holding an
10
+ // occupant of that name could never have it taken back. PUBLIC guards nothing
11
+ // today — a public asker is {} and carries no id at all — and that is exactly
12
+ // why it is claimed now, while claiming it is free.
13
+ export const OWNER = 'OWNER';
14
+ export const PUBLIC = 'PUBLIC';
15
+ export const RESERVED_IDS = [OWNER, PUBLIC];
16
+ // An invitation as one object of values, which is what it already is. A being
17
+ // who hands one on sends it as args, and args are values; this is the one
18
+ // place that is spelled, so nobody spells it with a cast. Absent stays absent:
19
+ // an invitation to a public being carries no heir and no secret, and a key
20
+ // present and undefined is not the same object once JSON has been through it.
21
+ export const invitationArgs = (inv) => ({
22
+ ward: inv.ward,
23
+ ...(inv.heir !== undefined ? { heir: inv.heir } : {}),
24
+ ...(inv.secret !== undefined ? { secret: inv.secret } : {}),
25
+ });
26
+ // Whether a value that arrived is an invitation. The shape is the spec's, so
27
+ // the reading of it is too, and it is one reading: a form that
28
+ // asks a guest for one, a faculty handed one to wake her maker by, and a
29
+ // shell that finds one in a link all ask the same question, and a kinder
30
+ // answer in one of them is a value that fails at a door instead of at the
31
+ // edge it came in by. A ward pk is a hundred and twenty-eight lowercase hex,
32
+ // and a heir comes with its secret or neither comes: an invitation to a
33
+ // public being carries no heir, and a heir with no secret opens nothing.
34
+ export const isInvitation = (v) => {
35
+ if (v === null || typeof v !== 'object' || Array.isArray(v))
36
+ return false;
37
+ const o = v;
38
+ if (typeof o.ward !== 'string' || !/^[0-9a-f]{128}$/.test(o.ward))
39
+ return false;
40
+ const heir = typeof o.heir === 'string', secret = typeof o.secret === 'string';
41
+ return (heir && secret) || (!heir && !secret && !('heir' in o) && !('secret' in o));
42
+ };
43
+ // Whether what came back from an empty ask is a blueprint. Every describe on
44
+ // the far side of a door is somebody else's code, so nothing may be written
45
+ // into a standing's record as a blueprint without being read as one first: a
46
+ // side walks `asks` by name, and a list of anything else, or no list at all,
47
+ // is a side that breaks on a far ward's answer. The asks are checked to the
48
+ // depth a side reads them, a name and an input each, and no further: what a
49
+ // far being puts beside those is hers.
50
+ export const isBlueprint = (v) => {
51
+ if (v === null || typeof v !== 'object' || Array.isArray(v))
52
+ return false;
53
+ const { asks, notes } = v;
54
+ if (!Array.isArray(asks) || notes === undefined)
55
+ return false;
56
+ return asks.every((a) => a !== null && typeof a === 'object' && !Array.isArray(a) && typeof a.name === 'string' && a.input !== null && typeof a.input === 'object' && !Array.isArray(a.input));
57
+ };
58
+ export const WORD_KEY = Symbol.for('quo.word');
@@ -0,0 +1,11 @@
1
+ export declare class Failed extends Error {
2
+ }
3
+ export declare function same(a: unknown, b: unknown): boolean;
4
+ export type Assert = {
5
+ ok(value: unknown, message?: string): asserts value;
6
+ equal(actual: unknown, expected: unknown, message?: string): void;
7
+ notEqual(actual: unknown, expected: unknown, message?: string): void;
8
+ deepEqual(actual: unknown, expected: unknown, message?: string): void;
9
+ match(actual: string, re: RegExp, message?: string): void;
10
+ };
11
+ export declare const assert: Assert;
@@ -0,0 +1,106 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // The five assertions the conformance suite makes, and no more. Node has all
3
+ // five in `node:assert/strict`, and naming that module would tie the suite to
4
+ // one terrain -- the suite is the ward's truth, and the ward's truth has to be
5
+ // checkable wherever a ward runs. So they are written here, in the language
6
+ // alone, and `test/assert.test.ts` holds them to Node's own behaviour.
7
+ export class Failed extends Error {
8
+ }
9
+ const show = (v) => {
10
+ if (typeof v === 'symbol')
11
+ return v.toString();
12
+ if (typeof v === 'bigint')
13
+ return `${v}n`;
14
+ if (v === undefined)
15
+ return 'undefined';
16
+ if (typeof v === 'function')
17
+ return `[function ${v.name}]`;
18
+ // A ward's word is a frozen object under one symbol key, and JSON shows it
19
+ // as `{}`. A red estate chapter saying `{} is not {}` names nothing, so a
20
+ // value whose own keys are all symbols is shown by its keys.
21
+ if (v !== null && typeof v === 'object') {
22
+ const keys = Object.keys(v);
23
+ const syms = Object.getOwnPropertySymbols(v).filter((s) => Object.getOwnPropertyDescriptor(v, s).enumerable);
24
+ if (keys.length === 0 && syms.length > 0)
25
+ return `{ ${syms.map((s) => `${s.toString()}: ${show(v[s])}`).join(', ')} }`;
26
+ }
27
+ try {
28
+ return JSON.stringify(v) ?? Object.prototype.toString.call(v);
29
+ }
30
+ catch {
31
+ return Object.prototype.toString.call(v); // a cycle, or a null prototype
32
+ }
33
+ };
34
+ const fail = (why, message) => {
35
+ throw new Failed(message ? `${message}: ${why}` : why);
36
+ };
37
+ // Structural, and strict about shape the way `node:assert/strict` is: a value
38
+ // is not equal to one of another kind, and an array is not equal to an object
39
+ // that happens to hold the same keys.
40
+ // The four kinds this compares, and every other object is refused rather than
41
+ // guessed at. A Date, a RegExp, a boxed primitive and a class instance each
42
+ // carry state no key walk can see, so two of them with the same keys are
43
+ // equal here and unequal in node, which is a wrong yes: the one answer a
44
+ // suite must never give. A refusal is a red test that says so.
45
+ const KNOWN = [Object.prototype, null, Array.prototype, Uint8Array.prototype];
46
+ // What node compares: own enumerable keys, strings then enumerable symbols.
47
+ // Not `Reflect.ownKeys`, which also lists what a definition hid.
48
+ const keysOf = (v) => [...Object.keys(v), ...Object.getOwnPropertySymbols(v).filter((s) => Object.getOwnPropertyDescriptor(v, s).enumerable)];
49
+ export function same(a, b) {
50
+ if (Object.is(a, b))
51
+ return true;
52
+ if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null)
53
+ return false;
54
+ const proto = Object.getPrototypeOf(a);
55
+ if (proto !== Object.getPrototypeOf(b))
56
+ return false;
57
+ if (!KNOWN.includes(proto))
58
+ return false; // a Date, a RegExp, a boxed number, a class of hers
59
+ if (Array.isArray(a) !== Array.isArray(b))
60
+ return false;
61
+ if (a instanceof Uint8Array && b instanceof Uint8Array)
62
+ return a.length === b.length && a.every((x, i) => x === b[i]);
63
+ // An array is its indices and whatever else was hung on it, and a hole is
64
+ // not a present undefined: `[, 1]` and `[undefined, 1]` differ in node and
65
+ // must differ here. `every` skips holes, so the loop is written out.
66
+ if (Array.isArray(a) && Array.isArray(b)) {
67
+ if (a.length !== b.length)
68
+ return false;
69
+ for (let i = 0; i < a.length; i += 1) {
70
+ if (i in a !== i in b)
71
+ return false;
72
+ if (i in a && !same(a[i], b[i]))
73
+ return false;
74
+ }
75
+ const extra = (v) => keysOf(v).filter((k) => typeof k !== 'string' || !/^(?:0|[1-9]\d*)$/.test(k));
76
+ const xa = extra(a), xb = extra(b);
77
+ const at = (v, k) => v[k];
78
+ return xa.length === xb.length && xa.every((k) => xb.includes(k) && same(at(a, k), at(b, k)));
79
+ }
80
+ const ka = keysOf(a), kb = keysOf(b);
81
+ if (ka.length !== kb.length)
82
+ return false;
83
+ return ka.every((k) => kb.includes(k) && same(a[k], b[k]));
84
+ }
85
+ export const assert = {
86
+ ok(value, message) {
87
+ if (!value)
88
+ fail(`${show(value)} is not truthy`, message);
89
+ },
90
+ equal(actual, expected, message) {
91
+ if (!Object.is(actual, expected))
92
+ fail(`${show(actual)} !== ${show(expected)}`, message);
93
+ },
94
+ notEqual(actual, expected, message) {
95
+ if (Object.is(actual, expected))
96
+ fail(`${show(actual)} === ${show(expected)}`, message);
97
+ },
98
+ deepEqual(actual, expected, message) {
99
+ if (!same(actual, expected))
100
+ fail(`${show(actual)} is not ${show(expected)}`, message);
101
+ },
102
+ match(actual, re, message) {
103
+ if (typeof actual !== 'string' || !re.test(actual))
104
+ fail(`${show(actual)} does not match ${String(re)}`, message);
105
+ },
106
+ };
@@ -0,0 +1,198 @@
1
+ import { Being } from '../being/being.ts';
2
+ import type { Asker, Blueprint, Invitation, Json, JsonObject, OccupantRecord, Reply, Stance } from '../being/types.ts';
3
+ export declare class Printer extends Being {
4
+ static cells: {
5
+ jobs: JsonObject[];
6
+ asks: JsonObject[];
7
+ };
8
+ static asks: {
9
+ print: {
10
+ input: {
11
+ type: string;
12
+ };
13
+ };
14
+ };
15
+ describe(): Blueprint;
16
+ print({ doc }: JsonObject, asker: Asker): {
17
+ printed: string | number | boolean | Json[] | {
18
+ [key: string]: Json;
19
+ } | null;
20
+ };
21
+ }
22
+ export declare class Shop extends Being {
23
+ static cells: {
24
+ printerId: string | null;
25
+ sales: JsonObject[];
26
+ minted: number;
27
+ };
28
+ static asks: {
29
+ hello: {
30
+ input: {
31
+ type: string;
32
+ };
33
+ };
34
+ buy: {
35
+ input: {
36
+ type: string;
37
+ properties: {
38
+ item: {
39
+ type: string;
40
+ };
41
+ };
42
+ };
43
+ };
44
+ refund: {
45
+ input: {
46
+ type: string;
47
+ };
48
+ for: (rec: OccupantRecord | undefined) => boolean;
49
+ };
50
+ };
51
+ answer(asker: Asker, method?: string, args?: JsonObject): Promise<Reply>;
52
+ invite(tier?: string): Promise<Invitation>;
53
+ keepPrinter(invitation: Invitation): Promise<boolean>;
54
+ hello({ invitation }: JsonObject, asker: Asker): Promise<{
55
+ welcome: boolean;
56
+ }>;
57
+ buy({ item }: JsonObject, asker: Asker): Promise<{
58
+ error: string;
59
+ retry?: undefined;
60
+ ok?: undefined;
61
+ receipt?: undefined;
62
+ } | {
63
+ error: string;
64
+ retry: boolean;
65
+ ok?: undefined;
66
+ receipt?: undefined;
67
+ } | {
68
+ error?: undefined;
69
+ retry?: undefined;
70
+ ok: boolean;
71
+ receipt: Json;
72
+ }>;
73
+ refund(): {
74
+ ok: boolean;
75
+ };
76
+ }
77
+ export declare class Customer extends Being {
78
+ static cells: {
79
+ heard: JsonObject[];
80
+ };
81
+ static asks: {
82
+ hi: {
83
+ input: {
84
+ type: string;
85
+ };
86
+ };
87
+ };
88
+ join(invitation: Invitation): Promise<string | number | boolean | typeof import("../being/silence.ts").silence | Json[] | import("../being/types.ts").Word<import("../being/types.ts").WordName> | {
89
+ [key: string]: Json;
90
+ } | null>;
91
+ buy(item: string): Promise<import("../being/types.ts").Answer>;
92
+ learn(): Promise<import("../being/types.ts").Answer>;
93
+ hi(_args: JsonObject, asker: Asker): {
94
+ heard: string;
95
+ };
96
+ }
97
+ export declare class Echo {
98
+ s: Stance;
99
+ constructor(stance: Stance);
100
+ answer(asker: Asker, method?: string, args?: JsonObject): Reply;
101
+ }
102
+ export declare class Maker extends Being {
103
+ static cells: {
104
+ made: string[];
105
+ };
106
+ static asks: {
107
+ open: {
108
+ input: {
109
+ type: string;
110
+ properties: {
111
+ class: {
112
+ type: string;
113
+ };
114
+ key: {
115
+ type: string;
116
+ };
117
+ id: {
118
+ type: string;
119
+ };
120
+ };
121
+ required: string[];
122
+ };
123
+ };
124
+ say: {
125
+ input: {
126
+ type: string;
127
+ properties: {
128
+ id: {
129
+ type: string;
130
+ };
131
+ };
132
+ required: string[];
133
+ };
134
+ };
135
+ borrow: {
136
+ input: {
137
+ type: string;
138
+ properties: {
139
+ name: {
140
+ type: string;
141
+ };
142
+ id: {
143
+ type: string;
144
+ };
145
+ };
146
+ required: string[];
147
+ };
148
+ };
149
+ };
150
+ open({ class: className, key, id }: JsonObject): Promise<{
151
+ made: string | null;
152
+ }>;
153
+ say({ id }: JsonObject): Promise<{
154
+ said: Json;
155
+ }>;
156
+ borrow({ name, id }: JsonObject): Promise<{
157
+ lent: string | null;
158
+ }>;
159
+ }
160
+ export declare class Member extends Being {
161
+ static cells: {
162
+ heard: JsonObject[];
163
+ };
164
+ static asks: {
165
+ ping: {
166
+ input: {
167
+ type: string;
168
+ };
169
+ };
170
+ relay: {
171
+ input: {
172
+ type: string;
173
+ properties: {
174
+ id: {
175
+ type: string;
176
+ };
177
+ method: {
178
+ type: string;
179
+ };
180
+ time: {
181
+ type: string;
182
+ };
183
+ };
184
+ required: string[];
185
+ };
186
+ };
187
+ };
188
+ ping(_args: JsonObject, asker: Asker): {
189
+ pong: string | null;
190
+ };
191
+ relay({ id, method, args, time }: JsonObject): Promise<{
192
+ said: string;
193
+ out: null;
194
+ } | {
195
+ said: null;
196
+ out: Json;
197
+ }>;
198
+ }