@idleware/ringi 0.6.1 → 0.7.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 +7 -18
- package/package.json +1 -1
- package/src/main/resources/profiles/a2a-1.json +0 -4
- package/src/main/resources/skill/ringi/SKILL.md +2 -18
- package/target/dts/adapters/host-posix/index.d.ts +2 -2
- package/target/dts/adapters/transport-git/branches.d.ts +2 -3
- package/target/dts/adapters/transport-git/index.d.ts +0 -1
- package/target/dts/adapters/transport-git/remote/types.d.ts +0 -1
- package/target/dts/adapters/transport-git/repo.d.ts +0 -1
- package/target/dts/clients/cli/agent/index.d.ts +0 -2
- package/target/dts/clients/cli/shared/index.d.ts +0 -1
- package/target/dts/core/agents/heartbeat/index.d.ts +2 -5
- package/target/dts/core/agents/heartbeat/pulse.d.ts +1 -3
- package/target/dts/core/agents/overview.d.ts +1 -5
- package/target/dts/core/agents/ports/host.d.ts +5 -37
- package/target/dts/core/agents/sessions/agent.d.ts +0 -17
- package/target/dts/core/agents/sessions/index.d.ts +0 -1
- package/target/dts/core/hub/history/index.d.ts +1 -11
- package/target/dts/core/hub/ports/store.d.ts +1 -5
- package/target/dts/core/hub/protocol/model.d.ts +0 -1
- package/target/dts/core/hub/protocol/reading.d.ts +0 -1
- package/target/dts/core/hub/rooms/index.d.ts +0 -4
- package/target/dts/core/hub/rooms/messages.d.ts +0 -1
- package/target/dts/core/hub/rooms/rooms.d.ts +1 -1
- package/target/dts/core/hub/signals/model.d.ts +0 -2
- package/target/dts/core/hub/usecases/hubs.d.ts +0 -1
- package/target/dts/core/hub/usecases/room.d.ts +0 -1
- package/target/dts/core/hub/usecases/rooms.d.ts +1 -5
- package/target/dts/core/hub/usecases/send.d.ts +0 -1
- package/target/dts/core/hub/usecases/view.d.ts +0 -22
- package/target/dts/core/hub/work/index.d.ts +0 -1
- package/target/dts/index.d.ts +0 -1
- package/target/esm/adapters/host-posix/index.js +30 -32
- package/target/esm/adapters/transport-git/branches.js +13 -20
- package/target/esm/adapters/transport-git/index.js +1 -6
- package/target/esm/adapters/transport-git/marks.js +1 -1
- package/target/esm/adapters/transport-git/remote/admit.js +0 -2
- package/target/esm/adapters/transport-git/remote/heartbeat-push.js +1 -1
- package/target/esm/adapters/transport-git/remote/main.js +1 -4
- package/target/esm/adapters/transport-git/repo.js +0 -1
- package/target/esm/clients/cli/agent/index.js +4 -10
- package/target/esm/clients/cli/arg-parse.js +1 -1
- package/target/esm/clients/cli/commands.js +6 -7
- package/target/esm/clients/cli/help.js +6 -13
- package/target/esm/clients/cli/operator/heartbeat-format.js +1 -1
- package/target/esm/clients/cli/operator/hub-commands.js +1 -1
- package/target/esm/clients/cli/operator/index.js +1 -1
- package/target/esm/clients/cli/operator/room.js +46 -7
- package/target/esm/clients/cli/operator/where-format.js +1 -3
- package/target/esm/clients/cli/shared/index.js +1 -2
- package/target/esm/clients/cli/shared/messages.js +1 -1
- package/target/esm/clients/cli/shared/profile.js +2 -2
- package/target/esm/clients/cli/shared/work.js +1 -1
- package/target/esm/composition/index.js +1 -3
- package/target/esm/core/agents/heartbeat/index.js +16 -23
- package/target/esm/core/agents/heartbeat/pulse.js +18 -33
- package/target/esm/core/agents/heartbeat/tools.js +1 -2
- package/target/esm/core/agents/overview.js +5 -6
- package/target/esm/core/agents/ports/host.js +2 -2
- package/target/esm/core/agents/sessions/agent.js +3 -23
- package/target/esm/core/agents/sessions/binding.js +5 -7
- package/target/esm/core/agents/sessions/index.js +3 -7
- package/target/esm/core/agents/sessions/join.js +1 -5
- package/target/esm/core/agents/sessions/resume.js +3 -4
- package/target/esm/core/agents/sessions/wait.js +10 -31
- package/target/esm/core/hub/capabilities.js +4 -2
- package/target/esm/core/hub/history/index.js +3 -1
- package/target/esm/core/hub/ports/store.js +3 -3
- package/target/esm/core/hub/protocol/index.js +3 -3
- package/target/esm/core/hub/protocol/model.js +2 -3
- package/target/esm/core/hub/protocol/reading.js +1 -3
- package/target/esm/core/hub/rooms/compat.js +1 -2
- package/target/esm/core/hub/rooms/hubs.js +2 -5
- package/target/esm/core/hub/rooms/index.js +3 -3
- package/target/esm/core/hub/rooms/messages.js +5 -10
- package/target/esm/core/hub/rooms/rooms.js +9 -38
- package/target/esm/core/hub/signals/effective.js +1 -21
- package/target/esm/core/hub/signals/index.js +2 -2
- package/target/esm/core/hub/signals/pins.js +1 -1
- package/target/esm/core/hub/usecases/hubs.js +0 -3
- package/target/esm/core/hub/usecases/room.js +2 -3
- package/target/esm/core/hub/usecases/rooms.js +4 -17
- package/target/esm/core/hub/usecases/roster.js +1 -1
- package/target/esm/core/hub/usecases/send.js +2 -12
- package/target/esm/core/hub/usecases/view.js +2 -6
- package/target/esm/core/hub/work/task.js +4 -11
- package/target/esm/index.js +1 -2
- package/target/esm/lib/json.js +1 -1
- package/target/dts/adapters/host-posix/group-state.d.ts +0 -7
- package/target/dts/adapters/host-posix/groups.d.ts +0 -1
- package/target/dts/adapters/host-posix/launch.d.ts +0 -7
- package/target/dts/adapters/host-posix/probes.d.ts +0 -5
- package/target/dts/adapters/host-posix/stats.d.ts +0 -9
- package/target/dts/adapters/transport-kafka/index.d.ts +0 -2
- package/target/dts/adapters/transport-temporal/index.d.ts +0 -2
- package/target/dts/clients/cli/operator/room-lifecycle.d.ts +0 -5
- package/target/dts/clients/cli/operator/room-list.d.ts +0 -5
- package/target/dts/clients/cli/operator/room-members.d.ts +0 -4
- package/target/dts/clients/cli/operator/watch.d.ts +0 -2
- package/target/dts/clients/cli/shared/budget.d.ts +0 -7
- package/target/dts/core/agents/turns/budgets.d.ts +0 -5
- package/target/dts/core/agents/turns/dispatch.d.ts +0 -9
- package/target/dts/core/agents/turns/exhaustion.d.ts +0 -11
- package/target/dts/core/agents/turns/grants.d.ts +0 -4
- package/target/dts/core/agents/turns/index.d.ts +0 -4
- package/target/dts/core/agents/turns/limits.d.ts +0 -2
- package/target/dts/core/agents/turns/messages.d.ts +0 -10
- package/target/dts/core/agents/turns/pings.d.ts +0 -5
- package/target/dts/core/agents/turns/plan.d.ts +0 -3
- package/target/dts/core/agents/turns/poll.d.ts +0 -8
- package/target/dts/core/agents/turns/results.d.ts +0 -3
- package/target/dts/core/agents/turns/seat.d.ts +0 -2
- package/target/dts/core/agents/turns/types.d.ts +0 -59
- package/target/dts/core/hub/decisions/budget.d.ts +0 -15
- package/target/dts/core/hub/decisions/check.d.ts +0 -6
- package/target/dts/core/hub/decisions/index.d.ts +0 -5
- package/target/dts/core/hub/decisions/proposal.d.ts +0 -38
- package/target/dts/core/hub/decisions/usage.d.ts +0 -12
- package/target/dts/core/hub/usecases/budget.d.ts +0 -23
- package/target/dts/core/hub/usecases/propose.d.ts +0 -17
- package/target/esm/adapters/host-posix/group-state.js +0 -24
- package/target/esm/adapters/host-posix/groups.js +0 -43
- package/target/esm/adapters/host-posix/launch.js +0 -80
- package/target/esm/adapters/host-posix/probes.js +0 -66
- package/target/esm/adapters/host-posix/stats.js +0 -27
- package/target/esm/adapters/transport-kafka/index.js +0 -4
- package/target/esm/adapters/transport-temporal/index.js +0 -4
- package/target/esm/clients/cli/operator/room-lifecycle.js +0 -23
- package/target/esm/clients/cli/operator/room-list.js +0 -27
- package/target/esm/clients/cli/operator/room-members.js +0 -15
- package/target/esm/clients/cli/operator/watch.js +0 -15
- package/target/esm/clients/cli/shared/budget.js +0 -50
- package/target/esm/core/agents/turns/budgets.js +0 -48
- package/target/esm/core/agents/turns/dispatch.js +0 -40
- package/target/esm/core/agents/turns/exhaustion.js +0 -16
- package/target/esm/core/agents/turns/grants.js +0 -36
- package/target/esm/core/agents/turns/index.js +0 -33
- package/target/esm/core/agents/turns/limits.js +0 -11
- package/target/esm/core/agents/turns/messages.js +0 -32
- package/target/esm/core/agents/turns/pings.js +0 -30
- package/target/esm/core/agents/turns/plan.js +0 -29
- package/target/esm/core/agents/turns/poll.js +0 -48
- package/target/esm/core/agents/turns/results.js +0 -40
- package/target/esm/core/agents/turns/seat.js +0 -44
- package/target/esm/core/agents/turns/types.js +0 -3
- package/target/esm/core/hub/decisions/budget.js +0 -40
- package/target/esm/core/hub/decisions/check.js +0 -43
- package/target/esm/core/hub/decisions/index.js +0 -10
- package/target/esm/core/hub/decisions/proposal.js +0 -73
- package/target/esm/core/hub/decisions/usage.js +0 -39
- package/target/esm/core/hub/usecases/budget.js +0 -78
- package/target/esm/core/hub/usecases/propose.js +0 -39
|
@@ -1,48 +1,20 @@
|
|
|
1
|
-
// rooms: a room opened with its contract,
|
|
1
|
+
// rooms: a room opened with its contract, profile, members and quorum; and the root's control changes.
|
|
2
2
|
import { DEFAULT_PROFILE, parseProfile } from '../work/index.js';
|
|
3
3
|
import { locked } from '../ports/index.js';
|
|
4
4
|
import { fail, strictJson } from '../../../lib/index.js';
|
|
5
5
|
import { compose } from '../protocol/index.js';
|
|
6
6
|
import { readProfileResource } from './hubs.js';
|
|
7
7
|
import { contractAt } from './compat.js';
|
|
8
|
-
export const roomNames = (H
|
|
9
|
-
|
|
10
|
-
const missing = (H, name, quiet) => {
|
|
11
|
-
if (quiet)
|
|
12
|
-
return null;
|
|
13
|
-
const gone = roomNames(H, true).find(a => a.startsWith(`${name}@`));
|
|
14
|
-
return fail(gone ? `room ${name} is archived as ${gone}; read it with --room ${gone}` : `no room ${name} in hub ${H.name}; rooms: ${roomNames(H).join(', ') || 'none'}`);
|
|
15
|
-
};
|
|
8
|
+
export const roomNames = (H) => H.store.roomNames();
|
|
9
|
+
const missing = (H, name, quiet) => quiet ? null : fail(`no room ${name} in hub ${H.name}; rooms: ${roomNames(H).join(', ') || 'none'}`);
|
|
16
10
|
// The genesis names its room, in the root's hand: a history offered under another name is not that room.
|
|
17
11
|
const checkNamed = (s, name) => {
|
|
18
|
-
const named = s.archived ? name.slice(0, name.lastIndexOf('@')) : name;
|
|
19
12
|
const subject = s.control[0]?.rev === s.genesis ? s.control[0].text.split('\n')[0] : '(none)';
|
|
20
|
-
|
|
21
|
-
if (subject !== `room ${named}` || !archiveName)
|
|
13
|
+
if (subject !== `room ${name}`)
|
|
22
14
|
fail(`room ${name}: its genesis is "${subject}"; refusing a room's history under another name`);
|
|
23
15
|
};
|
|
24
|
-
// The contract
|
|
25
|
-
|
|
26
|
-
const contracts = (s) => {
|
|
27
|
-
const atControl = new Map();
|
|
28
|
-
let current = s.base;
|
|
29
|
-
for (const rec of s.control) {
|
|
30
|
-
current = /^Contract: ([0-9a-f]{40,64})$/m.exec(rec.text)?.[1] ?? current;
|
|
31
|
-
atControl.set(rec.rev, current);
|
|
32
|
-
}
|
|
33
|
-
return { atControl, current };
|
|
34
|
-
};
|
|
35
|
-
const authorityOf = (H, atControl) => {
|
|
36
|
-
const tables = new Map();
|
|
37
|
-
return control => {
|
|
38
|
-
const rev = control ? atControl.get(control) : undefined;
|
|
39
|
-
if (!rev)
|
|
40
|
-
return null;
|
|
41
|
-
if (!tables.has(rev))
|
|
42
|
-
tables.set(rev, contractAt(H.store, H.name, rev).authority);
|
|
43
|
-
return tables.get(rev);
|
|
44
|
-
};
|
|
45
|
-
};
|
|
16
|
+
// The contract the room follows: the hub contract it was created on, or the last one the operator moved it to.
|
|
17
|
+
const contractRev = (s) => s.control.reduce((current, rec) => /^Contract: ([0-9a-f]{40,64})$/m.exec(rec.text)?.[1] ?? current, s.base);
|
|
46
18
|
// The room's profile is fixed when the room is made: its content is copied into the genesis control entry, so no
|
|
47
19
|
// later change of the hub's profiles or contract reinterprets the room's history. Rooms made before this carry none
|
|
48
20
|
// and use the default profile of the contract they were created on.
|
|
@@ -61,11 +33,10 @@ export const openRoom = (H, name, { quiet = false } = {}) => {
|
|
|
61
33
|
if (!s)
|
|
62
34
|
return missing(H, name, quiet);
|
|
63
35
|
checkNamed(s, name);
|
|
64
|
-
const
|
|
36
|
+
const current = contractRev(s);
|
|
65
37
|
const contract = current === H.main ? H.contract : contractAt(H.store, H.name, current);
|
|
66
|
-
return { hub: H, s, name,
|
|
67
|
-
|
|
68
|
-
members: membersOf(H, s, name), quorum: quorumOf(s) };
|
|
38
|
+
return { hub: H, s, name, head: s.head, genesis: s.genesis, contractRev: current, contract,
|
|
39
|
+
profile: parseProfile(profileOf(H, s, name), `room ${name}: profile`), members: membersOf(H, s, name), quorum: quorumOf(s) };
|
|
69
40
|
};
|
|
70
41
|
export const room = (H, name) => openRoom(H, name);
|
|
71
42
|
export const ROOM_MD = (name) => `# room ${name}\n\nA ringi room: members.json lists who takes part; profile.json is what a piece of work is here, fixed when the room was made.\n`;
|
|
@@ -1,31 +1,11 @@
|
|
|
1
1
|
// effective: the signals a message made, judged on the room as it is now (thread order is fixed, so this does not
|
|
2
2
|
// change).
|
|
3
|
-
import * as D from '../decisions/index.js';
|
|
4
3
|
import { taskFor, taskOf } from '../work/index.js';
|
|
5
|
-
import { one } from '../protocol/index.js';
|
|
6
4
|
const isWorkSignal = (fx) => fx === 'opened' || fx === 'assigned' || fx.startsWith('state.');
|
|
7
5
|
// What the message did to its piece of work: opened, assigned, a state.
|
|
8
6
|
const workSignals = (R, all, m) => {
|
|
9
7
|
const work = taskFor(all, m, R.profile);
|
|
10
8
|
return work ? (taskOf(all, work, R.profile).effects.get(m.id) ?? []).filter(isWorkSignal) : [];
|
|
11
9
|
};
|
|
12
|
-
|
|
13
|
-
const ownSignals = (R, all, m) => [
|
|
14
|
-
...m.kind === 'proposal' ? ['proposed'] : [],
|
|
15
|
-
...m.kind === 'usage' && D.counted(all, R.authorityAt, m) ? [`usage.${one(m, 'usage')}`] : [],
|
|
16
|
-
];
|
|
17
|
-
// An answer to a proposal: a counted stamp, the decision, its revocation.
|
|
18
|
-
const answerSignals = (R, all, m) => {
|
|
19
|
-
const p = m.reId ? all.get(m.reId) : undefined;
|
|
20
|
-
if (p?.kind !== 'proposal' || p.bad)
|
|
21
|
-
return [];
|
|
22
|
-
const info = D.proposalOf(all, p, R.authorityAt);
|
|
23
|
-
const decided = m.kind === 'decision';
|
|
24
|
-
return [
|
|
25
|
-
...m.kind === 'stamp' && info.reviewers.includes(m.from) ? [`stamp.${one(m, 'stamp')}`] : [],
|
|
26
|
-
...decided && info.decision?.id === m.id ? [`decision.${info.decision.decision}`] : [],
|
|
27
|
-
...decided && info.revoked?.id === m.id ? ['decision.revoked'] : [],
|
|
28
|
-
];
|
|
29
|
-
};
|
|
30
|
-
export const effective = (R, all, m) => m.bad || m.invalid ? [] : [...workSignals(R, all, m), ...ownSignals(R, all, m), ...answerSignals(R, all, m)];
|
|
10
|
+
export const effective = (R, all, m) => m.bad || m.invalid ? [] : workSignals(R, all, m);
|
|
31
11
|
//# sourceMappingURL=effective.js.map
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
// after a crash between message and tag changes nothing and is restored with `signals --repair`.
|
|
12
12
|
//
|
|
13
13
|
// Marks are the second layer, in the same namespace: where attention is, not what was decided. `read` says a message
|
|
14
|
-
// reached its reader (made on delivery); `taken` says a member took a piece of work. A mark changes no state
|
|
15
|
-
//
|
|
14
|
+
// reached its reader (made on delivery); `taken` says a member took a piece of work. A mark changes no state
|
|
15
|
+
// or assignment. It is checked only for being possible: its target is an accepted message of the room, its
|
|
16
16
|
// actor a member; `read` only for a message addressed to the actor or to all, `taken` only for a message that opens
|
|
17
17
|
// work.
|
|
18
18
|
export * from './model.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// pins: a reader's pins, the stored object of each signal it accepted. A changed or vanished one is an alarm.
|
|
2
|
-
// A signal's identity in any store
|
|
2
|
+
// A signal's identity in any store: its tag's name `<actor>.<signal>.<message12>`.
|
|
3
3
|
const keyOf = (ref) => ref.split('/').at(-1);
|
|
4
4
|
export const pins = (records, checked, accepted = {}) => {
|
|
5
5
|
const now = new Map(records.map(x => [`${x.actor}.${x.name}`, x]));
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// hubs: the operator's hubs on this machine: list, create, switch, add a signed replica, amend the shared contract.
|
|
2
|
-
import fs from 'node:fs';
|
|
3
2
|
import { DEFAULT_PROFILE, PROFILES_CAPABILITY, parseProfile } from '../work/index.js';
|
|
4
3
|
import { OPERATOR, config, createHub, hubNames, openHub, roomNames, setConfig, transportOf } from '../rooms/index.js';
|
|
5
4
|
import { hubPorts } from '../ports/index.js';
|
|
@@ -56,8 +55,6 @@ const setKeys = (contract, set) => {
|
|
|
56
55
|
// The files the amendment brings besides the contract; a profile is checked before it reaches the contract.
|
|
57
56
|
const extraFiles = (x) => {
|
|
58
57
|
const files = {};
|
|
59
|
-
if (x.authority)
|
|
60
|
-
files['authority.json'] = json(strictJson(fs.readFileSync(x.authority, 'utf8'), x.authority));
|
|
61
58
|
for (const f of x.files ?? []) {
|
|
62
59
|
if (/^profiles\/[^/]+\.json$/.test(f.path))
|
|
63
60
|
parseProfile(f.content.toString('utf8'), f.path);
|
|
@@ -53,10 +53,9 @@ export const files = ({ R, me }, ref, path) => {
|
|
|
53
53
|
return { m, files: m.files.filter(f => !path || f.path === path).map(f => ({ path: f.path, content: R.hub.store.file(m.id, f.path) })) };
|
|
54
54
|
};
|
|
55
55
|
export const members = ({ R, me }) => {
|
|
56
|
-
const { logs
|
|
57
|
-
const cards = new Map(ordered([...all.values()].filter(m => m.kind === 'card' && !m.bad)).map(m => [m.from, m]));
|
|
56
|
+
const { logs } = linked(R, me);
|
|
58
57
|
return Object.entries(R.members).map(([id, info]) => ({ id, role: info.role ?? 'member',
|
|
59
|
-
messages: (logs.get(id) ?? []).filter(m => !(m.kind && HIDDEN.has(m.kind))).length
|
|
58
|
+
messages: (logs.get(id) ?? []).filter(m => !(m.kind && HIDDEN.has(m.kind))).length }));
|
|
60
59
|
};
|
|
61
60
|
// --- signals ---
|
|
62
61
|
// The room's signals, each checked against its message and against what this reader accepted before; `repair` first
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// rooms: the operator's rooms in a hub: list, create, switch, admit and remove members,
|
|
1
|
+
// rooms: the operator's rooms in a hub: list, create, switch, admit and remove members, delete, move to a
|
|
2
2
|
// newer contract, and accept a new baseline for a log after reviewing an alarm.
|
|
3
3
|
import crypto from 'node:crypto';
|
|
4
4
|
import { DEFAULT_PROFILE, parseProfile } from '../work/index.js';
|
|
@@ -22,13 +22,10 @@ const opens = (H, n) => {
|
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
|
-
export const rooms = (H
|
|
25
|
+
export const rooms = (H) => {
|
|
26
26
|
const cur = config().room;
|
|
27
|
-
const view = (n, R) => ({ name: n, current: n === cur
|
|
28
|
-
|
|
29
|
-
const live = roomNames(H).flatMap(n => { const R = opens(H, n); return R ? [view(n, R)] : []; });
|
|
30
|
-
const gone = archived ? roomNames(H, true).flatMap(n => { const R = opens(H, n); return R ? [view(n, R)] : []; }) : [];
|
|
31
|
-
return [...live, ...gone];
|
|
27
|
+
const view = (n, R) => ({ name: n, current: n === cur, members: Object.keys(R.members).length, profile: R.profile.name, genesis: R.genesis });
|
|
28
|
+
return roomNames(H).flatMap(n => { const R = opens(H, n); return R ? [view(n, R)] : []; });
|
|
32
29
|
};
|
|
33
30
|
// A room carries its profile from the start: later changes to the hub's profiles do not reach it.
|
|
34
31
|
// `quorum`: the room's work starts by itself once it has that many agents; until then a join waits.
|
|
@@ -57,16 +54,6 @@ export const use = (H, name) => {
|
|
|
57
54
|
setConfig({ hub: H.name, room: R.name });
|
|
58
55
|
return R;
|
|
59
56
|
};
|
|
60
|
-
export const archive = (H, R) => {
|
|
61
|
-
notSigned(H, 'archive');
|
|
62
|
-
if (R.archived)
|
|
63
|
-
fail(`${R.name} is already archived`);
|
|
64
|
-
const name = `${R.name}@${R.genesis.slice(0, 8)}`;
|
|
65
|
-
locked(`hub-${H.name}`, () => H.store.archiveRoom(R.s, name));
|
|
66
|
-
if (config().room === R.name)
|
|
67
|
-
setConfig({ room: null });
|
|
68
|
-
return name;
|
|
69
|
-
};
|
|
70
57
|
// The room and everything kept for it: in the store (deleteRoom) and its readers' state. The sessions bound to it,
|
|
71
58
|
// on this machine or another, leave it on their own when they find its branch gone (core/agents/sessions).
|
|
72
59
|
export const erase = (H, R) => {
|
|
@@ -5,7 +5,7 @@ import { OPERATOR, controlChange } from '../rooms/index.js';
|
|
|
5
5
|
import { fail } from '../../../lib/index.js';
|
|
6
6
|
import { AGENT_RE, ID_RE } from '../protocol/index.js';
|
|
7
7
|
import { loadState, readerLock, saveState } from '../history/index.js';
|
|
8
|
-
// Removing
|
|
8
|
+
// Removing or deleting in a signed hub needs revocation published to every replica: not in this version.
|
|
9
9
|
export const notSigned = (H, what) => { if (H.signed)
|
|
10
10
|
fail(`room ${what} is not supported on signed hubs yet: a local change would come back with the next fetch`); };
|
|
11
11
|
export const admit = (H, R, who, key) => {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// send: a message from the actor, its recipients, trailers and files checked before it is written.
|
|
2
|
-
import * as D from '../decisions/index.js';
|
|
3
2
|
import { OPERATOR, append } from '../rooms/index.js';
|
|
4
|
-
import { fail, note
|
|
3
|
+
import { fail, note } from '../../../lib/index.js';
|
|
5
4
|
import { ID_RE, TOKEN_RE, checkOutgoing, compose, lookup } from '../protocol/index.js';
|
|
6
5
|
import { linked, readerLock } from '../history/index.js';
|
|
7
6
|
import { isRef } from './actor.js';
|
|
@@ -44,14 +43,6 @@ const checkTrailers = (P, x, to, assign, re) => {
|
|
|
44
43
|
if (x.roles && !x.roles.split(',').every(role))
|
|
45
44
|
fail('--roles takes "<id>=<label>, …"; labels mean what the room profile says');
|
|
46
45
|
};
|
|
47
|
-
// The grant a piece of work spends: an approved decision with a budget, not revoked.
|
|
48
|
-
const grantOf = (R, all, ref) => {
|
|
49
|
-
if (!ref)
|
|
50
|
-
return null;
|
|
51
|
-
const d = lookup(all, ref);
|
|
52
|
-
const g = D.grantOf(all, R.authorityAt, d.id) ?? fail(`${short(d.id)} is not an approved decision with a budget`);
|
|
53
|
-
return g.revoked ? fail(`grant ${short(g.id)} was revoked`) : g.id;
|
|
54
|
-
};
|
|
55
46
|
// A message from the actor. The operator may omit `to`: the room, or the assignees when there are any.
|
|
56
47
|
export const send = ({ R, me }, x) => {
|
|
57
48
|
const P = R.profile;
|
|
@@ -60,12 +51,11 @@ export const send = ({ R, me }, x) => {
|
|
|
60
51
|
const assign = x.assign ? [...new Set(x.assign)] : null;
|
|
61
52
|
const to = recipients(me, x, re, assign);
|
|
62
53
|
checkTrailers(P, x, to, assign, re);
|
|
63
|
-
const grant = grantOf(R, all, x.grant);
|
|
64
54
|
const stagedNow = staged({ R, me });
|
|
65
55
|
const entries = outgoing(stagedNow, x.files ?? []);
|
|
66
56
|
const text = compose(x.text, [
|
|
67
57
|
['To', to.join(', ')], ['Re', re?.id], ['Kind', x.task && P.opens], ['State', x.state], ['Assign', assign?.join(', ')],
|
|
68
|
-
['Roles', x.roles], ['
|
|
58
|
+
['Roles', x.roles], ['Hop', re && String(re.hopEff + 1)],
|
|
69
59
|
]);
|
|
70
60
|
checkOutgoing(text, isRef(R));
|
|
71
61
|
const id = append(R, me, text, entries);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// view: how messages
|
|
1
|
+
// view: how messages and work are shown: as text framed for people and models, and as the JSON
|
|
2
2
|
// shapes every interface (the CLI's --json, a control panel) returns.
|
|
3
3
|
import { bytes, when } from '../../../lib/index.js';
|
|
4
4
|
import { KNOWN } from '../protocol/index.js';
|
|
@@ -44,9 +44,5 @@ export const asJson = (m) => ({ id: m.id, from: m.from, trust: m.trust, to: m.to
|
|
|
44
44
|
assign: m.assign, roles: m.roles, hop: m.hop, hopEff: m.hopEff, bad: m.bad, time: new Date(m.time * 1000).toISOString(), subject: m.subject,
|
|
45
45
|
body: m.body, files: m.files.map(f => ({ path: f.path, size: f.size })), refused: m.refused, trailers: m.trailers });
|
|
46
46
|
export const taskView = (t, taken) => ({ id: t.root.id, subject: t.root.subject, requester: t.requester,
|
|
47
|
-
assignees: t.assignees, roles: t.roles, taken,
|
|
48
|
-
export const proposalView = (x) => ({ id: x.proposal.id, subject: x.proposal.subject, from: x.proposal.from,
|
|
49
|
-
decider: x.decider, state: x.state, budget: x.budget, stamps: x.stamps, missing: x.missing });
|
|
50
|
-
export const grantView = (x, usage) => ({ grant: x.grant.id, proposal: x.proposal.id,
|
|
51
|
-
subject: x.proposal.subject, budget: x.grant.budget, revoked: x.grant.revoked, usage });
|
|
47
|
+
assignees: t.assignees, roles: t.roles, taken, state: t.state, by: t.by, at: new Date(t.at * 1000).toISOString() });
|
|
52
48
|
//# sourceMappingURL=view.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// task: a piece of work folded over its messages in thread order, by the room's profile.
|
|
2
|
-
import {
|
|
2
|
+
import { ordered } from '../protocol/index.js';
|
|
3
3
|
// Who a principal of a rule is in a piece of work.
|
|
4
4
|
const PRINCIPALS = {
|
|
5
5
|
requester: (who, t) => who === t.requester,
|
|
@@ -16,12 +16,6 @@ export const taskFor = (all, m, profile) => {
|
|
|
16
16
|
return x;
|
|
17
17
|
return null;
|
|
18
18
|
};
|
|
19
|
-
const grant = (profile, t, b, m) => {
|
|
20
|
-
if (!one(m, 'grant') || !allows(profile.rules.grant, m.from, b))
|
|
21
|
-
return null;
|
|
22
|
-
t.grant = one(m, 'grant');
|
|
23
|
-
return 'grant';
|
|
24
|
-
};
|
|
25
19
|
const roles = (profile, t, b, m) => {
|
|
26
20
|
if (!m.roles || !allows(profile.rules.roles, m.from, b))
|
|
27
21
|
return null;
|
|
@@ -43,12 +37,11 @@ const state = (profile, t, b, m) => {
|
|
|
43
37
|
Object.assign(t, { state: m.state, by: m.from, at: m.time });
|
|
44
38
|
return `state.${m.state}`;
|
|
45
39
|
};
|
|
46
|
-
const STEPS = [
|
|
40
|
+
const STEPS = [roles, assign, state];
|
|
47
41
|
const opening = (root, profile, msgs) => ({ root, msgs, state: profile.initial, by: root.from, at: root.time,
|
|
48
42
|
requester: root.from, roles: { ...root.roles }, assignees: root.assign ?? (root.to.includes('*') ? [] : root.to.filter(x => x !== root.from)),
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const partOf = (all, m, root, profile) => !m.bad && !(m.kind && HEARTBEATS.has(m.kind)) && taskFor(all, m, profile) === root;
|
|
43
|
+
effects: new Map([[root.id, ['opened', ...(root.assign ? ['assigned'] : [])]]]) });
|
|
44
|
+
const partOf = (all, m, root, profile) => !m.bad && taskFor(all, m, profile) === root;
|
|
52
45
|
// A work item folds over its messages in thread order. Every right is judged on the work as it was before the
|
|
53
46
|
// message, so a label given in a message authorizes nothing in that same message, while its holder may still hand it
|
|
54
47
|
// over and reassign in one reply. Opening sets the initial state and assignees (Assign, else To minus the opener; none
|
package/target/esm/index.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
// The library: the message protocol, profiles,
|
|
1
|
+
// The library: the message protocol, profiles, signals and the Store port, for programs that coordinate
|
|
2
2
|
// through ringi without its command line (a framework's own runner, another store, another client).
|
|
3
3
|
// Importing it wires this machine's defaults (composition/); a program that brings its own adapters calls wire().
|
|
4
4
|
import './composition/index.js';
|
|
5
5
|
export * from './core/hub/protocol/index.js';
|
|
6
6
|
export * from './core/hub/work/index.js';
|
|
7
|
-
export * as decide from './core/hub/decisions/index.js';
|
|
8
7
|
export * as signals from './core/hub/signals/index.js';
|
|
9
8
|
export { openHub, openRoom, createHub, contractAt } from './core/hub/rooms/index.js';
|
|
10
9
|
//# sourceMappingURL=index.js.map
|
package/target/esm/lib/json.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// json: JSON read strictly. JSON.parse silently keeps the last of duplicate
|
|
2
|
-
// fields; for contracts and
|
|
2
|
+
// fields; for contracts and profiles that hides a second value, so the structure is checked first and a duplicate
|
|
3
3
|
// field is refused.
|
|
4
4
|
import { fail } from './fail.js';
|
|
5
5
|
const LITERAL = /^(?:true|false|null|-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?)/;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export type GroupMember = {
|
|
2
|
-
group: number;
|
|
3
|
-
state: string;
|
|
4
|
-
};
|
|
5
|
-
export declare const procMember: (text: string) => GroupMember | null;
|
|
6
|
-
export declare const psMember: (text: string) => GroupMember | null;
|
|
7
|
-
export declare const groupRunning: (group: number, members: Array<GroupMember | null>) => boolean | null;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const groupAlive: (group: number) => boolean;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { Ancestor, ProcessRows } from '../../core/agents/ports/host.ts';
|
|
2
|
-
export declare const supported: boolean;
|
|
3
|
-
export declare const alive: (pid: number) => boolean;
|
|
4
|
-
export declare const snapshot: () => ProcessRows | null;
|
|
5
|
-
export declare const ancestors: (first: number) => Ancestor[];
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export declare const seconds: (time: string) => number;
|
|
2
|
-
export declare const procStat: (line: string) => {
|
|
3
|
-
ppid: number;
|
|
4
|
-
cpu: number;
|
|
5
|
-
} | null;
|
|
6
|
-
export declare const treeCpu: (pid: number, rows: Map<number, {
|
|
7
|
-
ppid: number;
|
|
8
|
-
cpu: number;
|
|
9
|
-
}> | null) => number | null;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { Hub } from '../../../core/hub/rooms/index.ts';
|
|
2
|
-
import type { Opts } from '../args.ts';
|
|
3
|
-
export declare const archiveRoom: (H: Hub, arg: string | undefined, o: Opts) => void;
|
|
4
|
-
export declare const deleteRoom: (H: Hub, arg: string | undefined, o: Opts) => void;
|
|
5
|
-
export declare const rebaseRoomContract: (H: Hub, arg: string | undefined, o: Opts) => void;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { Hub } from '../../../core/hub/rooms/index.ts';
|
|
2
|
-
import type { Opts } from '../args.ts';
|
|
3
|
-
export declare const listRoom: (H: Hub, arg: string | undefined, o: Opts) => void;
|
|
4
|
-
export declare const createRoom: (H: Hub, arg: string | undefined, o: Opts) => void;
|
|
5
|
-
export declare const switchRoom: (H: Hub, arg: string | undefined, o: Opts) => void;
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { Hub } from '../../../core/hub/rooms/index.ts';
|
|
2
|
-
import type { Opts } from '../args.ts';
|
|
3
|
-
export declare const admitRoom: (H: Hub, arg: string | undefined, o: Opts) => void;
|
|
4
|
-
export declare const removeRoom: (H: Hub, arg: string | undefined, o: Opts) => void;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { Opts } from '../args.ts';
|
|
2
|
-
import type { Ctx } from '../context.ts';
|
|
3
|
-
export declare const propose: (a: Ctx, o: Opts) => void;
|
|
4
|
-
export declare const stamp_: (a: Ctx, o: Opts) => void;
|
|
5
|
-
export declare const decide: (a: Ctx, o: Opts) => void;
|
|
6
|
-
export declare const proposals: (a: Ctx, o: Opts) => void;
|
|
7
|
-
export declare const grants: (a: Ctx, o: Opts) => void;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { Room } from '../../hub/rooms/index.ts';
|
|
2
|
-
import type { All } from '../../hub/protocol/index.ts';
|
|
3
|
-
import type { ReaderState } from '../../hub/history/index.ts';
|
|
4
|
-
import type { Group, Planning, WatchContext } from './types.ts';
|
|
5
|
-
export declare const reserveGroups: (c: WatchContext, R: Room, all: All, groups: Map<string | null, Group>, st: ReaderState) => Planning;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { Room } from '../../hub/rooms/index.ts';
|
|
2
|
-
import type { Ended } from '../ports/host.ts';
|
|
3
|
-
import type { Run, WatchContext } from './types.ts';
|
|
4
|
-
type Dispatch = {
|
|
5
|
-
why?: string;
|
|
6
|
-
done?: Promise<Ended>;
|
|
7
|
-
};
|
|
8
|
-
export declare const dispatch: (c: WatchContext, R: Room, run: Run) => Dispatch;
|
|
9
|
-
export {};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import type { Room } from '../../hub/rooms/index.ts';
|
|
2
|
-
import type { All } from '../../hub/protocol/index.ts';
|
|
3
|
-
import type { Group, Planning, Reserve, WatchContext } from './types.ts';
|
|
4
|
-
export declare const reportExhausted: ({ c, R, all, grp, r, p }: {
|
|
5
|
-
c: WatchContext;
|
|
6
|
-
R: Room;
|
|
7
|
-
all: All;
|
|
8
|
-
grp: Group;
|
|
9
|
-
r: Reserve;
|
|
10
|
-
p: Planning;
|
|
11
|
-
}) => void;
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { Room } from '../../hub/rooms/index.ts';
|
|
2
|
-
import type { All } from '../../hub/protocol/index.ts';
|
|
3
|
-
import type { Group, Reserve, WatchContext } from './types.ts';
|
|
4
|
-
export declare const reserveGrant: (c: WatchContext, R: Room, all: All, grp: Group) => Reserve;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { Room } from '../../hub/rooms/index.ts';
|
|
2
|
-
import type { All, Logs, Message } from '../../hub/protocol/index.ts';
|
|
3
|
-
import type { ReaderState } from '../../hub/history/index.ts';
|
|
4
|
-
import type { Group, WatchContext } from './types.ts';
|
|
5
|
-
export declare const collectMessages: (c: WatchContext, R: Room, logs: Logs, st: ReaderState, all: All) => {
|
|
6
|
-
retry: Message[];
|
|
7
|
-
cursors: Record<string, string>;
|
|
8
|
-
go: Message[];
|
|
9
|
-
};
|
|
10
|
-
export declare const groupMessages: (R: Room, all: All, go: Message[]) => Map<string | null, Group>;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { Room } from '../../hub/rooms/index.ts';
|
|
2
|
-
import type { Logs } from '../../hub/protocol/index.ts';
|
|
3
|
-
import type { ReaderState } from '../../hub/history/index.ts';
|
|
4
|
-
import type { WatchContext } from './types.ts';
|
|
5
|
-
export declare const answerWatchPings: (c: WatchContext, R: Room, logs: Logs, st: ReaderState) => Record<string, string>;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type * as D from '../../hub/decisions/index.ts';
|
|
2
|
-
import type { Hub, Room } from '../../hub/rooms/index.ts';
|
|
3
|
-
import type { Message } from '../../hub/protocol/index.ts';
|
|
4
|
-
export type WatchOptions = {
|
|
5
|
-
seat: string;
|
|
6
|
-
exec: string;
|
|
7
|
-
hub?: string;
|
|
8
|
-
scope?: string;
|
|
9
|
-
handoff?: boolean;
|
|
10
|
-
once?: boolean;
|
|
11
|
-
requireGrant?: boolean;
|
|
12
|
-
interval?: number;
|
|
13
|
-
from?: string[];
|
|
14
|
-
maxHop?: number;
|
|
15
|
-
maxRuns?: number;
|
|
16
|
-
window?: number;
|
|
17
|
-
};
|
|
18
|
-
export type WatchContext = {
|
|
19
|
-
w: WatchOptions;
|
|
20
|
-
H0: Hub;
|
|
21
|
-
R0: Room;
|
|
22
|
-
me: string;
|
|
23
|
-
raw: string;
|
|
24
|
-
handle: string;
|
|
25
|
-
cmd: string;
|
|
26
|
-
interval: number;
|
|
27
|
-
allow: Set<string> | null;
|
|
28
|
-
maxHop: number;
|
|
29
|
-
maxRuns: number;
|
|
30
|
-
span: number;
|
|
31
|
-
runSeq: number;
|
|
32
|
-
log: (line: string) => void;
|
|
33
|
-
};
|
|
34
|
-
export type Group = {
|
|
35
|
-
grant: string | null;
|
|
36
|
-
msgs: Message[];
|
|
37
|
-
task: Message | null;
|
|
38
|
-
};
|
|
39
|
-
export type Run = Group & {
|
|
40
|
-
run?: string;
|
|
41
|
-
timeout: number | null;
|
|
42
|
-
};
|
|
43
|
-
export type Reserve = {
|
|
44
|
-
why?: string;
|
|
45
|
-
lost?: boolean;
|
|
46
|
-
wait?: boolean;
|
|
47
|
-
exhausted?: boolean;
|
|
48
|
-
gr?: D.Grant;
|
|
49
|
-
run?: string;
|
|
50
|
-
};
|
|
51
|
-
export type Plan = {
|
|
52
|
-
runs: Run[];
|
|
53
|
-
hold: boolean;
|
|
54
|
-
lost: boolean;
|
|
55
|
-
};
|
|
56
|
-
export type Planning = Plan & {
|
|
57
|
-
ownRuns: number[];
|
|
58
|
-
exhausted: Record<string, boolean>;
|
|
59
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export declare const ROOT = "operator";
|
|
2
|
-
export type Budget = {
|
|
3
|
-
runs: number;
|
|
4
|
-
'run-seconds': number;
|
|
5
|
-
concurrency: number;
|
|
6
|
-
};
|
|
7
|
-
export type Authority = {
|
|
8
|
-
decide?: Record<string, Partial<Budget>>;
|
|
9
|
-
};
|
|
10
|
-
export type AuthorityAt = (control: string | null) => Authority | null;
|
|
11
|
-
export declare const ids: (v: string | null) => string[];
|
|
12
|
-
export declare const parseBudget: (s: string | null | undefined) => Budget | null | undefined;
|
|
13
|
-
export declare const budgetText: (b: Budget) => string;
|
|
14
|
-
export declare const parseDue: (s: string) => string;
|
|
15
|
-
export declare const mayDecide: (authority: Authority | null, decider: string, proposer: string, budget: Budget | null) => boolean;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { All, Message } from '../protocol/index.ts';
|
|
2
|
-
import type { AuthorityAt, Budget } from './budget.ts';
|
|
3
|
-
export type Grant = {
|
|
4
|
-
id: string;
|
|
5
|
-
budget: Budget;
|
|
6
|
-
proposal: Message;
|
|
7
|
-
revoked: boolean;
|
|
8
|
-
};
|
|
9
|
-
export type Proposal = {
|
|
10
|
-
proposal: Message;
|
|
11
|
-
decider: string;
|
|
12
|
-
reviewers: string[];
|
|
13
|
-
budget: Budget | null;
|
|
14
|
-
due: number | null;
|
|
15
|
-
stamps: Record<string, {
|
|
16
|
-
stamp: string;
|
|
17
|
-
id: string;
|
|
18
|
-
reason: string;
|
|
19
|
-
}>;
|
|
20
|
-
missing: string[];
|
|
21
|
-
decision: {
|
|
22
|
-
decision: string;
|
|
23
|
-
id: string;
|
|
24
|
-
by: string;
|
|
25
|
-
time: number;
|
|
26
|
-
} | null;
|
|
27
|
-
revoked: {
|
|
28
|
-
id: string;
|
|
29
|
-
by: string;
|
|
30
|
-
time: number;
|
|
31
|
-
} | null;
|
|
32
|
-
superseded: Message | null;
|
|
33
|
-
state: string;
|
|
34
|
-
grant: Grant | null;
|
|
35
|
-
};
|
|
36
|
-
export declare const proposalOf: (all: All, p: Message, authorityAt: AuthorityAt, now?: number) => Proposal;
|
|
37
|
-
export declare const proposals: (all: All, authorityAt: AuthorityAt) => Proposal[];
|
|
38
|
-
export declare const grantOf: (all: All, authorityAt: AuthorityAt, id: string) => Grant | null;
|