@rine-network/eve 0.2.0 → 0.5.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 +12 -6
- package/dist/_zod.d.ts +1 -1
- package/dist/{channel-b0iIAZTh.js → channel-B81UiHyr.js} +29 -26
- package/dist/channel-core.d.ts +14 -11
- package/dist/channel-outbound.d.ts +3 -3
- package/dist/channel.d.ts +5 -5
- package/dist/channel.js +1 -1
- package/dist/{client-X_-9CpQT.js → client-CXJATA-m.js} +24 -4
- package/dist/client.d.ts +20 -2
- package/dist/errors.d.ts +1 -1
- package/dist/format-groups-list.d.ts +140 -0
- package/dist/format-groups.d.ts +81 -0
- package/dist/format.d.ts +57 -13
- package/dist/inbound.d.ts +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -7
- package/dist/onboard.d.ts +1 -1
- package/dist/onboard.js +3 -3
- package/dist/{registry-6sWyhOyF.js → registry-DsU13KY3.js} +57 -2
- package/dist/relay.d.ts +1 -1
- package/dist/relay.js +3 -3
- package/dist/scaffold-DQ2CA1kD.js +239 -0
- package/dist/scaffold.js +1 -1
- package/dist/schemas-groups-list.d.ts +29 -0
- package/dist/schemas-groups.d.ts +95 -9
- package/dist/schemas-payments.d.ts +2 -2
- package/dist/schemas.d.ts +27 -7
- package/dist/skill-content.d.ts +8 -2
- package/dist/tool-DeOeMNlK.js +618 -0
- package/dist/tool.d.ts +8 -8
- package/dist/tools/discovery.d.ts +8 -2
- package/dist/tools/groups-admin.d.ts +25 -0
- package/dist/tools/groups-admission.d.ts +56 -0
- package/dist/tools/groups-list.d.ts +21 -0
- package/dist/tools/groups-resolve.d.ts +80 -0
- package/dist/tools/groups.d.ts +22 -9
- package/dist/tools/index.d.ts +6 -4
- package/dist/tools/index.js +3 -3
- package/dist/tools/messaging.d.ts +14 -12
- package/dist/tools-CQDZG-qN.js +1149 -0
- package/dist/transcript.d.ts +2 -2
- package/dist/types.d.ts +4 -1
- package/dist/webhook.d.ts +9 -2
- package/dist/webhook.js +34 -14
- package/dist/x402.d.ts +3 -3
- package/package.json +3 -3
- package/dist/scaffold-0luQyBRK.js +0 -146
- package/dist/tool-BC49DldZ.js +0 -259
- package/dist/tools-BcVm_Onx.js +0 -535
package/dist/transcript.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Token-budgeted, role-tagged transcript rendering for the Eve channel's
|
|
3
|
-
* push-injection
|
|
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
|
-
*
|
|
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, VoteResponseSchema } 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,9 @@ 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>;
|
|
23
|
+
export type VoteResponse = Infer<typeof VoteResponseSchema>;
|
|
21
24
|
export {};
|
package/dist/webhook.d.ts
CHANGED
|
@@ -5,13 +5,14 @@
|
|
|
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.
|
|
8
|
+
* down. The client is built lazily inside the call.
|
|
9
9
|
*/
|
|
10
10
|
/** Options shared by register/delete. */
|
|
11
11
|
export interface WebhookOptions {
|
|
12
12
|
/** Public base URL of the deployed Eve agent (e.g. `https://x.vercel.app`). */
|
|
13
13
|
baseUrl: string;
|
|
14
|
-
/** Acting agent handle
|
|
14
|
+
/** Acting agent name, handle or UUID; falls back to `RINE_AGENT`, then to
|
|
15
|
+
* the org's only agent. */
|
|
15
16
|
agent?: string;
|
|
16
17
|
apiUrl?: string;
|
|
17
18
|
configDir?: string;
|
|
@@ -27,6 +28,12 @@ export interface RegisteredWebhook {
|
|
|
27
28
|
/**
|
|
28
29
|
* Register a rine webhook pointing at the deployed agent's inbound route. Returns
|
|
29
30
|
* the webhook id + the HMAC secret (shown once) for `RINE_WEBHOOK_SECRET`.
|
|
31
|
+
*
|
|
32
|
+
* The whole acting-agent ladder runs here, because this is the one Eve
|
|
33
|
+
* entry point that must name a *specific* agent — the webhook is created against
|
|
34
|
+
* an agent id, not an org. So a bare name works, a single-agent org needs no
|
|
35
|
+
* `--agent` at all, and the refusal names the org's agents rather than asserting
|
|
36
|
+
* the caller forgot an env var they may well have set to the wrong thing.
|
|
30
37
|
*/
|
|
31
38
|
export declare function registerRineWebhook(opts: WebhookOptions): Promise<RegisteredWebhook>;
|
|
32
39
|
/** Delete a previously-registered webhook by id (best-effort teardown). */
|
package/dist/webhook.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as getRineClient, t as actingAgent } from "./client-CXJATA-m.js";
|
|
2
2
|
import { asAgentUuid, asWebhookUuid } from "@rine-network/sdk";
|
|
3
|
-
import { UUID_RE,
|
|
3
|
+
import { ACTOR_SURFACES, UUID_RE, normalizeActor, resolveAgent } from "@rine-network/core";
|
|
4
4
|
//#region src/webhook.ts
|
|
5
5
|
/**
|
|
6
6
|
* Prod inbound wiring — `npx @rine-network/eve webhook --url <publicBase>`.
|
|
@@ -9,33 +9,53 @@ 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.
|
|
12
|
+
* down. The client is built lazily inside the call.
|
|
13
13
|
*/
|
|
14
14
|
const DEFAULT_INBOUND_PATH = "/rine/v1/inbound";
|
|
15
|
+
/**
|
|
16
|
+
* How Eve spells the acting agent in a refusal.
|
|
17
|
+
*
|
|
18
|
+
* `ACTOR_SURFACES.ts` with the environment rung switched back on: the SDK
|
|
19
|
+
* itself reads no environment, but Eve is a *surface* and
|
|
20
|
+
* `actingAgent()` climbs to `RINE_AGENT` on its behalf — the scaffolder even
|
|
21
|
+
* writes the variable into every generated `.env.example`. A refusal that
|
|
22
|
+
* omitted it would hide the lever this deployment is configured with.
|
|
23
|
+
*/
|
|
24
|
+
const EVE_SURFACE = {
|
|
25
|
+
...ACTOR_SURFACES.ts,
|
|
26
|
+
readsEnv: true
|
|
27
|
+
};
|
|
15
28
|
function inboundUrl(opts) {
|
|
16
29
|
const path = opts.path ?? process.env.RINE_INBOUND_PATH ?? DEFAULT_INBOUND_PATH;
|
|
17
30
|
return `${opts.baseUrl.replace(/\/$/, "")}${path}`;
|
|
18
31
|
}
|
|
19
|
-
async function resolveAgentUuid(apiUrl, agent) {
|
|
20
|
-
if (UUID_RE.test(agent)) return asAgentUuid(agent);
|
|
21
|
-
return asAgentUuid(await resolveToUuid(apiUrl, agent));
|
|
22
|
-
}
|
|
23
32
|
/**
|
|
24
33
|
* Register a rine webhook pointing at the deployed agent's inbound route. Returns
|
|
25
34
|
* the webhook id + the HMAC secret (shown once) for `RINE_WEBHOOK_SECRET`.
|
|
35
|
+
*
|
|
36
|
+
* The whole acting-agent ladder runs here, because this is the one Eve
|
|
37
|
+
* entry point that must name a *specific* agent — the webhook is created against
|
|
38
|
+
* an agent id, not an org. So a bare name works, a single-agent org needs no
|
|
39
|
+
* `--agent` at all, and the refusal names the org's agents rather than asserting
|
|
40
|
+
* the caller forgot an env var they may well have set to the wrong thing.
|
|
26
41
|
*/
|
|
27
42
|
async function registerRineWebhook(opts) {
|
|
28
|
-
const agent = opts.agent ?? process.env.RINE_AGENT;
|
|
29
|
-
if (!agent) throw new Error("no acting agent — set RINE_AGENT or pass --agent <handle>");
|
|
30
|
-
const apiUrl = opts.apiUrl ?? resolveApiUrl();
|
|
31
43
|
const client = getRineClient({
|
|
32
|
-
agent,
|
|
33
44
|
apiUrl: opts.apiUrl,
|
|
34
45
|
configDir: opts.configDir
|
|
35
46
|
});
|
|
36
|
-
const
|
|
47
|
+
const orgAgents = async () => (await client.identity.listAgents()).map((a) => ({
|
|
48
|
+
...a,
|
|
49
|
+
verification_words: a.verification_words ?? void 0,
|
|
50
|
+
warnings: a.warnings ?? void 0,
|
|
51
|
+
poll_url: a.poll_url ?? void 0
|
|
52
|
+
}));
|
|
53
|
+
const named = actingAgent(opts);
|
|
54
|
+
const resolved = named !== void 0 && UUID_RE.test(named) ? { agentId: named } : await resolveAgent(await orgAgents(), named, void 0, EVE_SURFACE, normalizeActor(opts.agent) === void 0 ? "environment" : "argument");
|
|
55
|
+
if (resolved.warning !== void 0) console.warn(`rine: ${resolved.warning}`);
|
|
56
|
+
const agentUuid = asAgentUuid(resolved.agentId);
|
|
37
57
|
const url = inboundUrl(opts);
|
|
38
|
-
const created = await client.webhooks.create(agentUuid, url);
|
|
58
|
+
const created = await client.withAgent(agentUuid).webhooks.create(agentUuid, url);
|
|
39
59
|
return {
|
|
40
60
|
id: created.id,
|
|
41
61
|
secret: created.secret,
|
|
@@ -45,7 +65,7 @@ async function registerRineWebhook(opts) {
|
|
|
45
65
|
/** Delete a previously-registered webhook by id (best-effort teardown). */
|
|
46
66
|
async function deleteRineWebhook(id, opts = {}) {
|
|
47
67
|
await getRineClient({
|
|
48
|
-
agent: opts
|
|
68
|
+
agent: actingAgent(opts),
|
|
49
69
|
apiUrl: opts.apiUrl,
|
|
50
70
|
configDir: opts.configDir
|
|
51
71
|
}).webhooks.delete(asWebhookUuid(id));
|
package/dist/x402.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* x402 payment-aware inbound re-surfacing for the rine channel
|
|
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
|
-
*
|
|
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
|
|
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.
|
|
3
|
+
"version": "0.5.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.
|
|
52
|
-
"@rine-network/sdk": "^0.
|
|
51
|
+
"@rine-network/core": "^0.14.0",
|
|
52
|
+
"@rine-network/sdk": "^0.11.0",
|
|
53
53
|
"zod": "^3.25.0",
|
|
54
54
|
"zod-to-json-schema": "^3.24.1"
|
|
55
55
|
},
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { t as RINE_TOOL_META } from "./registry-6sWyhOyF.js";
|
|
2
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
//#region src/skill-content.ts
|
|
5
|
-
/**
|
|
6
|
-
* The rine skill text — plain constants with NO `eve` import, so the scaffolder
|
|
7
|
-
* and CLI can write `agent/skills/rine/SKILL.md` without resolving the `eve` peer
|
|
8
|
-
* dependency. `skill.ts` wraps {@link RINE_SKILL_BODY} in `defineSkill` for the
|
|
9
|
-
* TypeScript-skill path.
|
|
10
|
-
*/
|
|
11
|
-
const RINE_SKILL_DESCRIPTION = "Use when communicating with other AI agents over the rine network — sending or replying to agent-to-agent messages, discovering agents, or coordinating in groups.";
|
|
12
|
-
/** The skill body (no frontmatter) — used by `rineSkill()`'s `markdown`. */
|
|
13
|
-
const RINE_SKILL_BODY = `# rine — agent-to-agent messaging
|
|
14
|
-
|
|
15
|
-
rine is an end-to-end-encrypted messaging network for AI agents. Each agent has a
|
|
16
|
-
handle like \`name@org\`. You are reachable on rine: other agents message you and
|
|
17
|
-
your replies are encrypted and delivered back to them automatically.
|
|
18
|
-
|
|
19
|
-
## When messages arrive
|
|
20
|
-
|
|
21
|
-
Inbound rine messages are delivered to you as a normal turn. The context line tells
|
|
22
|
-
you who sent it and whether their signature verified. **Just answer** — your final
|
|
23
|
-
reply is encrypted and sent back to the sender in the same conversation. You do not
|
|
24
|
-
need to call a tool to reply to an inbound rine message.
|
|
25
|
-
|
|
26
|
-
Call \`rine_reply\` only when you want to reply to a *specific* earlier message by
|
|
27
|
-
its id; call \`rine_send\` to start a *new* conversation with another agent.
|
|
28
|
-
|
|
29
|
-
## Reaching other agents
|
|
30
|
-
|
|
31
|
-
- \`rine_discover\` — search the public directory by text/category/language to find
|
|
32
|
-
an agent's handle. Do this before messaging an agent you don't already know.
|
|
33
|
-
- \`rine_inspect\` — read an agent's full public profile (verification, oversight).
|
|
34
|
-
- \`rine_send\` — send a 1:1 message (\`name@org\` / UUID) or a group message
|
|
35
|
-
(\`#group@org\`). End-to-end encrypted; a real, irreversible network action.
|
|
36
|
-
- \`rine_send_and_wait\` — 1:1 only: send and block up to N seconds for a reply.
|
|
37
|
-
- \`rine_check_inbox\` / \`rine_read\` — pull or read mail by id (rarely needed, since
|
|
38
|
-
inbound is pushed to you as a turn).
|
|
39
|
-
- \`rine_thread\` — fetch the full decrypted transcript of a conversation by its id
|
|
40
|
-
(both sides, oldest→newest). Use to recover earlier context on demand.
|
|
41
|
-
|
|
42
|
-
## Groups
|
|
43
|
-
|
|
44
|
-
Groups are end-to-end encrypted (MLS / RFC 9420 by default, with forward secrecy).
|
|
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.
|
|
47
|
-
|
|
48
|
-
## Trust
|
|
49
|
-
|
|
50
|
-
Every inbound message is HPKE-decrypted and its sender signature is verified before
|
|
51
|
-
it reaches you; unverified mail is dropped by default. Treat the sender handle in the
|
|
52
|
-
context line as authenticated. Do not put secrets in messages you would not want the
|
|
53
|
-
recipient agent to read.
|
|
54
|
-
`;
|
|
55
|
-
/** The full SKILL.md file contents (frontmatter + body) the scaffolder writes. */
|
|
56
|
-
const RINE_SKILL_FILE = `---
|
|
57
|
-
description: ${RINE_SKILL_DESCRIPTION}
|
|
58
|
-
---
|
|
59
|
-
|
|
60
|
-
${RINE_SKILL_BODY}`;
|
|
61
|
-
//#endregion
|
|
62
|
-
//#region src/scaffold.ts
|
|
63
|
-
/**
|
|
64
|
-
* `init` scaffolding — writes the thin `agent/` files that wire rine into an Eve
|
|
65
|
-
* project: the one-line channel re-export, one re-export file per selected tool
|
|
66
|
-
* (Eve discovers tools by filename, so the slug IS the tool name), the skill
|
|
67
|
-
* markdown, and a `.env.example` block. Pure content builders are exported for
|
|
68
|
-
* tests; {@link scaffoldRine} does the filesystem writes.
|
|
69
|
-
*/
|
|
70
|
-
const ENV_MARKER = "# rine — @rine-network/eve";
|
|
71
|
-
const DEFAULT_INBOUND_PATH = "/rine/v1/inbound";
|
|
72
|
-
/** The default-export channel file (`agent/channels/rine.ts`). */
|
|
73
|
-
function channelFileContent() {
|
|
74
|
-
return `import { rineChannel } from "@rine-network/eve/channel";\n\n// Inbound rine messages start/resume a session here; replies flow back over rine.\n// Identity comes from env: RINE_CONFIG_DIR, RINE_AGENT, RINE_WEBHOOK_SECRET.\nexport default rineChannel();\n`;
|
|
75
|
-
}
|
|
76
|
-
/** A single tool's re-export file (`agent/tools/<name>.ts`). */
|
|
77
|
-
function toolFileContent(spec) {
|
|
78
|
-
return `import { ${spec.factoryName} } from "@rine-network/eve/tools";\n\nexport default ${spec.factoryName}();\n`;
|
|
79
|
-
}
|
|
80
|
-
/** The `.env.example` block (with the inbound path applied). */
|
|
81
|
-
function envExampleBlock(path) {
|
|
82
|
-
return `${ENV_MARKER}
|
|
83
|
-
RINE_CONFIG_DIR=
|
|
84
|
-
RINE_AGENT=
|
|
85
|
-
# RINE_API_URL=https://rine.network
|
|
86
|
-
RINE_WEBHOOK_SECRET=
|
|
87
|
-
# RINE_WEBHOOK_ID=
|
|
88
|
-
# RINE_INBOUND_PATH=${path}
|
|
89
|
-
# x402 payments (optional). RINE_X402_AUTO_PAY=1 auto-pays quotes at/below your
|
|
90
|
-
# policy's autoPayThreshold with no LLM turn (default OFF). RINE_FACILITATOR is the
|
|
91
|
-
# rine_fulfill facilitator — a preset name (cdp/payai/x402-rs) or a base URL.
|
|
92
|
-
# RINE_X402_AUTO_PAY=
|
|
93
|
-
# RINE_FACILITATOR=
|
|
94
|
-
`;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Resolve a `--tools` selection to the ordered tool specs. Accepts `"all"`,
|
|
98
|
-
* `"none"`, or a comma-separated list of tool names (`rine_send`) and/or domains
|
|
99
|
-
* (`messaging`/`discovery`/`groups`). Unknown tokens throw.
|
|
100
|
-
*/
|
|
101
|
-
function resolveToolSelection(value) {
|
|
102
|
-
const v = (value ?? "all").trim();
|
|
103
|
-
if (v === "none") return [];
|
|
104
|
-
if (v === "all") return [...RINE_TOOL_META];
|
|
105
|
-
const tokens = v.split(",").map((t) => t.trim()).filter(Boolean);
|
|
106
|
-
const out = [];
|
|
107
|
-
for (const spec of RINE_TOOL_META) if (tokens.includes(spec.name) || tokens.includes(spec.domain)) out.push(spec);
|
|
108
|
-
const matchedDomains = new Set(RINE_TOOL_META.map((s) => s.domain));
|
|
109
|
-
const matchedNames = new Set(RINE_TOOL_META.map((s) => s.name));
|
|
110
|
-
for (const tok of tokens) if (!matchedDomains.has(tok) && !matchedNames.has(tok)) throw new Error(`unknown tool/domain '${tok}' (valid: all, none, messaging, discovery, groups, or a rine_* tool name)`);
|
|
111
|
-
return out;
|
|
112
|
-
}
|
|
113
|
-
/** Write `content` to `file`, honoring `force`; record into the result. */
|
|
114
|
-
function writeFile(file, content, force, res) {
|
|
115
|
-
if (existsSync(file) && !force) {
|
|
116
|
-
res.skipped.push(file);
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
mkdirSync(dirname(file), { recursive: true });
|
|
120
|
-
writeFileSync(file, content, "utf-8");
|
|
121
|
-
res.written.push(file);
|
|
122
|
-
}
|
|
123
|
-
/** Scaffold the rine channel, tools, skill, and `.env.example` block. */
|
|
124
|
-
function scaffoldRine(opts = {}) {
|
|
125
|
-
const cwd = opts.cwd ?? process.cwd();
|
|
126
|
-
const agentDir = join(cwd, opts.dir ?? "agent");
|
|
127
|
-
const path = opts.path ?? DEFAULT_INBOUND_PATH;
|
|
128
|
-
const res = {
|
|
129
|
-
written: [],
|
|
130
|
-
skipped: []
|
|
131
|
-
};
|
|
132
|
-
const force = opts.force ?? false;
|
|
133
|
-
if (opts.channel ?? true) writeFile(join(agentDir, "channels", "rine.ts"), channelFileContent(), force, res);
|
|
134
|
-
for (const spec of resolveToolSelection(opts.tools)) writeFile(join(agentDir, "tools", `${spec.name}.ts`), toolFileContent(spec), force, res);
|
|
135
|
-
writeFile(join(agentDir, "skills", "rine", "SKILL.md"), RINE_SKILL_FILE, force, res);
|
|
136
|
-
const envFile = join(cwd, ".env.example");
|
|
137
|
-
const block = envExampleBlock(path);
|
|
138
|
-
const existing = existsSync(envFile) ? readFileSync(envFile, "utf-8") : "";
|
|
139
|
-
if (!existing.includes(ENV_MARKER)) {
|
|
140
|
-
writeFileSync(envFile, existing.length > 0 ? `${existing.trimEnd()}\n\n${block}` : block, "utf-8");
|
|
141
|
-
res.written.push(envFile);
|
|
142
|
-
} else res.skipped.push(envFile);
|
|
143
|
-
return res;
|
|
144
|
-
}
|
|
145
|
-
//#endregion
|
|
146
|
-
export { toolFileContent as a, RINE_SKILL_FILE as c, scaffoldRine as i, envExampleBlock as n, RINE_SKILL_BODY as o, resolveToolSelection as r, RINE_SKILL_DESCRIPTION as s, channelFileContent as t };
|
package/dist/tool-BC49DldZ.js
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
import { t as getRineClient } from "./client-X_-9CpQT.js";
|
|
2
|
-
import { APIConnectionError, AuthenticationError, AuthorizationError, ConfigError, CryptoError, NotFoundError, RateLimitError, RineApiError, RineTimeoutError, SchemaValidationError, ValidationError } from "@rine-network/sdk";
|
|
3
|
-
import { resolveApiUrl } from "@rine-network/core";
|
|
4
|
-
import { always, never, once } from "eve/tools/approval";
|
|
5
|
-
import { ZodError } from "zod";
|
|
6
|
-
//#region src/format.ts
|
|
7
|
-
/** One thread turn as a role-tagged line: `[sent] you: …` / `[received] alice@org: …`. */
|
|
8
|
-
function renderThreadLine(e) {
|
|
9
|
-
const who = e.direction === "sent" ? "you" : e.senderHandle ?? "unknown";
|
|
10
|
-
return `[${e.direction}] ${who}: ${e.text}`;
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Render a both-sided transcript (oldest→newest) for `rine_thread`. Each turn is
|
|
14
|
-
* a role-tagged line; `[unavailable]` text passes through unchanged.
|
|
15
|
-
*/
|
|
16
|
-
function renderThread(entries) {
|
|
17
|
-
if (entries.length === 0) return "No messages in this conversation.";
|
|
18
|
-
return entries.map(renderThreadLine).join("\n");
|
|
19
|
-
}
|
|
20
|
-
/** Honest signature note — never claims "verified" for an unverifiable message. */
|
|
21
|
-
function verifiedNote(msg) {
|
|
22
|
-
return msg.verified ? "signature verified" : `signature ${msg.verification_status}`;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* THE PLAINTEXT-IS-JSON FOOTGUN. Outbound sends wrap `{ text: body }`, and the
|
|
26
|
-
* SDK auto-`JSON.parse`s inbound `application/json` plaintext into a structured
|
|
27
|
-
* value. Unwrap defensively so the model sees prose, never raw JSON:
|
|
28
|
-
* - a string → returned as-is
|
|
29
|
-
* - `{ text: "…" }` → the inner text
|
|
30
|
-
* - anything else → compact JSON (last resort)
|
|
31
|
-
*/
|
|
32
|
-
function unwrapText(plaintext) {
|
|
33
|
-
if (typeof plaintext === "string") return plaintext;
|
|
34
|
-
if (plaintext === null || plaintext === void 0) return "";
|
|
35
|
-
if (typeof plaintext === "object") {
|
|
36
|
-
const text = plaintext.text;
|
|
37
|
-
if (typeof text === "string") return text;
|
|
38
|
-
}
|
|
39
|
-
try {
|
|
40
|
-
return JSON.stringify(plaintext);
|
|
41
|
-
} catch {
|
|
42
|
-
return String(plaintext);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
/** Body of a message: decrypt error if unreadable, else the unwrapped plaintext. */
|
|
46
|
-
function renderMessageBody(msg) {
|
|
47
|
-
if (msg.decrypt_error) return `[unreadable] ${msg.decrypt_error}`;
|
|
48
|
-
return unwrapText(msg.plaintext);
|
|
49
|
-
}
|
|
50
|
-
/** Sender label: prefer the human handle, fall back to the agent UUID. */
|
|
51
|
-
function senderLabel(msg) {
|
|
52
|
-
return msg.sender_handle ?? msg.from_agent_id ?? "unknown sender";
|
|
53
|
-
}
|
|
54
|
-
/** A single message rendered across multiple labeled lines (for `rine_read`). */
|
|
55
|
-
function renderSingleMessage(msg) {
|
|
56
|
-
const lines = [
|
|
57
|
-
`Message ${msg.id}`,
|
|
58
|
-
`from: ${senderLabel(msg)}`,
|
|
59
|
-
`type: ${msg.type}`
|
|
60
|
-
];
|
|
61
|
-
if (msg.group_handle ?? msg.group_id) lines.push(`group: ${msg.group_handle ?? msg.group_id}`);
|
|
62
|
-
lines.push(`body: ${renderMessageBody(msg)}`);
|
|
63
|
-
lines.push(`(${verifiedNote(msg)})`);
|
|
64
|
-
return lines.join("\n");
|
|
65
|
-
}
|
|
66
|
-
/** One inbox row: compact single line keyed by id + sender + body preview. */
|
|
67
|
-
function renderInboxRow(msg) {
|
|
68
|
-
const from = senderLabel(msg);
|
|
69
|
-
const where = msg.group_handle ? ` in ${msg.group_handle}` : "";
|
|
70
|
-
return `${msg.id} from ${from}${where}: ${renderMessageBody(msg)} (${verifiedNote(msg)})`;
|
|
71
|
-
}
|
|
72
|
-
/** A numbered inbox list, or the empty-state line. */
|
|
73
|
-
function renderInbox(items) {
|
|
74
|
-
if (items.length === 0) return "No new messages.";
|
|
75
|
-
return items.map((msg, i) => `${i + 1}. ${renderInboxRow(msg)}`).join("\n");
|
|
76
|
-
}
|
|
77
|
-
/** One discovery row. */
|
|
78
|
-
function renderAgentSummary(a) {
|
|
79
|
-
const verified = a.verified ? " [verified]" : "";
|
|
80
|
-
const desc = a.description ? ` — ${a.description}` : "";
|
|
81
|
-
const cat = a.category ? ` (${a.category})` : "";
|
|
82
|
-
return `${a.handle}${verified}${cat}${desc}`;
|
|
83
|
-
}
|
|
84
|
-
/** A numbered discovery list, or the empty-state line. */
|
|
85
|
-
function renderDiscover(items) {
|
|
86
|
-
if (items.length === 0) return "No agents matched.";
|
|
87
|
-
return items.map((a, i) => `${i + 1}. ${renderAgentSummary(a)}`).join("\n");
|
|
88
|
-
}
|
|
89
|
-
/** A full agent profile (for `rine_inspect`). */
|
|
90
|
-
function renderProfile(p) {
|
|
91
|
-
const lines = [
|
|
92
|
-
`${p.name} (${p.handle})`,
|
|
93
|
-
`id: ${p.id}`,
|
|
94
|
-
`verified: ${p.verified ? "yes" : "no"}`,
|
|
95
|
-
`human oversight: ${p.human_oversight ? "yes" : "no"}`
|
|
96
|
-
];
|
|
97
|
-
if (p.category) lines.push(`category: ${p.category}`);
|
|
98
|
-
if (p.description) lines.push(`description: ${p.description}`);
|
|
99
|
-
return lines.join("\n");
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Self-diagnose a group's E2EE mode. Uses `mls_group_id !== null`, OR the
|
|
103
|
-
* explicit `mls_enabled`/`mls_pending` flags. With MLS support present this is a
|
|
104
|
-
* CAPABILITY flag, not a failure flag (R9).
|
|
105
|
-
*/
|
|
106
|
-
function groupIsMls(g) {
|
|
107
|
-
return Boolean(g.mls_enabled || g.mls_group_id !== null || g.mls_pending);
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
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).
|
|
112
|
-
*/
|
|
113
|
-
function renderGroup(g) {
|
|
114
|
-
const lines = [`Group ${g.handle} (id ${g.id})`];
|
|
115
|
-
if (groupIsMls(g)) {
|
|
116
|
-
lines.push("[OK] MLS group — end-to-end encrypted (RFC 9420), readable/postable from here.");
|
|
117
|
-
if (g.mls_group_id) lines.push(`mls_group_id: ${g.mls_group_id}`);
|
|
118
|
-
} else lines.push("[OK] sender-key group — readable/postable from here.");
|
|
119
|
-
lines.push(`enrollment: ${g.enrollment_policy}`);
|
|
120
|
-
lines.push(`visibility: ${g.visibility}`);
|
|
121
|
-
return lines.join("\n");
|
|
122
|
-
}
|
|
123
|
-
//#endregion
|
|
124
|
-
//#region src/errors.ts
|
|
125
|
-
/**
|
|
126
|
-
* `formatError(err)` — invariant R2: turn any thrown SDK error into a readable
|
|
127
|
-
* string for the LLM, never a stack trace. Tools wrap their one `await client.*`
|
|
128
|
-
* call in `try/catch → formatError` and RESOLVE (never reject) for mapped errors.
|
|
129
|
-
*
|
|
130
|
-
* Ordering matters: the TS SDK error classes form a hierarchy rooted at
|
|
131
|
-
* `RineApiError`, so this maps MOST-SPECIFIC FIRST and lets `RineApiError` be the
|
|
132
|
-
* catch-all for API errors.
|
|
133
|
-
*/
|
|
134
|
-
/** The synchronous message thrown by `sendAndWait` for a `#` group handle. */
|
|
135
|
-
const GROUP_ON_WAIT_PREFIX = "sendAndWait() does not support group handles";
|
|
136
|
-
/**
|
|
137
|
-
* True when `err` is the plain `Error` `sendAndWait` throws for a group handle.
|
|
138
|
-
* The `send_and_wait` tool checks this BEFORE `formatError` and returns the
|
|
139
|
-
* "1:1 only" guidance; it is not a typed SDK error class.
|
|
140
|
-
*/
|
|
141
|
-
function isGroupUnsupportedOnWait(err) {
|
|
142
|
-
return err instanceof Error && err.message.startsWith(GROUP_ON_WAIT_PREFIX);
|
|
143
|
-
}
|
|
144
|
-
/** The fixed reply for the group-on-`sendAndWait` case. */
|
|
145
|
-
const GROUP_ON_WAIT_MESSAGE = "rine_send_and_wait is 1:1 only; use rine_send for groups.";
|
|
146
|
-
function formatError(err) {
|
|
147
|
-
if (err instanceof ZodError) {
|
|
148
|
-
const first = err.issues[0];
|
|
149
|
-
return `Invalid input: ${first?.path.length ? first.path.join(".") : "input"} — ${first?.message ?? "validation failed"}.`;
|
|
150
|
-
}
|
|
151
|
-
if (err instanceof AuthenticationError) return "rine auth failed — onboard with `npx @rine-network/eve onboard` or set RINE_CONFIG_DIR to your credentials directory.";
|
|
152
|
-
if (err instanceof AuthorizationError) return `Not authorized: ${err.detail}.`;
|
|
153
|
-
if (err instanceof NotFoundError) return `Not found: ${err.detail}. Try rine_discover to find the right handle.`;
|
|
154
|
-
if (err instanceof RateLimitError) return `Rate-limited; retry after ${err.retryAfter ?? "a few"}s.`;
|
|
155
|
-
if (err instanceof ValidationError) return `Invalid input: ${err.detail}.`;
|
|
156
|
-
if (err instanceof SchemaValidationError) return `Invalid input: ${err.message}.`;
|
|
157
|
-
if (err instanceof RineTimeoutError) return "Request timed out; try again or raise the timeout.";
|
|
158
|
-
if (err instanceof ConfigError) return String(err.message);
|
|
159
|
-
if (err instanceof CryptoError) return `Encryption error: ${err.message} (check your agent keys are on disk).`;
|
|
160
|
-
if (err instanceof APIConnectionError) return `Could not reach rine: ${err.message}.`;
|
|
161
|
-
if (err instanceof RineApiError) return `${err.status}: ${err.detail}`;
|
|
162
|
-
return String(messageOf(err));
|
|
163
|
-
}
|
|
164
|
-
function messageOf(err) {
|
|
165
|
-
if (err instanceof Error) return err.message;
|
|
166
|
-
return String(err ?? "unknown error");
|
|
167
|
-
}
|
|
168
|
-
//#endregion
|
|
169
|
-
//#region src/tool.ts
|
|
170
|
-
/**
|
|
171
|
-
* 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).
|
|
174
|
-
*
|
|
175
|
-
* Unlike the Mastra integration (which threads identity through a `RequestContext`),
|
|
176
|
-
* Eve tools run in the app runtime with full `process.env` access, so identity is
|
|
177
|
-
* resolved straight from the environment via `getRineClient` — no per-call context
|
|
178
|
-
* plumbing, no credentials in the model-visible input schema.
|
|
179
|
-
*
|
|
180
|
-
* A tool's per-tool body is just `(client, input, apiUrl) => string`; this helper
|
|
181
|
-
* supplies the surrounding contract. The concrete `defineTool({...})` (with the
|
|
182
|
-
* model-facing description + schemas) lives in each domain module; this file only
|
|
183
|
-
* builds the `execute` closure and the shared option/body types.
|
|
184
|
-
*/
|
|
185
|
-
/**
|
|
186
|
-
* Resolve {@link RineToolOpts.needsApproval} to an Eve `needsApproval` callback,
|
|
187
|
-
* or `undefined` (no gate) when unset. Only the mutating tool factories apply it.
|
|
188
|
-
*/
|
|
189
|
-
function approvalGate(opts) {
|
|
190
|
-
switch (opts.needsApproval) {
|
|
191
|
-
case "always": return always();
|
|
192
|
-
case "once": return once();
|
|
193
|
-
case "never": return never();
|
|
194
|
-
default: return;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
/** The acting agent for a tool: factory override → `RINE_AGENT` env → none. */
|
|
198
|
-
function resolveAgent(opts) {
|
|
199
|
-
return opts.agent ?? process.env.RINE_AGENT ?? void 0;
|
|
200
|
-
}
|
|
201
|
-
/** Resolve the effective `AsyncRineClient` for one `execute` call (lazy, R1). */
|
|
202
|
-
function resolveClient(opts) {
|
|
203
|
-
if (opts.client) {
|
|
204
|
-
const agent = resolveAgent(opts);
|
|
205
|
-
return agent ? opts.client.withAgent(agent) : opts.client;
|
|
206
|
-
}
|
|
207
|
-
return getRineClient({
|
|
208
|
-
configDir: opts.configDir,
|
|
209
|
-
apiUrl: opts.apiUrl,
|
|
210
|
-
agent: resolveAgent(opts)
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* The same resolved `apiUrl` the client is built against (factory override →
|
|
215
|
-
* `RINE_API_URL` env → `resolveApiUrl()`). Exposed so handle→UUID pre-resolution
|
|
216
|
-
* hits the SAME server WebFinger the client uses.
|
|
217
|
-
*/
|
|
218
|
-
function resolveApiUrlFor(opts) {
|
|
219
|
-
return opts.apiUrl ?? resolveApiUrl();
|
|
220
|
-
}
|
|
221
|
-
/** Brand a model-supplied recipient string for the SDK send surface. */
|
|
222
|
-
function asRecipient(to) {
|
|
223
|
-
return to;
|
|
224
|
-
}
|
|
225
|
-
/**
|
|
226
|
-
* Belt-and-suspenders ciphertext redactor for `read` / `check_inbox` (R4).
|
|
227
|
-
* The renderers + `outputSchema: z.string()` already guarantee the `execute`
|
|
228
|
-
* return is redacted text; this coerces ANY value to plain text before it can
|
|
229
|
-
* reach the model, in Eve's `ToolModelOutput` shape.
|
|
230
|
-
*/
|
|
231
|
-
function redactToText(output) {
|
|
232
|
-
return {
|
|
233
|
-
type: "text",
|
|
234
|
-
value: typeof output === "string" ? output : ""
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Build an Eve-tool `execute(input, ctx)` from a zod schema + body, applying:
|
|
239
|
-
* 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).
|
|
242
|
-
*
|
|
243
|
-
* Eve hands `execute` the raw model input as `Record<string, unknown>`; we own the
|
|
244
|
-
* parse because Eve receives a JSON Schema (not the zod schema) and may not apply
|
|
245
|
-
* zod defaults. The Eve `ToolContext` is intentionally ignored — rine identity is
|
|
246
|
-
* environment-resolved (R3), not session-scoped.
|
|
247
|
-
*/
|
|
248
|
-
function makeExecute(schema, opts, body) {
|
|
249
|
-
return async (raw) => {
|
|
250
|
-
try {
|
|
251
|
-
const input = schema.parse(raw);
|
|
252
|
-
return await body(resolveClient(opts), input, resolveApiUrlFor(opts));
|
|
253
|
-
} catch (err) {
|
|
254
|
-
return formatError(err);
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
}
|
|
258
|
-
//#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 };
|