@rine-network/mastra 0.1.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.
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Setup helper — `npx @rine-network/mastra onboard` (SPEC §11, D-not-tools).
3
+ *
4
+ * Runs the SDK's RSA time-lock proof-of-work to register a fresh org, then
5
+ * creates the first agent and prints its handle + verification words. This is
6
+ * NEVER a `createTool` — a ~30–60 s PoW does not belong in an LLM turn; it is an
7
+ * out-of-band CLI a human runs once.
8
+ *
9
+ * I-1: no client is built at module load — `runOnboard` constructs the client
10
+ * lazily, only when invoked. The PoW + credential write are delegated wholesale
11
+ * to the SDK's `register(opts)` (over rine-core `performRegistration`); the agent
12
+ * keypair is generated + persisted by `client.createAgent(name)`.
13
+ *
14
+ * Config resolution is explicit (D-config-resolve): `register` REQUIRES concrete
15
+ * `apiUrl`/`configDir` strings, so we resolve them via rine-core unless the caller
16
+ * passed overrides (the SDK never resolves them itself).
17
+ */
18
+ /** Options for {@link runOnboard}. */
19
+ export interface OnboardOptions {
20
+ /** Registration email address. */
21
+ email: string;
22
+ /** Organisation slug (validated client-side by the SDK's `register`). */
23
+ slug: string;
24
+ /** Organisation display name (the first agent's name derives from it). */
25
+ name: string;
26
+ /** API base URL; when omitted, `resolveApiUrl()` is used. */
27
+ apiUrl?: string;
28
+ /** Config dir for credential + key persistence; `resolveConfigDir()` if omitted. */
29
+ configDir?: string;
30
+ /**
31
+ * Handle-safe first-agent name (handle local-part); defaults to
32
+ * {@link agentNameFromOrgName}(`name`, `slug`). A free-form `name` like
33
+ * "My Org" is invalid verbatim (server rejects uppercase/spaces).
34
+ */
35
+ agentName?: string;
36
+ }
37
+ /**
38
+ * Derive a server-valid agent name (handle local-part: 1–200 lowercase alnum +
39
+ * interior hyphens) from a free-form display name: lowercase, fold non-alnum
40
+ * runs to single hyphens, trim edges, cap at 200; fall back to `slug` if empty.
41
+ */
42
+ export declare function agentNameFromOrgName(name: string, slug: string): string;
43
+ /** Where {@link runOnboard} writes its progress/output (stdout by default). */
44
+ export interface OnboardIO {
45
+ log: (line: string) => void;
46
+ }
47
+ /**
48
+ * Register a fresh org (RSA PoW), create its first agent, and print the handle +
49
+ * verification words. Returns the new agent's handle. Errors propagate (this is a
50
+ * CLI, not an LLM tool — a failed onboard should exit non-zero).
51
+ */
52
+ export declare function runOnboard(opts: OnboardOptions, io?: OnboardIO): Promise<string>;
53
+ /** Parsed `onboard` CLI arguments. */
54
+ export interface OnboardArgs {
55
+ email: string;
56
+ slug: string;
57
+ name: string;
58
+ apiUrl?: string;
59
+ configDir?: string;
60
+ agentName?: string;
61
+ }
62
+ /**
63
+ * Parse `onboard` argv (the slice AFTER the `onboard` subcommand). Throws on a
64
+ * missing required flag or unknown flag so the bin can print usage + exit 1.
65
+ * Pure + side-effect-free so it is unit-testable without running a real PoW.
66
+ */
67
+ export declare function parseOnboardArgs(argv: readonly string[]): OnboardArgs;
68
+ /**
69
+ * The `bin` entry point. `argv` is the full `process.argv.slice(2)` (with the
70
+ * `onboard` subcommand as the first element). Prints usage + exits non-zero on a
71
+ * parse error; otherwise runs the onboard flow.
72
+ */
73
+ export declare function main(argv: readonly string[], io?: OnboardIO): Promise<void>;
@@ -0,0 +1,134 @@
1
+ import { resolveApiUrl, resolveConfigDir } from "@rine-network/core";
2
+ import { AsyncRineClient, register } from "@rine-network/sdk";
3
+ //#region src/onboard.ts
4
+ /**
5
+ * Setup helper — `npx @rine-network/mastra onboard` (SPEC §11, D-not-tools).
6
+ *
7
+ * Runs the SDK's RSA time-lock proof-of-work to register a fresh org, then
8
+ * creates the first agent and prints its handle + verification words. This is
9
+ * NEVER a `createTool` — a ~30–60 s PoW does not belong in an LLM turn; it is an
10
+ * out-of-band CLI a human runs once.
11
+ *
12
+ * I-1: no client is built at module load — `runOnboard` constructs the client
13
+ * lazily, only when invoked. The PoW + credential write are delegated wholesale
14
+ * to the SDK's `register(opts)` (over rine-core `performRegistration`); the agent
15
+ * keypair is generated + persisted by `client.createAgent(name)`.
16
+ *
17
+ * Config resolution is explicit (D-config-resolve): `register` REQUIRES concrete
18
+ * `apiUrl`/`configDir` strings, so we resolve them via rine-core unless the caller
19
+ * passed overrides (the SDK never resolves them itself).
20
+ */
21
+ /**
22
+ * Derive a server-valid agent name (handle local-part: 1–200 lowercase alnum +
23
+ * interior hyphens) from a free-form display name: lowercase, fold non-alnum
24
+ * runs to single hyphens, trim edges, cap at 200; fall back to `slug` if empty.
25
+ */
26
+ function agentNameFromOrgName(name, slug) {
27
+ const derived = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 200).replace(/-+$/g, "");
28
+ return derived.length > 0 ? derived : slug;
29
+ }
30
+ const stdoutIO = { log: (line) => process.stdout.write(`${line}\n`) };
31
+ /**
32
+ * Register a fresh org (RSA PoW), create its first agent, and print the handle +
33
+ * verification words. Returns the new agent's handle. Errors propagate (this is a
34
+ * CLI, not an LLM tool — a failed onboard should exit non-zero).
35
+ */
36
+ async function runOnboard(opts, io = stdoutIO) {
37
+ const apiUrl = opts.apiUrl ?? resolveApiUrl();
38
+ const configDir = opts.configDir ?? resolveConfigDir();
39
+ io.log(`Onboarding org "${opts.slug}" at ${apiUrl} …`);
40
+ io.log("Solving registration proof-of-work (this takes ~30–60 s) …");
41
+ let lastPct = -1;
42
+ await register({
43
+ apiUrl,
44
+ configDir,
45
+ email: opts.email,
46
+ slug: opts.slug,
47
+ name: opts.name,
48
+ onProgress: (pct) => {
49
+ const whole = Math.floor(pct);
50
+ if (whole > lastPct) {
51
+ lastPct = whole;
52
+ io.log(` proof-of-work ${whole}%`);
53
+ }
54
+ }
55
+ });
56
+ io.log("Registered. Creating your first agent …");
57
+ const client = new AsyncRineClient({
58
+ configDir,
59
+ apiUrl
60
+ });
61
+ const agentName = opts.agentName ?? agentNameFromOrgName(opts.name, opts.slug);
62
+ const agent = await client.createAgent(agentName);
63
+ io.log("");
64
+ io.log(`Agent ready: ${agent.handle}`);
65
+ if (agent.verification_words) io.log(`Verification words: ${agent.verification_words}`);
66
+ io.log(`Config dir: ${configDir}`);
67
+ io.log("Set RINE_CONFIG_DIR to this path (or RINE_CLIENT_ID/RINE_CLIENT_SECRET) so your Mastra tools authenticate.");
68
+ return agent.handle;
69
+ }
70
+ const USAGE = "Usage: npx @rine-network/mastra onboard --email <e> --slug <s> --name <n> [--agent-name <a>] [--api-url <u>] [--config-dir <d>]";
71
+ /**
72
+ * Parse `onboard` argv (the slice AFTER the `onboard` subcommand). Throws on a
73
+ * missing required flag or unknown flag so the bin can print usage + exit 1.
74
+ * Pure + side-effect-free so it is unit-testable without running a real PoW.
75
+ */
76
+ function parseOnboardArgs(argv) {
77
+ const flags = {};
78
+ for (let i = 0; i < argv.length; i++) {
79
+ const arg = argv[i];
80
+ if (!arg?.startsWith("--")) throw new Error(`Unexpected argument: ${arg}`);
81
+ const key = arg.slice(2);
82
+ const value = argv[++i];
83
+ if (value === void 0) throw new Error(`Missing value for --${key}`);
84
+ flags[key] = value;
85
+ }
86
+ const known = new Set([
87
+ "email",
88
+ "slug",
89
+ "name",
90
+ "agent-name",
91
+ "api-url",
92
+ "config-dir"
93
+ ]);
94
+ for (const key of Object.keys(flags)) if (!known.has(key)) throw new Error(`Unknown flag: --${key}`);
95
+ const missing = [
96
+ "email",
97
+ "slug",
98
+ "name"
99
+ ].filter((k) => !flags[k]);
100
+ if (missing.length > 0) throw new Error(`Missing required flag(s): ${missing.map((m) => `--${m}`).join(", ")}`);
101
+ return {
102
+ email: flags.email,
103
+ slug: flags.slug,
104
+ name: flags.name,
105
+ apiUrl: flags["api-url"],
106
+ configDir: flags["config-dir"],
107
+ agentName: flags["agent-name"]
108
+ };
109
+ }
110
+ /**
111
+ * The `bin` entry point. `argv` is the full `process.argv.slice(2)` (with the
112
+ * `onboard` subcommand as the first element). Prints usage + exits non-zero on a
113
+ * parse error; otherwise runs the onboard flow.
114
+ */
115
+ async function main(argv, io = stdoutIO) {
116
+ const [sub, ...rest] = argv;
117
+ if (sub !== "onboard") {
118
+ io.log(USAGE);
119
+ process.exitCode = 1;
120
+ return;
121
+ }
122
+ let args;
123
+ try {
124
+ args = parseOnboardArgs(rest);
125
+ } catch (err) {
126
+ io.log(err instanceof Error ? err.message : String(err));
127
+ io.log(USAGE);
128
+ process.exitCode = 1;
129
+ return;
130
+ }
131
+ await runOnboard(args, io);
132
+ }
133
+ //#endregion
134
+ export { agentNameFromOrgName, main, parseOnboardArgs, runOnboard };
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Zod input schemas for the 4 group tools (split out of `schemas.ts` to hold the
3
+ * ~200-LOC budget — the schema concentration the SPEC §4 endorses, one file per
4
+ * domain). Same authoring rules: HOST `zod`, rich `.describe()` on every field,
5
+ * NO identity/credentials in the schema (host-injected via `ctx.requestContext`).
6
+ *
7
+ * Groups are MLS-capable by default — `enableMls` (default true) on create is the
8
+ * headline inversion vs the Python siblings (D-mls).
9
+ */
10
+ import { z } from "zod";
11
+ export declare const groupCreateInput: z.ZodObject<{
12
+ name: z.ZodString;
13
+ enrollment: z.ZodDefault<z.ZodEnum<["open", "closed", "majority", "unanimity"]>>;
14
+ visibility: z.ZodDefault<z.ZodEnum<["public", "private"]>>;
15
+ description: z.ZodOptional<z.ZodString>;
16
+ enableMls: z.ZodDefault<z.ZodBoolean>;
17
+ }, "strip", z.ZodTypeAny, {
18
+ name: string;
19
+ enrollment: "open" | "closed" | "majority" | "unanimity";
20
+ visibility: "public" | "private";
21
+ enableMls: boolean;
22
+ description?: string | undefined;
23
+ }, {
24
+ name: string;
25
+ enrollment?: "open" | "closed" | "majority" | "unanimity" | undefined;
26
+ visibility?: "public" | "private" | undefined;
27
+ description?: string | undefined;
28
+ enableMls?: boolean | undefined;
29
+ }>;
30
+ export declare const groupInviteInput: z.ZodObject<{
31
+ group: z.ZodString;
32
+ agentToInvite: z.ZodString;
33
+ message: z.ZodOptional<z.ZodString>;
34
+ }, "strip", z.ZodTypeAny, {
35
+ group: string;
36
+ agentToInvite: string;
37
+ message?: string | undefined;
38
+ }, {
39
+ group: string;
40
+ agentToInvite: string;
41
+ message?: string | undefined;
42
+ }>;
43
+ export declare const groupRemoveInput: z.ZodObject<{
44
+ group: z.ZodString;
45
+ agentId: z.ZodString;
46
+ }, "strip", z.ZodTypeAny, {
47
+ group: string;
48
+ agentId: string;
49
+ }, {
50
+ group: string;
51
+ agentId: string;
52
+ }>;
53
+ export declare const groupInspectInput: z.ZodObject<{
54
+ group: z.ZodString;
55
+ }, "strip", z.ZodTypeAny, {
56
+ group: string;
57
+ }, {
58
+ group: string;
59
+ }>;
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Shared Zod input schemas for the 11 rine tools.
3
+ *
4
+ * Authored with the HOST `zod` (`import { z } from "zod"`) — the single hoisted
5
+ * instance Mastra validates against — NOT the SDK's re-exported `z`. Rich
6
+ * `.describe()` on EVERY field: the field descriptions are the #1 lever on
7
+ * tool-call accuracy (the AI-DX). Identity/credentials NEVER appear here — the
8
+ * acting agent + config dir are read from `ctx.requestContext`, never the model-
9
+ * visible input schema (I-2 / Mastra's own security rule).
10
+ *
11
+ * `messageType`/`idempotencyKey`/etc. ports drop the Python `tag`/`jurisdiction`/
12
+ * `pricingModel` discover fields (the TS `DiscoveryFilters` lacks them) and add
13
+ * `enableMls` (default true) on group_create — the headline inversion (D-mls).
14
+ */
15
+ import { z } from "zod";
16
+ export declare const sendInput: z.ZodObject<{
17
+ to: z.ZodString;
18
+ body: z.ZodString;
19
+ messageType: z.ZodDefault<z.ZodString>;
20
+ idempotencyKey: z.ZodOptional<z.ZodString>;
21
+ }, "strip", z.ZodTypeAny, {
22
+ to: string;
23
+ body: string;
24
+ messageType: string;
25
+ idempotencyKey?: string | undefined;
26
+ }, {
27
+ to: string;
28
+ body: string;
29
+ messageType?: string | undefined;
30
+ idempotencyKey?: string | undefined;
31
+ }>;
32
+ export declare const sendAndWaitInput: z.ZodObject<{
33
+ to: z.ZodString;
34
+ body: z.ZodString;
35
+ waitSeconds: z.ZodDefault<z.ZodNumber>;
36
+ messageType: z.ZodDefault<z.ZodString>;
37
+ }, "strip", z.ZodTypeAny, {
38
+ to: string;
39
+ body: string;
40
+ messageType: string;
41
+ waitSeconds: number;
42
+ }, {
43
+ to: string;
44
+ body: string;
45
+ messageType?: string | undefined;
46
+ waitSeconds?: number | undefined;
47
+ }>;
48
+ export declare const checkInboxInput: z.ZodObject<{
49
+ limit: z.ZodDefault<z.ZodNumber>;
50
+ }, "strip", z.ZodTypeAny, {
51
+ limit: number;
52
+ }, {
53
+ limit?: number | undefined;
54
+ }>;
55
+ export declare const readInput: z.ZodObject<{
56
+ messageId: z.ZodString;
57
+ }, "strip", z.ZodTypeAny, {
58
+ messageId: string;
59
+ }, {
60
+ messageId: string;
61
+ }>;
62
+ export declare const replyInput: z.ZodObject<{
63
+ messageId: z.ZodString;
64
+ body: z.ZodString;
65
+ messageType: z.ZodDefault<z.ZodString>;
66
+ }, "strip", z.ZodTypeAny, {
67
+ body: string;
68
+ messageType: string;
69
+ messageId: string;
70
+ }, {
71
+ body: string;
72
+ messageId: string;
73
+ messageType?: string | undefined;
74
+ }>;
75
+ export declare const discoverInput: z.ZodObject<{
76
+ q: z.ZodOptional<z.ZodString>;
77
+ category: z.ZodOptional<z.ZodString>;
78
+ language: z.ZodOptional<z.ZodString>;
79
+ verified: z.ZodOptional<z.ZodBoolean>;
80
+ limit: z.ZodDefault<z.ZodNumber>;
81
+ }, "strip", z.ZodTypeAny, {
82
+ limit: number;
83
+ verified?: boolean | undefined;
84
+ q?: string | undefined;
85
+ category?: string | undefined;
86
+ language?: string | undefined;
87
+ }, {
88
+ verified?: boolean | undefined;
89
+ limit?: number | undefined;
90
+ q?: string | undefined;
91
+ category?: string | undefined;
92
+ language?: string | undefined;
93
+ }>;
94
+ export declare const inspectInput: z.ZodObject<{
95
+ handleOrId: z.ZodString;
96
+ }, "strip", z.ZodTypeAny, {
97
+ handleOrId: string;
98
+ }, {
99
+ handleOrId: string;
100
+ }>;
101
+ export { groupCreateInput, groupInspectInput, groupInviteInput, groupRemoveInput, } from "./schemas-groups.js";
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Tier-3 thread map (D-tier3-store): a durable `(handle, conversation_id) →
3
+ * runId` map. This is OUR responsibility — the LangGraph `thread_id` analog —
4
+ * and is SEPARATE from Mastra's own workflow-snapshot storage (`@mastra/libsql`/
5
+ * `@mastra/pg`). The snapshot is Mastra's; this map tells the resumer WHICH
6
+ * suspended run an inbound rine message belongs to, so a fresh process finds it.
7
+ *
8
+ * Two implementations:
9
+ * - {@link InMemoryThreadMap} — tests / single-process ephemeral use.
10
+ * - {@link SqliteThreadMap} — the documented production default; libsql-backed
11
+ * (file URL for durability across restarts, `:memory:` for a throwaway).
12
+ *
13
+ * I-1: building a `SqliteThreadMap` opens a libsql handle, so do it where the
14
+ * driver/resumer is wired (a long-lived host start), never at module import.
15
+ */
16
+ /**
17
+ * Durable map keying a rine thread `(handle, conversation_id)` to the suspended
18
+ * Mastra workflow `runId` that owns it. All methods are async so a SQL-backed
19
+ * implementation fits the same interface as the in-memory one.
20
+ */
21
+ export interface ThreadMapStore {
22
+ /** The `runId` for this thread, or `undefined` if none is mapped. */
23
+ get(handle: string, conversation: string): Promise<string | undefined>;
24
+ /** Map (or remap) this thread to `runId`. */
25
+ set(handle: string, conversation: string, runId: string): Promise<void>;
26
+ /** Drop the mapping for this thread (e.g. once the run has completed). */
27
+ delete(handle: string, conversation: string): Promise<void>;
28
+ }
29
+ /**
30
+ * In-process `(handle, conversation) → runId` map. Per-process only — it does
31
+ * NOT survive a restart, so it is for tests / single-long-lived-process demos.
32
+ * Use {@link SqliteThreadMap} for anything that must outlive the process.
33
+ */
34
+ export declare class InMemoryThreadMap implements ThreadMapStore {
35
+ private readonly map;
36
+ get(handle: string, conversation: string): Promise<string | undefined>;
37
+ set(handle: string, conversation: string, runId: string): Promise<void>;
38
+ delete(handle: string, conversation: string): Promise<void>;
39
+ }
40
+ /** Options for {@link SqliteThreadMap.open}. */
41
+ export interface SqliteThreadMapOptions {
42
+ /**
43
+ * libsql URL. `file:rine-threadmap.db` (durable, the production default),
44
+ * `:memory:` (ephemeral), or a remote `libsql://…` for a hosted Turso DB.
45
+ */
46
+ url: string;
47
+ /** Optional auth token for a remote libsql/Turso URL. */
48
+ authToken?: string;
49
+ }
50
+ /**
51
+ * libsql-backed {@link ThreadMapStore} — the documented production default. A
52
+ * file URL persists the map so a FRESH process can resolve an inbound message's
53
+ * `(handle, conversation)` to the right suspended `runId` and resume it.
54
+ *
55
+ * Construct via the async {@link SqliteThreadMap.open} factory so the table is
56
+ * created before the first `get`/`set`. The libsql handle is owned here; call
57
+ * {@link close} on teardown.
58
+ */
59
+ export declare class SqliteThreadMap implements ThreadMapStore {
60
+ private readonly client;
61
+ private constructor();
62
+ /** Open the store and ensure its table exists. */
63
+ static open(opts: SqliteThreadMapOptions): Promise<SqliteThreadMap>;
64
+ get(handle: string, conversation: string): Promise<string | undefined>;
65
+ set(handle: string, conversation: string, runId: string): Promise<void>;
66
+ delete(handle: string, conversation: string): Promise<void>;
67
+ /** Close the underlying libsql handle. */
68
+ close(): void;
69
+ }
package/dist/tool.d.ts ADDED
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Shared `createTool` plumbing every rine tool reuses (no duplicated logic):
3
+ * identity injection (I-1 lazy client + I-2 no-creds-in-schema) and the
4
+ * try/catch → `formatError` wrapper (I-3 errors→strings, never a reject).
5
+ *
6
+ * A tool's per-tool body is just `(client, inputData) => string`; this helper
7
+ * supplies the surrounding contract:
8
+ * 1. read the acting agent + config-dir/api-url overrides from
9
+ * `ctx.requestContext` (NEVER `inputSchema`), falling back to the
10
+ * `rineToolkit(opts)` overrides closed over at factory time,
11
+ * 2. lazily build/get the shared `AsyncRineClient` (I-1 — first call only),
12
+ * 3. run the body, and on any thrown SDK error return `formatError(err)` so
13
+ * the tool RESOLVES a readable string and never rejects (I-3).
14
+ *
15
+ * `createTool` from `@mastra/core/tools` is invoked by each domain module; this
16
+ * file only builds the `execute` closure and the shared option/ctx types.
17
+ */
18
+ import type { AgentHandle, AgentUuid, AsyncRineClient, GroupHandle, GroupUuid } from "@rine-network/sdk";
19
+ import { type RineClientOpts } from "./client.js";
20
+ import { type RineToolContext } from "./context.js";
21
+ /**
22
+ * Per-factory overrides threaded from `rineToolkit(opts)` / an individual
23
+ * `createRine<X>Tool(opts)` call. A live `client` may be passed so every tool in
24
+ * one `rineToolkit(...)` call shares ONE lazily-built client (AC-11); when
25
+ * omitted, each tool resolves its own client lazily on first `execute`.
26
+ */
27
+ export interface RineToolOpts extends RineClientOpts {
28
+ /** A shared client to reuse (set by `rineToolkit` for AC-11). */
29
+ client?: AsyncRineClient;
30
+ }
31
+ /**
32
+ * Resolve the effective `AsyncRineClient` for one `execute` call: prefer a
33
+ * shared client from the toolkit, else build one from the ctx-injected identity
34
+ * layered over the factory defaults. Lazy by construction — only runs inside
35
+ * `execute` (I-1).
36
+ */
37
+ export declare function resolveClient(opts: RineToolOpts, ctx: RineToolContext | undefined): AsyncRineClient;
38
+ /**
39
+ * The same resolved `apiUrl` `resolveClient` builds its client against (ctx
40
+ * override → factory override → `resolveApiUrl()`). Exposed so handle→UUID
41
+ * pre-resolution (`resolveToUuid`) hits the SAME server WebFinger the client
42
+ * uses, since the SDK client has no public `apiUrl` getter.
43
+ */
44
+ export declare function resolveApiUrlFor(opts: RineToolOpts, ctx: RineToolContext | undefined): string;
45
+ /**
46
+ * The recipient union `client.send`/`sendAndWait` accept. The model supplies a
47
+ * free-form `to` string (a `name@org` handle, a `#group@org` handle, or a UUID);
48
+ * the SDK normalizes + validates it at runtime, so this brands the string once,
49
+ * in one documented place, rather than scattering casts.
50
+ */
51
+ type Recipient = AgentHandle | AgentUuid | GroupHandle | GroupUuid;
52
+ /** Brand a model-supplied recipient string for the SDK send surface. */
53
+ export declare function asRecipient(to: string): Recipient;
54
+ /**
55
+ * I-2 layer (c): the belt-and-suspenders ciphertext redactor for `read` /
56
+ * `check_inbox` (SPEC §2.2 / D-output). Layers (a) plaintext-only renderers and
57
+ * (b) `outputSchema: z.string()` already guarantee the `execute` return is a
58
+ * redacted string; this coerces ANY value to plain text content before it can
59
+ * reach the model, so even a regression that returned a richer object containing
60
+ * ciphertext could not surface it. Returns Mastra's default text-content shape.
61
+ */
62
+ export declare function redactToText(output: unknown): {
63
+ type: "text";
64
+ value: string;
65
+ };
66
+ /**
67
+ * A tool body: one client call rendered to a string. The wrapper handles errors.
68
+ * `apiUrl` is the server the client is bound to (for handle→UUID pre-resolution);
69
+ * bodies that don't resolve handles ignore it.
70
+ */
71
+ export type RineToolBody<I> = (client: AsyncRineClient, inputData: I, apiUrl: string) => Promise<string>;
72
+ /**
73
+ * Build a Mastra-tool `execute(inputData, ctx)` from a body, applying the
74
+ * lazy-client + try/catch→formatError contract. Use as the `execute` value of a
75
+ * `createTool({...})` config.
76
+ */
77
+ export declare function makeExecute<I>(opts: RineToolOpts, body: RineToolBody<I>): (inputData: I, ctx: RineToolContext) => Promise<string>;
78
+ export {};
@@ -0,0 +1,37 @@
1
+ /**
2
+ * `rineToolkit(opts)` — the aggregator (SPEC §7). Returns a plain keyed
3
+ * `Record<string, Tool>` (Mastra has no `BaseToolkit` class). The object KEY is
4
+ * the model-facing tool name, so each entry is keyed by its `id`
5
+ * (`toolName === id`). Drop the record straight into a Mastra `Agent`'s
6
+ * `tools: {}` map.
7
+ *
8
+ * `include` curates the surface: `"all"` (11), one domain
9
+ * (`"messaging"`/`"discovery"`/`"groups"`), or an array union of domains.
10
+ *
11
+ * AC-11 shared client: ONE lazily-built `AsyncRineClient` is created per
12
+ * `rineToolkit(...)` call and threaded into every tool's `opts.client`, so all
13
+ * tools share a client (and the warm OAuth token cache). Per-acting-agent
14
+ * variants derive cheaply via `client.withAgent(...)` inside each `execute`.
15
+ *
16
+ * The individual `createRine<X>Tool(opts)` factories are also re-exported for the
17
+ * "attach only what you need" ergonomic.
18
+ */
19
+ import type { Tool } from "@mastra/core/tools";
20
+ /** The domains a toolkit can be filtered to. */
21
+ export type RineToolDomain = "messaging" | "discovery" | "groups";
22
+ /** Options for {@link rineToolkit}. */
23
+ export interface RineToolkitOptions {
24
+ /** Explicit config dir; when omitted, `resolveConfigDir()` is used. */
25
+ configDir?: string;
26
+ /** Explicit API URL; when omitted, `resolveApiUrl()` is used. */
27
+ apiUrl?: string;
28
+ /** Acting agent (handle/name/UUID) sent on every request. */
29
+ agent?: string;
30
+ /** Which tools to include. Default `"all"`. */
31
+ include?: "all" | RineToolDomain | readonly RineToolDomain[];
32
+ }
33
+ /**
34
+ * Build the rine tool record. The returned object is keyed by each tool's `id`
35
+ * (so `toolName === id`), ready to spread into a Mastra `Agent`'s `tools` map.
36
+ */
37
+ export declare function rineToolkit(opts?: RineToolkitOptions): Record<string, Tool>;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * SDK return-type aliases for the renderers + tools.
3
+ *
4
+ * The SDK exports the `*Schema` Zod schemas from its root but NOT the inferred
5
+ * type aliases (`GroupRead`, `AgentSummary`, …), and it has no subpath exports.
6
+ * So we re-derive the handful we need via the schemas' `_output` projection — a
7
+ * thin, drift-proof bridge (if the SDK schema changes, these follow). These are
8
+ * type-only re-derivations; runtime tool schemas are authored with the host
9
+ * `zod` in `schemas.ts`.
10
+ */
11
+ import type { AgentProfileSchema, AgentSummarySchema, DecryptedMessageSchema, GroupReadSchema, InviteResultSchema, MessageReadSchema } from "@rine-network/sdk";
12
+ /** Project a Zod schema's output type without importing the SDK's `z` instance. */
13
+ type Infer<S> = S extends {
14
+ _output: infer O;
15
+ } ? O : never;
16
+ export type DecryptedMessage = Infer<typeof DecryptedMessageSchema>;
17
+ export type MessageRead = Infer<typeof MessageReadSchema>;
18
+ export type GroupRead = Infer<typeof GroupReadSchema>;
19
+ export type InviteResult = Infer<typeof InviteResultSchema>;
20
+ export type AgentSummary = Infer<typeof AgentSummarySchema>;
21
+ export type AgentProfile = Infer<typeof AgentProfileSchema>;
22
+ export {};
package/package.json ADDED
@@ -0,0 +1,86 @@
1
+ {
2
+ "name": "@rine-network/mastra",
3
+ "version": "0.1.0",
4
+ "description": "Native Mastra.ai tools for the rine network \u2014 E2E-encrypted (HPKE 1:1, MLS groups, PQ-hybrid) agent-to-agent messaging, discovery, and coordination as createTool tools, a toolkit aggregator, a lifecycle bridge, a Tier-3 workflow-resume bridge, and a setup CLI.",
5
+ "author": "mmmbs <mmmbs@proton.me>",
6
+ "license": "EUPL-1.2",
7
+ "type": "module",
8
+ "engines": {
9
+ "node": ">=22.13.0"
10
+ },
11
+ "bin": {
12
+ "rine-mastra": "bin/onboard.js"
13
+ },
14
+ "exports": {
15
+ ".": {
16
+ "types": "./dist/index.d.ts",
17
+ "import": "./dist/index.js",
18
+ "default": "./dist/index.js"
19
+ },
20
+ "./onboard": {
21
+ "types": "./dist/onboard.d.ts",
22
+ "import": "./dist/onboard.js",
23
+ "default": "./dist/onboard.js"
24
+ },
25
+ "./package.json": "./package.json"
26
+ },
27
+ "files": [
28
+ "dist/",
29
+ "bin/",
30
+ "README.md",
31
+ "MASTRA.md",
32
+ "AGENTS.md",
33
+ "LICENSE"
34
+ ],
35
+ "scripts": {
36
+ "build": "tsdown src/index.ts src/onboard.ts --format esm --outDir dist --clean && tsc -p tsconfig.build.json --emitDeclarationOnly",
37
+ "typecheck": "tsc --noEmit",
38
+ "test": "vitest run",
39
+ "test:watch": "vitest",
40
+ "lint": "biome check .",
41
+ "prepublishOnly": "node scripts/check-no-file-deps.mjs"
42
+ },
43
+ "dependencies": {
44
+ "@libsql/client": "^0.15.0",
45
+ "@rine-network/core": "^0.5.1",
46
+ "@rine-network/sdk": "^0.3.0"
47
+ },
48
+ "peerDependencies": {
49
+ "@mastra/core": ">=1.0.0 <2.0.0",
50
+ "zod": ">=3.25.0 || >=4.0.0"
51
+ },
52
+ "devDependencies": {
53
+ "@ai-sdk/openai-compatible": "^2.0.49",
54
+ "@biomejs/biome": "^1.9.0",
55
+ "@mastra/core": "^1.41.0",
56
+ "@mastra/libsql": "^1.12.1",
57
+ "@types/node": "^22.0.0",
58
+ "ai": "^6.0.0",
59
+ "tsdown": "^0.12.0",
60
+ "tsx": "^4.19.0",
61
+ "typescript": "^5.7.0",
62
+ "vitest": "^3.0.0",
63
+ "zod": "^3.25.0"
64
+ },
65
+ "homepage": "https://rine.network",
66
+ "repository": {
67
+ "type": "git",
68
+ "url": "https://codeberg.org/rine/rine-mastra"
69
+ },
70
+ "bugs": {
71
+ "url": "https://codeberg.org/rine/rine-mastra/issues"
72
+ },
73
+ "publishConfig": {
74
+ "access": "public"
75
+ },
76
+ "keywords": [
77
+ "mastra",
78
+ "rine",
79
+ "ai-agents",
80
+ "tools",
81
+ "a2a",
82
+ "e2ee",
83
+ "mls",
84
+ "messaging"
85
+ ]
86
+ }