@rine-network/eve 0.2.0 → 0.3.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 CHANGED
@@ -102,7 +102,7 @@ undecryptable mail is dropped by default.
102
102
  | `rine_reply` | Reply to a message by id, in-thread |
103
103
  | `rine_thread` | Decrypted both-sided transcript of a conversation |
104
104
  | `rine_discover` / `rine_inspect` | Search the directory / read a profile |
105
- | `rine_group_create` / `_invite` / `_remove` / `_inspect` | MLS-by-default groups |
105
+ | `rine_group_create` / `_invite` / `_remove` / `_inspect` / `_join` / `_invites` | MLS-by-default groups |
106
106
  | `rine_pay` | Pay a received `rine.v1.x402_payment_required` quote under the local spend policy |
107
107
  | `rine_fulfill` | Payee side: verify + settle a received payment and reply with a receipt |
108
108
 
package/dist/_zod.d.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  * accuracy) and parse the raw model input with the zod schema inside `execute`
10
10
  * (applying defaults + coercion). One source of truth (zod), version-independent.
11
11
  *
12
- * Every tool's `outputSchema` is `string` (R4) — a tool returns clean text, so
12
+ * Every tool's `outputSchema` is `string` — a tool returns clean text, so
13
13
  * ciphertext can never ride a struct field.
14
14
  */
15
15
  import { z, type ZodTypeAny } from "zod";
@@ -1,10 +1,10 @@
1
- import { _ as senderLabel, f as renderMessageBody, g as renderThreadLine, n as asRecipient, v as verifiedNote } from "./tool-BC49DldZ.js";
1
+ import { b as verifiedNote, m as renderMessageBody, n as asRecipient, v as renderThreadLine, y as senderLabel } from "./tool-xlLdY8kn.js";
2
2
  import { n as verifyRineSignature } from "./hmac-CoaKHmf6.js";
3
- import { t as getRineClient } from "./client-X_-9CpQT.js";
3
+ import { t as getRineClient } from "./client-DsG2xtKs.js";
4
4
  import { POST, defineChannel } from "eve/channels";
5
5
  import { X402Error, X402_MESSAGE_TYPE, asMessageUuid } from "@rine-network/sdk";
6
6
  //#region src/transcript.ts
7
- /** char ≈ 4 × tokens — the coarse proxy the spec specifies (REQ-CTX-01, OQ1). */
7
+ /** char ≈ 4 × tokens — the coarse proxy the spec specifies. */
8
8
  const CHARS_PER_TOKEN = 4;
9
9
  /** Marker prepended when older turns were dropped to fit the budget. */
10
10
  const OMITTED_MARKER = "[…earlier turns omitted]";
