@agentmesh-p2p/sdk 0.0.0-stage → 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.
Files changed (68) hide show
  1. package/README.md +182 -2
  2. package/dist/auth.d.ts +66 -0
  3. package/dist/auth.js +164 -0
  4. package/dist/authorizer.d.ts +41 -0
  5. package/dist/authorizer.js +201 -0
  6. package/dist/base58.d.ts +2 -0
  7. package/dist/base58.js +57 -0
  8. package/dist/biscuit.d.ts +75 -0
  9. package/dist/biscuit.js +250 -0
  10. package/dist/bytes.d.ts +10 -0
  11. package/dist/bytes.js +51 -0
  12. package/dist/challenges.d.ts +16 -0
  13. package/dist/challenges.js +55 -0
  14. package/dist/conformance-join.d.ts +1 -0
  15. package/dist/conformance-join.js +257 -0
  16. package/dist/conformance.d.ts +1 -0
  17. package/dist/conformance.js +60 -0
  18. package/dist/controlplane.d.ts +123 -0
  19. package/dist/controlplane.js +368 -0
  20. package/dist/credential.d.ts +66 -0
  21. package/dist/credential.js +124 -0
  22. package/dist/discovery.d.ts +50 -0
  23. package/dist/discovery.js +150 -0
  24. package/dist/gen/agentmesh_pb.d.ts +2740 -0
  25. package/dist/gen/agentmesh_pb.js +591 -0
  26. package/dist/gen/datalog.d.ts +39 -0
  27. package/dist/gen/datalog.js +84 -0
  28. package/dist/host.d.ts +47 -0
  29. package/dist/host.js +109 -0
  30. package/dist/http1.d.ts +68 -0
  31. package/dist/http1.js +371 -0
  32. package/dist/identity.d.ts +31 -0
  33. package/dist/identity.js +125 -0
  34. package/dist/index.d.ts +18 -0
  35. package/dist/index.js +30 -0
  36. package/dist/libp2p-http-node.d.ts +17 -0
  37. package/dist/libp2p-http-node.js +116 -0
  38. package/dist/libp2p-http.d.ts +165 -0
  39. package/dist/libp2p-http.js +581 -0
  40. package/dist/mcp.d.ts +67 -0
  41. package/dist/mcp.js +157 -0
  42. package/dist/mesh.d.ts +151 -0
  43. package/dist/mesh.js +370 -0
  44. package/dist/platform/ingress.browser.d.ts +1 -0
  45. package/dist/platform/ingress.browser.js +16 -0
  46. package/dist/platform/ingress.d.ts +1 -0
  47. package/dist/platform/ingress.js +15 -0
  48. package/dist/platform/state.browser.d.ts +5 -0
  49. package/dist/platform/state.browser.js +47 -0
  50. package/dist/platform/state.d.ts +5 -0
  51. package/dist/platform/state.js +44 -0
  52. package/dist/platform/transports.browser.d.ts +3 -0
  53. package/dist/platform/transports.browser.js +27 -0
  54. package/dist/platform/transports.d.ts +3 -0
  55. package/dist/platform/transports.js +27 -0
  56. package/dist/platform/types.d.ts +7 -0
  57. package/dist/platform/types.js +14 -0
  58. package/dist/platform/wasm.browser.d.ts +2 -0
  59. package/dist/platform/wasm.browser.js +16 -0
  60. package/dist/platform/wasm.d.ts +2 -0
  61. package/dist/platform/wasm.js +56 -0
  62. package/dist/session.d.ts +316 -0
  63. package/dist/session.js +1269 -0
  64. package/dist/sync.d.ts +41 -0
  65. package/dist/sync.js +111 -0
  66. package/dist/tar.d.ts +25 -0
  67. package/dist/tar.js +406 -0
  68. package/package.json +74 -4
