@rine-network/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +96 -0
- package/LICENSE +291 -0
- package/README.md +127 -0
- package/dist/_parity.d.ts +34 -0
- package/dist/agent.d.ts +115 -0
- package/dist/api/adapters.d.ts +47 -0
- package/dist/api/http.d.ts +164 -0
- package/dist/api/middleware.d.ts +100 -0
- package/dist/client.d.ts +523 -0
- package/dist/errors.d.ts +80 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +3028 -0
- package/dist/onboard.d.ts +40 -0
- package/dist/resources/conversation.d.ts +111 -0
- package/dist/resources/decrypt.d.ts +44 -0
- package/dist/resources/discovery.d.ts +66 -0
- package/dist/resources/groups.d.ts +146 -0
- package/dist/resources/identity.d.ts +272 -0
- package/dist/resources/messages.d.ts +110 -0
- package/dist/resources/polling.d.ts +43 -0
- package/dist/resources/streams.d.ts +50 -0
- package/dist/resources/webhooks.d.ts +92 -0
- package/dist/types.d.ts +1362 -0
- package/dist/utils/abort.d.ts +40 -0
- package/dist/utils/cursor-page.d.ts +23 -0
- package/dist/utils/schema.d.ts +58 -0
- package/dist/utils/seen-ids.d.ts +23 -0
- package/dist/utils/sleep.d.ts +10 -0
- package/dist/utils/sse.d.ts +28 -0
- package/package.json +70 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Standalone org registration — REQ-01, REQ-02, REQ-03.
|
|
3
|
+
*
|
|
4
|
+
* Module-level function (not a client method) because credentials don't
|
|
5
|
+
* exist yet at registration time. Delegates to rine-core's
|
|
6
|
+
* `performRegistration` for the PoW + credential persistence flow.
|
|
7
|
+
*/
|
|
8
|
+
import { validateSlug } from "@rine-network/core";
|
|
9
|
+
export { validateSlug };
|
|
10
|
+
export interface RegisterOptions {
|
|
11
|
+
/** API base URL (e.g. "https://rine.network"). */
|
|
12
|
+
apiUrl: string;
|
|
13
|
+
/** Path to the rine config directory for credential persistence. */
|
|
14
|
+
configDir: string;
|
|
15
|
+
/** Registration email address. */
|
|
16
|
+
email: string;
|
|
17
|
+
/** Organisation slug (validated client-side via `validateSlug`). */
|
|
18
|
+
slug: string;
|
|
19
|
+
/** Organisation display name. */
|
|
20
|
+
name: string;
|
|
21
|
+
/** Optional PoW progress callback — called with 0-100. */
|
|
22
|
+
onProgress?: (pct: number) => void;
|
|
23
|
+
}
|
|
24
|
+
/** Returned on successful registration. */
|
|
25
|
+
export interface RegistrationResult {
|
|
26
|
+
orgId: string;
|
|
27
|
+
clientId: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Register a new org on the Rine network.
|
|
31
|
+
*
|
|
32
|
+
* Solves the RSA time-lock proof-of-work, saves credentials to
|
|
33
|
+
* `{configDir}/credentials.json`, and caches the initial OAuth token.
|
|
34
|
+
*
|
|
35
|
+
* @throws {ValidationError} If the slug fails client-side validation.
|
|
36
|
+
* @throws {ConflictError} If the email or slug is already registered.
|
|
37
|
+
* @throws {RateLimitError} On 429 from the server.
|
|
38
|
+
* @throws {RineError} On PoW challenge expiry or other failures.
|
|
39
|
+
*/
|
|
40
|
+
export declare function register(opts: RegisterOptions): Promise<RegistrationResult>;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ConversationScope` — SPEC §11.2.
|
|
3
|
+
*
|
|
4
|
+
* A lightweight builder returned by `client.conversation(convId)` that
|
|
5
|
+
* auto-scopes `send`, `reply`, `messages`, and `history` to a single
|
|
6
|
+
* `conversation_id`. This is explicitly NOT the deferred "conversation
|
|
7
|
+
* management API" (SPEC §10.13) — no `metadata()` / `status()` /
|
|
8
|
+
* `participants()` methods in v0.1.
|
|
9
|
+
*
|
|
10
|
+
* Design notes:
|
|
11
|
+
*
|
|
12
|
+
* - `send()` routes through `client.reply(anchorMessageId, …)` when the
|
|
13
|
+
* scope was built from a message (the common case). The server's reply
|
|
14
|
+
* endpoint threads the new message into the original conversation.
|
|
15
|
+
* Scopes built from bare conversation id strings throw on `send()` —
|
|
16
|
+
* the old `parentConversationId` path only created sub-conversations.
|
|
17
|
+
*
|
|
18
|
+
* - `reply()` delegates straight through; the server infers the
|
|
19
|
+
* conversation from the parent message id. The scoped method exists
|
|
20
|
+
* for ergonomic symmetry (so agents inside the scope don't have to
|
|
21
|
+
* reach for `ctx.client.reply`).
|
|
22
|
+
*
|
|
23
|
+
* - `messages()` post-filters the agent-wide SSE stream by
|
|
24
|
+
* `conversation_id` — the server's stream endpoint is per-agent in
|
|
25
|
+
* v0.1, not per-conversation. When a server-side
|
|
26
|
+
* `GET /conversations/{id}/stream` ships, this method can switch
|
|
27
|
+
* transports without changing its public signature.
|
|
28
|
+
*
|
|
29
|
+
* - `history()` walks `client.inbox({ cursor, limit })` pages and drops
|
|
30
|
+
* items whose `conversation_id` does not match. Also a v0.1 trade
|
|
31
|
+
* (SPEC §11.2.2) — same migration story as `messages()`.
|
|
32
|
+
*
|
|
33
|
+
* Typed generics (`send<T>`, `messages<T>({ schema })`, etc.) landed in
|
|
34
|
+
* Step 19. The four methods thread a `<T = unknown>` generic and a
|
|
35
|
+
* `schema?: StandardSchemaV1<unknown, T>` slot so one schema written once
|
|
36
|
+
* narrows an entire conversation's payload type end-to-end.
|
|
37
|
+
*/
|
|
38
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
39
|
+
import type { AsyncRineClient, MessagesOptions, ReplyOptions } from "../client.js";
|
|
40
|
+
import { type AgentHandle, type AgentUuid, type DecryptedMessage, type GroupHandle, type GroupUuid, type MessageRead, type MessageUuid } from "../types.js";
|
|
41
|
+
type Recipient = AgentHandle | AgentUuid | GroupHandle | GroupUuid;
|
|
42
|
+
/** Options accepted by `ConversationScope.send` — maps to `ReplyOptions<T>`
|
|
43
|
+
* when the scope is message-anchored (the common case). */
|
|
44
|
+
export type ConversationSendOptions<T = unknown> = ReplyOptions<T>;
|
|
45
|
+
/** Options accepted by `ConversationScope.reply` — identical to `ReplyOptions<T>`. */
|
|
46
|
+
export type ConversationReplyOptions<T = unknown> = ReplyOptions<T>;
|
|
47
|
+
/** Options accepted by `ConversationScope.messages` — `MessagesOptions<T>`
|
|
48
|
+
* minus the `includeReserved` debug escape hatch, which is meaningless
|
|
49
|
+
* inside a scope that already drops everything except the pinned
|
|
50
|
+
* conversation. Using `Omit` keeps this type aligned with
|
|
51
|
+
* `MessagesOptions` for free as new fields land there. */
|
|
52
|
+
export type ConversationMessagesOptions<T = unknown> = Omit<MessagesOptions<T>, "includeReserved">;
|
|
53
|
+
export interface ConversationHistoryOptions<T = unknown> {
|
|
54
|
+
/** Page size forwarded to `client.inbox()`. Default: 50. */
|
|
55
|
+
limit?: number;
|
|
56
|
+
/** Starting cursor. Defaults to the first page. */
|
|
57
|
+
cursor?: string;
|
|
58
|
+
/** Hard cap on items yielded across all pages. Unbounded by default. */
|
|
59
|
+
maxItems?: number;
|
|
60
|
+
/** Agent override forwarded to `client.inbox()`. */
|
|
61
|
+
agent?: string;
|
|
62
|
+
signal?: AbortSignal;
|
|
63
|
+
/**
|
|
64
|
+
* Standard Schema v1 — narrows `plaintext` on every yielded message.
|
|
65
|
+
* A decrypt-failed envelope (with `decrypt_error`) is yielded untouched
|
|
66
|
+
* so callers can still observe the failure; a successful decrypt that
|
|
67
|
+
* fails schema validation throws `ValidationError` out of the generator.
|
|
68
|
+
*/
|
|
69
|
+
schema?: StandardSchemaV1<unknown, T>;
|
|
70
|
+
}
|
|
71
|
+
export declare class ConversationScope {
|
|
72
|
+
private readonly client;
|
|
73
|
+
readonly id: string;
|
|
74
|
+
/**
|
|
75
|
+
* Peer auto-wired when the scope was built via `client.conversation(msg)`.
|
|
76
|
+
* When set, the two-arg `scope.send(payload)` form routes to this peer
|
|
77
|
+
* without requiring an explicit recipient. Null when the scope was
|
|
78
|
+
* built from a bare conversation id.
|
|
79
|
+
*/
|
|
80
|
+
readonly peer: Recipient | null;
|
|
81
|
+
/**
|
|
82
|
+
* Anchor message id — set when the scope was built via
|
|
83
|
+
* `client.conversation(msg)`. When present, `scope.send()` routes
|
|
84
|
+
* through `client.reply(anchorMessageId, …)` so the server threads
|
|
85
|
+
* the new message into the existing conversation. Null when the
|
|
86
|
+
* scope was built from a bare conversation id string.
|
|
87
|
+
*/
|
|
88
|
+
readonly anchorMessageId: MessageUuid | null;
|
|
89
|
+
constructor(client: AsyncRineClient, id: string, peer?: Recipient | null, anchorMessageId?: MessageUuid | null);
|
|
90
|
+
/**
|
|
91
|
+
* Send a message in this conversation.
|
|
92
|
+
*
|
|
93
|
+
* scope.send(to, payload) // explicit recipient
|
|
94
|
+
* scope.send(payload) // uses the peer derived from the
|
|
95
|
+
* // originating message
|
|
96
|
+
*
|
|
97
|
+
* When the scope was built via `client.conversation(msg)` (i.e. it has
|
|
98
|
+
* an `anchorMessageId`), sends route through `client.reply()` so the
|
|
99
|
+
* server threads the new message into the existing conversation. A scope
|
|
100
|
+
* built from a bare conversation id string throws — `parentConversationId`
|
|
101
|
+
* on `POST /messages` only creates sub-conversations, not threads.
|
|
102
|
+
*/
|
|
103
|
+
send<T = unknown>(to: Recipient, payload: T, opts?: ConversationSendOptions<T>): Promise<MessageRead>;
|
|
104
|
+
send<T = unknown>(payload: T, opts?: ConversationSendOptions<T>): Promise<MessageRead>;
|
|
105
|
+
reply<T = unknown>(messageId: MessageUuid, payload: T, opts?: ConversationReplyOptions<T>): Promise<MessageRead>;
|
|
106
|
+
messages<T = unknown>(opts?: ConversationMessagesOptions<T>): AsyncIterable<DecryptedMessage<T>>;
|
|
107
|
+
history<T = unknown>(opts?: ConversationHistoryOptions<T>): AsyncIterable<DecryptedMessage<T>>;
|
|
108
|
+
private messagesGenerator;
|
|
109
|
+
private historyGenerator;
|
|
110
|
+
}
|
|
111
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared decryption helper used by `messages.inbox()`, `messages.read()`,
|
|
3
|
+
* `messages.sendAndWait()` (Phase 2), and `client.messages()` (§11.1).
|
|
4
|
+
*
|
|
5
|
+
* Dispatch is driven by `encryption_version`:
|
|
6
|
+
* - `hpke-v1` → `decryptMessage` (1:1, recipient's X25519 private key).
|
|
7
|
+
* - `sender-key-v1` → `decryptGroupMessage`. On a sender-key dispatch failure,
|
|
8
|
+
* optionally retries once after calling
|
|
9
|
+
* `fetchAndIngestPendingSKDistributions` (matches Python
|
|
10
|
+
* SDK `read()` discipline).
|
|
11
|
+
* - anything else → returned as-is with `decrypt_error` populated.
|
|
12
|
+
*
|
|
13
|
+
* Crypto failures (including the post-retry failure on the sender-key path)
|
|
14
|
+
* populate `decrypt_error` and do NOT throw — callers branch on
|
|
15
|
+
* `msg.decrypt_error !== null`. User cancellation (`AbortError`) is always
|
|
16
|
+
* re-thrown so a cancelled `inbox()` rejects cleanly instead of resolving
|
|
17
|
+
* with a page of "failed" items.
|
|
18
|
+
*/
|
|
19
|
+
import { type HttpClient as CoreHttpClient } from "@rine-network/core";
|
|
20
|
+
import type { DecryptedMessage } from "../types.js";
|
|
21
|
+
/**
|
|
22
|
+
* Looser input shape accepted by `decryptEnvelope` and its helpers.
|
|
23
|
+
*
|
|
24
|
+
* The `parse(DecryptedMessageSchema, raw)` adapter erases Zod's precise
|
|
25
|
+
* output type through its `z.ZodType<T>` parameter, so the value we pass
|
|
26
|
+
* here is statically typed with a few fields still optional even though
|
|
27
|
+
* the Zod `.default()` chains guarantee them at runtime. Accepting the
|
|
28
|
+
* loose type avoids sprinkling `as` casts at every call site; the two
|
|
29
|
+
* `applyDecrypt*` helpers normalize the output back to the full
|
|
30
|
+
* `DecryptedMessage` shape before returning.
|
|
31
|
+
*/
|
|
32
|
+
export type ParsedDecryptedMessage = Omit<DecryptedMessage, "metadata" | "verified" | "verification_status"> & {
|
|
33
|
+
metadata?: Record<string, unknown>;
|
|
34
|
+
verified?: boolean;
|
|
35
|
+
verification_status?: DecryptedMessage["verification_status"];
|
|
36
|
+
};
|
|
37
|
+
export interface DecryptEnvelopeOptions {
|
|
38
|
+
readonly core: CoreHttpClient;
|
|
39
|
+
readonly configDir: string;
|
|
40
|
+
readonly agentId: string;
|
|
41
|
+
readonly msg: ParsedDecryptedMessage;
|
|
42
|
+
readonly retrySenderKey?: boolean;
|
|
43
|
+
}
|
|
44
|
+
export declare function decryptEnvelope(opts: DecryptEnvelopeOptions): Promise<DecryptedMessage>;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discovery resource — discover, inspect, discoverGroups.
|
|
3
|
+
*/
|
|
4
|
+
import type { SDKHttpClient } from "../api/http.js";
|
|
5
|
+
export interface DiscoverGroupsOptions {
|
|
6
|
+
q?: string;
|
|
7
|
+
limit?: number;
|
|
8
|
+
cursor?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface DiscoveryFilters {
|
|
11
|
+
q?: string;
|
|
12
|
+
category?: string;
|
|
13
|
+
language?: string;
|
|
14
|
+
verified?: boolean;
|
|
15
|
+
limit?: number;
|
|
16
|
+
cursor?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare class DiscoveryResource {
|
|
19
|
+
private readonly http;
|
|
20
|
+
constructor(http: SDKHttpClient);
|
|
21
|
+
discover(filters?: DiscoveryFilters): Promise<import("../index.js").CursorPage<{
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
handle: string;
|
|
25
|
+
verified: boolean;
|
|
26
|
+
description?: string | null | undefined;
|
|
27
|
+
category?: string | null | undefined;
|
|
28
|
+
}>>;
|
|
29
|
+
/**
|
|
30
|
+
* Fetch a directory agent profile and unwrap the A2A card envelope
|
|
31
|
+
*
|
|
32
|
+
*
|
|
33
|
+
* Accepts either a UUID (pass-through) or an agent handle
|
|
34
|
+
* (`name@org.rine.network`, resolved via WebFinger by
|
|
35
|
+
* `resolveToUuid`). The directory route only accepts UUIDs, so the
|
|
36
|
+
* handle lookup has to happen client-side.
|
|
37
|
+
*
|
|
38
|
+
* Server response shape:
|
|
39
|
+
* ```
|
|
40
|
+
* {
|
|
41
|
+
* card: { name, description, rine: { agent_id, handle, category, verified, human_oversight } },
|
|
42
|
+
* directory_metadata: { registered_at, ... }
|
|
43
|
+
* }
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* Legacy flat shape is still accepted (the fallback `parse()` branch).
|
|
47
|
+
*/
|
|
48
|
+
inspect(handleOrId: string): Promise<{
|
|
49
|
+
id: string;
|
|
50
|
+
name: string;
|
|
51
|
+
handle: string;
|
|
52
|
+
human_oversight: boolean;
|
|
53
|
+
verified: boolean;
|
|
54
|
+
created_at?: string | null | undefined;
|
|
55
|
+
description?: string | null | undefined;
|
|
56
|
+
category?: string | null | undefined;
|
|
57
|
+
}>;
|
|
58
|
+
discoverGroups(opts?: DiscoverGroupsOptions): Promise<import("../index.js").CursorPage<{
|
|
59
|
+
id: string;
|
|
60
|
+
name: string;
|
|
61
|
+
handle: string;
|
|
62
|
+
visibility: string;
|
|
63
|
+
member_count: number;
|
|
64
|
+
description?: string | null | undefined;
|
|
65
|
+
}>>;
|
|
66
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Groups resource — create, get, list, join, members, invite,
|
|
3
|
+
* update, delete, removeMember, listRequests, vote.
|
|
4
|
+
*
|
|
5
|
+
* Step 10 — Track B: routes + bodies aligned with server endpoints per
|
|
6
|
+
* SPEC §10.6. Handle-resolution (`_resolveGroupAsync`) is not added here
|
|
7
|
+
* (Step 11+), so UUID-only parameters remain the current limit.
|
|
8
|
+
*/
|
|
9
|
+
import type { SDKHttpClient } from "../api/http.js";
|
|
10
|
+
import type { AgentUuid, GroupUuid, JoinRequestRead, JoinResult } from "../types.js";
|
|
11
|
+
export interface GroupCreateOptions {
|
|
12
|
+
description?: string;
|
|
13
|
+
enrollment?: "open" | "closed" | "majority" | "unanimity";
|
|
14
|
+
visibility?: "public" | "private";
|
|
15
|
+
signal?: AbortSignal;
|
|
16
|
+
}
|
|
17
|
+
export interface InviteOptions {
|
|
18
|
+
message?: string;
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
}
|
|
21
|
+
export interface GroupUpdateOptions {
|
|
22
|
+
description?: string;
|
|
23
|
+
enrollment?: "open" | "closed" | "majority" | "unanimity";
|
|
24
|
+
visibility?: "public" | "private";
|
|
25
|
+
voteDurationHours?: number;
|
|
26
|
+
signal?: AbortSignal;
|
|
27
|
+
}
|
|
28
|
+
export declare class GroupsResource {
|
|
29
|
+
private readonly http;
|
|
30
|
+
constructor(http: SDKHttpClient);
|
|
31
|
+
list(): Promise<import("../index.js").CursorPage<{
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
created_at: string;
|
|
35
|
+
handle: string;
|
|
36
|
+
enrollment_policy: string;
|
|
37
|
+
visibility: string;
|
|
38
|
+
isolated: boolean;
|
|
39
|
+
vote_duration_hours: number;
|
|
40
|
+
member_count: number;
|
|
41
|
+
description?: string | null | undefined;
|
|
42
|
+
}>>;
|
|
43
|
+
/**
|
|
44
|
+
* Create a new group. Two call styles:
|
|
45
|
+
*
|
|
46
|
+
* client.groups.create('my-group', { visibility: 'public' })
|
|
47
|
+
* client.groups.create({ name: 'my-group', visibility: 'public' })
|
|
48
|
+
*
|
|
49
|
+
* The options-bag form matches the rest of the SDK surface (`inbox`,
|
|
50
|
+
* `discover`, `sendAndWait`) and is the recommended ergonomic for
|
|
51
|
+
* first-time users; the positional form is kept for existing callers.
|
|
52
|
+
*/
|
|
53
|
+
create(nameOrOpts: string | ({
|
|
54
|
+
name: string;
|
|
55
|
+
} & GroupCreateOptions), maybeOpts?: GroupCreateOptions): Promise<{
|
|
56
|
+
id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
created_at: string;
|
|
59
|
+
handle: string;
|
|
60
|
+
enrollment_policy: string;
|
|
61
|
+
visibility: string;
|
|
62
|
+
isolated: boolean;
|
|
63
|
+
vote_duration_hours: number;
|
|
64
|
+
member_count: number;
|
|
65
|
+
description?: string | null | undefined;
|
|
66
|
+
}>;
|
|
67
|
+
get(groupId: GroupUuid): Promise<{
|
|
68
|
+
id: string;
|
|
69
|
+
name: string;
|
|
70
|
+
created_at: string;
|
|
71
|
+
handle: string;
|
|
72
|
+
enrollment_policy: string;
|
|
73
|
+
visibility: string;
|
|
74
|
+
isolated: boolean;
|
|
75
|
+
vote_duration_hours: number;
|
|
76
|
+
member_count: number;
|
|
77
|
+
description?: string | null | undefined;
|
|
78
|
+
}>;
|
|
79
|
+
/**
|
|
80
|
+
* Update group metadata.
|
|
81
|
+
*
|
|
82
|
+
* Route: `PATCH /groups/{id}` with body of camelCase → snake_case
|
|
83
|
+
* mapped fields. Previously missing from the TS SDK.
|
|
84
|
+
*/
|
|
85
|
+
update(groupId: GroupUuid, opts: GroupUpdateOptions): Promise<{
|
|
86
|
+
id: string;
|
|
87
|
+
name: string;
|
|
88
|
+
created_at: string;
|
|
89
|
+
handle: string;
|
|
90
|
+
enrollment_policy: string;
|
|
91
|
+
visibility: string;
|
|
92
|
+
isolated: boolean;
|
|
93
|
+
vote_duration_hours: number;
|
|
94
|
+
member_count: number;
|
|
95
|
+
description?: string | null | undefined;
|
|
96
|
+
}>;
|
|
97
|
+
/**
|
|
98
|
+
* Delete a group (owner only). Previously missing from the TS SDK.
|
|
99
|
+
*/
|
|
100
|
+
delete(groupId: GroupUuid, opts?: {
|
|
101
|
+
signal?: AbortSignal;
|
|
102
|
+
}): Promise<void>;
|
|
103
|
+
join(groupId: GroupUuid, opts?: {
|
|
104
|
+
message?: string;
|
|
105
|
+
signal?: AbortSignal;
|
|
106
|
+
}): Promise<JoinResult>;
|
|
107
|
+
invite(groupId: GroupUuid, agentId: AgentUuid, opts?: InviteOptions): Promise<{
|
|
108
|
+
status: string;
|
|
109
|
+
request_id?: string | null | undefined;
|
|
110
|
+
}>;
|
|
111
|
+
/**
|
|
112
|
+
* Remove a member from a group. Previously missing from the TS SDK.
|
|
113
|
+
*
|
|
114
|
+
* Route: `DELETE /groups/{groupId}/members/{agentId}`.
|
|
115
|
+
*/
|
|
116
|
+
removeMember(groupId: GroupUuid, agentId: AgentUuid, opts?: {
|
|
117
|
+
signal?: AbortSignal;
|
|
118
|
+
}): Promise<void>;
|
|
119
|
+
members(groupId: GroupUuid): Promise<import("../index.js").CursorPage<{
|
|
120
|
+
group_id: string;
|
|
121
|
+
agent_id: string;
|
|
122
|
+
role: string;
|
|
123
|
+
joined_at: string;
|
|
124
|
+
id?: string | null | undefined;
|
|
125
|
+
agent_handle?: string | null | undefined;
|
|
126
|
+
}>>;
|
|
127
|
+
/**
|
|
128
|
+
* List pending join requests for a group.
|
|
129
|
+
*
|
|
130
|
+
* Route: `GET /groups/{groupId}/requests` (fixes parity gap — TS
|
|
131
|
+
* previously used `/join-requests`). Returns a plain array to match
|
|
132
|
+
* Python SDK `groups.list_requests`.
|
|
133
|
+
*/
|
|
134
|
+
listRequests(groupId: GroupUuid): Promise<readonly JoinRequestRead[]>;
|
|
135
|
+
/**
|
|
136
|
+
* Vote on a pending join request (fixes audit C-adjacent — missing
|
|
137
|
+
* group segment).
|
|
138
|
+
*
|
|
139
|
+
* Route: `POST /groups/{groupId}/requests/{requestId}/vote`.
|
|
140
|
+
*/
|
|
141
|
+
vote(groupId: GroupUuid, requestId: string, choice: "approve" | "deny"): Promise<{
|
|
142
|
+
status: string;
|
|
143
|
+
your_vote: string;
|
|
144
|
+
request_id: string;
|
|
145
|
+
}>;
|
|
146
|
+
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity resource — whoami, createAgent, listAgents, getAgent, updateAgent,
|
|
3
|
+
* revokeAgent, rotateKeys, agent cards, poll tokens, quotas.
|
|
4
|
+
*/
|
|
5
|
+
import type { SDKHttpClient } from "../api/http.js";
|
|
6
|
+
import type { AgentUuid, ErasureResult, OrgRead } from "../types.js";
|
|
7
|
+
export interface CreateAgentOptions {
|
|
8
|
+
human_oversight?: boolean;
|
|
9
|
+
unlisted?: boolean;
|
|
10
|
+
signal?: AbortSignal;
|
|
11
|
+
}
|
|
12
|
+
export interface RotateKeysOptions {
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
}
|
|
15
|
+
export type UpdateAgentPatch = {
|
|
16
|
+
name?: string;
|
|
17
|
+
human_oversight?: boolean;
|
|
18
|
+
incoming_policy?: "accept_all" | "groups_only";
|
|
19
|
+
outgoing_policy?: "send_all" | "groups_only";
|
|
20
|
+
unlisted?: boolean;
|
|
21
|
+
};
|
|
22
|
+
export interface UpdateOrgPatch {
|
|
23
|
+
name?: string;
|
|
24
|
+
contact_email?: string;
|
|
25
|
+
country_code?: string;
|
|
26
|
+
slug?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface EraseOrgOptions {
|
|
29
|
+
confirm: boolean;
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
}
|
|
32
|
+
export interface AgentCardInput {
|
|
33
|
+
name: string;
|
|
34
|
+
description: string;
|
|
35
|
+
version?: string;
|
|
36
|
+
is_public?: boolean;
|
|
37
|
+
skills?: Array<{
|
|
38
|
+
id: string;
|
|
39
|
+
name: string;
|
|
40
|
+
description: string;
|
|
41
|
+
tags?: string[];
|
|
42
|
+
}>;
|
|
43
|
+
categories?: string[];
|
|
44
|
+
languages?: string[];
|
|
45
|
+
pricing_model?: "free" | "per_request" | "subscription" | "negotiated";
|
|
46
|
+
}
|
|
47
|
+
export declare class IdentityResource {
|
|
48
|
+
private readonly http;
|
|
49
|
+
constructor(http: SDKHttpClient);
|
|
50
|
+
/**
|
|
51
|
+
* Fetch the current org identity, agent list, and trust tier.
|
|
52
|
+
*
|
|
53
|
+
* Routes: `GET /agents` + `GET /org` — the server does not expose a
|
|
54
|
+
* single `/agents/whoami` endpoint; the Python SDK makes both calls and
|
|
55
|
+
* composes the `WhoAmI` client-side (`_client.py:605-621`). This TS
|
|
56
|
+
* implementation mirrors that exactly.
|
|
57
|
+
*/
|
|
58
|
+
whoami(opts?: {
|
|
59
|
+
signal?: AbortSignal;
|
|
60
|
+
}): Promise<{
|
|
61
|
+
trust_tier: number;
|
|
62
|
+
org: {
|
|
63
|
+
id: string;
|
|
64
|
+
name: string;
|
|
65
|
+
trust_tier: number;
|
|
66
|
+
agent_count: number;
|
|
67
|
+
created_at: string;
|
|
68
|
+
slug?: string | null | undefined;
|
|
69
|
+
contact_email?: string | null | undefined;
|
|
70
|
+
country_code?: string | null | undefined;
|
|
71
|
+
};
|
|
72
|
+
agents: {
|
|
73
|
+
id: string;
|
|
74
|
+
name: string;
|
|
75
|
+
created_at: string;
|
|
76
|
+
handle: string;
|
|
77
|
+
human_oversight: boolean;
|
|
78
|
+
incoming_policy: string;
|
|
79
|
+
outgoing_policy: string;
|
|
80
|
+
revoked_at?: string | null | undefined;
|
|
81
|
+
unlisted?: boolean | undefined;
|
|
82
|
+
verification_words?: string | null | undefined;
|
|
83
|
+
warnings?: string[] | null | undefined;
|
|
84
|
+
poll_url?: string | null | undefined;
|
|
85
|
+
}[];
|
|
86
|
+
}>;
|
|
87
|
+
/**
|
|
88
|
+
* Create a new agent with locally generated E2EE keypairs.
|
|
89
|
+
*
|
|
90
|
+
* Matches Python `rine._onboard.create_agent` flow:
|
|
91
|
+
* 1. Generate Ed25519 + X25519 keypairs via rine-core `generateAgentKeys()`.
|
|
92
|
+
* 2. POST `/agents` with `{name, human_oversight, unlisted, signing_public_key,
|
|
93
|
+
* encryption_public_key}` (public keys as JWKs). The server's `AgentCreate`
|
|
94
|
+
* schema is `extra="forbid"`, so no other fields may be sent on creation.
|
|
95
|
+
* 3. Persist private keys under `{configDir}/keys/{agentId}/` via
|
|
96
|
+
* rine-core `saveAgentKeys()` so the new agent can immediately participate
|
|
97
|
+
* in E2EE send/receive without any manual key setup.
|
|
98
|
+
*
|
|
99
|
+
* Partial failure: if the POST succeeds but `saveAgentKeys` throws, the
|
|
100
|
+
* server-side agent exists but the caller has no private keys — surfaced
|
|
101
|
+
* as the raw I/O error. Callers must treat this as a partial failure.
|
|
102
|
+
*/
|
|
103
|
+
createAgent(name: string, opts?: CreateAgentOptions): Promise<{
|
|
104
|
+
id: string;
|
|
105
|
+
name: string;
|
|
106
|
+
created_at: string;
|
|
107
|
+
handle: string;
|
|
108
|
+
human_oversight: boolean;
|
|
109
|
+
incoming_policy: string;
|
|
110
|
+
outgoing_policy: string;
|
|
111
|
+
revoked_at?: string | null | undefined;
|
|
112
|
+
unlisted?: boolean | undefined;
|
|
113
|
+
verification_words?: string | null | undefined;
|
|
114
|
+
warnings?: string[] | null | undefined;
|
|
115
|
+
poll_url?: string | null | undefined;
|
|
116
|
+
}>;
|
|
117
|
+
listAgents(opts?: {
|
|
118
|
+
includeRevoked?: boolean;
|
|
119
|
+
}): Promise<{
|
|
120
|
+
id: string;
|
|
121
|
+
name: string;
|
|
122
|
+
created_at: string;
|
|
123
|
+
handle: string;
|
|
124
|
+
human_oversight: boolean;
|
|
125
|
+
incoming_policy: string;
|
|
126
|
+
outgoing_policy: string;
|
|
127
|
+
revoked_at?: string | null | undefined;
|
|
128
|
+
unlisted?: boolean | undefined;
|
|
129
|
+
verification_words?: string | null | undefined;
|
|
130
|
+
warnings?: string[] | null | undefined;
|
|
131
|
+
poll_url?: string | null | undefined;
|
|
132
|
+
}[]>;
|
|
133
|
+
getAgent(agentId: AgentUuid): Promise<{
|
|
134
|
+
id: string;
|
|
135
|
+
name: string;
|
|
136
|
+
created_at: string;
|
|
137
|
+
handle: string;
|
|
138
|
+
human_oversight: boolean;
|
|
139
|
+
incoming_policy: string;
|
|
140
|
+
outgoing_policy: string;
|
|
141
|
+
revoked_at?: string | null | undefined;
|
|
142
|
+
unlisted?: boolean | undefined;
|
|
143
|
+
verification_words?: string | null | undefined;
|
|
144
|
+
warnings?: string[] | null | undefined;
|
|
145
|
+
poll_url?: string | null | undefined;
|
|
146
|
+
}>;
|
|
147
|
+
updateAgent(agentId: AgentUuid, patch: UpdateAgentPatch): Promise<{
|
|
148
|
+
id: string;
|
|
149
|
+
name: string;
|
|
150
|
+
created_at: string;
|
|
151
|
+
handle: string;
|
|
152
|
+
human_oversight: boolean;
|
|
153
|
+
incoming_policy: string;
|
|
154
|
+
outgoing_policy: string;
|
|
155
|
+
revoked_at?: string | null | undefined;
|
|
156
|
+
unlisted?: boolean | undefined;
|
|
157
|
+
verification_words?: string | null | undefined;
|
|
158
|
+
warnings?: string[] | null | undefined;
|
|
159
|
+
poll_url?: string | null | undefined;
|
|
160
|
+
}>;
|
|
161
|
+
revokeAgent(agentId: AgentUuid): Promise<{
|
|
162
|
+
id: string;
|
|
163
|
+
name: string;
|
|
164
|
+
created_at: string;
|
|
165
|
+
handle: string;
|
|
166
|
+
human_oversight: boolean;
|
|
167
|
+
incoming_policy: string;
|
|
168
|
+
outgoing_policy: string;
|
|
169
|
+
revoked_at?: string | null | undefined;
|
|
170
|
+
unlisted?: boolean | undefined;
|
|
171
|
+
verification_words?: string | null | undefined;
|
|
172
|
+
warnings?: string[] | null | undefined;
|
|
173
|
+
poll_url?: string | null | undefined;
|
|
174
|
+
}>;
|
|
175
|
+
/**
|
|
176
|
+
* Rotate this agent's signing + encryption keypairs.
|
|
177
|
+
*
|
|
178
|
+
* Route: `POST /agents/{id}/keys`.
|
|
179
|
+
*
|
|
180
|
+
* Generates fresh Ed25519 + X25519 keypairs locally, uploads the public
|
|
181
|
+
* halves to the server (JWK-encoded), then overwrites the on-disk private
|
|
182
|
+
* keys via `saveAgentKeys()`. Matches Python `AsyncRineClient.rotate_keys`
|
|
183
|
+
* flow.
|
|
184
|
+
*
|
|
185
|
+
* Key rotation is visible to future peers immediately; messages encrypted
|
|
186
|
+
* to the previous encryption key can still be decrypted as long as the
|
|
187
|
+
* caller retains a copy of the old private key out-of-band (the SDK does
|
|
188
|
+
* not keep a history of rotated-out keys).
|
|
189
|
+
*
|
|
190
|
+
* Partial failure: if the POST succeeds but `saveAgentKeys` throws mid-write,
|
|
191
|
+
* the server has the new public keys while the on-disk state may be
|
|
192
|
+
* inconsistent (`saveAgentKeys` writes signing.key then encryption.key as
|
|
193
|
+
* two separate file ops, not atomically). Senders will encrypt to the new
|
|
194
|
+
* keys the server advertises but the client may still hold the old private
|
|
195
|
+
* half — silent decryption failure. Track as rine-core follow-up.
|
|
196
|
+
*/
|
|
197
|
+
rotateKeys(agentId: AgentUuid, opts?: RotateKeysOptions): Promise<{
|
|
198
|
+
id: string;
|
|
199
|
+
name: string;
|
|
200
|
+
created_at: string;
|
|
201
|
+
handle: string;
|
|
202
|
+
human_oversight: boolean;
|
|
203
|
+
incoming_policy: string;
|
|
204
|
+
outgoing_policy: string;
|
|
205
|
+
revoked_at?: string | null | undefined;
|
|
206
|
+
unlisted?: boolean | undefined;
|
|
207
|
+
verification_words?: string | null | undefined;
|
|
208
|
+
warnings?: string[] | null | undefined;
|
|
209
|
+
poll_url?: string | null | undefined;
|
|
210
|
+
}>;
|
|
211
|
+
getAgentCard(agentId: AgentUuid): Promise<{
|
|
212
|
+
id: string;
|
|
213
|
+
name: string;
|
|
214
|
+
created_at: string;
|
|
215
|
+
agent_id: string;
|
|
216
|
+
is_public: boolean;
|
|
217
|
+
skills: Record<string, unknown>[];
|
|
218
|
+
rine: Record<string, unknown>;
|
|
219
|
+
description?: string | null | undefined;
|
|
220
|
+
version?: string | null | undefined;
|
|
221
|
+
updated_at?: string | null | undefined;
|
|
222
|
+
}>;
|
|
223
|
+
/**
|
|
224
|
+
* Upsert an agent card.
|
|
225
|
+
*
|
|
226
|
+
* Body shape: `{name, description, version?, is_public?, skills?, rine?}`
|
|
227
|
+
* where `categories`, `languages` and `pricing_model` are nested inside
|
|
228
|
+
* the `rine` sub-object — matches Python exactly. The previous TS
|
|
229
|
+
* flattened everything, which the server silently dropped.
|
|
230
|
+
*/
|
|
231
|
+
setAgentCard(agentId: AgentUuid, card: AgentCardInput): Promise<{
|
|
232
|
+
id: string;
|
|
233
|
+
name: string;
|
|
234
|
+
created_at: string;
|
|
235
|
+
agent_id: string;
|
|
236
|
+
is_public: boolean;
|
|
237
|
+
skills: Record<string, unknown>[];
|
|
238
|
+
rine: Record<string, unknown>;
|
|
239
|
+
description?: string | null | undefined;
|
|
240
|
+
version?: string | null | undefined;
|
|
241
|
+
updated_at?: string | null | undefined;
|
|
242
|
+
}>;
|
|
243
|
+
deleteAgentCard(agentId: AgentUuid): Promise<void>;
|
|
244
|
+
/**
|
|
245
|
+
* Regenerate the agent's poll token.
|
|
246
|
+
*
|
|
247
|
+
* Route: `POST /agents/{id}/poll-token` — the old `/poll-token/regenerate`
|
|
248
|
+
* path never existed on the server.
|
|
249
|
+
*/
|
|
250
|
+
regeneratePollToken(agentId: AgentUuid): Promise<{
|
|
251
|
+
poll_url: string;
|
|
252
|
+
}>;
|
|
253
|
+
revokePollToken(agentId: AgentUuid): Promise<void>;
|
|
254
|
+
getQuotas(): Promise<{
|
|
255
|
+
tier: number;
|
|
256
|
+
quotas: Record<string, {
|
|
257
|
+
limit: number | null;
|
|
258
|
+
used?: number | null | undefined;
|
|
259
|
+
}>;
|
|
260
|
+
}>;
|
|
261
|
+
/** Lazy-cached org ID for erase/export URL paths. */
|
|
262
|
+
private cachedOrgId;
|
|
263
|
+
/** Fetch the caller's org UUID, caching on the instance. */
|
|
264
|
+
private getOrgId;
|
|
265
|
+
updateOrg(patch: UpdateOrgPatch, opts?: {
|
|
266
|
+
signal?: AbortSignal;
|
|
267
|
+
}): Promise<OrgRead>;
|
|
268
|
+
eraseOrg(opts: EraseOrgOptions): Promise<ErasureResult>;
|
|
269
|
+
exportOrg(opts?: {
|
|
270
|
+
signal?: AbortSignal;
|
|
271
|
+
}): Promise<unknown[]>;
|
|
272
|
+
}
|