@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,35 +1,33 @@
|
|
|
1
|
-
// host-posix: macOS
|
|
2
|
-
//
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return
|
|
14
|
-
|
|
15
|
-
const timer = setTimeout(() => { clearInterval(held); resolve(null); }, Math.max(0, deadline - clock.monotonic()));
|
|
16
|
-
const clear = () => { clearTimeout(timer); clearInterval(held); };
|
|
17
|
-
done.then(value => { clear(); resolve(value); }, error => { clear(); reject(error); });
|
|
18
|
-
});
|
|
1
|
+
// host-posix: what macOS and Linux say about a process, and a detached start, behind ProcessHost
|
|
2
|
+
// (core/agents/ports/host.ts). Elsewhere every probe says nothing rather than guess.
|
|
3
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
const supported = process.platform === 'darwin' || process.platform === 'linux';
|
|
6
|
+
// A process of another user that we may not signal still exists.
|
|
7
|
+
const alive = (pid) => {
|
|
8
|
+
try {
|
|
9
|
+
process.kill(pid, 0);
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
catch (e) {
|
|
13
|
+
return e.code === 'EPERM';
|
|
14
|
+
}
|
|
19
15
|
};
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
awaitQuiescence: (handle, deadline) => observe(own(handle).done, deadline, clock),
|
|
33
|
-
};
|
|
16
|
+
// Up to twelve parents by name, from one `ps` call each; a sandbox that denies `ps` gets none.
|
|
17
|
+
const ancestors = (first) => {
|
|
18
|
+
const result = [];
|
|
19
|
+
for (let pid = first, i = 0; i < 12 && pid > 1; i++) {
|
|
20
|
+
const r = spawnSync('ps', ['-o', 'ppid=,comm=', '-p', String(pid)], { encoding: 'utf8' });
|
|
21
|
+
const m = r.status === 0 ? /^\s*(\d+)\s+(.*)$/.exec(String(r.stdout ?? '').trim()) : null;
|
|
22
|
+
if (!m)
|
|
23
|
+
break;
|
|
24
|
+
result.push({ pid, name: path.basename(m[2].trim()).toLowerCase() });
|
|
25
|
+
pid = Number(m[1]);
|
|
26
|
+
}
|
|
27
|
+
return result;
|
|
34
28
|
};
|
|
29
|
+
export const hostPosix = () => ({
|
|
30
|
+
supported, alive, ancestors,
|
|
31
|
+
start: ({ file, args, env }) => { spawn(file, [...args], { detached: true, stdio: 'ignore', env }).unref(); },
|
|
32
|
+
});
|
|
35
33
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// branches: a room is one linear branch from its genesis. What its commits are (messages or control records), the
|
|
2
|
-
// room's control files, and the room's life: create,
|
|
2
|
+
// room's control files, and the room's life: create, delete.
|
|
3
3
|
import { fail } from '../../lib/index.js';
|
|
4
4
|
import * as Remote from './remote.js';
|
|
5
5
|
import { ZERO } from './run.js';
|
|
@@ -9,17 +9,17 @@ import { ID_RE, parse } from '../../core/hub/protocol/index.js';
|
|
|
9
9
|
const ROOT = 'operator';
|
|
10
10
|
export const CONTROL_FILES = new Set(['ROOM.md', 'members.json', 'profile.json', 'allowed_signers']);
|
|
11
11
|
export class Branches extends Repo {
|
|
12
|
-
ref(name) { return
|
|
12
|
+
ref(name) { return `refs/heads/${name}`; }
|
|
13
13
|
tip(name) { return this.rev(this.ref(name)); }
|
|
14
14
|
// Every branch but the contract's, by name.
|
|
15
15
|
roomBranches() {
|
|
16
16
|
return this.git(['for-each-ref', '--format=%(refname:lstrip=2)', 'refs/heads/']).split('\n').filter(b => b && b !== 'main');
|
|
17
17
|
}
|
|
18
|
-
// Every branch but the contract's is a room
|
|
19
|
-
roomNames(
|
|
20
|
-
const prefix =
|
|
18
|
+
// Every branch but the contract's is a room.
|
|
19
|
+
roomNames() {
|
|
20
|
+
const prefix = 'refs/heads/';
|
|
21
21
|
const names = this.git(['for-each-ref', '--format=%(refname)', prefix]).split('\n').filter(Boolean).map(r => r.slice(prefix.length))
|
|
22
|
-
.filter(n => ID_RE.test(n
|
|
22
|
+
.filter(n => ID_RE.test(n) && n !== 'main');
|
|
23
23
|
return names.sort();
|
|
24
24
|
}
|
|
25
25
|
// A control record: the room's genesis, or a root commit of Kind: room.
|
|
@@ -42,7 +42,7 @@ export class Branches extends Repo {
|
|
|
42
42
|
// On a signed hub the branch's verification says which commits are control records, and why the others that are no
|
|
43
43
|
// valid message are skipped; a commit off the branch's first parents is never a message (remote.ts).
|
|
44
44
|
judged(room, tip, entries) {
|
|
45
|
-
if (this.trust !== 'signed'
|
|
45
|
+
if (this.trust !== 'signed')
|
|
46
46
|
return entries;
|
|
47
47
|
const b = Remote.branch(this.h, { name: room.name, ref: this.ref(room.name), genesis: room.genesis }, tip);
|
|
48
48
|
const control = new Set(b.control);
|
|
@@ -63,11 +63,10 @@ export class Branches extends Repo {
|
|
|
63
63
|
return null;
|
|
64
64
|
const genesis = this.git(['rev-list', '--first-parent', '--reverse', tip, '^refs/heads/main']).split('\n')[0]
|
|
65
65
|
|| this.git(['rev-list', '--first-parent', '--reverse', tip]).split('\n').filter(Boolean).at(-1);
|
|
66
|
-
|
|
67
|
-
if (this.trust === 'signed' && !archived && this.h.remoteAlarms?.[ref])
|
|
66
|
+
if (this.trust === 'signed' && this.h.remoteAlarms?.[ref])
|
|
68
67
|
fail(`ALARM ${this.h.remoteAlarms[ref]}; room ${name} is quarantined`);
|
|
69
|
-
const control = this.entries({ name, genesis
|
|
70
|
-
return { name,
|
|
68
|
+
const control = this.entries({ name, genesis }, tip).filter(e => e.control).map(e => ({ rev: e.sha, text: e.text }));
|
|
69
|
+
return { name, head: control.at(-1).rev, genesis, tip, base: this.rev(`${genesis}^`) ?? ZERO, control };
|
|
71
70
|
}
|
|
72
71
|
// Control files are read at a control record, never at the branch's tip.
|
|
73
72
|
controlFile(room, name, rev) {
|
|
@@ -93,13 +92,7 @@ export class Branches extends Repo {
|
|
|
93
92
|
refsUnder(prefix) {
|
|
94
93
|
return this.git(['for-each-ref', '--format=%(refname) %(objectname)', prefix]).split('\n').filter(Boolean).map(l => l.split(' '));
|
|
95
94
|
}
|
|
96
|
-
//
|
|
97
|
-
archiveRoom(room, as) {
|
|
98
|
-
const tip = this.rev(this.ref(room.name)) ?? fail(`room ${room.name} is gone`);
|
|
99
|
-
this.git(['update-ref', `refs/archive/${as}`, tip, ZERO]);
|
|
100
|
-
this.git(['update-ref', '-d', this.ref(room.name), tip]);
|
|
101
|
-
}
|
|
102
|
-
// Every ref of the room in one transaction: its branch (or archive), every tag on its commits (signals, heartbeats,
|
|
95
|
+
// Every ref of the room in one transaction: its branch, every tag on its commits (signals, heartbeats,
|
|
103
96
|
// anyone's), what the store keeps under its genesis (pins, evidence) and its unpublished commits. Objects are left to
|
|
104
97
|
// the repository.
|
|
105
98
|
deleteRoom(room) {
|
|
@@ -114,10 +107,10 @@ export class Branches extends Repo {
|
|
|
114
107
|
this.git(['update-ref', '--stdin'], { input: ['start', ...refs.map(r => `delete ${r}`), 'prepare', 'commit', ''].join('\n') });
|
|
115
108
|
}
|
|
116
109
|
remote(room) {
|
|
117
|
-
return { name: room.name, ref: this.ref(room.name), head: room.head, genesis: room.genesis
|
|
110
|
+
return { name: room.name, ref: this.ref(room.name), head: room.head, genesis: room.genesis };
|
|
118
111
|
}
|
|
119
112
|
roster(room) {
|
|
120
|
-
if (this.trust !== 'signed'
|
|
113
|
+
if (this.trust !== 'signed')
|
|
121
114
|
return null;
|
|
122
115
|
const v = Remote.verifyRoom(this.h, this.remote(room));
|
|
123
116
|
return { members: v.members, signers: v.entries };
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
// (the root's, on top of main); then every message is a commit by its author, and
|
|
5
5
|
// every control record (Kind: room) a commit by the root
|
|
6
6
|
// refs/tags/<agent>.<signal>.<message12> signals: annotated tags without text on the message's commit
|
|
7
|
-
// refs/archive/<room>@<genesis8> an archived room, read-only
|
|
8
7
|
// refs/ringi/accepted/<genesis>/<reader>/<author> readers' pins of each author's accepted last message
|
|
9
8
|
// A member's log is its own commits in the room's branch, in branch order. The control files at the root of a room's
|
|
10
9
|
// tree (members, profile, signers) change only in the root's control records.
|
|
@@ -85,8 +84,6 @@ export class GitStore extends Marks {
|
|
|
85
84
|
}
|
|
86
85
|
// One message on top of the room's branch.
|
|
87
86
|
append(room, who, text, entries) {
|
|
88
|
-
if (room.archived)
|
|
89
|
-
fail(`room ${room.name} is archived: read-only`);
|
|
90
87
|
if (checkOutgoing(text, s => this.isRef(s)).trailers['ringi-files'])
|
|
91
88
|
fail('Ringi-Files is store metadata; supply attachments instead');
|
|
92
89
|
const own = entries.find(e => CONTROL_FILES.has(e.path));
|
|
@@ -103,8 +100,7 @@ export class GitStore extends Marks {
|
|
|
103
100
|
return this.trust === 'signed' ? Remote.verify(this.h, this.remote(room), id, head) : null;
|
|
104
101
|
}
|
|
105
102
|
pin(room, reader, id, rev) {
|
|
106
|
-
|
|
107
|
-
this.git(['update-ref', `refs/ringi/accepted/${room.genesis}/${reader}/${id}`, rev]);
|
|
103
|
+
this.git(['update-ref', `refs/ringi/accepted/${room.genesis}/${reader}/${id}`, rev]);
|
|
108
104
|
}
|
|
109
105
|
unpin(room, reader, id) {
|
|
110
106
|
this.gitOk(['update-ref', '-d', `refs/ringi/accepted/${room.genesis}/${reader}/${id}`]);
|
|
@@ -122,7 +118,6 @@ export class GitStore extends Marks {
|
|
|
122
118
|
joinKey(room, who) { return Remote.join(this.h, this.remote(room), who, this.home); }
|
|
123
119
|
// A room's transport alarm is the room's, whichever author the operator forgets.
|
|
124
120
|
forgetLog(room, _id) { Remote.forget(this.h, this.remote(room)); }
|
|
125
|
-
rootKey() { return this.d.root ?? fail(`hub ${this.d.name} has no pinned root`); }
|
|
126
121
|
rootRoster() { return Remote.rootRoster(this.h); }
|
|
127
122
|
}
|
|
128
123
|
//# sourceMappingURL=index.js.map
|
|
@@ -75,7 +75,7 @@ export class Marks extends Branches {
|
|
|
75
75
|
return [];
|
|
76
76
|
return [{ ref: t.ref, object: t.object, name: t.name, actor: t.actor, target: o?.target ?? '', tagger: o?.tagger ?? '', text: o?.text ?? '' }];
|
|
77
77
|
});
|
|
78
|
-
if (this.trust !== 'signed'
|
|
78
|
+
if (this.trust !== 'signed')
|
|
79
79
|
return records;
|
|
80
80
|
return Remote.withVerification(this.h, () => records.filter(s => {
|
|
81
81
|
const why = Remote.verifySignal(this.h, this.remote(room), s.ref, s.object);
|
|
@@ -63,8 +63,6 @@ const admissionKey = (H, R, who, publicKey) => {
|
|
|
63
63
|
C.fail('room admit is for signed hubs; local membership is added by join');
|
|
64
64
|
if (who === ROOT)
|
|
65
65
|
C.fail('the root is already pinned; root replacement requires a separate trust transition');
|
|
66
|
-
if (R.archived)
|
|
67
|
-
C.fail('cannot admit into an archived room');
|
|
68
66
|
const key = keyInput(publicKey);
|
|
69
67
|
return key;
|
|
70
68
|
};
|
|
@@ -5,7 +5,7 @@ import { checkHeartbeat, heartbeatRef } from './heartbeat.js';
|
|
|
5
5
|
import { checkUrl } from './keys.js';
|
|
6
6
|
import { SHA, TAG_ACCEPT, TAG_TRACK, TAGS } from './types.js';
|
|
7
7
|
// Publish only the actor's exact heartbeat with an explicit old OID. A racing beat is ordinary contention, never a
|
|
8
|
-
// signal rewrite alarm. Neither success nor failure changes immutable acceptance pins or
|
|
8
|
+
// signal rewrite alarm. Neither success nor failure changes immutable acceptance pins or history state.
|
|
9
9
|
export const pushHeartbeat = (H, R, who, sha, expected) => {
|
|
10
10
|
const ref = heartbeatRef(who, R.genesis);
|
|
11
11
|
if (!SHA.test(sha) || (expected !== null && !SHA.test(expected)))
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// main: the hub's contract branch verified: every commit signed by the root since the pinned genesis.
|
|
2
2
|
import * as C from '../../../lib/index.js';
|
|
3
3
|
import { memo } from './cache.js';
|
|
4
|
-
import {
|
|
4
|
+
import { isRemote, rev } from './git.js';
|
|
5
5
|
import { parseKey, rootKey } from './keys.js';
|
|
6
6
|
import { blobText } from './roster.js';
|
|
7
7
|
import { chain, checkSignature, linear } from './signature.js';
|
|
@@ -34,8 +34,5 @@ const checkContract = (H, sha, key) => {
|
|
|
34
34
|
const meta = C.strictJson(blobText(H, sha, name), name);
|
|
35
35
|
if (meta.schema !== 'ringi-hub' || meta.trust !== 'signed' || parseKey(meta.root).line !== key.line)
|
|
36
36
|
C.fail(`${name} must declare signed trust and the pinned root key`);
|
|
37
|
-
const authority = git(H, ['cat-file', '-e', `${sha}:authority.json`], { ok: true });
|
|
38
|
-
if (authority.status === 0)
|
|
39
|
-
C.strictJson(blobText(H, sha, 'authority.json'), 'authority.json');
|
|
40
37
|
};
|
|
41
38
|
//# sourceMappingURL=main.js.map
|
|
@@ -102,7 +102,6 @@ export class Repo {
|
|
|
102
102
|
const r = this.gitOk(['show', `${rev}:${name}`]);
|
|
103
103
|
return r.status === 0 ? r.stdout : null;
|
|
104
104
|
}
|
|
105
|
-
contractFiles(rev) { return this.git(['ls-tree', '-r', '--name-only', rev]).split('\n').filter(Boolean); }
|
|
106
105
|
amendContract(who, text, files) {
|
|
107
106
|
const head = this.contractHead();
|
|
108
107
|
const sha = this.commit(who, text, this.tree(`${head}^{tree}`, Object.entries(files).map(([p, c]) => ({ path: p, content: c, mode: '100644' }))), [head]);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
// agent: the commands only an agent runs, as the agent its session is bound to (`ringi agent inbox`, whoami,
|
|
2
|
-
//
|
|
1
|
+
// agent: the commands only an agent runs, as the agent its session is bound to (`ringi agent inbox`, whoami, wait,
|
|
2
|
+
// take); joining and leaving a room are session.ts.
|
|
3
3
|
import * as Agent from '../../../core/agents/sessions/agent.js';
|
|
4
4
|
import { asJson, render } from '../../../core/hub/usecases/view.js';
|
|
5
|
-
import { fail, short
|
|
6
|
-
import { dump, flag,
|
|
5
|
+
import { fail, short } from '../../../lib/index.js';
|
|
6
|
+
import { dump, flag, opt, out } from '../args.js';
|
|
7
7
|
import { scopeLine, waiting } from '../shared/index.js';
|
|
8
8
|
const options = (o) => ({ peek: flag(o, 'peek'), limit: opt(o, 'limit') ? Number(opt(o, 'limit')) : undefined });
|
|
9
9
|
export const showInbox = ({ R, me, s }, res, o) => {
|
|
@@ -31,12 +31,6 @@ export const whoami = (a) => {
|
|
|
31
31
|
const { session: s, profile, members } = Agent.whoami(a);
|
|
32
32
|
out(`${s.agent} in ${s.hub}/${s.room} (genesis ${short(s.genesis)}, profile ${profile}), session ${s.handle}, ${s.state}\nscope: ${scopeLine(s, a.R.quorum !== null)}\nmembers: ${members.join(', ')}`);
|
|
33
33
|
};
|
|
34
|
-
export const card = (a, o) => out(`card ${short(Agent.card(a, textOf(o)))}`);
|
|
35
|
-
export const ping = (a, o) => {
|
|
36
|
-
const r = Agent.ping(a, { to: o._[0] ?? fail('usage: ringi agent ping <id> [-m <note>] [--next <s>] [--re <msg>]'),
|
|
37
|
-
text: list(o, 'm').length ? list(o, 'm').join('\n\n') : undefined, next: opt(o, 'next') ? Number(opt(o, 'next')) : undefined, re: opt(o, 're') });
|
|
38
|
-
out(`ping ${short(r.id)} to ${r.to}${r.previous ? (r.previous.answeredAt !== null ? `; ${r.to} answered the previous one at ${when(r.previous.answeredAt)}` : `; no pong to the previous one (${short(r.previous.id)})`) : ''}`);
|
|
39
|
-
};
|
|
40
34
|
export const wait = async (a, o) => {
|
|
41
35
|
const r = await Agent.wait(a, { ...options(o), max: opt(o, 'max') === undefined ? undefined : Number(opt(o, 'max')) });
|
|
42
36
|
if (r.inbox)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Parse one option at a time, keeping positional arguments and repeated values in order.
|
|
2
2
|
import { fail } from '../../lib/index.js';
|
|
3
|
-
const BOOLS = new Set(['task', 'peek', 'all', 'json', 'help', 'once', 'project', 'follow', 'short', 'yes', '
|
|
3
|
+
const BOOLS = new Set(['task', 'peek', 'all', 'json', 'help', 'once', 'project', 'follow', 'short', 'yes', 'md', 'signed', 'repair', 'clear', 'published']);
|
|
4
4
|
const MULTI = new Set(['m', 'attach', 'set', 'drop']);
|
|
5
5
|
const SHORT = { m: 'm', F: 'file', n: 'n', o: 'out', h: 'help' };
|
|
6
6
|
const option = (a) => {
|
|
@@ -3,17 +3,16 @@
|
|
|
3
3
|
import { about } from '../../core/hub/usecases/context.js';
|
|
4
4
|
import { agent } from '../../core/agents/sessions/context.js';
|
|
5
5
|
import { fail } from '../../lib/index.js';
|
|
6
|
-
import {
|
|
6
|
+
import { inbox, take, wait, whoami } from './agent/index.js';
|
|
7
7
|
import { flag, out, parseArgs } from './args.js';
|
|
8
8
|
import { operatorCtx } from './context.js';
|
|
9
9
|
import { helpMarkdown, helpText } from './help.js';
|
|
10
10
|
import { forget, heartbeats, hub, pulse, roomCmd, sessions, where } from './operator/index.js';
|
|
11
11
|
import { join, leave, resume, stop } from './agent/session.js';
|
|
12
|
-
import { add, cat,
|
|
12
|
+
import { add, cat, get, log, profileCmd, read, reply, send, signals, tasks, thread, who } from './shared/index.js';
|
|
13
13
|
import { skill } from './skill/index.js';
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const AGENT = { ...SHARED, inbox, whoami, status: whoami, card, ping, wait, take };
|
|
14
|
+
const SHARED = { add, send, reply, read, thread, tasks, log, cat, get, who, signals, profile: profileCmd };
|
|
15
|
+
const AGENT = { ...SHARED, inbox, whoami, status: whoami, wait, take };
|
|
17
16
|
const agentCommand = (_, rest) => {
|
|
18
17
|
const [sub = 'whoami', ...more] = rest;
|
|
19
18
|
const fn = AGENT[sub] ?? fail(`unknown: ringi agent ${sub}; see ringi help`);
|
|
@@ -28,10 +27,10 @@ const DIRECT = new Map([
|
|
|
28
27
|
['--version', version], ['-v', version], ['version', version],
|
|
29
28
|
['help', help], ['--help', help], ['-h', help], ['skill', skill], ['agent', agentCommand],
|
|
30
29
|
['hub', hub], ['room', roomCmd], ['where', where], ['sessions', sessions], ['heartbeats', heartbeats],
|
|
31
|
-
['pulse', pulse], ['forget', forget], ['
|
|
30
|
+
['pulse', pulse], ['forget', forget], ['join', join], ['continue', resume], ['stop', stop], ['leave', leave]
|
|
32
31
|
]);
|
|
33
32
|
const unknown = (cmd) => {
|
|
34
|
-
if (['inbox', 'whoami', '
|
|
33
|
+
if (['inbox', 'whoami', 'wait', 'take'].includes(cmd))
|
|
35
34
|
fail(`${cmd} is an agent command: ringi agent ${cmd}`);
|
|
36
35
|
return fail(`unknown command ${cmd}; see ringi help`);
|
|
37
36
|
};
|
|
@@ -7,21 +7,16 @@ export const TABLE = [
|
|
|
7
7
|
['hub create <name> [--signed [--url <git url>]]', 'operator', 'another hub: asserted senders, or signed with a root key made on this machine; --url publishes it'],
|
|
8
8
|
['hub add <name> <git url> --root <public key|file> [--genesis <sha>]', 'operator', 'a replica of a signed hub; the root key comes from you, out of band, never from the hub'],
|
|
9
9
|
['hub switch <name>', 'operator', 'change the terminal\'s current hub; agents stay where they are'],
|
|
10
|
-
['hub amend -m <subject> [--set <key>=<value>]... [--
|
|
11
|
-
['room list
|
|
10
|
+
['hub amend -m <subject> [--set <key>=<value>]... [--attach <file>:profiles/<name>.json]...', 'operator', 'refine the shared contract: version, capabilities, default profile, profiles'],
|
|
11
|
+
['room list', 'operator', 'rooms of the current hub'],
|
|
12
12
|
['room create <id> [--profile <name>] [--quorum <agents>]', 'operator', 'a room for one piece of work, following a profile; becomes the current room; --quorum: its work starts by itself once that many agents joined (1: at once)'],
|
|
13
13
|
['room switch <id>', 'operator', 'change the terminal\'s current room; agents stay where they are'],
|
|
14
14
|
['room admit <agent> <public key|file>', 'operator', 'signed hubs: admit the key an agent made on its own machine'],
|
|
15
15
|
['room remove <agent>', 'operator', 'local hubs: take an agent out of the current room'],
|
|
16
|
-
['room archive [<id>]', 'operator', 'local hubs: a room (default: the current one) is read-only from now on, wakes nobody; its sessions leave on their own'],
|
|
17
16
|
['room delete [<id>] --yes', 'operator', 'local hubs: erase a room (default: the current one) and everything kept for it; its sessions leave on their own'],
|
|
18
17
|
['room rebase-contract <id>', 'operator', 'move a room onto the hub\'s current contract'],
|
|
19
|
-
['where [-n n] [--short] [--follow]', 'operator', 'hub, room, sessions (active, stopped, gone), open work
|
|
20
|
-
['send -m <subject> [-m <body>]... [--to <ids>] [--task] [--re <msg>] [--state <s>] [--assign <ids>] [--roles <id>=<label>,...] [--
|
|
21
|
-
['propose -m <subject> [-m <body>] --decider <id> [--reviewers <ids>] [--due 2h|<ISO>] [--budget runs=<n>,run-seconds=<n>,concurrency=<n>] [--supersedes <proposal>]', 'both', 'a proposal; it circulates to the reviewers and the decider'],
|
|
22
|
-
['stamp <proposal> approve|object|abstain -m <reason>', 'both', 'a named reviewer\'s stamp on that exact revision'],
|
|
23
|
-
['decide <proposal> approved|rejected|revoked -m <reason>', 'both', 'the named decider, with authority; an approval with a budget is a grant'],
|
|
24
|
-
['proposals [--all] | grants', 'both', 'open proposals with their stamps; grants with their usage'],
|
|
18
|
+
['where [-n n] [--short] [--follow]', 'operator', 'hub, room, sessions (active, stopped, gone), open work, latest messages'],
|
|
19
|
+
['send -m <subject> [-m <body>]... [--to <ids>] [--task] [--re <msg>] [--state <s>] [--assign <ids>] [--roles <id>=<label>,...] [--attach <src>[:<dest>]]...', 'operator', 'a message as operator; without --to it goes to the room and wakes nobody; --task opens work of the room\'s profile'],
|
|
25
20
|
['add <src>[:<dest>]... | add [--drop <path>]... [--clear]', 'both', 'stage files for your next message, like git add: their content is taken now; results and state travel only as attachments'],
|
|
26
21
|
['tasks [--all] | log [-n n] | read <msg> | thread <msg> | cat <msg> [<path>] | get <msg> [-o <dir>] | who', 'both', 'reading the room (agents: ringi agent …)'],
|
|
27
22
|
['signals [--all] [--repair]', 'both', 'what happened (signals) and where attention is (read and taken marks), each checked; --repair restores your missing signals'],
|
|
@@ -30,7 +25,6 @@ export const TABLE = [
|
|
|
30
25
|
['heartbeats [--json] | heartbeats --published [--room <id>]', 'operator', 'each session\'s pulse on this machine, from its process and its tool\'s trace, without the model: working, waiting (for what) or gone; --published: the room\'s heartbeat tags as an orchestrator reads them'],
|
|
31
26
|
['pulse [--beat <s>] [--once]', 'operator', 'beat for every session here: sync its hub, put its heartbeat tag on the last pulled commit of its room; join and continue start it (RINGI_PULSE=off: not)'],
|
|
32
27
|
['forget <room>/<log>', 'operator', 'after a changed-history alarm: accept a new baseline for that log'],
|
|
33
|
-
['watch [<hub>:]<room>/<agent> --exec <cmd> [--handoff] [--scope <text>] [--once] [--require-grant] [--from <ids>] [--max-hop n] [--max-runs n] [--window s] [--interval s]', 'operator', 'headless turns for one agent: answers pings, spends grants, writes usage receipts; --handoff, run from the agent\'s own chat, moves its seat and scope to the watcher; exits with the failed turn\'s status'],
|
|
34
28
|
['skill install [--project] | uninstall | status | show', 'operator', 'the skill for Claude Code, Codex and Cursor'],
|
|
35
29
|
['join <hub> <room> [--as <id>] [--scope <text>]', 'session', 'bind this chat to a room as an agent, with what the operator delegates'],
|
|
36
30
|
['continue [[<hub>:]<room>/<agent>]', 'session', 'resume this chat\'s binding, also after a restart; naming one takes over a paused or gone one'],
|
|
@@ -39,10 +33,9 @@ export const TABLE = [
|
|
|
39
33
|
['agent whoami', 'agent', 'identity, room, profile, scope'],
|
|
40
34
|
['agent inbox [--peek] [--limit n]', 'agent', 'what is new for you; marks it seen and leaves a read mark on each (--peek: neither)'],
|
|
41
35
|
['agent take <work>', 'agent', 'a taken mark: you are on it; others see it in tasks and read. It changes no state'],
|
|
42
|
-
['agent send … | reply <msg> -m … [--state <s>] [--assign <ids>] [--roles …] [--
|
|
43
|
-
['agent propose | stamp | decide | proposals | grants', 'agent', 'decisions, as the joined agent'],
|
|
36
|
+
['agent send … | reply <msg> -m … [--state <s>] [--assign <ids>] [--roles …] [--attach …] [--all]', 'agent', 'write; answer the message you act on'],
|
|
44
37
|
['agent tasks | log | read | thread | cat | get | who | signals | profile', 'agent', 'reading, as the joined agent'],
|
|
45
|
-
['agent
|
|
38
|
+
['agent wait [--max <s>]', 'agent', 'hold the line only when the operator asks'],
|
|
46
39
|
];
|
|
47
40
|
export const helpText = () => {
|
|
48
41
|
const groups = [['operator', 'operator: in a terminal, in the current hub and room'], ['session', 'session: in a chat, on the operator\'s words'], ['agent', 'agent: during a turn, in the session\'s own room'], ['both', 'operator in a terminal, or an agent as ringi agent …']];
|
|
@@ -3,6 +3,6 @@ import { short } from '../../../lib/index.js';
|
|
|
3
3
|
export const publishedLine = (h) => `${h.agent.padEnd(12)} ${(h.waits ? `${h.state} (${h.waits})` : h.state).padEnd(22)} ${h.age}s ago${h.overdue ? ', overdue' : ''} on ${short(h.target)}`;
|
|
4
4
|
export const pulseLine = ({ session: s, tool, beat: b }) => {
|
|
5
5
|
const state = b.waits ? `${b.state} (${b.waits})` : b.state;
|
|
6
|
-
return `${s.agent.padEnd(12)} ${`${s.hub}/${s.room}`.padEnd(24)} ${state.padEnd(22)} alive ${b.alive === null ? '?' : b.alive ? 'yes' : 'no'} quiet ${b.quiet}s
|
|
6
|
+
return `${s.agent.padEnd(12)} ${`${s.hub}/${s.room}`.padEnd(24)} ${state.padEnd(22)} alive ${b.alive === null ? '?' : b.alive ? 'yes' : 'no'} quiet ${b.quiet}s ${tool} ${s.handle}`;
|
|
7
7
|
};
|
|
8
8
|
//# sourceMappingURL=heartbeat-format.js.map
|
|
@@ -31,7 +31,7 @@ export const addHub = (o) => {
|
|
|
31
31
|
export const amendHub = (o) => {
|
|
32
32
|
const H = Hubs.hubOf(opt(o, 'hub'));
|
|
33
33
|
const files = list(o, 'attach').flatMap(attachments).map(e => ({ path: e.path, content: fs.readFileSync(e.file) }));
|
|
34
|
-
const r = Hubs.amend(H, { text: textOf(o), set: list(o, 'set'),
|
|
34
|
+
const r = Hubs.amend(H, { text: textOf(o), set: list(o, 'set'), files });
|
|
35
35
|
return out(`amended hub ${H.name}: contract ${r.version}; rooms keep their base until ringi room rebase-contract <room>`);
|
|
36
36
|
};
|
|
37
37
|
//# sourceMappingURL=hub-commands.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// operator: the commands only the operator runs, as the operator of this machine in its terminal context: hubs, rooms,
|
|
2
|
-
// where things stand, sessions, heartbeats
|
|
2
|
+
// where things stand, sessions, heartbeats and the pulse.
|
|
3
3
|
export { heartbeats, pulse } from './heartbeat.js';
|
|
4
4
|
export { hub } from './hub.js';
|
|
5
5
|
export { roomCmd } from './room.js';
|
|
@@ -1,11 +1,50 @@
|
|
|
1
|
-
// room: `ringi room
|
|
1
|
+
// room: `ringi room list | create | switch | admit | remove | delete | rebase-contract`.
|
|
2
|
+
import { roomsActive } from '../../../core/agents/overview.js';
|
|
2
3
|
import * as Hubs from '../../../core/hub/usecases/hubs.js';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import * as Rooms from '../../../core/hub/usecases/rooms.js';
|
|
5
|
+
import { fail, short } from '../../../lib/index.js';
|
|
6
|
+
import { flag, opt, out } from '../args.js';
|
|
7
|
+
const list = H => {
|
|
8
|
+
const rs = roomsActive(H);
|
|
9
|
+
for (const r of rs)
|
|
10
|
+
out(`${r.current ? '*' : ' '} ${r.name.padEnd(16)} ${r.members} member(s), ${r.active} active session(s), profile ${r.profile} genesis ${short(r.genesis)}`);
|
|
11
|
+
if (!rs.length)
|
|
12
|
+
out(`no rooms in hub ${H.name}: ringi room create <id>`);
|
|
13
|
+
};
|
|
14
|
+
const create = (H, arg, o) => {
|
|
15
|
+
const quorum = opt(o, 'quorum');
|
|
16
|
+
const r = Rooms.create(H, arg ?? '', { profile: opt(o, 'profile'), quorum: quorum === undefined ? undefined : Number(quorum) });
|
|
17
|
+
const start = quorum === undefined ? '' : ` Its work starts by itself at a quorum of ${quorum} agent(s).`;
|
|
18
|
+
out(`created room ${arg} in hub ${H.name} with profile ${r.profile}; it is the current room.${start} In each chat that should take part, say "join ${arg} as <id>"`);
|
|
19
|
+
};
|
|
20
|
+
const use = (H, arg) => {
|
|
21
|
+
const R = Rooms.use(H, arg ?? fail('usage: ringi room switch <id>'));
|
|
22
|
+
out(`current room: ${H.name}/${R.name}; agents keep their own rooms`);
|
|
23
|
+
};
|
|
24
|
+
const admit = (H, arg, o) => {
|
|
25
|
+
const R = Rooms.roomIn(H, opt(o, 'room'));
|
|
26
|
+
Rooms.admit(H, R, arg ?? fail('usage: ringi room admit <agent> <public key|file>'), o._[2] ?? fail('usage: ringi room admit <agent> <public key|file>'));
|
|
27
|
+
out(`admitted ${arg} to ${H.name}/${R.name}: its signed messages are accepted from now on; it can join`);
|
|
28
|
+
};
|
|
29
|
+
const remove = (H, arg, o) => {
|
|
30
|
+
const R = Rooms.roomIn(H, opt(o, 'room'));
|
|
31
|
+
Rooms.remove(H, R, arg ?? fail('usage: ringi room remove <agent>'));
|
|
32
|
+
out(`removed ${arg} from ${R.name}: it can no longer write or be woken there; returning needs a fresh join`);
|
|
33
|
+
};
|
|
34
|
+
// Without an id, the room of the current context.
|
|
35
|
+
const erase = (H, arg, o) => {
|
|
36
|
+
const R = Rooms.roomIn(H, arg ?? opt(o, 'room'));
|
|
37
|
+
if (!flag(o, 'yes'))
|
|
38
|
+
fail(`deleting ${R.name} in hub ${H.name} erases it and everything kept for it, for good. Run again with --yes`);
|
|
39
|
+
Rooms.erase(H, R);
|
|
40
|
+
out(`deleted room ${R.name}: its branch, signals, pins, evidence and readers' state. Sessions bound to it leave it on their next turn`);
|
|
41
|
+
};
|
|
42
|
+
const rebase = (H, arg) => {
|
|
43
|
+
const R = Rooms.roomIn(H, arg ?? fail('usage: ringi room rebase-contract <id>'));
|
|
44
|
+
Rooms.rebase(H, R);
|
|
45
|
+
out(`room ${R.name} now follows the hub contract at ${short(H.main)} (${H.contract.version})`);
|
|
46
|
+
};
|
|
47
|
+
const COMMANDS = new Map([['list', list], ['create', create], ['switch', use], ['admit', admit], ['remove', remove], ['delete', erase], ['rebase-contract', rebase]]);
|
|
9
48
|
export const roomCmd = (o) => {
|
|
10
49
|
const [sub, arg] = o._;
|
|
11
50
|
const H = Hubs.hubOf(opt(o, 'hub'));
|
|
@@ -12,13 +12,11 @@ const quorumLine = (R) => {
|
|
|
12
12
|
const agents = Object.values(R.members).filter(m => m.role !== 'root').length;
|
|
13
13
|
return agents >= R.quorum ? `; started at its quorum of ${R.quorum} agents` : `; waiting for a quorum of ${R.quorum} agents, has ${agents}`;
|
|
14
14
|
};
|
|
15
|
-
const roomLine = (R) => `room ${R.name}
|
|
15
|
+
const roomLine = (R) => `room ${R.name}, genesis ${short(R.genesis)}, profile ${R.profile.name}; members: ${Object.entries(R.members).map(([id, i]) => i.role === 'root' ? `${id} (root)` : id).join(', ')}` + quorumLine(R);
|
|
16
16
|
export const printOverview = (w, R) => {
|
|
17
17
|
out(roomLine(R));
|
|
18
18
|
out(w.sessions.length ? `sessions:\n${w.sessions.map(s => ` ${sessionLine(s)}`).join('\n')}` : 'sessions: none joined');
|
|
19
19
|
out(w.work.length ? `open work:\n${w.work.map(t => ` ${taskLine(t)}`).join('\n')}` : 'open work: none');
|
|
20
|
-
if (w.proposals.length)
|
|
21
|
-
out(`open proposals:\n${w.proposals.map(x => ` ${short(x.proposal.id)} ${x.state} → ${x.decider} ${x.proposal.subject}`).join('\n')}`);
|
|
22
20
|
};
|
|
23
21
|
export const showMessage = (R, o, all, m) => out(flag(o, 'short') ? ` ${oneLine(m)}` : `\n${render(all, m, { max: 2000, files: () => withSizes(R, m) })}`);
|
|
24
22
|
//# sourceMappingURL=where-format.js.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// shared: the commands both run: `ringi send` acts as the operator, `ringi agent send` as the agent its session is
|
|
2
|
-
// bound to; messages, files, work
|
|
3
|
-
export { decide, grants, proposals, propose, stamp_ } from './budget.js';
|
|
2
|
+
// bound to; messages, files, work and signals.
|
|
4
3
|
export { cat, get } from './files.js';
|
|
5
4
|
export { add, read, reply, send, thread } from './messages.js';
|
|
6
5
|
export { profileCmd, who } from './profile.js';
|
|
@@ -6,7 +6,7 @@ import { bytes, fail, short, words } from '../../../lib/index.js';
|
|
|
6
6
|
import { attachments, dump, flag, list, opt, out, textOf } from '../args.js';
|
|
7
7
|
const sendInput = (o) => ({
|
|
8
8
|
text: textOf(o), to: words(opt(o, 'to')), all: flag(o, 'all'), task: flag(o, 'task'),
|
|
9
|
-
state: opt(o, 'state'), assign: opt(o, 'assign') ? words(opt(o, 'assign')) : undefined, roles: opt(o, 'roles'),
|
|
9
|
+
state: opt(o, 'state'), assign: opt(o, 'assign') ? words(opt(o, 'assign')) : undefined, roles: opt(o, 'roles'),
|
|
10
10
|
files: list(o, 'attach').flatMap(attachments)
|
|
11
11
|
});
|
|
12
12
|
const sent = (r) => out(`sent ${short(r.id)} to ${r.to.join(', ')}${r.files ? ` with ${r.files} file(s)` : ''}`);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// profile: `profile` (what work is in the room) and `who` (its members
|
|
1
|
+
// profile: `profile` (what work is in the room) and `who` (its members).
|
|
2
2
|
import * as Room from '../../../core/hub/usecases/room.js';
|
|
3
3
|
import { dump, flag, out } from '../args.js';
|
|
4
4
|
export const profileCmd = ({ R }, o) => {
|
|
@@ -12,6 +12,6 @@ export const profileCmd = ({ R }, o) => {
|
|
|
12
12
|
};
|
|
13
13
|
export const who = (a) => {
|
|
14
14
|
for (const x of Room.members(a))
|
|
15
|
-
out(`${x.id.padEnd(12)} ${x.role.padEnd(7)} ${String(x.messages).padStart(4)} msg
|
|
15
|
+
out(`${x.id.padEnd(12)} ${x.role.padEnd(7)} ${String(x.messages).padStart(4)} msg`);
|
|
16
16
|
};
|
|
17
17
|
//# sourceMappingURL=profile.js.map
|
|
@@ -5,7 +5,7 @@ import { short, when } from '../../../lib/index.js';
|
|
|
5
5
|
import { dump, flag, opt, out } from '../args.js';
|
|
6
6
|
export const taskLine = (t) => {
|
|
7
7
|
const roles = Object.keys(t.roles).length ? ` [${Object.entries(t.roles).map(([id, label]) => `${id}=${label}`).join(' ')}]` : '';
|
|
8
|
-
return `${short(t.id)} ${t.state.padEnd(14)} ${t.requester} → ${t.assignees.join(',') || '(open)'}${roles}${t.taken.length ? ` taken by ${t.taken.join(',')}` : ''}
|
|
8
|
+
return `${short(t.id)} ${t.state.padEnd(14)} ${t.requester} → ${t.assignees.join(',') || '(open)'}${roles}${t.taken.length ? ` taken by ${t.taken.join(',')}` : ''} ${when(Date.parse(t.at) / 1000).slice(5)} by ${t.by} ${t.subject}`;
|
|
9
9
|
};
|
|
10
10
|
export const tasks = (a, o) => {
|
|
11
11
|
const { views } = Room.tasks(a, { all: flag(o, 'all') });
|
|
@@ -15,8 +15,6 @@ import { cursor } from '../adapters/tool-cursor/index.js';
|
|
|
15
15
|
import { hostPosix } from '../adapters/host-posix/index.js';
|
|
16
16
|
import { keysFile } from '../adapters/keys-file/index.js';
|
|
17
17
|
import { gitTransport } from '../adapters/transport-git/transport.js';
|
|
18
|
-
import { kafka } from '../adapters/transport-kafka/index.js';
|
|
19
|
-
import { temporal } from '../adapters/transport-temporal/index.js';
|
|
20
18
|
// The package this file belongs to, run from its source (src/main/ts) or its build (target/esm).
|
|
21
19
|
const packageOf = (dir) => fs.existsSync(path.join(dir, 'package.json')) ? dir : packageOf(path.dirname(dir));
|
|
22
20
|
const PACKAGE = packageOf(path.dirname(fileURLToPath(import.meta.url)));
|
|
@@ -26,7 +24,7 @@ export const build = {
|
|
|
26
24
|
};
|
|
27
25
|
const root = path.resolve(process.env.RINGI_HOME || path.join(os.homedir(), '.ringi'));
|
|
28
26
|
// The git store signs with keys kept as files under the home, made only for a signed hub.
|
|
29
|
-
const transports = { git: gitTransport(root, { signer: () => keysFile(root) })
|
|
27
|
+
const transports = { git: gitTransport(root, { signer: () => keysFile(root) }) };
|
|
30
28
|
wireHub({ build, state: stateFs({ root, build }), transports, store: 'git' });
|
|
31
29
|
// In the order a session is recognised by.
|
|
32
30
|
wireAgents({ tools: [claude, codex, cursor], host: hostPosix() });
|