@@ -40,14 +40,14 @@ function renderTranscriptContext(entries, tokenBudget) {
40
40
  * Inbound webhook helpers for the rine channel: extracting the message id from a
41
41
  * rine standard-webhook body, and the continuation-token codec.
42
42
  *
43
- * The continuation token is how the channel makes outbound replies STATELESS (R7):
43
+ * The continuation token is how the channel makes outbound replies STATELESS:
44
44
  * it encodes the rine `conversation_id`, the reply target (the group handle for
45
45
  * group mail, else the sender handle), and — for 1:1 inbound only — the inbound
46
46
  * `message id` so the `message.completed` handler can reply IN-PLACE (via the reply
47
47
  * endpoint, preserving the inbound conversation) without any durable per-session map.
48
48
  * Because the token bakes in the per-message `m`, it differs on every 1:1 inbound
49
49
  * turn, so Eve does NOT resume a prior session from it — cross-turn continuity comes
50
- * from the general thread primitive (push-injected transcript, Slice E), not session
50
+ * from the general thread primitive (push-injected transcript), not session
51
51
  * resume. The message id is optional: group inbound and tokens minted by an older
52
52
  * build carry only `{c,r}` and decode with `messageId === undefined`, so the outbound
53
53
  * handler falls back to the `send()+parentConversationId` broadcast path.
@@ -133,7 +133,7 @@ function messageIdFromWebhook(body) {
133
133
  //#endregion
134
134
  //#region src/x402.ts
135
135
  /**
136
- * x402 payment-aware inbound re-surfacing for the rine channel (D1 + D2).
136
+ * x402 payment-aware inbound re-surfacing for the rine channel.
137
137
  *
138
138
  * The three x402 payment frames are first-class message types carrying a verbatim
139
139
  * x402 V2 object, NOT a chat turn. v1.0 dropped them wholesale (a stateless gateway
@@ -146,7 +146,7 @@ function messageIdFromWebhook(body) {
146
146
  * - `x402_payment` → the signed authorization + guidance to `rine_fulfill`.
147
147
  * - `x402_receipt` → the settlement outcome, informational (no reply).
148
148
  *
149
- * D2 auto-pay (opt-in, DEFAULT OFF): when enabled, a `payment_required` at/below the
149
+ * Auto-pay (opt-in, DEFAULT OFF): when enabled, a `payment_required` at/below the
150
150
  * policy's `autoPayThreshold` is paid with NO LLM turn — still bounded by the policy
151
151
  * caps, deny-by-default, journal and reserve-lock (all in rine-core). Any decline
152
152
  * falls back to surfacing the quote to the model.
@@ -200,7 +200,7 @@ function x402GuidanceLine(msg) {
200
200
  return `x402 receipt from ${who} (${note}). This is informational — no reply is expected.`;
201
201
  }
202
202
  /**
203
- * D2 auto-pay attempt. Returns `null` when the quote was paid (no session needed),
203
+ * Auto-pay attempt. Returns `null` when the quote was paid (no session needed),
204
204
  * or a one-line decline note when auto-pay was refused or errored (the caller then
205
205
  * surfaces the quote to the model). A policy refusal / above-threshold quote is a
206
206
  * typed {@link X402Error}; anything else (network, wallet) is reported verbatim.
@@ -232,7 +232,7 @@ async function surfaceX402(deps, msg, messageId, note) {
232
232
  return new Response("ok", { status: 200 });
233
233
  }
234
234
  /**
235
- * Handle a verified inbound x402 frame (D1). `payment_required` may auto-pay (D2)
235
+ * Handle a verified inbound x402 frame. `payment_required` may auto-pay
236
236
  * when enabled and at/below threshold; otherwise, and for `payment` / `receipt`,
237
237
  * the frame is surfaced to the model as a payment-aware turn.
238
238
  */
@@ -256,9 +256,9 @@ async function handleX402Inbound(deps, msg, messageId) {
256
256
  * `defineChannel` route; the OUTBOUND half (`processCompletion`/`processFailure`)
257
257
  * lives in `channel-outbound.ts`.
258
258
  *
259
- * - INBOUND (`processInbound`): HMAC-verify (transport auth, R5) → parse → dedupe
259
+ * - INBOUND (`processInbound`): HMAC-verify (transport auth) → parse → dedupe
260
260
  * → `client.read(id)` to HPKE-decrypt + verify the sender's Ed25519 signature
261
- * (content auth, R5) → loop-guard → mark delivered → start/resume the session.
261
+ * (content auth) → loop-guard → mark delivered → start/resume the session.
262
262
  *
263
263
  * TRUST NOTE: `verified === true` cryptographically binds the message's *signer*
264
264
  * (the envelope `kid`), but the SDK exposes only the server-asserted
@@ -272,11 +272,11 @@ function senderContextLine(msg) {
272
272
  const where = msg.group_handle ? ` in group ${msg.group_handle}` : "";
273
273
  return `Inbound rine message from ${senderLabel(msg)}${where} (type ${msg.type}, ${verifiedNote(msg)}). Your reply is delivered back to the sender over rine.`;
274
274
  }
275
- /** Cap on turns fetched for the push-injected transcript (REQ-SRV-04). */
275
+ /** Cap on turns fetched for the push-injected transcript. */
276
276
  const THREAD_FETCH_LIMIT = 50;
277
277
  /**
278
278
  * The inbound pipeline. Returns the HTTP {@link Response} the route should send.
279
- * Status codes are retry-aware (R8/#10): `5xx` = transient (caller should retry),
279
+ * Status codes are retry-aware: `5xx` = transient (caller should retry),
280
280
  * `4xx` = terminal drop, `2xx` = accepted/benign-ignore.
281
281
  */
282
282
  async function processInbound(deps) {
@@ -331,15 +331,15 @@ async function processInbound(deps) {
331
331
  * unit-testable with fake clients. `channel.ts` wires these to Eve's
332
332
  * `message.completed` / failure events; the INBOUND half lives in `channel-core.ts`.
333
333
  *
334
- * On a terminal assistant message (R6) reply back over rine IN-PLACE via the reply
335
- * endpoint, preserving the inbound conversation (R7); falls back to
334
+ * On a terminal assistant message, reply back over rine IN-PLACE via the reply
335
+ * endpoint, preserving the inbound conversation; falls back to
336
336
  * `parentConversationId` for legacy tokens. A session started by an x402 frame never
337
337
  * prose-replies into the payment thread (the pay / fulfill tools transmit the signed
338
338
  * frame in-thread instead) — the `x402` continuation-token flag short-circuits both.
339
339
  */
340
340
  /**
341
341
  * Outbound for `message.completed`: every TERMINAL assistant message (any
342
- * `finishReason` except the intermediate `tool-calls`, R6) with text becomes a
342
+ * `finishReason` except the intermediate `tool-calls`) with text becomes a
343
343
  * reply. When the continuation token carries the inbound message id we reply
344
344
  * IN-PLACE via the reply endpoint (same conversation, no fork) keeping the
345
345
  * connector's `replyMessageType` unchanged — type-preserving, so terminal/wake
@@ -386,15 +386,15 @@ async function processFailure(continuationToken, client) {
386
386
  const DEFAULT_INBOUND_PATH = "/rine/v1/inbound";
387
387
  const DEFAULT_REPLY_TYPE = "rine.v1.task_response";
388
388
  const DEFAULT_MAX_BODY_BYTES = 512 * 1024;
389
- /** Default token budget for the push-injected transcript (REQ-CTX-01, ≈8000 chars). */
389
+ /** Default token budget for the push-injected transcript (≈8000 chars). */
390
390
  const DEFAULT_THREAD_CONTEXT_TOKEN_BUDGET = 2e3;
391
391
  /**
392
- * Message types never auto-replied to (loop guard, R2): the connector's OWN
392
+ * Message types never auto-replied to (loop guard): the connector's OWN
393
393
  * outbound types (task_response/error/receipt), so two rine-eve agents don't
394
394
  * auto-reply to each other forever.
395
395
  *
396
396
  * The three x402 payment frames are NOT here: v1.1 re-surfaces them as
397
- * payment-aware agent turns (D1), routed by `handleX402Inbound` with the prose
397
+ * payment-aware agent turns, routed by `handleX402Inbound` with the prose
398
398
  * auto-reply suppressed (the `x402` continuation-token flag), never by the generic
399
399
  * assistant reply. Adding them here would revert to the v1.0 silent-drop behavior.
400
400
  */
@@ -4,9 +4,9 @@
4
4
  * `defineChannel` route; the OUTBOUND half (`processCompletion`/`processFailure`)
5
5
  * lives in `channel-outbound.ts`.
6
6
  *
7
- * - INBOUND (`processInbound`): HMAC-verify (transport auth, R5) → parse → dedupe
7
+ * - INBOUND (`processInbound`): HMAC-verify (transport auth) → parse → dedupe
8
8
  * → `client.read(id)` to HPKE-decrypt + verify the sender's Ed25519 signature
9
- * (content auth, R5) → loop-guard → mark delivered → start/resume the session.
9
+ * (content auth) → loop-guard → mark delivered → start/resume the session.
10
10
  *
11
11
  * TRUST NOTE: `verified === true` cryptographically binds the message's *signer*
12
12
  * (the envelope `kid`), but the SDK exposes only the server-asserted
@@ -41,7 +41,7 @@ export interface InboundDeps {
41
41
  /** Inbound types to ignore (loop guard). */
42
42
  ignoreTypes: readonly string[];
43
43
  /**
44
- * D2 opt-in auto-pay (default OFF). When true, an inbound `x402_payment_required`
44
+ * Opt-in auto-pay (default OFF). When true, an inbound `x402_payment_required`
45
45
  * at/below the policy's `autoPayThreshold` is paid with NO LLM turn — still
46
46
  * bounded by the caps, deny-by-default, journal and reserve-lock. Any decline
47
47
  * falls back to surfacing the quote to the model.
@@ -51,13 +51,13 @@ export interface InboundDeps {
51
51
  seen?: Set<string>;
52
52
  /**
53
53
  * Approximate token budget for the role-tagged transcript push-injected into the
54
- * session context (REQ-CTX-01). When unset, only the sender line is injected.
54
+ * session context. When unset, only the sender line is injected.
55
55
  */
56
56
  threadContextTokenBudget?: number;
57
57
  }
58
58
  /**
59
59
  * The inbound pipeline. Returns the HTTP {@link Response} the route should send.
60
- * Status codes are retry-aware (R8/#10): `5xx` = transient (caller should retry),
60
+ * Status codes are retry-aware: `5xx` = transient (caller should retry),
61
61
  * `4xx` = terminal drop, `2xx` = accepted/benign-ignore.
62
62
  */
63
63
  export declare function processInbound(deps: InboundDeps): Promise<Response>;
@@ -3,8 +3,8 @@
3
3
  * unit-testable with fake clients. `channel.ts` wires these to Eve's
4
4
  * `message.completed` / failure events; the INBOUND half lives in `channel-core.ts`.
5
5
  *
6
- * On a terminal assistant message (R6) reply back over rine IN-PLACE via the reply
7
- * endpoint, preserving the inbound conversation (R7); falls back to
6
+ * On a terminal assistant message, reply back over rine IN-PLACE via the reply
7
+ * endpoint, preserving the inbound conversation; falls back to
8
8
  * `parentConversationId` for legacy tokens. A session started by an x402 frame never
9
9
  * prose-replies into the payment thread (the pay / fulfill tools transmit the signed
10
10
  * frame in-thread instead) — the `x402` continuation-token flag short-circuits both.
@@ -19,7 +19,7 @@ export interface CompletionDeps {
19
19
  }
20
20
  /**
21
21
  * Outbound for `message.completed`: every TERMINAL assistant message (any
22
- * `finishReason` except the intermediate `tool-calls`, R6) with text becomes a
22
+ * `finishReason` except the intermediate `tool-calls`) with text becomes a
23
23
  * reply. When the continuation token carries the inbound message id we reply
24
24
  * IN-PLACE via the reply endpoint (same conversation, no fork) keeping the
25
25
  * connector's `replyMessageType` unchanged — type-preserving, so terminal/wake
package/dist/channel.d.ts CHANGED
@@ -15,12 +15,12 @@ export { processCompletion, processFailure } from "./channel-outbound.js";
15
15
  export type { ChannelSend, InboundDeps } from "./channel-core.js";
16
16
  export type { CompletionDeps } from "./channel-outbound.js";
17
17
  /**
18
- * Message types never auto-replied to (loop guard, R2): the connector's OWN
18
+ * Message types never auto-replied to (loop guard): the connector's OWN
19
19
  * outbound types (task_response/error/receipt), so two rine-eve agents don't
20
20
  * auto-reply to each other forever.
21
21
  *
22
22
  * The three x402 payment frames are NOT here: v1.1 re-surfaces them as
23
- * payment-aware agent turns (D1), routed by `handleX402Inbound` with the prose
23
+ * payment-aware agent turns, routed by `handleX402Inbound` with the prose
24
24
  * auto-reply suppressed (the `x402` continuation-token flag), never by the generic
25
25
  * assistant reply. Adding them here would revert to the v1.0 silent-drop behavior.
26
26
  */
@@ -47,7 +47,7 @@ export interface RineChannelOptions {
47
47
  maxBodyBytes?: number;
48
48
  /**
49
49
  * Approximate token budget for the role-tagged recent-transcript push-injected
50
- * into the stateless Eve session context on each inbound (REQ-CTX-01). Older
50
+ * into the stateless Eve session context on each inbound. Older
51
51
  * turns are truncated first with a `[…earlier turns omitted]` marker; a
52
52
  * single-message thread injects no extra transcript. Default ~2000 tokens.
53
53
  */
@@ -55,7 +55,7 @@ export interface RineChannelOptions {
55
55
  /** A pre-built client (tests / advanced use); otherwise env-resolved lazily. */
56
56
  client?: AsyncRineClient;
57
57
  /**
58
- * x402 payment behavior (D2). `autoPay` is OPT-IN and DEFAULT OFF: when true, an
58
+ * x402 payment behavior. `autoPay` is OPT-IN and DEFAULT OFF: when true, an
59
59
  * inbound `x402_payment_required` at/below the policy's `autoPayThreshold` is paid
60
60
  * with no LLM turn (still bounded by the caps, deny-by-default, journal and
61
61
  * reserve-lock). Off ⇒ every quote is surfaced to the agent, which pays via
package/dist/channel.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as processInbound, i as processFailure, n as rineChannel, o as senderContextLine, r as processCompletion, t as DEFAULT_IGNORE_TYPES } from "./channel-b0iIAZTh.js";
1
+ import { a as processInbound, i as processFailure, n as rineChannel, o as senderContextLine, r as processCompletion, t as DEFAULT_IGNORE_TYPES } from "./channel-WlN3x1wP.js";
2
2
  export { DEFAULT_IGNORE_TYPES, processCompletion, processFailure, processInbound, rineChannel, senderContextLine };
@@ -2,7 +2,7 @@ import { AsyncRineClient } from "@rine-network/sdk";
2
2
  import { resolveApiUrl, resolveConfigDir } from "@rine-network/core";
3
3
  //#region src/client.ts
4
4
  /**
5
- * Lazy `AsyncRineClient` construction (invariant R1: side-effect-free import).
5
+ * Lazy `AsyncRineClient` construction (side-effect-free import).
6
6
  *
7
7
  * No client is built at module load. The SDK client is created the first time a
8
8
  * tool's `execute` (or a channel handler) actually fires, then memoized per
@@ -24,7 +24,7 @@ function cacheKey(configDir, apiUrl) {
24
24
  /**
25
25
  * Get (or lazily build + memoize) the shared `AsyncRineClient` for `opts`,
26
26
  * already scoped to `opts.agent` when present. Call ONLY from inside a tool
27
- * `execute` / a channel handler — never at module top level (R1).
27
+ * `execute` / a channel handler — never at module top level.
28
28
  */
29
29
  function getRineClient(opts = {}) {
30
30
  const configDir = opts.configDir ?? resolveConfigDir();
package/dist/client.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Lazy `AsyncRineClient` construction (invariant R1: side-effect-free import).
2
+ * Lazy `AsyncRineClient` construction (side-effect-free import).
3
3
  *
4
4
  * No client is built at module load. The SDK client is created the first time a
5
5
  * tool's `execute` (or a channel handler) actually fires, then memoized per
@@ -27,7 +27,7 @@ export interface RineClientOpts {
27
27
  /**
28
28
  * Get (or lazily build + memoize) the shared `AsyncRineClient` for `opts`,
29
29
  * already scoped to `opts.agent` when present. Call ONLY from inside a tool
30
- * `execute` / a channel handler — never at module top level (R1).
30
+ * `execute` / a channel handler — never at module top level.
31
31
  */
32
32
  export declare function getRineClient(opts?: RineClientOpts): AsyncRineClient;
33
33
  /** Test-only: drop all memoized clients (not part of the public surface). */
package/dist/errors.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * `formatError(err)` — invariant R2: turn any thrown SDK error into a readable
2
+ * `formatError(err)` — turns any thrown SDK error into a readable
3
3
  * string for the LLM, never a stack trace. Tools wrap their one `await client.*`
4
4
  * call in `try/catch → formatError` and RESOLVE (never reject) for mapped errors.
5
5
  *
package/dist/format.d.ts CHANGED
@@ -2,12 +2,12 @@
2
2
  * Pure render functions: turn SDK return values into the human-readable strings
3
3
  * tools + the channel hand to the LLM / send back over rine.
4
4
  *
5
- * Invariant R4: these read ONLY `plaintext` / `decrypt_error` / verification
5
+ * These read ONLY `plaintext` / `decrypt_error` / verification
6
6
  * fields. They NEVER read `encrypted_payload` or any envelope/ciphertext field,
7
7
  * so ciphertext can never reach the LLM context through a rendered string.
8
8
  */
9
9
  import type { ThreadEntry } from "@rine-network/sdk";
10
- import type { AgentProfile, AgentSummary, DecryptedMessage, GroupRead } from "./types.js";
10
+ import type { AgentProfile, AgentSummary, DecryptedMessage, GroupRead, JoinRequestRead, JoinResult } from "./types.js";
11
11
  /** One thread turn as a role-tagged line: `[sent] you: …` / `[received] alice@org: …`. */
12
12
  export declare function renderThreadLine(e: ThreadEntry): string;
13
13
  /**
@@ -41,11 +41,15 @@ export declare function renderProfile(p: AgentProfile): string;
41
41
  /**
42
42
  * Self-diagnose a group's E2EE mode. Uses `mls_group_id !== null`, OR the
43
43
  * explicit `mls_enabled`/`mls_pending` flags. With MLS support present this is a
44
- * CAPABILITY flag, not a failure flag (R9).
44
+ * CAPABILITY flag, not a failure flag.
45
45
  */
46
46
  export declare function groupIsMls(g: GroupRead): boolean;
47
47
  /**
48
48
  * A group rendered for `rine_group_inspect`. Both the MLS and sender-key branches
49
- * are `[OK]` — an MLS group is readable/postable from here (R9).
49
+ * are `[OK]` — an MLS group is readable/postable from here.
50
50
  */
51
51
  export declare function renderGroup(g: GroupRead): string;
52
+ /** `rine_group_join` outcome: immediate membership vs a pending vote. */
53
+ export declare function renderJoinResult(target: string, result: JoinResult): string;
54
+ /** A numbered list of the caller's pending group invites, or the empty-state line. */
55
+ export declare function renderInvites(items: readonly JoinRequestRead[]): string;
package/dist/inbound.d.ts CHANGED
@@ -2,14 +2,14 @@
2
2
  * Inbound webhook helpers for the rine channel: extracting the message id from a
3
3
  * rine standard-webhook body, and the continuation-token codec.
4
4
  *
5
- * The continuation token is how the channel makes outbound replies STATELESS (R7):
5
+ * The continuation token is how the channel makes outbound replies STATELESS:
6
6
  * it encodes the rine `conversation_id`, the reply target (the group handle for
7
7
  * group mail, else the sender handle), and — for 1:1 inbound only — the inbound
8
8
  * `message id` so the `message.completed` handler can reply IN-PLACE (via the reply
9
9
  * endpoint, preserving the inbound conversation) without any durable per-session map.
10
10
  * Because the token bakes in the per-message `m`, it differs on every 1:1 inbound
11
11
  * turn, so Eve does NOT resume a prior session from it — cross-turn continuity comes
12
- * from the general thread primitive (push-injected transcript, Slice E), not session
12
+ * from the general thread primitive (push-injected transcript), not session
13
13
  * resume. The message id is optional: group inbound and tokens minted by an older
14
14
  * build carry only `{c,r}` and decode with `messageId === undefined`, so the outbound
15
15
  * handler falls back to the `send()+parentConversationId` broadcast path.
@@ -35,7 +35,7 @@ export interface ReplyContext {
35
35
  */
36
36
  readonly messageId?: string;
37
37
  /**
38
- * Marks a session started by an inbound x402 payment frame (D1). The terminal
38
+ * Marks a session started by an inbound x402 payment frame. The terminal
39
39
  * assistant message is NEVER prose-replied into a payment thread — that would
40
40
  * corrupt the handshake. The signed payment / receipt is transmitted in-thread
41
41
  * by the pay / fulfill tools instead, so `processCompletion` short-circuits when
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * reachability + outbound replies, file-discovered rine **tools** for agency, a
7
7
  * **skill**, and an out-of-band **onboard / init / webhook / relay** CLI.
8
8
  *
9
- * Import is side-effect-free (R1): nothing here builds a client, reads a
9
+ * Import is side-effect-free: nothing here builds a client, reads a
10
10
  * credential, or opens a socket at module load.
11
11
  *
12
12
  * Most consumers don't import from here — they run `npx @rine-network/eve init`,
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
- import { o as formatError } from "./tool-BC49DldZ.js";
2
- import { a as processInbound, c as handleX402Inbound, d as x402GuidanceLine, f as decodeReplyToken, i as processFailure, l as isX402Frame, m as messageIdFromWebhook, n as rineChannel, o as senderContextLine, p as encodeReplyToken, r as processCompletion, s as X402_FRAME_TYPES, u as renderX402Body } from "./channel-b0iIAZTh.js";
1
+ import { o as formatError } from "./tool-xlLdY8kn.js";
2
+ import { a as processInbound, c as handleX402Inbound, d as x402GuidanceLine, f as decodeReplyToken, i as processFailure, l as isX402Frame, m as messageIdFromWebhook, n as rineChannel, o as senderContextLine, p as encodeReplyToken, r as processCompletion, s as X402_FRAME_TYPES, u as renderX402Body } from "./channel-WlN3x1wP.js";
3
3
  import { n as verifyRineSignature, t as signRineBody } from "./hmac-CoaKHmf6.js";
4
- import { t as getRineClient } from "./client-X_-9CpQT.js";
5
- import { a as rineReadTool, c as rineSendTool, d as rineGroupInspectTool, f as rineGroupInviteTool, h as rineInspectTool, i as rineCheckInboxTool, l as rineThreadTool, m as rineDiscoverTool, n as rineFulfillTool, o as rineReplyTool, p as rineGroupRemoveTool, r as rinePayTool, s as rineSendAndWaitTool, t as RINE_TOOLS, u as rineGroupCreateTool } from "./tools-BcVm_Onx.js";
6
- import { t as RINE_TOOL_META } from "./registry-6sWyhOyF.js";
7
- import { a as toolFileContent, c as RINE_SKILL_FILE, i as scaffoldRine, n as envExampleBlock, o as RINE_SKILL_BODY, r as resolveToolSelection, s as RINE_SKILL_DESCRIPTION, t as channelFileContent } from "./scaffold-0luQyBRK.js";
4
+ import { t as getRineClient } from "./client-DsG2xtKs.js";
5
+ import { _ as rineInspectTool, a as rineReadTool, c as rineSendTool, d as rineGroupInspectTool, f as rineGroupInviteTool, g as rineDiscoverTool, h as rineGroupRemoveTool, i as rineCheckInboxTool, l as rineThreadTool, m as rineGroupJoinTool, n as rineFulfillTool, o as rineReplyTool, p as rineGroupInvitesTool, r as rinePayTool, s as rineSendAndWaitTool, t as RINE_TOOLS, u as rineGroupCreateTool } from "./tools-BhkhV3Mv.js";
6
+ import { t as RINE_TOOL_META } from "./registry-Bn4EqPcp.js";
7
+ import { a as toolFileContent, c as RINE_SKILL_FILE, i as scaffoldRine, n as envExampleBlock, o as RINE_SKILL_BODY, r as resolveToolSelection, s as RINE_SKILL_DESCRIPTION, t as channelFileContent } from "./scaffold-3cEUy3jD.js";
8
8
  import { agentNameFromOrgName, parseOnboardArgs, runOnboard } from "./onboard.js";
9
9
  import { deleteRineWebhook, registerRineWebhook } from "./webhook.js";
10
10
  import { buildRelayBody, drainOnce, runRelay } from "./relay.js";
@@ -24,4 +24,4 @@ function rineSkill() {
24
24
  });
25
25
  }
26
26
  //#endregion
27
- export { RINE_SKILL_BODY, RINE_SKILL_DESCRIPTION, RINE_SKILL_FILE, RINE_TOOLS, RINE_TOOL_META, X402_FRAME_TYPES, agentNameFromOrgName, buildRelayBody, channelFileContent, decodeReplyToken, deleteRineWebhook, drainOnce, encodeReplyToken, envExampleBlock, formatError, getRineClient, handleX402Inbound, isX402Frame, messageIdFromWebhook, parseOnboardArgs, processCompletion, processFailure, processInbound, registerRineWebhook, renderX402Body, resolveToolSelection, rineChannel, rineCheckInboxTool, rineDiscoverTool, rineFulfillTool, rineGroupCreateTool, rineGroupInspectTool, rineGroupInviteTool, rineGroupRemoveTool, rineInspectTool, rinePayTool, rineReadTool, rineReplyTool, rineSendAndWaitTool, rineSendTool, rineSkill, rineThreadTool, runOnboard, runRelay, scaffoldRine, senderContextLine, signRineBody, toolFileContent, verifyRineSignature, x402GuidanceLine };
27
+ export { RINE_SKILL_BODY, RINE_SKILL_DESCRIPTION, RINE_SKILL_FILE, RINE_TOOLS, RINE_TOOL_META, X402_FRAME_TYPES, agentNameFromOrgName, buildRelayBody, channelFileContent, decodeReplyToken, deleteRineWebhook, drainOnce, encodeReplyToken, envExampleBlock, formatError, getRineClient, handleX402Inbound, isX402Frame, messageIdFromWebhook, parseOnboardArgs, processCompletion, processFailure, processInbound, registerRineWebhook, renderX402Body, resolveToolSelection, rineChannel, rineCheckInboxTool, rineDiscoverTool, rineFulfillTool, rineGroupCreateTool, rineGroupInspectTool, rineGroupInviteTool, rineGroupInvitesTool, rineGroupJoinTool, rineGroupRemoveTool, rineInspectTool, rinePayTool, rineReadTool, rineReplyTool, rineSendAndWaitTool, rineSendTool, rineSkill, rineThreadTool, runOnboard, runRelay, scaffoldRine, senderContextLine, signRineBody, toolFileContent, verifyRineSignature, x402GuidanceLine };
package/dist/onboard.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * creates the first agent and prints its handle + verification words. A ~30–60 s
6
6
  * PoW does not belong in an LLM turn; it is a one-time CLI a human runs.
7
7
  *
8
- * R1: no client is built at module load — `runOnboard` constructs the client
8
+ * No client is built at module load — `runOnboard` constructs the client
9
9
  * lazily. The PoW + credential write are delegated to the SDK's `register(opts)`;
10
10
  * the agent keypair is generated + persisted by `client.createAgent(name)`.
11
11
  */
package/dist/onboard.js CHANGED
@@ -8,7 +8,7 @@ import { resolveApiUrl, resolveConfigDir } from "@rine-network/core";
8
8
  * creates the first agent and prints its handle + verification words. A ~30–60 s
9
9
  * PoW does not belong in an LLM turn; it is a one-time CLI a human runs.
10
10
  *
11
- * R1: no client is built at module load — `runOnboard` constructs the client
11
+ * No client is built at module load — `runOnboard` constructs the client
12
12
  * lazily. The PoW + credential write are delegated to the SDK's `register(opts)`;
13
13
  * the agent keypair is generated + persisted by `client.createAgent(name)`.
14
14
  */
@@ -65,6 +65,16 @@ const RINE_TOOL_META = [
65
65
  factoryName: "rineGroupInspectTool",
66
66
  domain: "groups"
67
67
  },
68
+ {
69
+ name: "rine_group_join",
70
+ factoryName: "rineGroupJoinTool",
71
+ domain: "groups"
72
+ },
73
+ {
74
+ name: "rine_group_invites",
75
+ factoryName: "rineGroupInvitesTool",
76
+ domain: "groups"
77
+ },
68
78
  {
69
79
  name: "rine_pay",
70
80
  factoryName: "rinePayTool",
package/dist/relay.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * stands in for the cloud webhook: it polls the agent's inbox and re-POSTs each
6
6
  * new message — HMAC-signed with `RINE_WEBHOOK_SECRET` — to the LOCAL channel
7
7
  * route. It deliberately reuses the SAME inbound route + HMAC + decrypt path as
8
- * production (R8); the relay only replaces the transport that carries the
8
+ * production; the relay only replaces the transport that carries the
9
9
  * notification, never the message handling. The body carries just the id +
10
10
  * routing fields; the channel re-reads + decrypts by id, exactly as in prod.
11
11
  */
package/dist/relay.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as signRineBody } from "./hmac-CoaKHmf6.js";
2
- import { t as getRineClient } from "./client-X_-9CpQT.js";
2
+ import { t as getRineClient } from "./client-DsG2xtKs.js";
3
3
  import { resolveApiUrl } from "@rine-network/core";
4
4
  //#region src/relay.ts
5
5
  /**
@@ -9,7 +9,7 @@ import { resolveApiUrl } from "@rine-network/core";
9
9
  * stands in for the cloud webhook: it polls the agent's inbox and re-POSTs each
10
10
  * new message — HMAC-signed with `RINE_WEBHOOK_SECRET` — to the LOCAL channel
11
11
  * route. It deliberately reuses the SAME inbound route + HMAC + decrypt path as
12
- * production (R8); the relay only replaces the transport that carries the
12
+ * production; the relay only replaces the transport that carries the
13
13
  * notification, never the message handling. The body carries just the id +
14
14
  * routing fields; the channel re-reads + decrypts by id, exactly as in prod.
15
15
  */
@@ -1,4 +1,4 @@
1
- import { t as RINE_TOOL_META } from "./registry-6sWyhOyF.js";
1
+ import { t as RINE_TOOL_META } from "./registry-Bn4EqPcp.js";
2
2
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
4
  //#region src/skill-content.ts
@@ -43,7 +43,8 @@ its id; call \`rine_send\` to start a *new* conversation with another agent.
43
43
 
44
44
  Groups are end-to-end encrypted (MLS / RFC 9420 by default, with forward secrecy).
45
45
  \`rine_group_create\`, \`rine_group_invite\`, \`rine_group_remove\`,
46
- \`rine_group_inspect\`. Sending to a \`#group@org\` handle posts to the whole group.
46
+ \`rine_group_inspect\`, \`rine_group_join\`, \`rine_group_invites\`. Sending to a
47
+ \`#group@org\` handle posts to the whole group.
47
48
 
48
49
  ## Trust
49
50
 
package/dist/scaffold.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as toolFileContent, i as scaffoldRine, n as envExampleBlock, r as resolveToolSelection, t as channelFileContent } from "./scaffold-0luQyBRK.js";
1
+ import { a as toolFileContent, i as scaffoldRine, n as envExampleBlock, r as resolveToolSelection, t as channelFileContent } from "./scaffold-3cEUy3jD.js";
2
2
  export { channelFileContent, envExampleBlock, resolveToolSelection, scaffoldRine, toolFileContent };
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Zod input schemas for the 4 group tools (split out of `schemas.ts` to hold the
2
+ * Zod input schemas for the 6 group tools (split out of `schemas.ts` to hold the
3
3
  * ~200-LOC budget — one file per domain). Same authoring rules: rich `.describe()`
4
- * on every field, NO identity/credentials in the schema (env-injected, R3).
4
+ * on every field, NO identity/credentials in the schema (env-injected).
5
5
  *
6
6
  * Groups are MLS-capable by default — `enableMls` (default true) on create.
7
7
  */
@@ -55,3 +55,15 @@ export declare const groupInspectInput: z.ZodObject<{
55
55
  }, {
56
56
  group: string;
57
57
  }>;
58
+ export declare const groupJoinInput: z.ZodObject<{
59
+ group: z.ZodString;
60
+ message: z.ZodOptional<z.ZodString>;
61
+ }, "strip", z.ZodTypeAny, {
62
+ group: string;
63
+ message?: string | undefined;
64
+ }, {
65
+ group: string;
66
+ message?: string | undefined;
67
+ }>;
68
+ /** No input: lists the caller's own pending group invites. */
69
+ export declare const groupInvitesInput: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Zod input schemas for the 2 x402 payment tools (split out of `schemas.ts` to
3
3
  * hold the ~200-LOC budget — one file per domain). Same authoring rules: rich
4
- * `.describe()` on every field, NO identity/credentials in the schema (env-injected,
5
- * R3). The facilitator is infra config, resolved from the tool factory / env —
4
+ * `.describe()` on every field, NO identity/credentials in the schema
5
+ * (env-injected). The facilitator is infra config, resolved from the tool factory / env —
6
6
  * never a model-visible input.
7
7
  */
8
8
  import { z } from "zod";
package/dist/schemas.d.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Rich `.describe()` on EVERY field: the field descriptions are the #1 lever on
5
5
  * tool-call accuracy (the AI-DX). Identity/credentials NEVER appear here — the
6
- * acting agent + config dir come from `process.env` (R3), never the model-visible
6
+ * acting agent + config dir come from `process.env`, never the model-visible
7
7
  * input schema.
8
8
  */
9
9
  import { z } from "zod";
@@ -102,5 +102,5 @@ export declare const inspectInput: z.ZodObject<{
102
102
  }, {
103
103
  handleOrId: string;
104
104
  }>;
105
- export { groupCreateInput, groupInspectInput, groupInviteInput, groupRemoveInput, } from "./schemas-groups.js";
105
+ export { groupCreateInput, groupInspectInput, groupInviteInput, groupInvitesInput, groupJoinInput, groupRemoveInput, } from "./schemas-groups.js";
106
106
  export { fulfillInput, payInput } from "./schemas-payments.js";
@@ -6,6 +6,6 @@
6
6
  */
7
7
  export declare const RINE_SKILL_DESCRIPTION = "Use when communicating with other AI agents over the rine network \u2014 sending or replying to agent-to-agent messages, discovering agents, or coordinating in groups.";
8
8
  /** The skill body (no frontmatter) — used by `rineSkill()`'s `markdown`. */
9
- export declare const RINE_SKILL_BODY = "# rine \u2014 agent-to-agent messaging\n\nrine is an end-to-end-encrypted messaging network for AI agents. Each agent has a\nhandle like `name@org`. You are reachable on rine: other agents message you and\nyour replies are encrypted and delivered back to them automatically.\n\n## When messages arrive\n\nInbound rine messages are delivered to you as a normal turn. The context line tells\nyou who sent it and whether their signature verified. **Just answer** \u2014 your final\nreply is encrypted and sent back to the sender in the same conversation. You do not\nneed to call a tool to reply to an inbound rine message.\n\nCall `rine_reply` only when you want to reply to a *specific* earlier message by\nits id; call `rine_send` to start a *new* conversation with another agent.\n\n## Reaching other agents\n\n- `rine_discover` \u2014 search the public directory by text/category/language to find\n an agent's handle. Do this before messaging an agent you don't already know.\n- `rine_inspect` \u2014 read an agent's full public profile (verification, oversight).\n- `rine_send` \u2014 send a 1:1 message (`name@org` / UUID) or a group message\n (`#group@org`). End-to-end encrypted; a real, irreversible network action.\n- `rine_send_and_wait` \u2014 1:1 only: send and block up to N seconds for a reply.\n- `rine_check_inbox` / `rine_read` \u2014 pull or read mail by id (rarely needed, since\n inbound is pushed to you as a turn).\n- `rine_thread` \u2014 fetch the full decrypted transcript of a conversation by its id\n (both sides, oldest\u2192newest). Use to recover earlier context on demand.\n\n## Groups\n\nGroups are end-to-end encrypted (MLS / RFC 9420 by default, with forward secrecy).\n`rine_group_create`, `rine_group_invite`, `rine_group_remove`,\n`rine_group_inspect`. Sending to a `#group@org` handle posts to the whole group.\n\n## Trust\n\nEvery inbound message is HPKE-decrypted and its sender signature is verified before\nit reaches you; unverified mail is dropped by default. Treat the sender handle in the\ncontext line as authenticated. Do not put secrets in messages you would not want the\nrecipient agent to read.\n";
9
+ export declare const RINE_SKILL_BODY = "# rine \u2014 agent-to-agent messaging\n\nrine is an end-to-end-encrypted messaging network for AI agents. Each agent has a\nhandle like `name@org`. You are reachable on rine: other agents message you and\nyour replies are encrypted and delivered back to them automatically.\n\n## When messages arrive\n\nInbound rine messages are delivered to you as a normal turn. The context line tells\nyou who sent it and whether their signature verified. **Just answer** \u2014 your final\nreply is encrypted and sent back to the sender in the same conversation. You do not\nneed to call a tool to reply to an inbound rine message.\n\nCall `rine_reply` only when you want to reply to a *specific* earlier message by\nits id; call `rine_send` to start a *new* conversation with another agent.\n\n## Reaching other agents\n\n- `rine_discover` \u2014 search the public directory by text/category/language to find\n an agent's handle. Do this before messaging an agent you don't already know.\n- `rine_inspect` \u2014 read an agent's full public profile (verification, oversight).\n- `rine_send` \u2014 send a 1:1 message (`name@org` / UUID) or a group message\n (`#group@org`). End-to-end encrypted; a real, irreversible network action.\n- `rine_send_and_wait` \u2014 1:1 only: send and block up to N seconds for a reply.\n- `rine_check_inbox` / `rine_read` \u2014 pull or read mail by id (rarely needed, since\n inbound is pushed to you as a turn).\n- `rine_thread` \u2014 fetch the full decrypted transcript of a conversation by its id\n (both sides, oldest\u2192newest). Use to recover earlier context on demand.\n\n## Groups\n\nGroups are end-to-end encrypted (MLS / RFC 9420 by default, with forward secrecy).\n`rine_group_create`, `rine_group_invite`, `rine_group_remove`,\n`rine_group_inspect`, `rine_group_join`, `rine_group_invites`. Sending to a\n`#group@org` handle posts to the whole group.\n\n## Trust\n\nEvery inbound message is HPKE-decrypted and its sender signature is verified before\nit reaches you; unverified mail is dropped by default. Treat the sender handle in the\ncontext line as authenticated. Do not put secrets in messages you would not want the\nrecipient agent to read.\n";
10
10
  /** The full SKILL.md file contents (frontmatter + body) the scaffolder writes. */
11
- export declare const RINE_SKILL_FILE = "---\ndescription: Use when communicating with other AI agents over the rine network \u2014 sending or replying to agent-to-agent messages, discovering agents, or coordinating in groups.\n---\n\n# rine \u2014 agent-to-agent messaging\n\nrine is an end-to-end-encrypted messaging network for AI agents. Each agent has a\nhandle like `name@org`. You are reachable on rine: other agents message you and\nyour replies are encrypted and delivered back to them automatically.\n\n## When messages arrive\n\nInbound rine messages are delivered to you as a normal turn. The context line tells\nyou who sent it and whether their signature verified. **Just answer** \u2014 your final\nreply is encrypted and sent back to the sender in the same conversation. You do not\nneed to call a tool to reply to an inbound rine message.\n\nCall `rine_reply` only when you want to reply to a *specific* earlier message by\nits id; call `rine_send` to start a *new* conversation with another agent.\n\n## Reaching other agents\n\n- `rine_discover` \u2014 search the public directory by text/category/language to find\n an agent's handle. Do this before messaging an agent you don't already know.\n- `rine_inspect` \u2014 read an agent's full public profile (verification, oversight).\n- `rine_send` \u2014 send a 1:1 message (`name@org` / UUID) or a group message\n (`#group@org`). End-to-end encrypted; a real, irreversible network action.\n- `rine_send_and_wait` \u2014 1:1 only: send and block up to N seconds for a reply.\n- `rine_check_inbox` / `rine_read` \u2014 pull or read mail by id (rarely needed, since\n inbound is pushed to you as a turn).\n- `rine_thread` \u2014 fetch the full decrypted transcript of a conversation by its id\n (both sides, oldest\u2192newest). Use to recover earlier context on demand.\n\n## Groups\n\nGroups are end-to-end encrypted (MLS / RFC 9420 by default, with forward secrecy).\n`rine_group_create`, `rine_group_invite`, `rine_group_remove`,\n`rine_group_inspect`. Sending to a `#group@org` handle posts to the whole group.\n\n## Trust\n\nEvery inbound message is HPKE-decrypted and its sender signature is verified before\nit reaches you; unverified mail is dropped by default. Treat the sender handle in the\ncontext line as authenticated. Do not put secrets in messages you would not want the\nrecipient agent to read.\n";
11
+ export declare const RINE_SKILL_FILE = "---\ndescription: Use when communicating with other AI agents over the rine network \u2014 sending or replying to agent-to-agent messages, discovering agents, or coordinating in groups.\n---\n\n# rine \u2014 agent-to-agent messaging\n\nrine is an end-to-end-encrypted messaging network for AI agents. Each agent has a\nhandle like `name@org`. You are reachable on rine: other agents message you and\nyour replies are encrypted and delivered back to them automatically.\n\n## When messages arrive\n\nInbound rine messages are delivered to you as a normal turn. The context line tells\nyou who sent it and whether their signature verified. **Just answer** \u2014 your final\nreply is encrypted and sent back to the sender in the same conversation. You do not\nneed to call a tool to reply to an inbound rine message.\n\nCall `rine_reply` only when you want to reply to a *specific* earlier message by\nits id; call `rine_send` to start a *new* conversation with another agent.\n\n## Reaching other agents\n\n- `rine_discover` \u2014 search the public directory by text/category/language to find\n an agent's handle. Do this before messaging an agent you don't already know.\n- `rine_inspect` \u2014 read an agent's full public profile (verification, oversight).\n- `rine_send` \u2014 send a 1:1 message (`name@org` / UUID) or a group message\n (`#group@org`). End-to-end encrypted; a real, irreversible network action.\n- `rine_send_and_wait` \u2014 1:1 only: send and block up to N seconds for a reply.\n- `rine_check_inbox` / `rine_read` \u2014 pull or read mail by id (rarely needed, since\n inbound is pushed to you as a turn).\n- `rine_thread` \u2014 fetch the full decrypted transcript of a conversation by its id\n (both sides, oldest\u2192newest). Use to recover earlier context on demand.\n\n## Groups\n\nGroups are end-to-end encrypted (MLS / RFC 9420 by default, with forward secrecy).\n`rine_group_create`, `rine_group_invite`, `rine_group_remove`,\n`rine_group_inspect`, `rine_group_join`, `rine_group_invites`. Sending to a\n`#group@org` handle posts to the whole group.\n\n## Trust\n\nEvery inbound message is HPKE-decrypted and its sender signature is verified before\nit reaches you; unverified mail is dropped by default. Treat the sender handle in the\ncontext line as authenticated. Do not put secrets in messages you would not want the\nrecipient agent to read.\n";
@@ -1,4 +1,4 @@
1
- import { t as getRineClient } from "./client-X_-9CpQT.js";
1
+ import { t as getRineClient } from "./client-DsG2xtKs.js";
2
2
  import { APIConnectionError, AuthenticationError, AuthorizationError, ConfigError, CryptoError, NotFoundError, RateLimitError, RineApiError, RineTimeoutError, SchemaValidationError, ValidationError } from "@rine-network/sdk";
3
3
  import { resolveApiUrl } from "@rine-network/core";
4
4
  import { always, never, once } from "eve/tools/approval";
@@ -101,14 +101,14 @@ function renderProfile(p) {
101
101
  /**
102
102
  * Self-diagnose a group's E2EE mode. Uses `mls_group_id !== null`, OR the
103
103
  * explicit `mls_enabled`/`mls_pending` flags. With MLS support present this is a
104
- * CAPABILITY flag, not a failure flag (R9).
104
+ * CAPABILITY flag, not a failure flag.
105
105
  */
106
106
  function groupIsMls(g) {
107
107
  return Boolean(g.mls_enabled || g.mls_group_id !== null || g.mls_pending);
108
108
  }
109
109
  /**
110
110
  * A group rendered for `rine_group_inspect`. Both the MLS and sender-key branches
111
- * are `[OK]` — an MLS group is readable/postable from here (R9).
111
+ * are `[OK]` — an MLS group is readable/postable from here.
112
112
  */
113
113
  function renderGroup(g) {
114
114
  const lines = [`Group ${g.handle} (id ${g.id})`];
@@ -120,10 +120,27 @@ function renderGroup(g) {
120
120
  lines.push(`visibility: ${g.visibility}`);
121
121
  return lines.join("\n");
122
122
  }
123
+ /** `rine_group_join` outcome: immediate membership vs a pending vote. */
124
+ function renderJoinResult(target, result) {
125
+ if (result.status === "joined") return `Joined ${target}.`;
126
+ return `Join request for ${target} submitted — pending approval (request ${result.request.id}).`;
127
+ }
128
+ /** One pending-invite row: group, inviter, status, and any message. */
129
+ function renderInviteRow(inv) {
130
+ const group = inv.group_handle ?? inv.group_name ?? inv.group_id;
131
+ const from = inv.invited_by ? ` invited by ${inv.invited_by}` : "";
132
+ const msg = inv.message ? `: "${inv.message}"` : "";
133
+ return `${group} (status ${inv.status})${from}${msg}`;
134
+ }
135
+ /** A numbered list of the caller's pending group invites, or the empty-state line. */
136
+ function renderInvites(items) {
137
+ if (items.length === 0) return "No pending group invites.";
138
+ return items.map((inv, i) => `${i + 1}. ${renderInviteRow(inv)}`).join("\n");
139
+ }
123
140
  //#endregion
124
141
  //#region src/errors.ts
125
142
  /**
126
- * `formatError(err)` — invariant R2: turn any thrown SDK error into a readable
143
+ * `formatError(err)` — turns any thrown SDK error into a readable
127
144
  * string for the LLM, never a stack trace. Tools wrap their one `await client.*`
128
145
  * call in `try/catch → formatError` and RESOLVE (never reject) for mapped errors.
129
146
  *
@@ -169,8 +186,8 @@ function messageOf(err) {
169
186
  //#region src/tool.ts
170
187
  /**
171
188
  * Shared `defineTool` plumbing every rine tool reuses (no duplicated logic):
172
- * env-based identity resolution (R3) and the try/catch → `formatError` wrapper
173
- * (R2 errors→strings, never a reject).
189
+ * env-based identity resolution and the try/catch → `formatError` wrapper
190
+ * (errors→strings, never a reject).
174
191
  *
175
192
  * Unlike the Mastra integration (which threads identity through a `RequestContext`),
176
193
  * Eve tools run in the app runtime with full `process.env` access, so identity is
@@ -198,7 +215,7 @@ function approvalGate(opts) {
198
215
  function resolveAgent(opts) {
199
216
  return opts.agent ?? process.env.RINE_AGENT ?? void 0;
200
217
  }
201
- /** Resolve the effective `AsyncRineClient` for one `execute` call (lazy, R1). */
218
+ /** Resolve the effective `AsyncRineClient` for one `execute` call (lazy). */
202
219
  function resolveClient(opts) {
203
220
  if (opts.client) {
204
221
  const agent = resolveAgent(opts);
@@ -223,7 +240,7 @@ function asRecipient(to) {
223
240
  return to;
224
241
  }
225
242
  /**
226
- * Belt-and-suspenders ciphertext redactor for `read` / `check_inbox` (R4).
243
+ * Belt-and-suspenders ciphertext redactor for `read` / `check_inbox`.
227
244
  * The renderers + `outputSchema: z.string()` already guarantee the `execute`
228
245
  * return is redacted text; this coerces ANY value to plain text before it can
229
246
  * reach the model, in Eve's `ToolModelOutput` shape.
@@ -237,13 +254,13 @@ function redactToText(output) {
237
254
  /**
238
255
  * Build an Eve-tool `execute(input, ctx)` from a zod schema + body, applying:
239
256
  * 1. zod `.parse(raw)` of the model input (defaults + coercion + validation),
240
- * 2. the lazy env-resolved client (R1/R3),
241
- * 3. the try/catch→formatError contract (R2 — resolves a string, never rejects).
257
+ * 2. the lazy env-resolved client,
258
+ * 3. the try/catch→formatError contract (resolves a string, never rejects).
242
259
  *
243
260
  * Eve hands `execute` the raw model input as `Record<string, unknown>`; we own the
244
261
  * parse because Eve receives a JSON Schema (not the zod schema) and may not apply
245
262
  * zod defaults. The Eve `ToolContext` is intentionally ignored — rine identity is
246
- * environment-resolved (R3), not session-scoped.
263
+ * environment-resolved, not session-scoped.
247
264
  */
248
265
  function makeExecute(schema, opts, body) {
249
266
  return async (raw) => {
@@ -256,4 +273,4 @@ function makeExecute(schema, opts, body) {
256
273
  };
257
274
  }
258
275
  //#endregion
259
- export { senderLabel as _, GROUP_ON_WAIT_MESSAGE as a, groupIsMls as c, renderInbox as d, renderMessageBody as f, renderThreadLine as g, renderThread as h, redactToText as i, renderDiscover as l, renderSingleMessage as m, asRecipient as n, formatError as o, renderProfile as p, makeExecute as r, isGroupUnsupportedOnWait as s, approvalGate as t, renderGroup as u, verifiedNote as v };
276
+ export { renderThread as _, GROUP_ON_WAIT_MESSAGE as a, verifiedNote as b, groupIsMls as c, renderInbox as d, renderInvites as f, renderSingleMessage as g, renderProfile as h, redactToText as i, renderDiscover as l, renderMessageBody as m, asRecipient as n, formatError as o, renderJoinResult as p, makeExecute as r, isGroupUnsupportedOnWait as s, approvalGate as t, renderGroup as u, renderThreadLine as v, senderLabel as y };
package/dist/tool.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Shared `defineTool` plumbing every rine tool reuses (no duplicated logic):
3
- * env-based identity resolution (R3) and the try/catch → `formatError` wrapper
4
- * (R2 errors→strings, never a reject).
3
+ * env-based identity resolution and the try/catch → `formatError` wrapper
4
+ * (errors→strings, never a reject).
5
5
  *
6
6
  * Unlike the Mastra integration (which threads identity through a `RequestContext`),
7
7
  * Eve tools run in the app runtime with full `process.env` access, so identity is
@@ -47,7 +47,7 @@ export interface RineToolOpts extends RineClientOpts {
47
47
  * or `undefined` (no gate) when unset. Only the mutating tool factories apply it.
48
48
  */
49
49
  export declare function approvalGate(opts: RineToolOpts): ((ctx: NeedsApprovalContext) => boolean) | undefined;
50
- /** Resolve the effective `AsyncRineClient` for one `execute` call (lazy, R1). */
50
+ /** Resolve the effective `AsyncRineClient` for one `execute` call (lazy). */
51
51
  export declare function resolveClient(opts: RineToolOpts): AsyncRineClient;
52
52
  /**
53
53
  * The same resolved `apiUrl` the client is built against (factory override →
@@ -64,7 +64,7 @@ type Recipient = AgentHandle | AgentUuid | GroupHandle | GroupUuid;
64
64
  /** Brand a model-supplied recipient string for the SDK send surface. */
65
65
  export declare function asRecipient(to: string): Recipient;
66
66
  /**
67
- * Belt-and-suspenders ciphertext redactor for `read` / `check_inbox` (R4).
67
+ * Belt-and-suspenders ciphertext redactor for `read` / `check_inbox`.
68
68
  * The renderers + `outputSchema: z.string()` already guarantee the `execute`
69
69
  * return is redacted text; this coerces ANY value to plain text before it can
70
70
  * reach the model, in Eve's `ToolModelOutput` shape.
@@ -79,13 +79,13 @@ export type RineToolBody<I> = (client: AsyncRineClient, input: I, apiUrl: string
79
79
  /**
80
80
  * Build an Eve-tool `execute(input, ctx)` from a zod schema + body, applying:
81
81
  * 1. zod `.parse(raw)` of the model input (defaults + coercion + validation),
82
- * 2. the lazy env-resolved client (R1/R3),
83
- * 3. the try/catch→formatError contract (R2 — resolves a string, never rejects).
82
+ * 2. the lazy env-resolved client,
83
+ * 3. the try/catch→formatError contract (resolves a string, never rejects).
84
84
  *
85
85
  * Eve hands `execute` the raw model input as `Record<string, unknown>`; we own the
86
86
  * parse because Eve receives a JSON Schema (not the zod schema) and may not apply
87
87
  * zod defaults. The Eve `ToolContext` is intentionally ignored — rine identity is
88
- * environment-resolved (R3), not session-scoped.
88
+ * environment-resolved, not session-scoped.
89
89
  */
90
90
  export declare function makeExecute<S extends ZodTypeAny>(schema: S, opts: RineToolOpts, body: RineToolBody<z.infer<S>>): (raw: unknown) => Promise<string>;
91
91
  export {};
@@ -1,12 +1,17 @@
1
1
  /**
2
- * The 4 group tool factories: `rine_group_create`, `rine_group_invite`,
3
- * `rine_group_remove`, `rine_group_inspect`. Groups are MLS-by-default.
2
+ * The 6 group tool factories: `rine_group_create`, `rine_group_invite`,
3
+ * `rine_group_remove`, `rine_group_inspect`, `rine_group_join`,
4
+ * `rine_group_invites`. Groups are MLS-by-default.
4
5
  *
5
6
  * The TS SDK's `groups.invite`/`removeMember` take BRANDED UUIDs positionally, so
6
7
  * invite/remove/inspect PRE-RESOLVE handle→UUID here:
7
8
  * - a group → `groups.list()` + local match (`findGroup`),
8
9
  * - an agent → `resolveToUuid` (WebFinger) → its UUID (or pass a UUID through),
9
10
  * so unlisted agents resolve too.
11
+ * `join` resolves a handle the same way but against the caller's PENDING
12
+ * INVITES (`groups.listInvites()`) — an invitee isn't a member yet, so it can't
13
+ * appear in `groups.list()`. A bare UUID always passes through unchanged (the
14
+ * path for a publicly discovered open-enrollment group with no invite record).
10
15
  */
11
16
  import { type RineToolOpts } from "../tool.js";
12
17
  /** `rine_group_create` — create an MLS-by-default coordination group. */
@@ -17,3 +22,7 @@ export declare function rineGroupInviteTool(opts?: RineToolOpts): import("eve/to
17
22
  export declare function rineGroupRemoveTool(opts?: RineToolOpts): import("eve/tools").ToolDefinition<any, any>;
18
23
  /** `rine_group_inspect` — report a group's E2EE mode + policy. */
19
24
  export declare function rineGroupInspectTool(opts?: RineToolOpts): import("eve/tools").ToolDefinition<any, any>;
25
+ /** `rine_group_join` — accept an invite (or self-join an open group). */
26
+ export declare function rineGroupJoinTool(opts?: RineToolOpts): import("eve/tools").ToolDefinition<any, any>;
27
+ /** `rine_group_invites` — list the caller's pending group invites. */
28
+ export declare function rineGroupInvitesTool(opts?: RineToolOpts): import("eve/tools").ToolDefinition<any, any>;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The 12 rine tool factories, re-exported for `@rine-network/eve/tools`.
2
+ * The 16 rine tool factories, re-exported for `@rine-network/eve/tools`.
3
3
  *
4
4
  * Eve discovers tools by file: each lives as a default-export in
5
5
  * `agent/tools/<name>.ts`, and the filename slug IS the tool name. The `init`
@@ -11,7 +11,7 @@ import type { RineToolOpts } from "../tool.js";
11
11
  import { type RineToolMeta } from "./registry.js";
12
12
  export { rineCheckInboxTool, rineReadTool, rineReplyTool, rineSendAndWaitTool, rineSendTool, rineThreadTool, } from "./messaging.js";
13
13
  export { rineDiscoverTool, rineInspectTool } from "./discovery.js";
14
- export { rineGroupCreateTool, rineGroupInspectTool, rineGroupInviteTool, rineGroupRemoveTool, } from "./groups.js";
14
+ export { rineGroupCreateTool, rineGroupInspectTool, rineGroupInviteTool, rineGroupInvitesTool, rineGroupJoinTool, rineGroupRemoveTool, } from "./groups.js";
15
15
  export { rineFulfillTool, rinePayTool } from "./payments.js";
16
16
  export { RINE_TOOL_META, type RineToolMeta, type RineToolDomain, } from "./registry.js";
17
17
  export type { RineToolOpts } from "../tool.js";
@@ -1,3 +1,3 @@
1
- import { a as rineReadTool, c as rineSendTool, d as rineGroupInspectTool, f as rineGroupInviteTool, h as rineInspectTool, i as rineCheckInboxTool, l as rineThreadTool, m as rineDiscoverTool, n as rineFulfillTool, o as rineReplyTool, p as rineGroupRemoveTool, r as rinePayTool, s as rineSendAndWaitTool, t as RINE_TOOLS, u as rineGroupCreateTool } from "../tools-BcVm_Onx.js";
2
- import { t as RINE_TOOL_META } from "../registry-6sWyhOyF.js";
3
- export { RINE_TOOLS, RINE_TOOL_META, rineCheckInboxTool, rineDiscoverTool, rineFulfillTool, rineGroupCreateTool, rineGroupInspectTool, rineGroupInviteTool, rineGroupRemoveTool, rineInspectTool, rinePayTool, rineReadTool, rineReplyTool, rineSendAndWaitTool, rineSendTool, rineThreadTool };
1
+ import { _ as rineInspectTool, a as rineReadTool, c as rineSendTool, d as rineGroupInspectTool, f as rineGroupInviteTool, g as rineDiscoverTool, h as rineGroupRemoveTool, i as rineCheckInboxTool, l as rineThreadTool, m as rineGroupJoinTool, n as rineFulfillTool, o as rineReplyTool, p as rineGroupInvitesTool, r as rinePayTool, s as rineSendAndWaitTool, t as RINE_TOOLS, u as rineGroupCreateTool } from "../tools-BhkhV3Mv.js";
2
+ import { t as RINE_TOOL_META } from "../registry-Bn4EqPcp.js";
3
+ export { RINE_TOOLS, RINE_TOOL_META, rineCheckInboxTool, rineDiscoverTool, rineFulfillTool, rineGroupCreateTool, rineGroupInspectTool, rineGroupInviteTool, rineGroupInvitesTool, rineGroupJoinTool, rineGroupRemoveTool, rineInspectTool, rinePayTool, rineReadTool, rineReplyTool, rineSendAndWaitTool, rineSendTool, rineThreadTool };
@@ -5,7 +5,7 @@
5
5
  * `makeExecute` (lazy env client + formatError). The runtime tool NAME comes from
6
6
  * the filename slug of the scaffolded `agent/tools/<name>.ts`, not from here.
7
7
  *
8
- * R4 holds throughout: renderers read only plaintext/decrypt_error/verification,
8
+ * Renderers read only plaintext/decrypt_error/verification,
9
9
  * never the ciphertext envelope. `read`/`check_inbox` add a `toModelOutput`
10
10
  * redactor as defence-in-depth.
11
11
  */
@@ -1,5 +1,5 @@
1
- import { a as GROUP_ON_WAIT_MESSAGE, c as groupIsMls, d as renderInbox, f as renderMessageBody, h as renderThread, i as redactToText, l as renderDiscover, m as renderSingleMessage, n as asRecipient, p as renderProfile, r as makeExecute, s as isGroupUnsupportedOnWait, t as approvalGate, u as renderGroup, v as verifiedNote } from "./tool-BC49DldZ.js";
2
- import { t as RINE_TOOL_META } from "./registry-6sWyhOyF.js";
1
+ import { _ as renderThread, a as GROUP_ON_WAIT_MESSAGE, b as verifiedNote, c as groupIsMls, d as renderInbox, f as renderInvites, g as renderSingleMessage, h as renderProfile, i as redactToText, l as renderDiscover, m as renderMessageBody, n as asRecipient, p as renderJoinResult, r as makeExecute, s as isGroupUnsupportedOnWait, t as approvalGate, u as renderGroup } from "./tool-xlLdY8kn.js";
2
+ import { t as RINE_TOOL_META } from "./registry-Bn4EqPcp.js";
3
3
  import { FACILITATOR_PRESET, NotFoundError, X402Error, X402FacilitatorError, X402_ERROR, X402_MESSAGE_TYPE, asAgentUuid, asGroupUuid, asMessageUuid } from "@rine-network/sdk";
4
4
  import { UUID_RE, normalizeHandle, resolveToUuid } from "@rine-network/core";
5
5
  import { z } from "zod";
@@ -19,9 +19,9 @@ const STRING_OUTPUT = { type: "string" };
19
19
  //#endregion
20
20
  //#region src/schemas-groups.ts
21
21
  /**
22
- * Zod input schemas for the 4 group tools (split out of `schemas.ts` to hold the
22
+ * Zod input schemas for the 6 group tools (split out of `schemas.ts` to hold the
23
23
  * ~200-LOC budget — one file per domain). Same authoring rules: rich `.describe()`
24
- * on every field, NO identity/credentials in the schema (env-injected, R3).
24
+ * on every field, NO identity/credentials in the schema (env-injected).
25
25
  *
26
26
  * Groups are MLS-capable by default — `enableMls` (default true) on create.
27
27
  */
@@ -47,13 +47,19 @@ const groupRemoveInput = z.object({
47
47
  agentId: z.string().describe("The member to remove: a handle (`name@org`) or a UUID. Group keys are rotated after removal.")
48
48
  });
49
49
  const groupInspectInput = z.object({ group: z.string().describe("The group to inspect: a handle (`#name@org`) or a UUID. Reports its E2EE mode and policy.") });
50
+ const groupJoinInput = z.object({
51
+ group: z.string().describe("The group to join: a handle (`#name@org`), bare name, or a UUID. Resolved against your pending invites, or pass the UUID directly for a publicly discovered open-enrollment group."),
52
+ message: z.string().optional().describe("Optional message included with the join request (approval-gated groups only).")
53
+ });
54
+ /** No input: lists the caller's own pending group invites. */
55
+ const groupInvitesInput = z.object({});
50
56
  //#endregion
51
57
  //#region src/schemas-payments.ts
52
58
  /**
53
59
  * Zod input schemas for the 2 x402 payment tools (split out of `schemas.ts` to
54
60
  * hold the ~200-LOC budget — one file per domain). Same authoring rules: rich
55
- * `.describe()` on every field, NO identity/credentials in the schema (env-injected,
56
- * R3). The facilitator is infra config, resolved from the tool factory / env —
61
+ * `.describe()` on every field, NO identity/credentials in the schema
62
+ * (env-injected). The facilitator is infra config, resolved from the tool factory / env —
57
63
  * never a model-visible input.
58
64
  */
59
65
  const payInput = z.object({
@@ -73,7 +79,7 @@ const fulfillInput = z.object({
73
79
  *
74
80
  * Rich `.describe()` on EVERY field: the field descriptions are the #1 lever on
75
81
  * tool-call accuracy (the AI-DX). Identity/credentials NEVER appear here — the
76
- * acting agent + config dir come from `process.env` (R3), never the model-visible
82
+ * acting agent + config dir come from `process.env`, never the model-visible
77
83
  * input schema.
78
84
  */
79
85
  const DEFAULT_MESSAGE_TYPE = "rine.v1.task_request";
@@ -146,14 +152,19 @@ function rineInspectTool(opts = {}) {
146
152
  //#endregion
147
153
  //#region src/tools/groups.ts
148
154
  /**
149
- * The 4 group tool factories: `rine_group_create`, `rine_group_invite`,
150
- * `rine_group_remove`, `rine_group_inspect`. Groups are MLS-by-default.
155
+ * The 6 group tool factories: `rine_group_create`, `rine_group_invite`,
156
+ * `rine_group_remove`, `rine_group_inspect`, `rine_group_join`,
157
+ * `rine_group_invites`. Groups are MLS-by-default.
151
158
  *
152
159
  * The TS SDK's `groups.invite`/`removeMember` take BRANDED UUIDs positionally, so
153
160
  * invite/remove/inspect PRE-RESOLVE handle→UUID here:
154
161
  * - a group → `groups.list()` + local match (`findGroup`),
155
162
  * - an agent → `resolveToUuid` (WebFinger) → its UUID (or pass a UUID through),
156
163
  * so unlisted agents resolve too.
164
+ * `join` resolves a handle the same way but against the caller's PENDING
165
+ * INVITES (`groups.listInvites()`) — an invitee isn't a member yet, so it can't
166
+ * appear in `groups.list()`. A bare UUID always passes through unchanged (the
167
+ * path for a publicly discovered open-enrollment group with no invite record).
157
168
  */
158
169
  /** True for a bare UUID string (no `@`, matches the rine UUID shape). */
159
170
  function isUuid(s) {
@@ -185,6 +196,28 @@ async function resolveAgentUuid(apiUrl, target) {
185
196
  if (isUuid(target)) return asAgentUuid(target);
186
197
  return asAgentUuid(await resolveToUuid(apiUrl, target));
187
198
  }
199
+ /** Match a pending invite among the caller's invites by UUID, full handle, or bare name. */
200
+ function findInvite(invites, target) {
201
+ if (isUuid(target)) return invites.find((inv) => inv.group_id === target);
202
+ if (!target.includes("@")) {
203
+ const want = bareLocalName(target);
204
+ return invites.find((inv) => inv.group_handle && bareLocalName(inv.group_handle) === want || inv.group_name === target);
205
+ }
206
+ const want = normalizeHandle(target.startsWith("#") ? target : `#${target}`);
207
+ return invites.find((inv) => inv.group_handle && normalizeHandle(inv.group_handle) === want);
208
+ }
209
+ /**
210
+ * Resolve a group handle/UUID to its `GroupUuid` for `rine_group_join`. A bare
211
+ * UUID passes straight through (the open-enrollment discovery case); a handle
212
+ * is resolved against the caller's PENDING INVITES, since an invitee isn't a
213
+ * member yet and so can't appear in `groups.list()`.
214
+ */
215
+ async function resolveGroupUuidForJoin(client, target) {
216
+ if (isUuid(target)) return asGroupUuid(target);
217
+ const match = findInvite(await client.groups.listInvites(), target);
218
+ if (!match) throw new NotFoundError(`No pending invite for group '${target}' — pass the group UUID directly for an open-enrollment group, or check rine_group_invites`);
219
+ return asGroupUuid(match.group_id);
220
+ }
188
221
  /** `rine_group_create` — create an MLS-by-default coordination group. */
189
222
  function rineGroupCreateTool(opts = {}) {
190
223
  return defineTool({
@@ -247,6 +280,31 @@ function rineGroupInspectTool(opts = {}) {
247
280
  })
248
281
  });
249
282
  }
283
+ /** `rine_group_join` — accept an invite (or self-join an open group). */
284
+ function rineGroupJoinTool(opts = {}) {
285
+ return defineTool({
286
+ description: "Join a group: accept a pending invite, or self-join a publicly discovered open-enrollment group by UUID. Instant for open enrollment; for closed/majority/unanimity groups this submits a request that members vote on. This is a real, irreversible network action.",
287
+ inputSchema: jsonSchema(groupJoinInput),
288
+ outputSchema: STRING_OUTPUT,
289
+ needsApproval: approvalGate(opts),
290
+ execute: makeExecute(groupJoinInput, opts, async (client, i) => {
291
+ const groupId = await resolveGroupUuidForJoin(client, i.group);
292
+ const result = await client.groups.join(groupId, { message: i.message });
293
+ return renderJoinResult(i.group, result);
294
+ })
295
+ });
296
+ }
297
+ /** `rine_group_invites` — list the caller's pending group invites. */
298
+ function rineGroupInvitesTool(opts = {}) {
299
+ return defineTool({
300
+ description: "List your agent's pending group invites — group, who invited you, status, and any message. Join one with rine_group_join using the group handle or id.",
301
+ inputSchema: jsonSchema(groupInvitesInput),
302
+ outputSchema: STRING_OUTPUT,
303
+ execute: makeExecute(groupInvitesInput, opts, async (client) => {
304
+ return renderInvites(await client.groups.listInvites());
305
+ })
306
+ });
307
+ }
250
308
  //#endregion
251
309
  //#region src/tools/messaging.ts
252
310
  /**
@@ -256,7 +314,7 @@ function rineGroupInspectTool(opts = {}) {
256
314
  * `makeExecute` (lazy env client + formatError). The runtime tool NAME comes from
257
315
  * the filename slug of the scaffolded `agent/tools/<name>.ts`, not from here.
258
316
  *
259
- * R4 holds throughout: renderers read only plaintext/decrypt_error/verification,
317
+ * Renderers read only plaintext/decrypt_error/verification,
260
318
  * never the ciphertext envelope. `read`/`check_inbox` add a `toModelOutput`
261
319
  * redactor as defence-in-depth.
262
320
  */
@@ -523,6 +581,8 @@ const FACTORIES = {
523
581
  rineGroupInviteTool,
524
582
  rineGroupRemoveTool,
525
583
  rineGroupInspectTool,
584
+ rineGroupJoinTool,
585
+ rineGroupInvitesTool,
526
586
  rinePayTool,
527
587
  rineFulfillTool
528
588
  };
@@ -532,4 +592,4 @@ const RINE_TOOLS = RINE_TOOL_META.map((m) => ({
532
592
  factory: FACTORIES[m.factoryName]
533
593
  }));
534
594
  //#endregion
535
- export { rineReadTool as a, rineSendTool as c, rineGroupInspectTool as d, rineGroupInviteTool as f, rineInspectTool as h, rineCheckInboxTool as i, rineThreadTool as l, rineDiscoverTool as m, rineFulfillTool as n, rineReplyTool as o, rineGroupRemoveTool as p, rinePayTool as r, rineSendAndWaitTool as s, RINE_TOOLS as t, rineGroupCreateTool as u };
595
+ export { rineInspectTool as _, rineReadTool as a, rineSendTool as c, rineGroupInspectTool as d, rineGroupInviteTool as f, rineDiscoverTool as g, rineGroupRemoveTool as h, rineCheckInboxTool as i, rineThreadTool as l, rineGroupJoinTool as m, rineFulfillTool as n, rineReplyTool as o, rineGroupInvitesTool as p, rinePayTool as r, rineSendAndWaitTool as s, RINE_TOOLS as t, rineGroupCreateTool as u };
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * Token-budgeted, role-tagged transcript rendering for the Eve channel's
3
- * push-injection (REQ-CTX-01). The Eve session is STATELESS per inbound message,
3
+ * push-injection. The Eve session is STATELESS per inbound message,
4
4
  * so cross-turn memory comes from injecting the recent thread into the session
5
5
  * `context[]` on each inbound. This module renders that transcript within a
6
6
  * char-approximated token budget, truncating the OLDEST turns first.
7
7
  *
8
- * R4 holds: it reads only `ThreadEntry.text` (already decrypted + rendered by the
8
+ * It reads only `ThreadEntry.text` (already decrypted + rendered by the
9
9
  * SDK), never any ciphertext field.
10
10
  */
11
11
  import type { ThreadEntry } from "@rine-network/sdk";
package/dist/types.d.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * schema changes, these follow). These are type-only re-derivations; runtime tool
8
8
  * schemas are authored with the host `zod` in `schemas.ts`.
9
9
  */
10
- import type { AgentProfileSchema, AgentSummarySchema, DecryptedMessageSchema, GroupReadSchema, InviteResultSchema, MessageReadSchema } from "@rine-network/sdk";
10
+ import type { AgentProfileSchema, AgentSummarySchema, DecryptedMessageSchema, GroupReadSchema, InviteResultSchema, JoinRequestReadSchema, JoinResultSchema, MessageReadSchema } from "@rine-network/sdk";
11
11
  /** Project a Zod schema's output type without importing the SDK's `z` instance. */
12
12
  type Infer<S> = S extends {
13
13
  _output: infer O;
@@ -16,6 +16,8 @@ export type DecryptedMessage = Infer<typeof DecryptedMessageSchema>;
16
16
  export type MessageRead = Infer<typeof MessageReadSchema>;
17
17
  export type GroupRead = Infer<typeof GroupReadSchema>;
18
18
  export type InviteResult = Infer<typeof InviteResultSchema>;
19
+ export type JoinResult = Infer<typeof JoinResultSchema>;
20
+ export type JoinRequestRead = Infer<typeof JoinRequestReadSchema>;
19
21
  export type AgentSummary = Infer<typeof AgentSummarySchema>;
20
22
  export type AgentProfile = Infer<typeof AgentProfileSchema>;
21
23
  export {};
package/dist/webhook.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * by webhook (no daemon, serverless-native). This registers a rine webhook that
6
6
  * POSTs new-message notifications to the channel route, and returns the HMAC
7
7
  * `secret` the channel verifies with (`RINE_WEBHOOK_SECRET`). `--delete` tears it
8
- * down. R1: the client is built lazily inside the call.
8
+ * down. The client is built lazily inside the call.
9
9
  */
10
10
  /** Options shared by register/delete. */
11
11
  export interface WebhookOptions {
package/dist/webhook.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as getRineClient } from "./client-X_-9CpQT.js";
1
+ import { t as getRineClient } from "./client-DsG2xtKs.js";
2
2
  import { asAgentUuid, asWebhookUuid } from "@rine-network/sdk";
3
3
  import { UUID_RE, resolveApiUrl, resolveToUuid } from "@rine-network/core";
4
4
  //#region src/webhook.ts
@@ -9,7 +9,7 @@ import { UUID_RE, resolveApiUrl, resolveToUuid } from "@rine-network/core";
9
9
  * by webhook (no daemon, serverless-native). This registers a rine webhook that
10
10
  * POSTs new-message notifications to the channel route, and returns the HMAC
11
11
  * `secret` the channel verifies with (`RINE_WEBHOOK_SECRET`). `--delete` tears it
12
- * down. R1: the client is built lazily inside the call.
12
+ * down. The client is built lazily inside the call.
13
13
  */
14
14
  const DEFAULT_INBOUND_PATH = "/rine/v1/inbound";
15
15
  function inboundUrl(opts) {
package/dist/x402.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * x402 payment-aware inbound re-surfacing for the rine channel (D1 + D2).
2
+ * x402 payment-aware inbound re-surfacing for the rine channel.
3
3
  *
4
4
  * The three x402 payment frames are first-class message types carrying a verbatim
5
5
  * x402 V2 object, NOT a chat turn. v1.0 dropped them wholesale (a stateless gateway
@@ -12,7 +12,7 @@
12
12
  * - `x402_payment` → the signed authorization + guidance to `rine_fulfill`.
13
13
  * - `x402_receipt` → the settlement outcome, informational (no reply).
14
14
  *
15
- * D2 auto-pay (opt-in, DEFAULT OFF): when enabled, a `payment_required` at/below the
15
+ * Auto-pay (opt-in, DEFAULT OFF): when enabled, a `payment_required` at/below the
16
16
  * policy's `autoPayThreshold` is paid with NO LLM turn — still bounded by the policy
17
17
  * caps, deny-by-default, journal and reserve-lock (all in rine-core). Any decline
18
18
  * falls back to surfacing the quote to the model.
@@ -31,7 +31,7 @@ export declare function renderX402Body(msg: DecryptedMessage): string;
31
31
  /** The routing-guidance line: what the model should do, and the do-not-reply rule. */
32
32
  export declare function x402GuidanceLine(msg: DecryptedMessage): string;
33
33
  /**
34
- * Handle a verified inbound x402 frame (D1). `payment_required` may auto-pay (D2)
34
+ * Handle a verified inbound x402 frame. `payment_required` may auto-pay
35
35
  * when enabled and at/below threshold; otherwise, and for `payment` / `receipt`,
36
36
  * the frame is surfaced to the model as a payment-aware turn.
37
37
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rine-network/eve",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Native Vercel Eve connector for the rine network \u2014 a custom channel that makes an Eve agent reachable over E2E-encrypted (HPKE 1:1, MLS groups RFC 9420, PQ-hybrid) agent-to-agent messaging, plus file-discovered rine tools, a skill, and an init/onboard/relay CLI.",
5
5
  "author": "mmmbs <mmmbs@proton.me>",
6
6
  "license": "EUPL-1.2",
@@ -48,8 +48,8 @@
48
48
  "prepublishOnly": "node scripts/check-no-file-deps.mjs"
49
49
  },
50
50
  "dependencies": {
51
- "@rine-network/core": "^0.11.0",
52
- "@rine-network/sdk": "^0.8.0",
51
+ "@rine-network/core": "^0.12.0",
52
+ "@rine-network/sdk": "^0.9.0",
53
53
  "zod": "^3.25.0",
54
54
  "zod-to-json-schema": "^3.24.1"
55
55
  },