@rine-network/mastra 0.4.0 → 0.6.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/AGENTS.md +12 -11
- package/MASTRA.md +85 -58
- package/README.md +20 -11
- package/dist/client.d.ts +6 -4
- package/dist/context.d.ts +3 -2
- package/dist/discovery.d.ts +8 -2
- package/dist/drivers.d.ts +4 -3
- package/dist/errors.d.ts +12 -5
- package/dist/format-groups-list.d.ts +143 -0
- package/dist/format-groups.d.ts +81 -0
- package/dist/format.d.ts +51 -15
- package/dist/groups-admin.d.ts +25 -0
- package/dist/groups-admission.d.ts +56 -0
- package/dist/groups-list.d.ts +21 -0
- package/dist/groups-resolve.d.ts +81 -0
- package/dist/groups.d.ts +19 -13
- package/dist/inbound.d.ts +11 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +0 -0
- package/dist/lifecycle.d.ts +9 -7
- package/dist/messaging.d.ts +14 -12
- package/dist/onboard.d.ts +1 -1
- package/dist/onboard.js +3 -3
- package/dist/payments.d.ts +2 -2
- package/dist/schemas-discovery.d.ts +46 -0
- package/dist/schemas-groups-list.d.ts +29 -0
- package/dist/schemas-groups.d.ts +86 -12
- package/dist/schemas-payments.d.ts +2 -1
- package/dist/schemas.d.ts +27 -33
- package/dist/threadmap.d.ts +2 -2
- package/dist/tool.d.ts +15 -12
- package/dist/tools.d.ts +5 -4
- package/dist/types.d.ts +2 -1
- package/package.json +3 -3
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The plural group renderers: the caller's own groups, a directory search, and
|
|
3
|
+
* one group's roster. `format.ts`'s `renderGroup` renders exactly ONE group and
|
|
4
|
+
* is what `rine_group_inspect` returns; these render pages, one numbered row
|
|
5
|
+
* each, in the shape `renderInbox`/`renderDiscover` already use.
|
|
6
|
+
*
|
|
7
|
+
* A sibling of `format.ts` rather than part of it, for the same reason
|
|
8
|
+
* `format-groups.ts` is one — `format.ts` holds its ~200-LOC budget.
|
|
9
|
+
*
|
|
10
|
+
* Ciphertext cannot leak into the model's context through these renderers: a
|
|
11
|
+
* group, a directory entry and a roster row carry no message payload at all.
|
|
12
|
+
*
|
|
13
|
+
* The types come from `@rine-network/sdk` directly: the SDK exports them
|
|
14
|
+
* alongside their schemas, so there is nothing here to re-derive.
|
|
15
|
+
*/
|
|
16
|
+
import { type AgentHandleMap, type GroupMember, type GroupRead, type GroupSummary } from "@rine-network/sdk";
|
|
17
|
+
/**
|
|
18
|
+
* What a group with no conversation renders instead of an id.
|
|
19
|
+
*
|
|
20
|
+
* A group's thread is created lazily on its first post, so a null
|
|
21
|
+
* `conversation_id` is the fact "nothing has been said in this group yet" — not
|
|
22
|
+
* an error, not a refusal, and not a missing field. The clause is never omitted
|
|
23
|
+
* on null: a model that sees it on some rows and not others reads the absence
|
|
24
|
+
* as a rendering fault rather than as a fact about the group.
|
|
25
|
+
*
|
|
26
|
+
* `format.ts`'s `renderGroup` imports it from here so the two renderers cannot
|
|
27
|
+
* tell a model two different things about the same group. The same sentence is
|
|
28
|
+
* printed by the CLI, crewai, langchain, hermes and eve; it is restated per
|
|
29
|
+
* package because there is no runtime module all of them import.
|
|
30
|
+
*/
|
|
31
|
+
export declare const NO_CONVERSATION = "(none \u2014 nothing has been said in this group yet)";
|
|
32
|
+
/**
|
|
33
|
+
* What a group renders in place of an agent list when this org holds no seat.
|
|
34
|
+
*
|
|
35
|
+
* The group list is ORG-scoped — it reports every group any agent of this org
|
|
36
|
+
* is in — so a row on it was never proof that the agent this host is acting as
|
|
37
|
+
* may post there. The empty list is that proof's absence stated plainly: no
|
|
38
|
+
* agent of this org is seated, and a send into the group would be refused.
|
|
39
|
+
*
|
|
40
|
+
* Never omitted, for the reason `NO_CONVERSATION` gives above: a clause a model
|
|
41
|
+
* sees on some rows and not others reads as a rendering fault rather than as a
|
|
42
|
+
* fact about the group. Restated per package because there is no runtime module
|
|
43
|
+
* all seven rendering surfaces import — though this package and its twin do
|
|
44
|
+
* share one (`@rine-network/sdk`), so the day either reworded its row would be
|
|
45
|
+
* the day the sentence belongs there instead.
|
|
46
|
+
*
|
|
47
|
+
* Pinned meanwhile: `tests/test_client-server-contract_group0.py` compares the
|
|
48
|
+
* four declared copies against `rine.group_words.NO_OWN_AGENTS`, which the
|
|
49
|
+
* three Python surfaces import, so a reword in one package fails there rather
|
|
50
|
+
* than shipping two answers to one question.
|
|
51
|
+
*/
|
|
52
|
+
export declare const NO_OWN_AGENTS = "(none \u2014 no agent of your org is seated in this group)";
|
|
53
|
+
/**
|
|
54
|
+
* The seated-agents clause, from the one place both renderers read it.
|
|
55
|
+
*
|
|
56
|
+
* `format.ts`'s `renderGroup` calls this too, so the row and the single-group
|
|
57
|
+
* view cannot tell a model two different things about the same group — the same
|
|
58
|
+
* reason `NO_CONVERSATION` is imported there rather than retyped.
|
|
59
|
+
*
|
|
60
|
+
* Each id renders as its HANDLE. The three cases, and why a name is never one
|
|
61
|
+
* of them, are stated once on `AgentHandleMap` in the SDK
|
|
62
|
+
* (`rine-ts-sdk/src/resources/agent-handles.ts`); this renderer is one of the
|
|
63
|
+
* four that follow them. In short: a known id prints its handle, an unknown one
|
|
64
|
+
* prints itself, an empty list prints {@link NO_OWN_AGENTS}. A model handed a
|
|
65
|
+
* UUID cannot tell which of its agents it names — that is the whole reason
|
|
66
|
+
* handle resolution exists here — but a UUID is still addressable, so an
|
|
67
|
+
* unresolved id is degraded, not lost.
|
|
68
|
+
*
|
|
69
|
+
* `handles` is omitted whenever the org's agent list could not be read; that is
|
|
70
|
+
* case 2 for every id, and it is why nothing here throws.
|
|
71
|
+
*
|
|
72
|
+
* `undefined` is accepted on purpose. `GroupReadSchema` defaults the field to
|
|
73
|
+
* `[]`, so a parsed row always has one — but a row that never went through that
|
|
74
|
+
* parse (a hand-built object, a fake) has nothing, and a renderer whose job is
|
|
75
|
+
* to state an absence must not throw on one.
|
|
76
|
+
*/
|
|
77
|
+
export declare function renderOwnAgents(ids: readonly string[] | undefined, handles?: AgentHandleMap): string;
|
|
78
|
+
/**
|
|
79
|
+
* How this package names a group's regime in one field, for a LIST ROW.
|
|
80
|
+
*
|
|
81
|
+
* One definition for the row, and for the row only. It is NOT what the create
|
|
82
|
+
* confirmation head asks: what a freshly created group runs is decided from the
|
|
83
|
+
* create RESULT, by `createdGroupMls` in `@rine-network/core`, because the row
|
|
84
|
+
* alone cannot tell a founded group from an unfounded one. `renderGroup`'s
|
|
85
|
+
* `[OK]` line re-derives its first clause from the predicates directly and has
|
|
86
|
+
* never called this either. So a reword here reaches this row and nothing else,
|
|
87
|
+
* and a reword in either of those two does not reach this row.
|
|
88
|
+
*
|
|
89
|
+
* The init window is reported as MLS because sends into it already are MLS, and
|
|
90
|
+
* a field that said "sender-key" there would state the opposite of what is
|
|
91
|
+
* happening. The window's own distinction is `rine_group_inspect`'s to make.
|
|
92
|
+
*
|
|
93
|
+
* A group created to run MLS whose ratchet tree was never founded really does
|
|
94
|
+
* carry sender-key traffic, so it names sender keys — and says the rest of the
|
|
95
|
+
* answer, because that row is otherwise field-for-field an open group's and
|
|
96
|
+
* nothing else on the page can tell the two apart. The parenthesis carries NO
|
|
97
|
+
* comma: the row below is comma-separated, which is the same reason its last
|
|
98
|
+
* clause opens with `; `. The whole sentence lives in `rine_group_inspect`; a
|
|
99
|
+
* list row is not the place for it.
|
|
100
|
+
*/
|
|
101
|
+
export declare function groupModeLabel(g: GroupRead): string;
|
|
102
|
+
/**
|
|
103
|
+
* A numbered list of the groups this org's agents are seated in, or the
|
|
104
|
+
* empty-state line.
|
|
105
|
+
*
|
|
106
|
+
* The list is org-scoped, and each row's `your agents` clause names which of
|
|
107
|
+
* this org's agents are seated in that group — an empty clause means none of
|
|
108
|
+
* them is, and a send into that group would be refused. The clause names them
|
|
109
|
+
* by handle because that is the spelling `rine_whoami` prints, so the two
|
|
110
|
+
* outputs can be read against each other — a UUID matched nothing this surface
|
|
111
|
+
* had ever shown the model. What neither tool says is which agent this host is
|
|
112
|
+
* acting AS: `WhoAmI` carries no such field and `renderWhoAmI` marks no row, so
|
|
113
|
+
* in a multi-agent org that still has to come from the host's own config (the
|
|
114
|
+
* `agent` this client was built with, which may itself have been given as a
|
|
115
|
+
* UUID).
|
|
116
|
+
*/
|
|
117
|
+
export declare function renderGroups(items: readonly GroupRead[], handles?: AgentHandleMap): string;
|
|
118
|
+
/**
|
|
119
|
+
* A numbered list of publicly listed groups, or the empty-state line.
|
|
120
|
+
*
|
|
121
|
+
* The header says what the list IS. `GET /directory/groups` is an
|
|
122
|
+
* unauthenticated public-visibility scan across every org and carries no
|
|
123
|
+
* identity at all, so nothing on a row can say whether this agent holds a seat
|
|
124
|
+
* in that group — while `renderGroups` above prints near-identical rows that
|
|
125
|
+
* end with exactly that. Two numbered lists told apart by two words in a header
|
|
126
|
+
* is not enough, so this one says the difference outright.
|
|
127
|
+
*
|
|
128
|
+
* It names no verb: the header states what the caller is looking at, and which
|
|
129
|
+
* tool to reach for next is the tool description's sentence, not this one's.
|
|
130
|
+
*/
|
|
131
|
+
export declare function renderGroupSummaries(items: readonly GroupSummary[]): string;
|
|
132
|
+
/**
|
|
133
|
+
* A numbered roster, or the empty-state line.
|
|
134
|
+
*
|
|
135
|
+
* The roster is members only. An invitation and a nomination hold a seat
|
|
136
|
+
* against the group's ceiling without appearing here — `rine_group_requests`
|
|
137
|
+
* is what reports those — so a roster shorter than the ceiling suggests is not
|
|
138
|
+
* a gap in this list.
|
|
139
|
+
*
|
|
140
|
+
* Every member is listed, from every org. Nothing here filters on whose agent
|
|
141
|
+
* a row is; `(yours)` marks this org's rows and takes none away.
|
|
142
|
+
*/
|
|
143
|
+
export declare function renderRoster(items: readonly GroupMember[]): string;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The admission strings this package composes itself: the outstanding list
|
|
3
|
+
* `rine_group_requests` renders, the line `rine_group_vote` returns, the refusal
|
|
4
|
+
* a vote from outside the electorate reads as, and what `rine_group_reclaim`
|
|
5
|
+
* did to the ratchet tree.
|
|
6
|
+
*
|
|
7
|
+
* They sit beside `format.ts`'s group renderers rather than in the tool module,
|
|
8
|
+
* in a sibling of their own for the same reason `schemas-groups.ts` is one —
|
|
9
|
+
* `format.ts` holds its ~200-LOC budget. Their wording is fixed across every
|
|
10
|
+
* surface that ships these verbs, so a vote reads the same here, from the CLI,
|
|
11
|
+
* and from the Python connectors.
|
|
12
|
+
*
|
|
13
|
+
* Every other group verb returns a sentence composed once, further in: a removal
|
|
14
|
+
* and a leave return `result.message` from the SDK, a sync returns
|
|
15
|
+
* `describeMlsRecovery`, and the reclamation half below returns
|
|
16
|
+
* `describeMlsReclamation`. The rest have no such sentence to return.
|
|
17
|
+
*/
|
|
18
|
+
import { type MlsAdmissionResult } from "@rine-network/sdk";
|
|
19
|
+
import type { JoinRequestRead, VoteResponse } from "./types.js";
|
|
20
|
+
/**
|
|
21
|
+
* The outstanding admissions of one group under one filter, oldest first.
|
|
22
|
+
*
|
|
23
|
+
* Sorted here rather than trusted from the wire: the ordering is what every
|
|
24
|
+
* surface promises a voter, and the Python connectors sort too — so leaving it
|
|
25
|
+
* to the server would make the same list read differently by stack.
|
|
26
|
+
*
|
|
27
|
+
* `groupRef` is the reference the caller gave, not a UUID it never named.
|
|
28
|
+
*/
|
|
29
|
+
export declare function renderRequests(groupRef: string, outstanding: string, rows: readonly JoinRequestRead[]): string;
|
|
30
|
+
/**
|
|
31
|
+
* The outcome of one vote.
|
|
32
|
+
*
|
|
33
|
+
* The leaf-and-Welcome sentence is conditioned on `mls_seated`, not on the
|
|
34
|
+
* server's `approved`. The seat the SDK attempts inside `vote()` is
|
|
35
|
+
* best-effort: a group running Sender Keys has no ratchet tree to mint a leaf
|
|
36
|
+
* in, and an add commit that fails is logged and swallowed so the vote can
|
|
37
|
+
* still be reported. On the status alone this claimed a Welcome for every vote
|
|
38
|
+
* that minted none — which is exactly the failure the seat exists to prevent,
|
|
39
|
+
* reported as a success.
|
|
40
|
+
*
|
|
41
|
+
* `invited` is the fourth answer a carried vote gives, and it is named rather
|
|
42
|
+
* than left to the bare status line. A member may nominate an agent into a
|
|
43
|
+
* `majority` or `unanimity` group, and the electorate can carry that nomination
|
|
44
|
+
* before the nominee has asked for anything; the request then resolves to a
|
|
45
|
+
* spendable invitation instead of a seat, so the agent that was never asked
|
|
46
|
+
* still decides for itself. Reporting it as "approved" would claim a membership
|
|
47
|
+
* that does not exist, and falling through to the bare line would leave a model
|
|
48
|
+
* reading a status word no other outcome uses.
|
|
49
|
+
*/
|
|
50
|
+
export declare function renderVote(groupRef: string, result: VoteResponse): string;
|
|
51
|
+
/**
|
|
52
|
+
* A vote the electorate rule refused, as something the model can act on —
|
|
53
|
+
* or `undefined` for any other failure, which the shared `formatError` owns.
|
|
54
|
+
*
|
|
55
|
+
* Branching on the server's error CODE, never on its sentence: three 403s on
|
|
56
|
+
* this route mean different things, and the detail is written for an operator
|
|
57
|
+
* and is rewritten whenever the wording improves. `no vote was recorded` is
|
|
58
|
+
* stated first because that is the fact an agent would otherwise have to infer
|
|
59
|
+
* from a status code, and a retry of the same call cannot change any of them.
|
|
60
|
+
*
|
|
61
|
+
* There is deliberately no `BarUnreachable` arm. `bar_unreachable` and
|
|
62
|
+
* `electorate_empty` are one refusal and two facts about the row: the route
|
|
63
|
+
* raises `ElectorateEmptyError` for both, so an arm keyed on the other token
|
|
64
|
+
* could never run, and the `ElectorateEmpty` sentence is true of both cases.
|
|
65
|
+
* The two are told apart where they differ — on the row, by
|
|
66
|
+
* {@link renderRequests}.
|
|
67
|
+
*/
|
|
68
|
+
export declare function renderVoteRefusal(groupRef: string, err: unknown): string | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* What one reclamation pass seated and what it retired.
|
|
71
|
+
*
|
|
72
|
+
* The pass seats first and reclaims second, so the report carries both: a leaf
|
|
73
|
+
* belonging to an agent this run has just seated is not an orphan, and a
|
|
74
|
+
* reclamation reported without the seating that preceded it would read as
|
|
75
|
+
* though the tree had been trimmed against a roster nobody caught up.
|
|
76
|
+
*
|
|
77
|
+
* The reclamation half is `describeMlsReclamation` rather than a sentence of
|
|
78
|
+
* this package's own — one implementation for the four TypeScript surfaces that
|
|
79
|
+
* report a reclamation, sentence for sentence identical to the Python twin.
|
|
80
|
+
*/
|
|
81
|
+
export declare function renderReclamation(groupRef: string, result: MlsAdmissionResult): string;
|
package/dist/format.d.ts
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
* with ONE inversion: the group MLS branch reads `[OK]` instead of `[WARN]`,
|
|
6
6
|
* because the TS SDK fully reads/posts MLS + PQ traffic.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* These read ONLY `plaintext` / `decrypt_error` / verification
|
|
9
9
|
* fields. They NEVER read `encrypted_payload` or any envelope/ciphertext field,
|
|
10
10
|
* so ciphertext can never reach the LLM context through a rendered string.
|
|
11
11
|
*/
|
|
12
|
-
import type { ThreadEntry } from "@rine-network/sdk";
|
|
12
|
+
import type { AgentHandleMap, SenderKeyExplainer, ThreadEntry, WhoAmI } from "@rine-network/sdk";
|
|
13
13
|
import type { AgentProfile, AgentSummary, DecryptedMessage, GroupRead, JoinRequestRead } from "./types.js";
|
|
14
14
|
/**
|
|
15
15
|
* Render a both-sided transcript (oldest→newest) for `rine_thread`. Each turn is a
|
|
@@ -27,29 +27,65 @@ export declare function verifiedNote(msg: DecryptedMessage): string;
|
|
|
27
27
|
* - anything else → compact JSON (last resort)
|
|
28
28
|
*/
|
|
29
29
|
export declare function unwrapText(plaintext: unknown): string;
|
|
30
|
-
/**
|
|
31
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Body of a message: decrypt error if unreadable, else the unwrapped plaintext.
|
|
32
|
+
*
|
|
33
|
+
* `explain` is the per-render tiering: pass it on a MULTI render (an inbox,
|
|
34
|
+
* one call per `renderInbox()`) so the no-sender-key cause explains itself in
|
|
35
|
+
* full on the first unreadable row and marks every subsequent one. Omit it on
|
|
36
|
+
* a SINGLE render (`rine_read`, a `rine_send_and_wait` reply) so the one row
|
|
37
|
+
* keeps the full sentence it already carries — there is nothing to tier when
|
|
38
|
+
* the caller asked for exactly one message. Every other decrypt-error cause is
|
|
39
|
+
* untouched either way; classification is the typed `decrypt_error_code`, never
|
|
40
|
+
* the words in `decrypt_error`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function renderMessageBody(msg: DecryptedMessage, explain?: SenderKeyExplainer): string;
|
|
32
43
|
/** A single message rendered across multiple labeled lines (for `rine_read`). */
|
|
33
44
|
export declare function renderSingleMessage(msg: DecryptedMessage): string;
|
|
34
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* A numbered inbox list, or the empty-state line.
|
|
47
|
+
*
|
|
48
|
+
* MULTI render: one explainer per `renderInbox()` call, so the
|
|
49
|
+
* no-sender-key cause explains itself once for this render and marks every
|
|
50
|
+
* later row with the same cause — never module-level, never per-row.
|
|
51
|
+
*/
|
|
35
52
|
export declare function renderInbox(items: readonly DecryptedMessage[]): string;
|
|
36
53
|
/** A numbered discovery list, or the empty-state line. */
|
|
37
54
|
export declare function renderDiscover(items: readonly AgentSummary[]): string;
|
|
38
55
|
/** A full agent profile (for `rine_inspect`). */
|
|
39
56
|
export declare function renderProfile(p: AgentProfile): string;
|
|
40
57
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
58
|
+
* This agent's own identity, for `rine_whoami`: the org it belongs to, the
|
|
59
|
+
* trust tier that org holds, and every handle it can act as.
|
|
60
|
+
*
|
|
61
|
+
* Revoked agents are dropped. The route returns them, and naming one here
|
|
62
|
+
* would offer the model a handle nothing can be sent from or to.
|
|
45
63
|
*/
|
|
46
|
-
export declare function
|
|
64
|
+
export declare function renderWhoAmI(me: WhoAmI): string;
|
|
47
65
|
/**
|
|
48
|
-
* A group rendered for `rine_group_inspect`.
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
66
|
+
* A group rendered for `rine_group_inspect`. Every branch renders `[OK]`: an
|
|
67
|
+
* MLS group is fully readable and postable here.
|
|
68
|
+
*
|
|
69
|
+
* Four states, not two. The second is the MLS init window: the group has no
|
|
70
|
+
* `mls_group_id` to render yet, while the server already accepts nothing but
|
|
71
|
+
* MLS there, so sends from here are MLS sends. Rendering that window as either
|
|
72
|
+
* of the other states says the opposite of what is happening.
|
|
73
|
+
*
|
|
74
|
+
* The third is a group created to run MLS whose ratchet tree was never founded.
|
|
75
|
+
* It reads to every other question exactly like the fourth — an ordinary
|
|
76
|
+
* sender-key group — so it used to fall into it, and the agent was never told
|
|
77
|
+
* the group had not got the encryption it was created for. It stays `[OK]`:
|
|
78
|
+
* every claim that marker makes is true here, the group carries traffic, and
|
|
79
|
+
* only the regime is other than intended. The sentence is the SDK's, and this
|
|
80
|
+
* surface asks for the no-verb spelling because `rine_group_reclaim` refuses on
|
|
81
|
+
* mastra — naming a verb that will not act is worse than naming none.
|
|
82
|
+
*
|
|
83
|
+
* `your agents` closes the gap the `[OK]` lines leave open: they describe how
|
|
84
|
+
* the GROUP is run, not whether this org may act in it. A group can be perfectly
|
|
85
|
+
* readable in the abstract and hold no seat of this org's at all. It names them
|
|
86
|
+
* by handle when `handles` resolves them — the rule is stated once on
|
|
87
|
+
* `AgentHandleMap` in the SDK, and `renderOwnAgents` is where it is applied.
|
|
52
88
|
*/
|
|
53
|
-
export declare function renderGroup(g: GroupRead): string;
|
|
89
|
+
export declare function renderGroup(g: GroupRead, handles?: AgentHandleMap): string;
|
|
54
90
|
/** A numbered list of the caller's pending group invites, or the empty-state line. */
|
|
55
91
|
export declare function renderInvites(items: readonly JoinRequestRead[]): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The 5 admission + membership-exit group tools: `rine_group_requests`,
|
|
3
|
+
* `rine_group_vote`, `rine_group_leave`, `rine_group_sync`,
|
|
4
|
+
* `rine_group_reclaim`.
|
|
5
|
+
*
|
|
6
|
+
* Split from `groups.ts` (which holds the six create/invite/inspect/join tools)
|
|
7
|
+
* so both files stay inside the ~200-LOC budget. Same idiom: one exported
|
|
8
|
+
* factory per tool, the SDK does the work, the tool renders.
|
|
9
|
+
*
|
|
10
|
+
* `rine_group_leave` is a distinct tool rather than a mode of
|
|
11
|
+
* `rine_group_remove`, which keeps its own "name your own agent to leave"
|
|
12
|
+
* behaviour: a leave destroys THIS host's key material, a removal acts on a
|
|
13
|
+
* third party, and one wrong argument should not turn one into the other.
|
|
14
|
+
*/
|
|
15
|
+
import { type RineToolOpts } from "./tool.js";
|
|
16
|
+
/** `rine_group_requests` — list a group's outstanding admissions. */
|
|
17
|
+
export declare function createRineGroupRequestsTool(opts?: RineToolOpts): import("@mastra/core/tools").Tool<any, any, any, any, import("@mastra/core/tools").ToolExecutionContext<any, any, unknown>, "rine_group_requests", unknown>;
|
|
18
|
+
/** `rine_group_vote` — approve or deny one pending join request. */
|
|
19
|
+
export declare function createRineGroupVoteTool(opts?: RineToolOpts): import("@mastra/core/tools").Tool<any, any, any, any, import("@mastra/core/tools").ToolExecutionContext<any, any, unknown>, "rine_group_vote", unknown>;
|
|
20
|
+
/** `rine_group_leave` — leave a group this agent is a member of. */
|
|
21
|
+
export declare function createRineGroupLeaveTool(opts?: RineToolOpts): import("@mastra/core/tools").Tool<any, any, any, any, import("@mastra/core/tools").ToolExecutionContext<any, any, unknown>, "rine_group_leave", unknown>;
|
|
22
|
+
/** `rine_group_sync` — catch this host's MLS state up with the group. */
|
|
23
|
+
export declare function createRineGroupSyncTool(opts?: RineToolOpts): import("@mastra/core/tools").Tool<any, any, any, any, import("@mastra/core/tools").ToolExecutionContext<any, any, unknown>, "rine_group_sync", unknown>;
|
|
24
|
+
/** `rine_group_reclaim` — seat the unseated, then retire the orphaned leaves. */
|
|
25
|
+
export declare function createRineGroupReclaimTool(opts?: RineToolOpts): import("@mastra/core/tools").Tool<any, any, any, any, import("@mastra/core/tools").ToolExecutionContext<any, any, unknown>, "rine_group_reclaim", unknown>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What an admission did, rendered for a model.
|
|
3
|
+
*
|
|
4
|
+
* A roster on `rine_group_create`, a batch on `rine_group_invite` and a single
|
|
5
|
+
* `agentToInvite` are the same operation at three entry points, so they answer
|
|
6
|
+
* in the same vocabulary. The two plural ones report one outcome per requested
|
|
7
|
+
* agent, in the order they were named: a batch never fails whole — naming 32
|
|
8
|
+
* agents and having one of them revoked costs that one agent its seat, not the
|
|
9
|
+
* other 31 theirs — which is only useful if the caller is told which one.
|
|
10
|
+
*
|
|
11
|
+
* Two reports, deliberately not merged. The server's says whether an
|
|
12
|
+
* **invitation** was minted; the MLS one says whether a ratchet-tree **leaf**
|
|
13
|
+
* was. An agent can be `invited` in the first and `no_key_package` in the
|
|
14
|
+
* second: it may join, and it will not be able to read a word until a leaf
|
|
15
|
+
* exists for it. Collapsing them into one number is how that goes unreported.
|
|
16
|
+
*
|
|
17
|
+
* On a `majority` or `unanimity` group the server's answer is `nominated`
|
|
18
|
+
* rather than `invited`: the invite files a join request the electorate
|
|
19
|
+
* decides, and no leaf is minted for it. So a nomination has no MLS report at
|
|
20
|
+
* all — the vote seats the member, and seating is what grants the key.
|
|
21
|
+
*
|
|
22
|
+
* The shapes and the reason→sentence maps are `@rine-network/core`'s, so this
|
|
23
|
+
* module is the rendering and nothing else. A skip used to print the raw wire
|
|
24
|
+
* token, which read as a refusal on exactly the groups it is not one for: an
|
|
25
|
+
* open group mints no invitation because it needs none, and `not_applicable`
|
|
26
|
+
* said nothing about that to a model deciding what to do next.
|
|
27
|
+
*/
|
|
28
|
+
import { type GroupAdmissionReport, type MlsAdmissionResult } from "@rine-network/core";
|
|
29
|
+
/** The refusal when a caller names both invite targets, or neither. */
|
|
30
|
+
export declare const INVITE_TARGET_REQUIRED = "Name exactly one of agentToInvite (one invitation) or agentsToInvite (a batch).";
|
|
31
|
+
/**
|
|
32
|
+
* What one `agentToInvite` produced, told from the row's own status.
|
|
33
|
+
*
|
|
34
|
+
* The singular route answers one row rather than a per-agent report, so the
|
|
35
|
+
* status word is all a caller has to go on — and `Invited X (status pending)`
|
|
36
|
+
* both claims something that did not happen and hands a model a word no other
|
|
37
|
+
* outcome of this tool uses. `invited` and `pending` are therefore named, and
|
|
38
|
+
* any other status still prints itself rather than being read as one of them.
|
|
39
|
+
*
|
|
40
|
+
* `invited` covers two shapes and the sentence names both. A closed group mints
|
|
41
|
+
* a real invitation row that occupies a ratchet-tree seat until it is accepted
|
|
42
|
+
* or expires; an open group answers `invited` having minted nothing at all,
|
|
43
|
+
* because nobody needs an invitation to join one — and it runs sender keys, so
|
|
44
|
+
* there is no ratchet tree for a seat to sit in.
|
|
45
|
+
*/
|
|
46
|
+
export declare function renderSingularInvite(agentRef: string, groupRef: string, status: string): string;
|
|
47
|
+
/** Per-agent invitation outcomes, one line each, in the order they were named. */
|
|
48
|
+
export declare function renderAdmission(report: GroupAdmissionReport): string;
|
|
49
|
+
/**
|
|
50
|
+
* What the MLS admission seated, and who is still without a leaf.
|
|
51
|
+
*
|
|
52
|
+
* `already_in_group` is filtered out of the unseated list: an agent that
|
|
53
|
+
* already holds a leaf is what a resumed admission looks like when it has
|
|
54
|
+
* nothing left to do, not a failure to report.
|
|
55
|
+
*/
|
|
56
|
+
export declare function renderMlsAdmission(mls: MlsAdmissionResult): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The group domain's three READ tools: `rine_groups` (the groups this agent's
|
|
3
|
+
* ORG belongs to), `rine_discover_groups` (the public directory) and
|
|
4
|
+
* `rine_group_roster` (who is in one group).
|
|
5
|
+
*
|
|
6
|
+
* A third group module beside `groups.ts` (the six founding/admission tools)
|
|
7
|
+
* and `groups-admin.ts` (the five admission and exit verbs), so all three hold
|
|
8
|
+
* the ~200-LOC budget.
|
|
9
|
+
*
|
|
10
|
+
* None of them mutates anything, so none carries a `destructiveHint`.
|
|
11
|
+
* `rine_discover_groups` reads the public directory and needs no membership at
|
|
12
|
+
* all — it answers for `public`-visibility groups across every org, and returns
|
|
13
|
+
* no roster for any of them.
|
|
14
|
+
*/
|
|
15
|
+
import { type RineToolOpts } from "./tool.js";
|
|
16
|
+
/** `rine_groups` — the groups this agent's ORG belongs to. */
|
|
17
|
+
export declare function createRineGroupsTool(opts?: RineToolOpts): import("@mastra/core/tools").Tool<any, any, any, any, import("@mastra/core/tools").ToolExecutionContext<any, any, unknown>, "rine_groups", unknown>;
|
|
18
|
+
/** `rine_discover_groups` — search the public group directory. */
|
|
19
|
+
export declare function createRineDiscoverGroupsTool(opts?: RineToolOpts): import("@mastra/core/tools").Tool<any, any, any, any, import("@mastra/core/tools").ToolExecutionContext<any, any, unknown>, "rine_discover_groups", unknown>;
|
|
20
|
+
/** `rine_group_roster` — who is in one group, and since when. */
|
|
21
|
+
export declare function createRineGroupRosterTool(opts?: RineToolOpts): import("@mastra/core/tools").Tool<any, any, any, any, import("@mastra/core/tools").ToolExecutionContext<any, any, unknown>, "rine_group_roster", unknown>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AGENT handle → UUID resolution for the group tools, and the two group
|
|
3
|
+
* resolutions that are the SDK's rather than this package's.
|
|
4
|
+
*
|
|
5
|
+
* 🔴 **Group references are not resolved here any more.** This module
|
|
6
|
+
* used to answer them from `groups.list()` and a local three-branch match, a
|
|
7
|
+
* fourth copy of a ladder the SDK now owns: `client.groups.resolveRef` reads a
|
|
8
|
+
* UUID from the group's own indexed row, a handle from the server's own lookup,
|
|
9
|
+
* and a bare name from the org's list — and answers with the group's whole
|
|
10
|
+
* record, so a verb handed the record reads no group of its own. Every group
|
|
11
|
+
* tool in this package calls that seam directly; nothing re-derives a row at a
|
|
12
|
+
* call site, and nothing here restates the ladder.
|
|
13
|
+
*
|
|
14
|
+
* What is left is the resolution the SDK does NOT do for these tools:
|
|
15
|
+
* - an agent → `resolveToUuid` (WebFinger) → its UUID (or pass a UUID
|
|
16
|
+
* through). WebFinger — not the public directory — so unlisted agents
|
|
17
|
+
* resolve too. This is the same resolution the SDK's own 1:1 send path uses.
|
|
18
|
+
* - a group for `rine_group_join`, which is a DIFFERENT ladder and is
|
|
19
|
+
* documented as such on {@link resolveJoinGroupUuid}.
|
|
20
|
+
*
|
|
21
|
+
* Split out of `groups.ts` so that file holds its six tool definitions and
|
|
22
|
+
* nothing else; the aggregator (`tools.ts`) never imports this module, so the
|
|
23
|
+
* shipped-surface gate's `id: "rine_*"` scan is unaffected by the move.
|
|
24
|
+
*/
|
|
25
|
+
import type { AsyncRineClient } from "@rine-network/sdk";
|
|
26
|
+
/**
|
|
27
|
+
* A tool's answer, led by the item-18 completion notice when there is one.
|
|
28
|
+
*
|
|
29
|
+
* 🔴 `resolveToUuid` completes a short handle before it reaches WebFinger —
|
|
30
|
+
* `kofi@acme` is looked up as `kofi@acme.rine.network` — and answers with the
|
|
31
|
+
* resolved UUID, never the handle it resolved. The model named one agent and
|
|
32
|
+
* the call may have invited, removed or seated another, with nothing in the
|
|
33
|
+
* answer saying so.
|
|
34
|
+
*
|
|
35
|
+
* 🔴 A LINE, not a key, and that is this surface's shape rather than a choice:
|
|
36
|
+
* every tool here declares `strResult`, so there is no object to hang a field
|
|
37
|
+
* on. `@rine-network/mcp` returns objects and rides the same sentence as a
|
|
38
|
+
* `handle_completion` key; the CLI writes it to stderr. The BYTES are
|
|
39
|
+
* {@link handleCompletionNotes}' in `@rine-network/core` and are retyped by
|
|
40
|
+
* none of the three.
|
|
41
|
+
*
|
|
42
|
+
* It leads rather than trails because a model reads the head of a tool result
|
|
43
|
+
* and acts on it — a caveat about which agent was actually touched is worth
|
|
44
|
+
* nothing underneath the report of touching them.
|
|
45
|
+
*/
|
|
46
|
+
export declare function withHandleCompletionLine(answer: string, spellings: readonly string[]): string;
|
|
47
|
+
/** Resolve an agent handle/UUID to its `AgentUuid` (UUIDs pass through). */
|
|
48
|
+
export declare function resolveAgentUuid(apiUrl: string, target: string): Promise<import("@rine-network/sdk").AgentUuid>;
|
|
49
|
+
/**
|
|
50
|
+
* Resolve a batch of agent handles/UUIDs, **in the order they were named**.
|
|
51
|
+
*
|
|
52
|
+
* Order is load-bearing: the server answers one admission entry per requested
|
|
53
|
+
* id in request order, so a report read against a re-ordered list names the
|
|
54
|
+
* wrong agents. Duplicates are dropped case-insensitively rather than sent
|
|
55
|
+
* twice, because the second copy of an id comes back `already_invited` and
|
|
56
|
+
* reads as a failure the caller did not cause.
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveAgentUuids(apiUrl: string, targets: string[]): Promise<import("@rine-network/sdk").AgentUuid[]>;
|
|
59
|
+
/**
|
|
60
|
+
* Resolve a group handle/UUID to its `GroupUuid` for `rine_group_join`.
|
|
61
|
+
*
|
|
62
|
+
* 🔴 The SDK's own join ladder, not a copy of one, and NOT the ladder the other
|
|
63
|
+
* twelve group tools take. `client.groups.resolveRef` is scoped at every rung
|
|
64
|
+
* to a group the ORG already owns or is seated in — which for a join is the one
|
|
65
|
+
* set the target cannot be in — and this package
|
|
66
|
+
* used to answer instead from `groups.listInvites()` alone, so the commonest
|
|
67
|
+
* join there is, a handle read straight off `rine_discover_groups`, was refused
|
|
68
|
+
* here with the server never having been asked. `resolveRefForJoin` walks the
|
|
69
|
+
* org's seats, then this agent's invitations, then the public directory,
|
|
70
|
+
* matching the handle exactly at every rung. What this package could always do
|
|
71
|
+
* it still does: a BARE name resolves against this agent's own pending
|
|
72
|
+
* invitations — and against nothing else, because that list is the only set
|
|
73
|
+
* bounded to groups that have already asked for this agent, and a join cannot
|
|
74
|
+
* be taken back (`rine-core/src/resolve-group-join.ts` `resolveGroupUuidForJoin`).
|
|
75
|
+
*
|
|
76
|
+
* The refusals it throws lead with `Group not found`, which is the phrase
|
|
77
|
+
* `formatError` (`./errors.ts`) keys on to append this surface's own discover
|
|
78
|
+
* verbs — the old `No pending invite` wording matched none of its three
|
|
79
|
+
* spellings, so a refused join carried no remedy at all.
|
|
80
|
+
*/
|
|
81
|
+
export declare function resolveJoinGroupUuid(client: AsyncRineClient, target: string): Promise<import("@rine-network/sdk").GroupUuid>;
|
package/dist/groups.d.ts
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 6 of the group domain's 13 tools: `rine_group_create`, `rine_group_invite`,
|
|
3
3
|
* `rine_group_remove`, `rine_group_inspect` (the INVERTED, MLS-capable
|
|
4
|
-
* section), `rine_group_join`, `rine_group_invites`.
|
|
4
|
+
* section), `rine_group_join`, `rine_group_invites`. The four admission and
|
|
5
|
+
* exit verbs — `rine_group_requests`, `rine_group_vote`, `rine_group_leave`,
|
|
6
|
+
* `rine_group_sync` — live in `groups-admin.ts`, so both files hold the
|
|
7
|
+
* ~200-LOC budget.
|
|
5
8
|
*
|
|
6
|
-
* `group_create` exposes `enableMls` (default true)
|
|
7
|
-
*
|
|
8
|
-
* `
|
|
9
|
+
* `group_create` exposes `enableMls` (default true): the SDK best-effort-inits
|
|
10
|
+
* an MLS group and the renderer reports `[OK] MLS`, not a `[WARN]` ceiling. It
|
|
11
|
+
* exposes no `visibility` default at all — see `schemas-groups.ts`.
|
|
9
12
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Admission is plural on both write verbs. `members` on create and
|
|
14
|
+
* `agentsToInvite` on invite each take a batch and report one outcome per
|
|
15
|
+
* agent, because a batch drops what it cannot admit rather than refusing
|
|
16
|
+
* everyone, and on an MLS group it mints every new leaf in one commit instead
|
|
17
|
+
* of one commit each.
|
|
18
|
+
*
|
|
19
|
+
* Handle→UUID resolution lives in `groups-resolve.ts` and the admission
|
|
20
|
+
* rendering in `groups-admission.ts`, so this file is those six tool
|
|
21
|
+
* definitions and their bodies.
|
|
16
22
|
*
|
|
17
23
|
* `rine_group_join`/`rine_group_invites` close the accept-side gap: an agent
|
|
18
24
|
* invited into a group previously had no tool to join it or see its pending
|
|
@@ -21,9 +27,9 @@
|
|
|
21
27
|
import { type RineToolOpts } from "./tool.js";
|
|
22
28
|
/** `rine_group_create` — create an MLS-by-default coordination group. */
|
|
23
29
|
export declare function createRineGroupCreateTool(opts?: RineToolOpts): import("@mastra/core/tools").Tool<any, any, any, any, import("@mastra/core/tools").ToolExecutionContext<any, any, unknown>, "rine_group_create", unknown>;
|
|
24
|
-
/** `rine_group_invite` — invite
|
|
30
|
+
/** `rine_group_invite` — invite one agent or a batch (handle→UUID pre-resolved). */
|
|
25
31
|
export declare function createRineGroupInviteTool(opts?: RineToolOpts): import("@mastra/core/tools").Tool<any, any, any, any, import("@mastra/core/tools").ToolExecutionContext<any, any, unknown>, "rine_group_invite", unknown>;
|
|
26
|
-
/** `rine_group_remove` —
|
|
32
|
+
/** `rine_group_remove` — evict a member, or leave (handle→UUID pre-resolved). */
|
|
27
33
|
export declare function createRineGroupRemoveTool(opts?: RineToolOpts): import("@mastra/core/tools").Tool<any, any, any, any, import("@mastra/core/tools").ToolExecutionContext<any, any, unknown>, "rine_group_remove", unknown>;
|
|
28
34
|
/** `rine_group_inspect` — report a group's E2EE mode + policy (`[OK] MLS` self-diagnosis). */
|
|
29
35
|
export declare function createRineGroupInspectTool(opts?: RineToolOpts): import("@mastra/core/tools").Tool<any, any, any, any, import("@mastra/core/tools").ToolExecutionContext<any, any, unknown>, "rine_group_inspect", unknown>;
|
package/dist/inbound.d.ts
CHANGED
|
@@ -10,13 +10,21 @@
|
|
|
10
10
|
* `createRun({runId})` would otherwise read an empty in-process run-map);
|
|
11
11
|
* a non-suspended / unknown run ⇒ skip, do NOT ack;
|
|
12
12
|
* 3. build `resumeData` from `plaintext` / `verified` / `from` ONLY
|
|
13
|
-
* (
|
|
13
|
+
* (JSON-serializable, never ciphertext or an SDK client) — a
|
|
14
14
|
* decrypt-failed message ⇒ skip, do NOT ack;
|
|
15
15
|
* 4. `createRun({runId}).resume({ step, resumeData })` to continue the run.
|
|
16
16
|
*
|
|
17
17
|
* **Lossless-by-default:** every skip path leaves the message in
|
|
18
18
|
* the rine inbox (no `markDelivered`), so a later poll can retry after the run is
|
|
19
19
|
* mapped / key recovery succeeds. The resumer NEVER acks.
|
|
20
|
+
*
|
|
21
|
+
* TRUST NOTE: `verified === true` on an inbound message means the envelope
|
|
22
|
+
* signature checked out AND the signing key it names belongs to the agent the
|
|
23
|
+
* server authenticated as the sender, so the `from` handed to the resumed step is
|
|
24
|
+
* the signer of that content. The signature covers the payload only — not this
|
|
25
|
+
* recipient, and no nonce — so an agent re-sending content it signed earlier
|
|
26
|
+
* produces a copy that verifies as its own. A workflow that must act on a payload
|
|
27
|
+
* once keys its own idempotency on `messageId`.
|
|
20
28
|
*/
|
|
21
29
|
import type { ThreadMapStore } from "./threadmap.js";
|
|
22
30
|
import type { DecryptedMessage } from "./types.js";
|
|
@@ -50,13 +58,13 @@ export interface ResumableRun {
|
|
|
50
58
|
}): Promise<unknown>;
|
|
51
59
|
}
|
|
52
60
|
/**
|
|
53
|
-
* The JSON-serializable payload handed to the suspended step on resume
|
|
61
|
+
* The JSON-serializable payload handed to the suspended step on resume:
|
|
54
62
|
* plaintext + signature facts ONLY — no ciphertext, no envelope, no SDK client.
|
|
55
63
|
*/
|
|
56
64
|
export interface ResumeData {
|
|
57
65
|
/** Unwrapped decrypted body (or a decrypt-error marker), never ciphertext. */
|
|
58
66
|
plaintext: string;
|
|
59
|
-
/** Whether the
|
|
67
|
+
/** Whether the signature verified as the server-authenticated sender's. */
|
|
60
68
|
verified: boolean;
|
|
61
69
|
/** Sender handle (or agent UUID fallback), for the resumed step's context. */
|
|
62
70
|
from: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -11,16 +11,18 @@
|
|
|
11
11
|
* (client builder, error formatter, renderers, schemas) is exported now so
|
|
12
12
|
* tests and downstream stages can consume it.
|
|
13
13
|
*
|
|
14
|
-
* Import is side-effect-free
|
|
14
|
+
* Import is side-effect-free: nothing here constructs a client, reads a
|
|
15
15
|
* credential, or opens a socket at module load.
|
|
16
16
|
*/
|
|
17
17
|
export { getRineClient } from "./client.js";
|
|
18
18
|
export type { RineClientOpts } from "./client.js";
|
|
19
19
|
export { formatError } from "./errors.js";
|
|
20
20
|
export type { RinePaymentToolOpts, RineToolOpts } from "./tool.js";
|
|
21
|
-
export {
|
|
22
|
-
export { createRineDiscoverTool, createRineInspectTool } from "./discovery.js";
|
|
21
|
+
export { createRineInboxTool, createRineReadTool, createRineReplyTool, createRineSendAndWaitTool, createRineSendTool, createRineThreadTool, } from "./messaging.js";
|
|
22
|
+
export { createRineDiscoverTool, createRineInspectTool, createRineWhoamiTool, } from "./discovery.js";
|
|
23
|
+
export { createRineDiscoverGroupsTool, createRineGroupRosterTool, createRineGroupsTool, } from "./groups-list.js";
|
|
23
24
|
export { createRineGroupCreateTool, createRineGroupInspectTool, createRineGroupInviteTool, createRineGroupInvitesTool, createRineGroupJoinTool, createRineGroupRemoveTool, } from "./groups.js";
|
|
25
|
+
export { createRineGroupLeaveTool, createRineGroupReclaimTool, createRineGroupRequestsTool, createRineGroupSyncTool, createRineGroupVoteTool, } from "./groups-admin.js";
|
|
24
26
|
export { createRineFulfillTool, createRinePayTool } from "./payments.js";
|
|
25
27
|
export { rineToolkit } from "./tools.js";
|
|
26
28
|
export type { RinePaymentsConfig, RineToolDomain, RineToolkitOptions, } from "./tools.js";
|
package/dist/index.js
CHANGED
|
Binary file
|