@@ -0,0 +1,150 @@
1
+ // Copyright 2026 Google LLC
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+ // The mesh's directory as a member uses it, as agentmesh-node does
15
+ // (internal/node/directory_client.go): the member keeps no DHT and asks the
16
+ // routers it holds over /mesh/directory/1.0.0, one DirectoryRequest per
17
+ // stream, one DirectoryResponse back. A request goes to one held router and
18
+ // to the next when it fails. The routers run the lookup across their own
19
+ // DHT. A key is the sha256 multihash of "mesh:service:<type>[:<name>]" for
20
+ // a service and of "mesh:peer:<peer_id>" for a member.
21
+ import { create, fromBinary, toBinary } from "@bufbuild/protobuf";
22
+ import { lpStream } from "@libp2p/utils";
23
+ import { sha256 } from "multiformats/hashes/sha2";
24
+ import { DirectoryRequestSchema, DirectoryResponseSchema, } from "./gen/agentmesh_pb.js";
25
+ /** api.DirectoryProtocolID. */
26
+ export const DIRECTORY_PROTOCOL = "/mesh/directory/1.0.0";
27
+ const REQUEST_TIMEOUT_MS = 10_000;
28
+ const MAX_DIRECTORY_MESSAGE_BYTES = 64 * 1024;
29
+ export const DEFAULT_LIMIT = 20;
30
+ export function isServiceType(value) {
31
+ return value === "mcp" || value === "inference" || value === "a2a" || value === "egress";
32
+ }
33
+ /** The sha256 multihash of a name: the two-byte header and the digest. */
34
+ async function directoryKey(name) {
35
+ return (await sha256.digest(new TextEncoder().encode(name))).bytes;
36
+ }
37
+ /** The directory key of a service type, or of one named service of that type (api.ServiceKey). */
38
+ export async function serviceKey(type, name) {
39
+ return directoryKey(["mesh:service", type, ...(name !== undefined && name !== "" ? [name] : [])].join(":"));
40
+ }
41
+ /** The directory key a member announces where it is reached under (api.PeerKey). */
42
+ export async function peerKey(peerId) {
43
+ return directoryKey(`mesh:peer:${peerId}`);
44
+ }
45
+ /** Splits "mcp://calculator" into its type and name; "" is the node's own catalog. */
46
+ export function parseServiceTarget(target) {
47
+ if (target === "") {
48
+ return { type: "", name: "" };
49
+ }
50
+ const m = /^(mcp|inference|a2a|egress):\/\/(.+)$/.exec(target);
51
+ if (!m) {
52
+ throw new Error(`service target must look like mcp://<name>, got ${JSON.stringify(target)}`);
53
+ }
54
+ return { type: m[1], name: m[2] };
55
+ }
56
+ /** No held router answered a directory request. */
57
+ export class DirectoryError extends Error {
58
+ constructor(message) {
59
+ super(message);
60
+ this.name = "DirectoryError";
61
+ }
62
+ }
63
+ /** One request to one router, answered or thrown. */
64
+ async function ask(conn, req, signal) {
65
+ const stream = await conn.newStream(DIRECTORY_PROTOCOL, { signal });
66
+ try {
67
+ const lp = lpStream(stream, { maxDataLength: MAX_DIRECTORY_MESSAGE_BYTES });
68
+ await lp.write(toBinary(DirectoryRequestSchema, req), { signal });
69
+ const resp = fromBinary(DirectoryResponseSchema, (await lp.read({ signal })).subarray());
70
+ if (resp.error !== "") {
71
+ throw new DirectoryError(resp.error);
72
+ }
73
+ return resp;
74
+ }
75
+ finally {
76
+ await stream.close().catch(() => stream.abort(new Error("directory stream not closed")));
77
+ }
78
+ }
79
+ /**
80
+ * Sends req to the held routers in turn until one answers. A router that
81
+ * is restarting costs the request a timeout, not an answer. A lookup one
82
+ * router answers with nothing is put to the next as well: a router cut
83
+ * off from the routers closest to the key answers from what it can reach.
84
+ */
85
+ export async function request(routers, req, signal) {
86
+ const lookup = req.request.case === "findProviders" || req.request.case === "findPeer";
87
+ let last;
88
+ let asked = 0;
89
+ let empty;
90
+ for (const router of routers) {
91
+ const conn = router.connection();
92
+ if (conn === undefined) {
93
+ continue;
94
+ }
95
+ asked++;
96
+ const bounded = signal === undefined ? AbortSignal.timeout(REQUEST_TIMEOUT_MS) : AbortSignal.any([signal, AbortSignal.timeout(REQUEST_TIMEOUT_MS)]);
97
+ try {
98
+ const resp = await ask(conn, req, bounded);
99
+ if (lookup && resp.providers.length === 0 && resp.peer === undefined) {
100
+ empty = resp;
101
+ continue;
102
+ }
103
+ return resp;
104
+ }
105
+ catch (err) {
106
+ last = err;
107
+ if (signal?.aborted === true) {
108
+ break;
109
+ }
110
+ }
111
+ }
112
+ if (empty !== undefined) {
113
+ return empty;
114
+ }
115
+ if (asked === 0) {
116
+ throw new DirectoryError("no held router to ask");
117
+ }
118
+ throw new DirectoryError(`no held router answered: ${last instanceof Error ? last.message : String(last)}`);
119
+ }
120
+ /**
121
+ * Announces this member as a provider of key, reached at addrs, to a held
122
+ * router; the router keeps the record and places it on the routers closest
123
+ * to the key.
124
+ */
125
+ export async function provide(routers, key, addrs, signal) {
126
+ await request(routers, create(DirectoryRequestSchema, { request: { case: "provide", value: { key, addrs } } }), signal);
127
+ }
128
+ /**
129
+ * Removes this member's record under key from the held router and from the
130
+ * routers it was placed on.
131
+ */
132
+ export async function withdraw(routers, key, signal) {
133
+ await request(routers, create(DirectoryRequestSchema, { request: { case: "withdraw", value: { key } } }), signal);
134
+ }
135
+ /** Who provides key, up to limit, with their addresses; empty when nobody does. */
136
+ export async function findProviders(routers, key, limit = DEFAULT_LIMIT, signal) {
137
+ const resp = await request(routers, create(DirectoryRequestSchema, { request: { case: "findProviders", value: { key, limit: Math.max(limit, 1) } } }), signal);
138
+ return resp.providers.slice(0, limit);
139
+ }
140
+ /**
141
+ * Where a peer is reached: its addresses, each ending in its peer ID,
142
+ * relayed ones included. Undefined when nobody knows the peer.
143
+ */
144
+ export async function findPeer(routers, peerId, signal) {
145
+ const resp = await request(routers, create(DirectoryRequestSchema, { request: { case: "findPeer", value: { peerId } } }), signal);
146
+ if (resp.peer === undefined || resp.peer.peerId !== peerId) {
147
+ return undefined;
148
+ }
149
+ return resp.peer;
150
+ }