@rine-network/eve 0.1.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 +25 -1
- package/dist/_zod.d.ts +1 -1
- package/dist/{channel-Bg8l58gg.js → channel-WlN3x1wP.js} +185 -29
- package/dist/channel-core.d.ts +15 -34
- package/dist/channel-outbound.d.ts +36 -0
- package/dist/channel.d.ts +26 -3
- package/dist/channel.js +2 -2
- package/dist/{client-X_-9CpQT.js → client-DsG2xtKs.js} +2 -2
- package/dist/client.d.ts +2 -2
- package/dist/errors.d.ts +1 -1
- package/dist/format.d.ts +8 -4
- package/dist/inbound.d.ts +22 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.js +7 -7
- package/dist/onboard.d.ts +1 -1
- package/dist/onboard.js +1 -1
- package/dist/{registry-BG7S2XJg.js → registry-Bn4EqPcp.js} +22 -1
- package/dist/relay.d.ts +1 -1
- package/dist/relay.js +2 -2
- package/dist/{scaffold-Dpac1TMU.js → scaffold-3cEUy3jD.js} +8 -2
- package/dist/scaffold.js +1 -1
- package/dist/schemas-groups.d.ts +15 -3
- package/dist/schemas-payments.d.ts +34 -0
- package/dist/schemas.d.ts +3 -2
- package/dist/skill-content.d.ts +2 -2
- package/dist/{tool-BC49DldZ.js → tool-xlLdY8kn.js} +29 -12
- package/dist/tool.d.ts +16 -7
- package/dist/tools/groups.d.ts +11 -2
- package/dist/tools/index.d.ts +3 -2
- package/dist/tools/index.js +3 -3
- package/dist/tools/messaging.d.ts +1 -1
- package/dist/tools/payments.d.ts +21 -0
- package/dist/tools/registry.d.ts +3 -2
- package/dist/{tools-Bm9N6tB5.js → tools-BhkhV3Mv.js} +237 -11
- package/dist/transcript.d.ts +2 -2
- package/dist/types.d.ts +3 -1
- package/dist/webhook.d.ts +1 -1
- package/dist/webhook.js +2 -2
- package/dist/x402.d.ts +38 -0
- package/package.json +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as GROUP_ON_WAIT_MESSAGE, c as groupIsMls, d as renderInbox, f as
|
|
2
|
-
import { t as RINE_TOOL_META } from "./registry-
|
|
3
|
-
import { NotFoundError, asAgentUuid, asGroupUuid, asMessageUuid } from "@rine-network/sdk";
|
|
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
|
+
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";
|
|
6
6
|
import { defineTool } from "eve/tools";
|
|
@@ -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
|
|
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
|
|
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,6 +47,31 @@ 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({});
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region src/schemas-payments.ts
|
|
58
|
+
/**
|
|
59
|
+
* Zod input schemas for the 2 x402 payment tools (split out of `schemas.ts` to
|
|
60
|
+
* hold the ~200-LOC budget — one file per domain). Same authoring rules: rich
|
|
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 —
|
|
63
|
+
* never a model-visible input.
|
|
64
|
+
*/
|
|
65
|
+
const payInput = z.object({
|
|
66
|
+
messageId: z.string().describe("The UUID of the received `rine.v1.x402_payment_required` quote to pay. The signed payment is sent back in the same conversation."),
|
|
67
|
+
autoPay: z.boolean().default(false).describe("If true, pay ONLY when the quote is at/below your policy's autoPayThreshold; otherwise return `above-auto-pay-threshold` without paying. Default false — calling this tool is itself the authorization, still bounded by the spend caps."),
|
|
68
|
+
emitMarker: z.boolean().default(true).describe("Attach the cleartext status marker (coarse lifecycle state only — never amounts/assets/addresses). Default true; set false for a fully-sealed payment."),
|
|
69
|
+
allowRepay: z.boolean().default(false).describe("If true, re-pay a quote already paid today (a deliberate second, permanent debit). Default false — a repeat pay of the same messageId returns `already-paid` without spending.")
|
|
70
|
+
});
|
|
71
|
+
const fulfillInput = z.object({
|
|
72
|
+
messageId: z.string().describe("The UUID of the received `rine.v1.x402_payment` (signed authorization) to fulfill. Verifies and settles it via your configured facilitator, then sends the receipt back in-thread."),
|
|
73
|
+
emitMarker: z.boolean().default(true).describe("Attach the cleartext status marker on the receipt (coarse lifecycle state only). Default true.")
|
|
74
|
+
});
|
|
50
75
|
//#endregion
|
|
51
76
|
//#region src/schemas.ts
|
|
52
77
|
/**
|
|
@@ -54,7 +79,7 @@ const groupInspectInput = z.object({ group: z.string().describe("The group to in
|
|
|
54
79
|
*
|
|
55
80
|
* Rich `.describe()` on EVERY field: the field descriptions are the #1 lever on
|
|
56
81
|
* tool-call accuracy (the AI-DX). Identity/credentials NEVER appear here — the
|
|
57
|
-
* acting agent + config dir come from `process.env
|
|
82
|
+
* acting agent + config dir come from `process.env`, never the model-visible
|
|
58
83
|
* input schema.
|
|
59
84
|
*/
|
|
60
85
|
const DEFAULT_MESSAGE_TYPE = "rine.v1.task_request";
|
|
@@ -127,14 +152,19 @@ function rineInspectTool(opts = {}) {
|
|
|
127
152
|
//#endregion
|
|
128
153
|
//#region src/tools/groups.ts
|
|
129
154
|
/**
|
|
130
|
-
* The
|
|
131
|
-
* `rine_group_remove`, `rine_group_inspect
|
|
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.
|
|
132
158
|
*
|
|
133
159
|
* The TS SDK's `groups.invite`/`removeMember` take BRANDED UUIDs positionally, so
|
|
134
160
|
* invite/remove/inspect PRE-RESOLVE handle→UUID here:
|
|
135
161
|
* - a group → `groups.list()` + local match (`findGroup`),
|
|
136
162
|
* - an agent → `resolveToUuid` (WebFinger) → its UUID (or pass a UUID through),
|
|
137
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).
|
|
138
168
|
*/
|
|
139
169
|
/** True for a bare UUID string (no `@`, matches the rine UUID shape). */
|
|
140
170
|
function isUuid(s) {
|
|
@@ -166,6 +196,28 @@ async function resolveAgentUuid(apiUrl, target) {
|
|
|
166
196
|
if (isUuid(target)) return asAgentUuid(target);
|
|
167
197
|
return asAgentUuid(await resolveToUuid(apiUrl, target));
|
|
168
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
|
+
}
|
|
169
221
|
/** `rine_group_create` — create an MLS-by-default coordination group. */
|
|
170
222
|
function rineGroupCreateTool(opts = {}) {
|
|
171
223
|
return defineTool({
|
|
@@ -228,6 +280,31 @@ function rineGroupInspectTool(opts = {}) {
|
|
|
228
280
|
})
|
|
229
281
|
});
|
|
230
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
|
+
}
|
|
231
308
|
//#endregion
|
|
232
309
|
//#region src/tools/messaging.ts
|
|
233
310
|
/**
|
|
@@ -237,7 +314,7 @@ function rineGroupInspectTool(opts = {}) {
|
|
|
237
314
|
* `makeExecute` (lazy env client + formatError). The runtime tool NAME comes from
|
|
238
315
|
* the filename slug of the scaffolded `agent/tools/<name>.ts`, not from here.
|
|
239
316
|
*
|
|
240
|
-
*
|
|
317
|
+
* Renderers read only plaintext/decrypt_error/verification,
|
|
241
318
|
* never the ciphertext envelope. `read`/`check_inbox` add a `toModelOutput`
|
|
242
319
|
* redactor as defence-in-depth.
|
|
243
320
|
*/
|
|
@@ -345,6 +422,151 @@ function rineReplyTool(opts = {}) {
|
|
|
345
422
|
});
|
|
346
423
|
}
|
|
347
424
|
//#endregion
|
|
425
|
+
//#region src/tools/payments.ts
|
|
426
|
+
/**
|
|
427
|
+
* The 2 x402 payment tool factories: `rine_pay` (payer) and `rine_fulfill`
|
|
428
|
+
* (payee). Thin adapters over the ts-sdk `client.payments` facade — signing,
|
|
429
|
+
* spend policy, journal, and facilitator verify/settle all live in rine-core; the
|
|
430
|
+
* wallet key is never surfaced. Each returns an Eve `defineTool` descriptor whose
|
|
431
|
+
* `execute` resolves to a TYPED STATUS STRING (never a reject for an expected
|
|
432
|
+
* refusal), so the agent reasons over the outcome.
|
|
433
|
+
*
|
|
434
|
+
* `rine_pay` reuses the shipped `rine_pay` MCP status vocabulary VERBATIM:
|
|
435
|
+
* `payment-submitted` / `no-wallet` / `not-payment-required` / `policy-refused` /
|
|
436
|
+
* `above-auto-pay-threshold` / `already-paid` / `wallet-busy`. `rine_fulfill`
|
|
437
|
+
* reports the PINNED payee vocabulary (`settled` / `settlement-failed` /
|
|
438
|
+
* `verification-failed` / `facilitator-error` / `no-facilitator` / `not-payment`),
|
|
439
|
+
* identical across every surface (CLI/MCP/eve/mastra), with the facilitator's
|
|
440
|
+
* network slug stored VERBATIM (never CAIP-2 string-matched).
|
|
441
|
+
*/
|
|
442
|
+
/** The `rine_pay` terminal statuses, reused verbatim from the MCP payer tool. */
|
|
443
|
+
const PAY_STATUS = {
|
|
444
|
+
SUBMITTED: "payment-submitted",
|
|
445
|
+
NO_WALLET: "no-wallet",
|
|
446
|
+
NOT_PAYMENT_REQUIRED: "not-payment-required",
|
|
447
|
+
POLICY_REFUSED: "policy-refused",
|
|
448
|
+
ABOVE_AUTO_PAY_THRESHOLD: "above-auto-pay-threshold",
|
|
449
|
+
ALREADY_PAID: "already-paid",
|
|
450
|
+
WALLET_BUSY: "wallet-busy"
|
|
451
|
+
};
|
|
452
|
+
/**
|
|
453
|
+
* The `rine_fulfill` payee statuses — PINNED across every surface (CLI/MCP/eve/
|
|
454
|
+
* mastra) so an LLM or operator script parses one vocabulary everywhere. Mirrors
|
|
455
|
+
* the MCP `rine_fulfill` reference set; eve emits the subset it can reach (the
|
|
456
|
+
* ts-sdk `fulfill` facade owns decryption, so `no-keys` never surfaces here).
|
|
457
|
+
*/
|
|
458
|
+
const FULFILL_STATUS = {
|
|
459
|
+
SETTLED: "settled",
|
|
460
|
+
SETTLEMENT_FAILED: "settlement-failed",
|
|
461
|
+
VERIFICATION_FAILED: "verification-failed",
|
|
462
|
+
FACILITATOR_ERROR: "facilitator-error",
|
|
463
|
+
NO_FACILITATOR: "no-facilitator",
|
|
464
|
+
NOT_PAYMENT: "not-payment"
|
|
465
|
+
};
|
|
466
|
+
/** `<status> — <detail>`: the stable, parseable typed-status line. */
|
|
467
|
+
function status(word, detail) {
|
|
468
|
+
return `${word} — ${detail}`;
|
|
469
|
+
}
|
|
470
|
+
/** Atomic-unit amount of a requirement (x402 V2 `amount`, else V1 spelling). */
|
|
471
|
+
function requirementSummary(r) {
|
|
472
|
+
return `${r.amount ?? r.maxAmountRequired ?? "?"} of ${r.asset} on ${r.network} → ${r.payTo}`;
|
|
473
|
+
}
|
|
474
|
+
/** Map an x402 pay refusal to its typed status line (parity with MCP rine_pay). */
|
|
475
|
+
function mapPayError(err, autoPay) {
|
|
476
|
+
if (err instanceof X402Error) switch (err.code) {
|
|
477
|
+
case X402_ERROR.ALREADY_PAID: return status(PAY_STATUS.ALREADY_PAID, `${err.message}. Pass allowRepay to pay it again.`);
|
|
478
|
+
case X402_ERROR.WALLET_BUSY: return status(PAY_STATUS.WALLET_BUSY, err.message);
|
|
479
|
+
case X402_ERROR.PER_TX_CAP_EXCEEDED:
|
|
480
|
+
if (autoPay) return status(PAY_STATUS.ABOVE_AUTO_PAY_THRESHOLD, `${err.message}. Re-run without autoPay to authorize explicitly.`);
|
|
481
|
+
return status(PAY_STATUS.POLICY_REFUSED, err.message);
|
|
482
|
+
default: return status(PAY_STATUS.POLICY_REFUSED, err.message);
|
|
483
|
+
}
|
|
484
|
+
throw err;
|
|
485
|
+
}
|
|
486
|
+
/** `rine_pay` — pay a received x402 quote in-thread (payer). */
|
|
487
|
+
function rinePayTool(opts = {}) {
|
|
488
|
+
return defineTool({
|
|
489
|
+
description: "Pay a received x402 payment request (rine.v1.x402_payment_required) in-thread. Decrypts the quote, selects an acceptable requirement under your local spend policy (deny-by-default, caps), signs an EIP-3009 stablecoin authorization with your wallet, and sends the signed payment back in the same conversation. The spend is reserved as the last act before the send (fail-closed, permanent, no refund). Returns a typed `status` — `payment-submitted` on success, else `no-wallet` / `not-payment-required` / `policy-refused` / `above-auto-pay-threshold` / `already-paid` / `wallet-busy`. Does NOT wait for settlement; the receipt arrives later as an ordinary inbox message.",
|
|
490
|
+
inputSchema: jsonSchema(payInput),
|
|
491
|
+
outputSchema: STRING_OUTPUT,
|
|
492
|
+
needsApproval: approvalGate(opts),
|
|
493
|
+
execute: makeExecute(payInput, opts, async (client, i) => {
|
|
494
|
+
const msg = await client.read(asMessageUuid(i.messageId));
|
|
495
|
+
if (msg.type !== X402_MESSAGE_TYPE.PAYMENT_REQUIRED) return status(PAY_STATUS.NOT_PAYMENT_REQUIRED, `message ${i.messageId} is type '${msg.type}', not an x402 payment request.`);
|
|
496
|
+
try {
|
|
497
|
+
await client.payments.walletAddress();
|
|
498
|
+
} catch {
|
|
499
|
+
return status(PAY_STATUS.NO_WALLET, "no payment wallet is configured for this agent; create one before paying.");
|
|
500
|
+
}
|
|
501
|
+
try {
|
|
502
|
+
const res = await client.payments.pay(msg, {
|
|
503
|
+
autoPay: i.autoPay,
|
|
504
|
+
emitMarker: i.emitMarker,
|
|
505
|
+
allowRepay: i.allowRepay
|
|
506
|
+
});
|
|
507
|
+
return status(PAY_STATUS.SUBMITTED, `sent x402 payment ${res.payment.id} (${requirementSummary(res.requirement)}). The settlement receipt will arrive as a later inbox message.`);
|
|
508
|
+
} catch (err) {
|
|
509
|
+
return mapPayError(err, i.autoPay);
|
|
510
|
+
}
|
|
511
|
+
})
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Resolve the facilitator config from factory opts or `RINE_FACILITATOR`. A
|
|
516
|
+
* `null` return means none is configured (surfaced as `no-facilitator`). An
|
|
517
|
+
* unrecognised reference — neither a preset name nor an `http(s)://` base URL —
|
|
518
|
+
* throws an actionable config error instead of being handed to `fetch` as a
|
|
519
|
+
* bogus URL: parity with the CLI/MCP `resolveFacilitator`, so a typo like
|
|
520
|
+
* `payia` surfaces as a config error naming the bad value, not an opaque
|
|
521
|
+
* `facilitator-error` from a doomed network call.
|
|
522
|
+
*/
|
|
523
|
+
function resolveFacilitator(opts) {
|
|
524
|
+
const ref = opts.facilitator ?? process.env.RINE_FACILITATOR;
|
|
525
|
+
if (!ref) return null;
|
|
526
|
+
const headers = opts.facilitatorHeaders;
|
|
527
|
+
const preset = FACILITATOR_PRESET[ref];
|
|
528
|
+
if (preset) return headers ? {
|
|
529
|
+
...preset,
|
|
530
|
+
headers
|
|
531
|
+
} : preset;
|
|
532
|
+
if (!/^https?:\/\//.test(ref)) throw new Error(`Unknown facilitator '${ref}'. Use a preset (${Object.keys(FACILITATOR_PRESET).join(" | ")}) or an http(s):// base URL.`);
|
|
533
|
+
return headers ? {
|
|
534
|
+
url: ref,
|
|
535
|
+
headers
|
|
536
|
+
} : { url: ref };
|
|
537
|
+
}
|
|
538
|
+
/** Render a settle-first {@link FulfillResult} to a typed outcome line. */
|
|
539
|
+
function renderFulfill(res) {
|
|
540
|
+
if (!res.verification.isValid) return status(FULFILL_STATUS.VERIFICATION_FAILED, `verification failed (${res.verification.invalidReason ?? "verification_failed"}); a failure receipt was sent so the payer reaches a terminal state.`);
|
|
541
|
+
const s = res.settlement;
|
|
542
|
+
if (s?.success) return status(FULFILL_STATUS.SETTLED, `receipt sent; tx ${s.transaction} on ${s.network}${s.payer ? `, payer ${s.payer}` : ""}.`);
|
|
543
|
+
return status(FULFILL_STATUS.SETTLEMENT_FAILED, `settlement did not succeed (${s?.errorReason ?? "unknown"}); receipt sent.`);
|
|
544
|
+
}
|
|
545
|
+
/** `rine_fulfill` — verify + settle a received payment and send the receipt (payee). */
|
|
546
|
+
function rineFulfillTool(opts = {}) {
|
|
547
|
+
return defineTool({
|
|
548
|
+
description: "Fulfill a received x402 payment (rine.v1.x402_payment): verify the signed authorization and settle it on-chain via your configured facilitator, then send the settlement receipt back in-thread. Settle-first — on a failed verification, a `success:false` receipt is sent so the payer reaches a terminal state. Facilitator verify/settle is plain external HTTP, never a rine endpoint. Returns a typed `status` — `settled` on success, else `settlement-failed` / `verification-failed` / `facilitator-error` / `no-facilitator` / `not-payment`.",
|
|
549
|
+
inputSchema: jsonSchema(fulfillInput),
|
|
550
|
+
outputSchema: STRING_OUTPUT,
|
|
551
|
+
needsApproval: approvalGate(opts),
|
|
552
|
+
execute: makeExecute(fulfillInput, opts, async (client, i) => {
|
|
553
|
+
const msg = await client.read(asMessageUuid(i.messageId));
|
|
554
|
+
if (msg.type !== X402_MESSAGE_TYPE.PAYMENT) return status(FULFILL_STATUS.NOT_PAYMENT, `message ${i.messageId} is type '${msg.type}', not an x402 payment authorization.`);
|
|
555
|
+
const facilitator = resolveFacilitator(opts);
|
|
556
|
+
if (!facilitator) return status(FULFILL_STATUS.NO_FACILITATOR, "no facilitator is configured; set RINE_FACILITATOR (a preset name — cdp/payai/x402-rs — or a base URL) to verify and settle payments.");
|
|
557
|
+
try {
|
|
558
|
+
return renderFulfill(await client.payments.fulfill(msg, {
|
|
559
|
+
facilitator,
|
|
560
|
+
emitMarker: i.emitMarker
|
|
561
|
+
}));
|
|
562
|
+
} catch (err) {
|
|
563
|
+
if (err instanceof X402FacilitatorError) return status(FULFILL_STATUS.FACILITATOR_ERROR, err.message);
|
|
564
|
+
throw err;
|
|
565
|
+
}
|
|
566
|
+
})
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
//#endregion
|
|
348
570
|
//#region src/tools/index.ts
|
|
349
571
|
const FACTORIES = {
|
|
350
572
|
rineSendTool,
|
|
@@ -358,7 +580,11 @@ const FACTORIES = {
|
|
|
358
580
|
rineGroupCreateTool,
|
|
359
581
|
rineGroupInviteTool,
|
|
360
582
|
rineGroupRemoveTool,
|
|
361
|
-
rineGroupInspectTool
|
|
583
|
+
rineGroupInspectTool,
|
|
584
|
+
rineGroupJoinTool,
|
|
585
|
+
rineGroupInvitesTool,
|
|
586
|
+
rinePayTool,
|
|
587
|
+
rineFulfillTool
|
|
362
588
|
};
|
|
363
589
|
/** The metadata registry with live factories attached (programmatic use). */
|
|
364
590
|
const RINE_TOOLS = RINE_TOOL_META.map((m) => ({
|
|
@@ -366,4 +592,4 @@ const RINE_TOOLS = RINE_TOOL_META.map((m) => ({
|
|
|
366
592
|
factory: FACTORIES[m.factoryName]
|
|
367
593
|
}));
|
|
368
594
|
//#endregion
|
|
369
|
-
export {
|
|
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 };
|
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 } 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.
|
|
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-
|
|
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.
|
|
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
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 payment-aware inbound re-surfacing for the rine channel.
|
|
3
|
+
*
|
|
4
|
+
* The three x402 payment frames are first-class message types carrying a verbatim
|
|
5
|
+
* x402 V2 object, NOT a chat turn. v1.0 dropped them wholesale (a stateless gateway
|
|
6
|
+
* that auto-replied prose into a payment handshake would corrupt it). v1.1 re-surfaces
|
|
7
|
+
* them as an agent turn with STRUCTURED payment context so the model can act via the
|
|
8
|
+
* dedicated pay / fulfill tools — while the terminal assistant prose stays suppressed
|
|
9
|
+
* in EVERY case (the `x402` continuation-token flag; the guard hazard never re-arms):
|
|
10
|
+
*
|
|
11
|
+
* - `x402_payment_required` → the quote + guidance to pay via `rine_pay`.
|
|
12
|
+
* - `x402_payment` → the signed authorization + guidance to `rine_fulfill`.
|
|
13
|
+
* - `x402_receipt` → the settlement outcome, informational (no reply).
|
|
14
|
+
*
|
|
15
|
+
* Auto-pay (opt-in, DEFAULT OFF): when enabled, a `payment_required` at/below the
|
|
16
|
+
* policy's `autoPayThreshold` is paid with NO LLM turn — still bounded by the policy
|
|
17
|
+
* caps, deny-by-default, journal and reserve-lock (all in rine-core). Any decline
|
|
18
|
+
* falls back to surfacing the quote to the model.
|
|
19
|
+
*/
|
|
20
|
+
import type { InboundDeps } from "./channel-core.js";
|
|
21
|
+
import type { DecryptedMessage } from "./types.js";
|
|
22
|
+
/** The three x402 frame types this module re-surfaces. */
|
|
23
|
+
export declare const X402_FRAME_TYPES: readonly ["rine.v1.x402_payment_required", "rine.v1.x402_payment", "rine.v1.x402_receipt"];
|
|
24
|
+
/** Whether a message type is one of the three x402 payment frames. */
|
|
25
|
+
export declare function isX402Frame(type: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* The structured payment body handed to the model as the turn's primary message.
|
|
28
|
+
* Reads only the decrypted plaintext (the verbatim x402 object) — never ciphertext.
|
|
29
|
+
*/
|
|
30
|
+
export declare function renderX402Body(msg: DecryptedMessage): string;
|
|
31
|
+
/** The routing-guidance line: what the model should do, and the do-not-reply rule. */
|
|
32
|
+
export declare function x402GuidanceLine(msg: DecryptedMessage): string;
|
|
33
|
+
/**
|
|
34
|
+
* Handle a verified inbound x402 frame. `payment_required` may auto-pay
|
|
35
|
+
* when enabled and at/below threshold; otherwise, and for `payment` / `receipt`,
|
|
36
|
+
* the frame is surfaced to the model as a payment-aware turn.
|
|
37
|
+
*/
|
|
38
|
+
export declare function handleX402Inbound(deps: InboundDeps, msg: DecryptedMessage, messageId: string): Promise<Response>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rine-network/eve",
|
|
3
|
-
"version": "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.
|
|
52
|
-
"@rine-network/sdk": "^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
|
},
|