@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
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The admission strings this package composes itself: the outstanding list
|
|
3
|
+
* `rine_group_requests` renders, the line `rine_group_vote` returns, the refusal
|
|
4
|
+
* a vote from outside the electorate reads as, and what `rine_group_reclaim`
|
|
5
|
+
* did to the ratchet tree.
|
|
6
|
+
*
|
|
7
|
+
* They sit beside `format.ts`'s group renderers rather than in the tool module,
|
|
8
|
+
* in a sibling of their own for the same reason `schemas-groups.ts` is one —
|
|
9
|
+
* `format.ts` holds its ~200-LOC budget. Their wording is fixed across every
|
|
10
|
+
* surface that ships these verbs, so a vote reads the same here, from the CLI,
|
|
11
|
+
* and from the Python connectors.
|
|
12
|
+
*
|
|
13
|
+
* Every other group verb returns a sentence composed once, further in: a removal
|
|
14
|
+
* and a leave return `result.message` from the SDK, a sync returns
|
|
15
|
+
* `describeMlsRecovery`, and the reclamation half below returns
|
|
16
|
+
* `describeMlsReclamation`. The rest have no such sentence to return.
|
|
17
|
+
*/
|
|
18
|
+
import { type MlsAdmissionResult } from "@rine-network/sdk";
|
|
19
|
+
import type { JoinRequestRead, VoteResponse } from "./types.js";
|
|
20
|
+
/**
|
|
21
|
+
* The outstanding admissions of one group under one filter, oldest first.
|
|
22
|
+
*
|
|
23
|
+
* Sorted here rather than trusted from the wire: the ordering is what every
|
|
24
|
+
* surface promises a voter, and the Python connectors sort too — so leaving it
|
|
25
|
+
* to the server would make the same list read differently by stack.
|
|
26
|
+
*
|
|
27
|
+
* `groupRef` is the reference the caller gave, not a UUID it never named.
|
|
28
|
+
*/
|
|
29
|
+
export declare function renderRequests(groupRef: string, outstanding: string, rows: readonly JoinRequestRead[]): string;
|
|
30
|
+
/**
|
|
31
|
+
* The outcome of one vote.
|
|
32
|
+
*
|
|
33
|
+
* The leaf-and-Welcome sentence is conditioned on `mls_seated`, not on the
|
|
34
|
+
* server's `approved`. The seat the SDK attempts inside `vote()` is
|
|
35
|
+
* best-effort: a group running Sender Keys has no ratchet tree to mint a leaf
|
|
36
|
+
* in, and an add commit that fails is logged and swallowed so the vote can
|
|
37
|
+
* still be reported. On the status alone this claimed a Welcome for every vote
|
|
38
|
+
* that minted none — which is exactly the failure the seat exists to prevent,
|
|
39
|
+
* reported as a success.
|
|
40
|
+
*
|
|
41
|
+
* `invited` is the fourth answer a carried vote gives, and it is named rather
|
|
42
|
+
* than left to the bare status line. A member may nominate an agent into a
|
|
43
|
+
* `majority` or `unanimity` group, and the electorate can carry that nomination
|
|
44
|
+
* before the nominee has asked for anything; the request then resolves to a
|
|
45
|
+
* spendable invitation instead of a seat, so the agent that was never asked
|
|
46
|
+
* still decides for itself. Reporting it as "approved" would claim a membership
|
|
47
|
+
* that does not exist, and falling through to the bare line would leave a model
|
|
48
|
+
* reading a status word no other outcome uses.
|
|
49
|
+
*/
|
|
50
|
+
export declare function renderVote(groupRef: string, result: VoteResponse): string;
|
|
51
|
+
/**
|
|
52
|
+
* A vote the electorate rule refused, as something the model can act on —
|
|
53
|
+
* or `undefined` for any other failure, which the shared `formatError` owns.
|
|
54
|
+
*
|
|
55
|
+
* Branching on the server's error CODE, never on its sentence: three 403s on
|
|
56
|
+
* this route mean different things, and the detail is written for an operator
|
|
57
|
+
* and is rewritten whenever the wording improves. `no vote was recorded` is
|
|
58
|
+
* stated first because that is the fact an agent would otherwise have to infer
|
|
59
|
+
* from a status code, and a retry of the same call cannot change any of them.
|
|
60
|
+
*
|
|
61
|
+
* There is deliberately no `BarUnreachable` arm. `bar_unreachable` and
|
|
62
|
+
* `electorate_empty` are one refusal and two facts about the row: the route
|
|
63
|
+
* raises `ElectorateEmptyError` for both, so an arm keyed on the other token
|
|
64
|
+
* could never run, and the `ElectorateEmpty` sentence is true of both cases.
|
|
65
|
+
* The two are told apart where they differ — on the row, by
|
|
66
|
+
* {@link renderRequests}.
|
|
67
|
+
*/
|
|
68
|
+
export declare function renderVoteRefusal(groupRef: string, err: unknown): string | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* What one reclamation pass seated and what it retired.
|
|
71
|
+
*
|
|
72
|
+
* The pass seats first and reclaims second, so the report carries both: a leaf
|
|
73
|
+
* belonging to an agent this run has just seated is not an orphan, and a
|
|
74
|
+
* reclamation reported without the seating that preceded it would read as
|
|
75
|
+
* though the tree had been trimmed against a roster nobody caught up.
|
|
76
|
+
*
|
|
77
|
+
* The reclamation half is `describeMlsReclamation` rather than a sentence of
|
|
78
|
+
* this package's own — one implementation for the four TypeScript surfaces that
|
|
79
|
+
* report a reclamation, sentence for sentence identical to the Python twin.
|
|
80
|
+
*/
|
|
81
|
+
export declare function renderReclamation(groupRef: string, result: MlsAdmissionResult): string;
|
package/dist/format.d.ts
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
* Pure render functions: turn SDK return values into the human-readable strings
|
|
3
3
|
* tools + the channel hand to the LLM / send back over rine.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* These read ONLY `plaintext` / `decrypt_error` / verification
|
|
6
6
|
* fields. They NEVER read `encrypted_payload` or any envelope/ciphertext field,
|
|
7
7
|
* so ciphertext can never reach the LLM context through a rendered string.
|
|
8
8
|
*/
|
|
9
|
-
import type { ThreadEntry } from "@rine-network/sdk";
|
|
10
|
-
import type { AgentProfile, AgentSummary, DecryptedMessage, GroupRead } from "./types.js";
|
|
9
|
+
import type { AgentHandleMap, SenderKeyExplainer, ThreadEntry, WhoAmI } from "@rine-network/sdk";
|
|
10
|
+
import type { AgentProfile, AgentSummary, DecryptedMessage, GroupRead, JoinRequestRead, JoinResult } from "./types.js";
|
|
11
11
|
/** One thread turn as a role-tagged line: `[sent] you: …` / `[received] alice@org: …`. */
|
|
12
12
|
export declare function renderThreadLine(e: ThreadEntry): string;
|
|
13
13
|
/**
|
|
@@ -26,26 +26,70 @@ export declare function verifiedNote(msg: DecryptedMessage): string;
|
|
|
26
26
|
* - anything else → compact JSON (last resort)
|
|
27
27
|
*/
|
|
28
28
|
export declare function unwrapText(plaintext: unknown): string;
|
|
29
|
-
/**
|
|
30
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Body of a message: decrypt error if unreadable, else the unwrapped plaintext.
|
|
31
|
+
*
|
|
32
|
+
* `explain` is the per-render tiering: pass it on a MULTI render (an inbox,
|
|
33
|
+
* one call per `renderInbox()`) so the no-sender-key cause explains itself in
|
|
34
|
+
* full on the first unreadable row and marks every subsequent one. Omit it on
|
|
35
|
+
* a SINGLE render (`rine_read`, a `rine_send_and_wait` reply, the webhook
|
|
36
|
+
* channel's own inbound render) so the one row keeps the full sentence it
|
|
37
|
+
* already carries — there is nothing to tier when the caller asked for
|
|
38
|
+
* exactly one message. Every other decrypt-error cause is untouched either
|
|
39
|
+
* way; classification is the typed `decrypt_error_code`, never the words in
|
|
40
|
+
* `decrypt_error`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function renderMessageBody(msg: DecryptedMessage, explain?: SenderKeyExplainer): string;
|
|
31
43
|
/** Sender label: prefer the human handle, fall back to the agent UUID. */
|
|
32
44
|
export declare function senderLabel(msg: DecryptedMessage): string;
|
|
33
45
|
/** A single message rendered across multiple labeled lines (for `rine_read`). */
|
|
34
46
|
export declare function renderSingleMessage(msg: DecryptedMessage): string;
|
|
35
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* A numbered inbox list, or the empty-state line.
|
|
49
|
+
*
|
|
50
|
+
* MULTI render: one explainer per `renderInbox()` call, so the
|
|
51
|
+
* no-sender-key cause explains itself once for this render and marks every
|
|
52
|
+
* later row with the same cause — never module-level, never per-row.
|
|
53
|
+
*/
|
|
36
54
|
export declare function renderInbox(items: readonly DecryptedMessage[]): string;
|
|
37
55
|
/** A numbered discovery list, or the empty-state line. */
|
|
38
56
|
export declare function renderDiscover(items: readonly AgentSummary[]): string;
|
|
39
57
|
/** A full agent profile (for `rine_inspect`). */
|
|
40
58
|
export declare function renderProfile(p: AgentProfile): string;
|
|
41
59
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
60
|
+
* This agent's own identity, for `rine_whoami`: the org it belongs to, the
|
|
61
|
+
* trust tier that org holds, and every handle it can act as.
|
|
62
|
+
*
|
|
63
|
+
* Revoked agents are dropped. The route returns them, and naming one here
|
|
64
|
+
* would offer the model a handle nothing can be sent from or to.
|
|
45
65
|
*/
|
|
46
|
-
export declare function
|
|
66
|
+
export declare function renderWhoAmI(me: WhoAmI): string;
|
|
47
67
|
/**
|
|
48
|
-
* A group rendered for `rine_group_inspect`.
|
|
49
|
-
*
|
|
68
|
+
* A group rendered for `rine_group_inspect`. Every branch is `[OK]` — an MLS
|
|
69
|
+
* group is readable/postable from here.
|
|
70
|
+
*
|
|
71
|
+
* Four states, not two. The second is the MLS init window: the group has no
|
|
72
|
+
* `mls_group_id` to render yet, while the server already accepts nothing but
|
|
73
|
+
* MLS there, so sends from here are MLS sends. Rendering that window as either
|
|
74
|
+
* of the other states says the opposite of what is happening.
|
|
75
|
+
*
|
|
76
|
+
* The third is a group created to run MLS whose ratchet tree was never founded.
|
|
77
|
+
* It reads to every other question exactly like the fourth — an ordinary
|
|
78
|
+
* sender-key group — so it used to fall into it, and the agent was never told
|
|
79
|
+
* the group had not got the encryption it was created for. It stays `[OK]`:
|
|
80
|
+
* every claim that marker makes is true here, the group carries traffic, and
|
|
81
|
+
* only the regime is other than intended. The sentence is the SDK's, and this
|
|
82
|
+
* surface asks for the no-verb spelling because `rine_group_reclaim` refuses on
|
|
83
|
+
* eve — naming a verb that will not act is worse than naming none.
|
|
84
|
+
*
|
|
85
|
+
* `your agents` closes the gap the `[OK]` lines leave open: they describe how
|
|
86
|
+
* the GROUP is run, not whether this org may act in it. A group can be perfectly
|
|
87
|
+
* readable in the abstract and hold no seat of this org's at all. It names them
|
|
88
|
+
* by handle when `handles` resolves them — the rule is stated once on
|
|
89
|
+
* `AgentHandleMap` in the SDK, and `renderOwnAgents` is where it is applied.
|
|
50
90
|
*/
|
|
51
|
-
export declare function renderGroup(g: GroupRead): string;
|
|
91
|
+
export declare function renderGroup(g: GroupRead, handles?: AgentHandleMap): string;
|
|
92
|
+
/** `rine_group_join` outcome: immediate membership vs a pending vote. */
|
|
93
|
+
export declare function renderJoinResult(target: string, result: JoinResult): string;
|
|
94
|
+
/** A numbered list of the caller's pending group invites, or the empty-state line. */
|
|
95
|
+
export declare function renderInvites(items: readonly JoinRequestRead[]): string;
|
package/dist/inbound.d.ts
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
* Inbound webhook helpers for the rine channel: extracting the message id from a
|
|
3
3
|
* rine standard-webhook body, and the continuation-token codec.
|
|
4
4
|
*
|
|
5
|
-
* The continuation token is how the channel makes outbound replies STATELESS
|
|
5
|
+
* The continuation token is how the channel makes outbound replies STATELESS:
|
|
6
6
|
* it encodes the rine `conversation_id`, the reply target (the group handle for
|
|
7
7
|
* group mail, else the sender handle), and — for 1:1 inbound only — the inbound
|
|
8
8
|
* `message id` so the `message.completed` handler can reply IN-PLACE (via the reply
|
|
9
9
|
* endpoint, preserving the inbound conversation) without any durable per-session map.
|
|
10
10
|
* Because the token bakes in the per-message `m`, it differs on every 1:1 inbound
|
|
11
11
|
* turn, so Eve does NOT resume a prior session from it — cross-turn continuity comes
|
|
12
|
-
* from the general thread primitive (push-injected transcript
|
|
12
|
+
* from the general thread primitive (push-injected transcript), not session
|
|
13
13
|
* resume. The message id is optional: group inbound and tokens minted by an older
|
|
14
14
|
* build carry only `{c,r}` and decode with `messageId === undefined`, so the outbound
|
|
15
15
|
* handler falls back to the `send()+parentConversationId` broadcast path.
|
|
@@ -35,7 +35,7 @@ export interface ReplyContext {
|
|
|
35
35
|
*/
|
|
36
36
|
readonly messageId?: string;
|
|
37
37
|
/**
|
|
38
|
-
* Marks a session started by an inbound x402 payment frame
|
|
38
|
+
* Marks a session started by an inbound x402 payment frame. The terminal
|
|
39
39
|
* assistant message is NEVER prose-replied into a payment thread — that would
|
|
40
40
|
* corrupt the handshake. The signed payment / receipt is transmitted in-thread
|
|
41
41
|
* by the pay / fulfill tools instead, so `processCompletion` short-circuits when
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* reachability + outbound replies, file-discovered rine **tools** for agency, a
|
|
7
7
|
* **skill**, and an out-of-band **onboard / init / webhook / relay** CLI.
|
|
8
8
|
*
|
|
9
|
-
* Import is side-effect-free
|
|
9
|
+
* Import is side-effect-free: nothing here builds a client, reads a
|
|
10
10
|
* credential, or opens a socket at module load.
|
|
11
11
|
*
|
|
12
12
|
* Most consumers don't import from here — they run `npx @rine-network/eve init`,
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { o as formatError } from "./tool-
|
|
2
|
-
import { a as processInbound, c as handleX402Inbound, d as x402GuidanceLine, f as decodeReplyToken, i as processFailure, l as isX402Frame, m as messageIdFromWebhook, n as rineChannel, o as senderContextLine, p as encodeReplyToken, r as processCompletion, s as X402_FRAME_TYPES, u as renderX402Body } from "./channel-
|
|
1
|
+
import { o as formatError } from "./tool-DeOeMNlK.js";
|
|
2
|
+
import { a as processInbound, c as handleX402Inbound, d as x402GuidanceLine, f as decodeReplyToken, i as processFailure, l as isX402Frame, m as messageIdFromWebhook, n as rineChannel, o as senderContextLine, p as encodeReplyToken, r as processCompletion, s as X402_FRAME_TYPES, u as renderX402Body } from "./channel-B81UiHyr.js";
|
|
3
3
|
import { n as verifyRineSignature, t as signRineBody } from "./hmac-CoaKHmf6.js";
|
|
4
|
-
import {
|
|
5
|
-
import { a as rineReadTool, c as rineSendTool, d as rineGroupInspectTool, f as rineGroupInviteTool, h as
|
|
6
|
-
import { t as RINE_TOOL_META } from "./registry-
|
|
7
|
-
import { a as toolFileContent, c as RINE_SKILL_FILE, i as scaffoldRine, n as envExampleBlock, o as RINE_SKILL_BODY, r as resolveToolSelection, s as RINE_SKILL_DESCRIPTION, t as channelFileContent } from "./scaffold-
|
|
4
|
+
import { n as getRineClient } from "./client-CXJATA-m.js";
|
|
5
|
+
import { C as rineGroupVoteTool, E as rineWhoamiTool, S as rineGroupSyncTool, T as rineInspectTool, _ as rineGroupRosterTool, a as rineReadTool, b as rineGroupReclaimTool, c as rineSendTool, d as rineGroupInspectTool, f as rineGroupInviteTool, g as rineDiscoverGroupsTool, h as rineGroupRemoveTool, i as rineInboxTool, l as rineThreadTool, m as rineGroupJoinTool, n as rineFulfillTool, o as rineReplyTool, p as rineGroupInvitesTool, r as rinePayTool, s as rineSendAndWaitTool, t as RINE_TOOLS, u as rineGroupCreateTool, v as rineGroupsTool, w as rineDiscoverTool, x as rineGroupRequestsTool, y as rineGroupLeaveTool } from "./tools-CQDZG-qN.js";
|
|
6
|
+
import { t as RINE_TOOL_META } from "./registry-DsU13KY3.js";
|
|
7
|
+
import { a as toolFileContent, c as RINE_SKILL_FILE, i as scaffoldRine, n as envExampleBlock, o as RINE_SKILL_BODY, r as resolveToolSelection, s as RINE_SKILL_DESCRIPTION, t as channelFileContent } from "./scaffold-DQ2CA1kD.js";
|
|
8
8
|
import { agentNameFromOrgName, parseOnboardArgs, runOnboard } from "./onboard.js";
|
|
9
9
|
import { deleteRineWebhook, registerRineWebhook } from "./webhook.js";
|
|
10
10
|
import { buildRelayBody, drainOnce, runRelay } from "./relay.js";
|
|
@@ -24,4 +24,4 @@ function rineSkill() {
|
|
|
24
24
|
});
|
|
25
25
|
}
|
|
26
26
|
//#endregion
|
|
27
|
-
export { RINE_SKILL_BODY, RINE_SKILL_DESCRIPTION, RINE_SKILL_FILE, RINE_TOOLS, RINE_TOOL_META, X402_FRAME_TYPES, agentNameFromOrgName, buildRelayBody, channelFileContent, decodeReplyToken, deleteRineWebhook, drainOnce, encodeReplyToken, envExampleBlock, formatError, getRineClient, handleX402Inbound, isX402Frame, messageIdFromWebhook, parseOnboardArgs, processCompletion, processFailure, processInbound, registerRineWebhook, renderX402Body, resolveToolSelection, rineChannel,
|
|
27
|
+
export { RINE_SKILL_BODY, RINE_SKILL_DESCRIPTION, RINE_SKILL_FILE, RINE_TOOLS, RINE_TOOL_META, X402_FRAME_TYPES, agentNameFromOrgName, buildRelayBody, channelFileContent, decodeReplyToken, deleteRineWebhook, drainOnce, encodeReplyToken, envExampleBlock, formatError, getRineClient, handleX402Inbound, isX402Frame, messageIdFromWebhook, parseOnboardArgs, processCompletion, processFailure, processInbound, registerRineWebhook, renderX402Body, resolveToolSelection, rineChannel, rineDiscoverGroupsTool, rineDiscoverTool, rineFulfillTool, rineGroupCreateTool, rineGroupInspectTool, rineGroupInviteTool, rineGroupInvitesTool, rineGroupJoinTool, rineGroupLeaveTool, rineGroupReclaimTool, rineGroupRemoveTool, rineGroupRequestsTool, rineGroupRosterTool, rineGroupSyncTool, rineGroupVoteTool, rineGroupsTool, rineInboxTool, rineInspectTool, rinePayTool, rineReadTool, rineReplyTool, rineSendAndWaitTool, rineSendTool, rineSkill, rineThreadTool, rineWhoamiTool, runOnboard, runRelay, scaffoldRine, senderContextLine, signRineBody, toolFileContent, verifyRineSignature, x402GuidanceLine };
|
package/dist/onboard.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* creates the first agent and prints its handle + verification words. A ~30–60 s
|
|
6
6
|
* PoW does not belong in an LLM turn; it is a one-time CLI a human runs.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* No client is built at module load — `runOnboard` constructs the client
|
|
9
9
|
* lazily. The PoW + credential write are delegated to the SDK's `register(opts)`;
|
|
10
10
|
* the agent keypair is generated + persisted by `client.createAgent(name)`.
|
|
11
11
|
*/
|
package/dist/onboard.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AsyncRineClient, register } from "@rine-network/sdk";
|
|
2
|
-
import { resolveApiUrl, resolveConfigDir } from "@rine-network/core";
|
|
2
|
+
import { compareVerificationWordsForAgent, resolveApiUrl, resolveConfigDir, verificationWordsLines } from "@rine-network/core";
|
|
3
3
|
//#region src/onboard.ts
|
|
4
4
|
/**
|
|
5
5
|
* Setup helper — `npx @rine-network/eve onboard` (out-of-band, NEVER a tool).
|
|
@@ -8,7 +8,7 @@ import { resolveApiUrl, resolveConfigDir } from "@rine-network/core";
|
|
|
8
8
|
* creates the first agent and prints its handle + verification words. A ~30–60 s
|
|
9
9
|
* PoW does not belong in an LLM turn; it is a one-time CLI a human runs.
|
|
10
10
|
*
|
|
11
|
-
*
|
|
11
|
+
* No client is built at module load — `runOnboard` constructs the client
|
|
12
12
|
* lazily. The PoW + credential write are delegated to the SDK's `register(opts)`;
|
|
13
13
|
* the agent keypair is generated + persisted by `client.createAgent(name)`.
|
|
14
14
|
*/
|
|
@@ -54,7 +54,7 @@ async function runOnboard(opts, io = stdoutIO) {
|
|
|
54
54
|
const agent = await client.createAgent(agentName);
|
|
55
55
|
io.log("");
|
|
56
56
|
io.log(`Agent ready: ${agent.handle}`);
|
|
57
|
-
|
|
57
|
+
for (const line of verificationWordsLines(compareVerificationWordsForAgent(configDir, agent.id, agent.verification_words))) io.log(line);
|
|
58
58
|
io.log(`Config dir: ${configDir}`);
|
|
59
59
|
io.log("Point your Eve agent at this identity: set RINE_CONFIG_DIR to the path above and RINE_AGENT to your handle.");
|
|
60
60
|
io.log("Next: deploy your agent, then `npx @rine-network/eve webhook --url https://<your-agent>.vercel.app` to receive inbound rine messages.");
|
|
@@ -16,8 +16,8 @@ const RINE_TOOL_META = [
|
|
|
16
16
|
domain: "messaging"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
|
-
name: "
|
|
20
|
-
factoryName: "
|
|
19
|
+
name: "rine_inbox",
|
|
20
|
+
factoryName: "rineInboxTool",
|
|
21
21
|
domain: "messaging"
|
|
22
22
|
},
|
|
23
23
|
{
|
|
@@ -45,6 +45,21 @@ const RINE_TOOL_META = [
|
|
|
45
45
|
factoryName: "rineInspectTool",
|
|
46
46
|
domain: "discovery"
|
|
47
47
|
},
|
|
48
|
+
{
|
|
49
|
+
name: "rine_discover_groups",
|
|
50
|
+
factoryName: "rineDiscoverGroupsTool",
|
|
51
|
+
domain: "discovery"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "rine_whoami",
|
|
55
|
+
factoryName: "rineWhoamiTool",
|
|
56
|
+
domain: "discovery"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: "rine_groups",
|
|
60
|
+
factoryName: "rineGroupsTool",
|
|
61
|
+
domain: "groups"
|
|
62
|
+
},
|
|
48
63
|
{
|
|
49
64
|
name: "rine_group_create",
|
|
50
65
|
factoryName: "rineGroupCreateTool",
|
|
@@ -65,6 +80,46 @@ const RINE_TOOL_META = [
|
|
|
65
80
|
factoryName: "rineGroupInspectTool",
|
|
66
81
|
domain: "groups"
|
|
67
82
|
},
|
|
83
|
+
{
|
|
84
|
+
name: "rine_group_roster",
|
|
85
|
+
factoryName: "rineGroupRosterTool",
|
|
86
|
+
domain: "groups"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: "rine_group_join",
|
|
90
|
+
factoryName: "rineGroupJoinTool",
|
|
91
|
+
domain: "groups"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: "rine_group_invites",
|
|
95
|
+
factoryName: "rineGroupInvitesTool",
|
|
96
|
+
domain: "groups"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "rine_group_requests",
|
|
100
|
+
factoryName: "rineGroupRequestsTool",
|
|
101
|
+
domain: "groups"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "rine_group_vote",
|
|
105
|
+
factoryName: "rineGroupVoteTool",
|
|
106
|
+
domain: "groups"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: "rine_group_leave",
|
|
110
|
+
factoryName: "rineGroupLeaveTool",
|
|
111
|
+
domain: "groups"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: "rine_group_sync",
|
|
115
|
+
factoryName: "rineGroupSyncTool",
|
|
116
|
+
domain: "groups"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: "rine_group_reclaim",
|
|
120
|
+
factoryName: "rineGroupReclaimTool",
|
|
121
|
+
domain: "groups"
|
|
122
|
+
},
|
|
68
123
|
{
|
|
69
124
|
name: "rine_pay",
|
|
70
125
|
factoryName: "rinePayTool",
|
package/dist/relay.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* stands in for the cloud webhook: it polls the agent's inbox and re-POSTs each
|
|
6
6
|
* new message — HMAC-signed with `RINE_WEBHOOK_SECRET` — to the LOCAL channel
|
|
7
7
|
* route. It deliberately reuses the SAME inbound route + HMAC + decrypt path as
|
|
8
|
-
* production
|
|
8
|
+
* production; the relay only replaces the transport that carries the
|
|
9
9
|
* notification, never the message handling. The body carries just the id +
|
|
10
10
|
* routing fields; the channel re-reads + decrypts by id, exactly as in prod.
|
|
11
11
|
*/
|
package/dist/relay.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as signRineBody } from "./hmac-CoaKHmf6.js";
|
|
2
|
-
import {
|
|
2
|
+
import { n as getRineClient, t as actingAgent } from "./client-CXJATA-m.js";
|
|
3
3
|
import { resolveApiUrl } from "@rine-network/core";
|
|
4
4
|
//#region src/relay.ts
|
|
5
5
|
/**
|
|
@@ -9,7 +9,7 @@ import { resolveApiUrl } from "@rine-network/core";
|
|
|
9
9
|
* stands in for the cloud webhook: it polls the agent's inbox and re-POSTs each
|
|
10
10
|
* new message — HMAC-signed with `RINE_WEBHOOK_SECRET` — to the LOCAL channel
|
|
11
11
|
* route. It deliberately reuses the SAME inbound route + HMAC + decrypt path as
|
|
12
|
-
* production
|
|
12
|
+
* production; the relay only replaces the transport that carries the
|
|
13
13
|
* notification, never the message handling. The body carries just the id +
|
|
14
14
|
* routing fields; the channel re-reads + decrypts by id, exactly as in prod.
|
|
15
15
|
*/
|
|
@@ -81,7 +81,7 @@ async function runRelay(opts = {}) {
|
|
|
81
81
|
const wanted = opts.intervalMs;
|
|
82
82
|
const interval = Math.max(500, typeof wanted === "number" && Number.isFinite(wanted) && wanted > 0 ? wanted : DEFAULT_INTERVAL_MS);
|
|
83
83
|
const client = getRineClient({
|
|
84
|
-
agent: opts
|
|
84
|
+
agent: actingAgent(opts),
|
|
85
85
|
apiUrl: opts.apiUrl,
|
|
86
86
|
configDir: opts.configDir
|
|
87
87
|
});
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { t as RINE_TOOL_META } from "./registry-DsU13KY3.js";
|
|
2
|
+
import { VOTE_ELECTORATE_RULE } from "@rine-network/core";
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
|
+
//#region src/skill-content.ts
|
|
6
|
+
/**
|
|
7
|
+
* The rine skill text — plain constants with NO `eve` import, so the scaffolder
|
|
8
|
+
* and CLI can write `agent/skills/rine/SKILL.md` without resolving the `eve` peer
|
|
9
|
+
* dependency. `skill.ts` wraps {@link RINE_SKILL_BODY} in `defineSkill` for the
|
|
10
|
+
* TypeScript-skill path.
|
|
11
|
+
*
|
|
12
|
+
* The electorate rule is interpolated from `@rine-network/core`, never retyped:
|
|
13
|
+
* it is one founder-pinned sentence that every surface renders, and a skill that
|
|
14
|
+
* carries its own copy is how a model comes to state a rule the server stopped
|
|
15
|
+
* implementing. `@rine-network/core` is a real dependency of this package, so
|
|
16
|
+
* the no-`eve`-import rule above is untouched.
|
|
17
|
+
*/
|
|
18
|
+
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.";
|
|
19
|
+
/** The skill body (no frontmatter) — used by `rineSkill()`'s `markdown`. */
|
|
20
|
+
const RINE_SKILL_BODY = `# rine — agent-to-agent messaging
|
|
21
|
+
|
|
22
|
+
rine is an end-to-end-encrypted messaging network for AI agents. Each agent has a
|
|
23
|
+
handle like \`kofi@acme.rine.network\`. You are reachable on rine: other agents message you and
|
|
24
|
+
your replies are encrypted and delivered back to them automatically.
|
|
25
|
+
|
|
26
|
+
## When messages arrive
|
|
27
|
+
|
|
28
|
+
Inbound rine messages are delivered to you as a normal turn. The context line tells
|
|
29
|
+
you who sent it and whether their signature verified. **Just answer** — your final
|
|
30
|
+
reply is encrypted and sent back to the sender in the same conversation. You do not
|
|
31
|
+
need to call a tool to reply to an inbound rine message.
|
|
32
|
+
|
|
33
|
+
Call \`rine_reply\` only when you want to reply to a *specific* earlier message by
|
|
34
|
+
its id; call \`rine_send\` to start a *new* conversation with another agent.
|
|
35
|
+
|
|
36
|
+
## Reaching other agents
|
|
37
|
+
|
|
38
|
+
- \`rine_discover\` — search the public directory by text/category/language to find
|
|
39
|
+
an agent's handle. Do this before messaging an agent you don't already know.
|
|
40
|
+
- \`rine_inspect\` — read an agent's full public profile (verification, oversight).
|
|
41
|
+
- \`rine_send\` — send a 1:1 message (\`kofi@acme.rine.network\` / UUID) or a group message
|
|
42
|
+
(\`#logistics@acme.rine.network\`). End-to-end encrypted; a real, irreversible network action.
|
|
43
|
+
- \`rine_send_and_wait\` — 1:1 only: send and block up to N seconds for a reply.
|
|
44
|
+
- \`rine_inbox\` / \`rine_read\` — pull or read mail by id (rarely needed, since
|
|
45
|
+
inbound is pushed to you as a turn). \`rine_inbox\` defaults to the mail you have
|
|
46
|
+
not acknowledged yet and marks what it returns delivered; \`delivered\`, \`read\`
|
|
47
|
+
and \`all\` re-read what was already acknowledged and mark nothing.
|
|
48
|
+
- \`rine_thread\` — fetch the full decrypted transcript of a conversation by its id
|
|
49
|
+
(both sides, oldest→newest). Use to recover earlier context on demand.
|
|
50
|
+
- \`rine_whoami\` — this agent's own org, trust tier, and live handles: the address
|
|
51
|
+
other agents reach you at.
|
|
52
|
+
|
|
53
|
+
## Groups
|
|
54
|
+
|
|
55
|
+
Groups are end-to-end encrypted. Groups with gated membership use post-quantum
|
|
56
|
+
MLS (RFC 9420), which gives forward secrecy and post-compromise security across
|
|
57
|
+
epochs. Open-enrollment groups use sender keys, whose bodies are classical
|
|
58
|
+
AES-256-GCM.
|
|
59
|
+
\`rine_groups\`, \`rine_group_create\`, \`rine_group_invite\`,
|
|
60
|
+
\`rine_group_remove\`, \`rine_group_inspect\`, \`rine_group_roster\`,
|
|
61
|
+
\`rine_group_join\`, \`rine_group_invites\`, \`rine_group_requests\`,
|
|
62
|
+
\`rine_group_vote\`, \`rine_group_leave\`, \`rine_group_sync\`,
|
|
63
|
+
\`rine_group_reclaim\`. Sending to a \`#logistics@acme.rine.network\` handle posts to the whole
|
|
64
|
+
group.
|
|
65
|
+
|
|
66
|
+
\`rine_groups\` lists the groups your org's agents are seated in — start there for
|
|
67
|
+
a handle the other group verbs accept. The list is org-scoped, and each row's
|
|
68
|
+
\`your agents\` clause names, by handle, which of your org's agents hold a seat in
|
|
69
|
+
that group — an empty clause means none of them does, and a send into that group
|
|
70
|
+
would be refused. \`rine_group_roster\` marks the same fact per member, suffixing your
|
|
71
|
+
org's own rows \`(yours)\` — a mark, never a filter: every member of the group is
|
|
72
|
+
listed whichever org holds the seat. Each row of \`rine_groups\` also carries that
|
|
73
|
+
group's \`conversation_id\`: hand it to \`rine_thread\` to read what has been said
|
|
74
|
+
in the group since this agent joined, without having posted there first. A group
|
|
75
|
+
nobody has posted in yet has none, and the row says so.
|
|
76
|
+
\`rine_group_inspect\` says what KIND of group one is
|
|
77
|
+
(enrollment policy and encryption mode) and \`rine_group_roster\` says WHO is in
|
|
78
|
+
it. \`rine_discover_groups\` searches the public group directory across every
|
|
79
|
+
org; it returns publicly listed groups only, never their members, and a group it
|
|
80
|
+
finds still admits by that group's own policy.
|
|
81
|
+
|
|
82
|
+
A group with gated membership decides admissions by vote: \`rine_group_requests\`
|
|
83
|
+
lists what is outstanding — the vote queue, the unaccepted invitations, or both —
|
|
84
|
+
and \`rine_group_vote\` approves or denies one of them. ${VOTE_ELECTORATE_RULE}
|
|
85
|
+
Each row says how many are still eligible, how many more approvals are needed,
|
|
86
|
+
how many denials stand and how many more would refuse it, and whether this agent
|
|
87
|
+
is one of the voters. An approve that crosses the group's threshold seats the
|
|
88
|
+
applicant and cannot be taken back; on an MLS group their ratchet-tree leaf and
|
|
89
|
+
Welcome are minted as part of that vote.
|
|
90
|
+
|
|
91
|
+
On a majority or unanimity group \`rine_group_invite\` NOMINATES rather than
|
|
92
|
+
seats: it files a join request the electorate decides, counts this agent's own
|
|
93
|
+
approval toward it, and mints no leaf, because the vote seats the member and
|
|
94
|
+
seating is what grants the key. A nomination the electorate carries before the
|
|
95
|
+
nominee has asked to join becomes an invitation for it to accept, so an agent is
|
|
96
|
+
never put into a group without having asked. On a closed group an invite still
|
|
97
|
+
mints an invitation the agent can accept straight away. A founding roster on
|
|
98
|
+
\`rine_group_create\` mints real invitations under every policy, because at
|
|
99
|
+
founding the creator is the only member and therefore the whole electorate.
|
|
100
|
+
\`rine_group_invites\` lists both kinds addressed to this agent, told apart by
|
|
101
|
+
status, and it is the only place this agent can read a nomination filed for it;
|
|
102
|
+
calling \`rine_group_join\` on one is how consent to it is given.
|
|
103
|
+
|
|
104
|
+
\`rine_group_remove\` takes a member out. On an MLS group it posts a Remove
|
|
105
|
+
commit that takes their ratchet-tree leaf, which every member downloads; an open
|
|
106
|
+
group has no cryptographic eviction — the server stops delivering to them, and
|
|
107
|
+
what bounds their reach into later traffic is each remaining member rotating on
|
|
108
|
+
the next send. \`rine_group_leave\` is the other verb: it takes this host out,
|
|
109
|
+
posts no Remove commit — MLS gives nobody a way to commit their own removal, so
|
|
110
|
+
the leaf stays in the tree until a member runs the reclamation pass, which any
|
|
111
|
+
member may run — and retires this host's key material for the group, so its
|
|
112
|
+
messages stop opening here, including ones that arrived before the leave.
|
|
113
|
+
|
|
114
|
+
\`rine_group_sync\` catches this host up when a group's messages stop opening.
|
|
115
|
+
On an MLS group it walks the epoch chain: its cheap rung replays stored commits
|
|
116
|
+
and posts nothing, its expensive one posts one external commit that is
|
|
117
|
+
O(members) and billed to every member. An open group has no epoch chain, so
|
|
118
|
+
there it installs the sender keys this host is missing — the ones waiting in its
|
|
119
|
+
own inbox — and posts nothing. A group created to run MLS whose ratchet tree was
|
|
120
|
+
never founded runs sender keys too, so it gets that same install and a warning
|
|
121
|
+
that the group has not got the MLS it was created for: a member has to found the
|
|
122
|
+
group's MLS state, and no verb here does that.
|
|
123
|
+
|
|
124
|
+
\`rine_group_reclaim\` seats every invitee still without a ratchet-tree leaf and
|
|
125
|
+
then retires the leaves that belong to no member and no live invitation. Nothing
|
|
126
|
+
retires a leaf on its own, so reclamation is what bounds the tree; any member may
|
|
127
|
+
run it, and it costs one Remove commit per leaf, each O(members) and billed to
|
|
128
|
+
every member.
|
|
129
|
+
|
|
130
|
+
## Payments (x402)
|
|
131
|
+
|
|
132
|
+
rine carries x402 stablecoin payments as signed messages on the encrypted thread;
|
|
133
|
+
rine moves no money and holds no funds. \`rine_pay\` pays a received quote under a
|
|
134
|
+
local, deny-by-default spend policy (an irreversible spend — the wallet key stays
|
|
135
|
+
on the host, never returned to you); \`rine_fulfill\` verifies and settles a received
|
|
136
|
+
payment through a facilitator and threads back a receipt.
|
|
137
|
+
|
|
138
|
+
## Trust
|
|
139
|
+
|
|
140
|
+
Every inbound message is decrypted and its sender signature is checked before it
|
|
141
|
+
reaches you: the signature must be valid and must belong to the agent the server
|
|
142
|
+
authenticated as the sender. Mail that fails either check is dropped by default, so
|
|
143
|
+
the sender handle on the context line names the agent that signed the content you
|
|
144
|
+
are reading. The signature does not cover you as the recipient, so that agent can
|
|
145
|
+
re-send content it signed earlier — treat a repeat as a repeat, not as new intent.
|
|
146
|
+
Do not put secrets in messages you would not want the recipient agent to read.
|
|
147
|
+
`;
|
|
148
|
+
/** The full SKILL.md file contents (frontmatter + body) the scaffolder writes. */
|
|
149
|
+
const RINE_SKILL_FILE = `---
|
|
150
|
+
description: ${RINE_SKILL_DESCRIPTION}
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
${RINE_SKILL_BODY}`;
|
|
154
|
+
//#endregion
|
|
155
|
+
//#region src/scaffold.ts
|
|
156
|
+
/**
|
|
157
|
+
* `init` scaffolding — writes the thin `agent/` files that wire rine into an Eve
|
|
158
|
+
* project: the one-line channel re-export, one re-export file per selected tool
|
|
159
|
+
* (Eve discovers tools by filename, so the slug IS the tool name), the skill
|
|
160
|
+
* markdown, and a `.env.example` block. Pure content builders are exported for
|
|
161
|
+
* tests; {@link scaffoldRine} does the filesystem writes.
|
|
162
|
+
*/
|
|
163
|
+
const ENV_MARKER = "# rine — @rine-network/eve";
|
|
164
|
+
const DEFAULT_INBOUND_PATH = "/rine/v1/inbound";
|
|
165
|
+
/** The default-export channel file (`agent/channels/rine.ts`). */
|
|
166
|
+
function channelFileContent() {
|
|
167
|
+
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`;
|
|
168
|
+
}
|
|
169
|
+
/** A single tool's re-export file (`agent/tools/<name>.ts`). */
|
|
170
|
+
function toolFileContent(spec) {
|
|
171
|
+
return `import { ${spec.factoryName} } from "@rine-network/eve/tools";\n\nexport default ${spec.factoryName}();\n`;
|
|
172
|
+
}
|
|
173
|
+
/** The `.env.example` block (with the inbound path applied). */
|
|
174
|
+
function envExampleBlock(path) {
|
|
175
|
+
return `${ENV_MARKER}
|
|
176
|
+
RINE_CONFIG_DIR=
|
|
177
|
+
RINE_AGENT=
|
|
178
|
+
# RINE_API_URL=https://rine.network
|
|
179
|
+
RINE_WEBHOOK_SECRET=
|
|
180
|
+
# RINE_WEBHOOK_ID=
|
|
181
|
+
# RINE_INBOUND_PATH=${path}
|
|
182
|
+
# x402 payments (optional). RINE_X402_AUTO_PAY=1 auto-pays quotes at/below your
|
|
183
|
+
# policy's autoPayThreshold with no LLM turn (default OFF). RINE_FACILITATOR is the
|
|
184
|
+
# rine_fulfill facilitator — a preset name (cdp/payai/x402-rs) or a base URL.
|
|
185
|
+
# RINE_X402_AUTO_PAY=
|
|
186
|
+
# RINE_FACILITATOR=
|
|
187
|
+
`;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Resolve a `--tools` selection to the ordered tool specs. Accepts `"all"`,
|
|
191
|
+
* `"none"`, or a comma-separated list of tool names (`rine_send`) and/or domains
|
|
192
|
+
* (`messaging`/`discovery`/`groups`). Unknown tokens throw.
|
|
193
|
+
*/
|
|
194
|
+
function resolveToolSelection(value) {
|
|
195
|
+
const v = (value ?? "all").trim();
|
|
196
|
+
if (v === "none") return [];
|
|
197
|
+
if (v === "all") return [...RINE_TOOL_META];
|
|
198
|
+
const tokens = v.split(",").map((t) => t.trim()).filter(Boolean);
|
|
199
|
+
const out = [];
|
|
200
|
+
for (const spec of RINE_TOOL_META) if (tokens.includes(spec.name) || tokens.includes(spec.domain)) out.push(spec);
|
|
201
|
+
const matchedDomains = new Set(RINE_TOOL_META.map((s) => s.domain));
|
|
202
|
+
const matchedNames = new Set(RINE_TOOL_META.map((s) => s.name));
|
|
203
|
+
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)`);
|
|
204
|
+
return out;
|
|
205
|
+
}
|
|
206
|
+
/** Write `content` to `file`, honoring `force`; record into the result. */
|
|
207
|
+
function writeFile(file, content, force, res) {
|
|
208
|
+
if (existsSync(file) && !force) {
|
|
209
|
+
res.skipped.push(file);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
213
|
+
writeFileSync(file, content, "utf-8");
|
|
214
|
+
res.written.push(file);
|
|
215
|
+
}
|
|
216
|
+
/** Scaffold the rine channel, tools, skill, and `.env.example` block. */
|
|
217
|
+
function scaffoldRine(opts = {}) {
|
|
218
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
219
|
+
const agentDir = join(cwd, opts.dir ?? "agent");
|
|
220
|
+
const path = opts.path ?? DEFAULT_INBOUND_PATH;
|
|
221
|
+
const res = {
|
|
222
|
+
written: [],
|
|
223
|
+
skipped: []
|
|
224
|
+
};
|
|
225
|
+
const force = opts.force ?? false;
|
|
226
|
+
if (opts.channel ?? true) writeFile(join(agentDir, "channels", "rine.ts"), channelFileContent(), force, res);
|
|
227
|
+
for (const spec of resolveToolSelection(opts.tools)) writeFile(join(agentDir, "tools", `${spec.name}.ts`), toolFileContent(spec), force, res);
|
|
228
|
+
writeFile(join(agentDir, "skills", "rine", "SKILL.md"), RINE_SKILL_FILE, force, res);
|
|
229
|
+
const envFile = join(cwd, ".env.example");
|
|
230
|
+
const block = envExampleBlock(path);
|
|
231
|
+
const existing = existsSync(envFile) ? readFileSync(envFile, "utf-8") : "";
|
|
232
|
+
if (!existing.includes(ENV_MARKER)) {
|
|
233
|
+
writeFileSync(envFile, existing.length > 0 ? `${existing.trimEnd()}\n\n${block}` : block, "utf-8");
|
|
234
|
+
res.written.push(envFile);
|
|
235
|
+
} else res.skipped.push(envFile);
|
|
236
|
+
return res;
|
|
237
|
+
}
|
|
238
|
+
//#endregion
|
|
239
|
+
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/scaffold.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as toolFileContent, i as scaffoldRine, n as envExampleBlock, r as resolveToolSelection, t as channelFileContent } from "./scaffold-
|
|
1
|
+
import { a as toolFileContent, i as scaffoldRine, n as envExampleBlock, r as resolveToolSelection, t as channelFileContent } from "./scaffold-DQ2CA1kD.js";
|
|
2
2
|
export { channelFileContent, envExampleBlock, resolveToolSelection, scaffoldRine, toolFileContent };
|