@kybernesis/identity 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/NOTICE +2 -0
- package/README.md +55 -0
- package/dist/arp-auth.d.ts +25 -0
- package/dist/arp-auth.js +99 -0
- package/dist/channel.d.ts +14 -0
- package/dist/channel.js +26 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/instructions.d.ts +4 -0
- package/dist/instructions.js +14 -0
- package/dist/peers.d.ts +29 -0
- package/dist/peers.js +92 -0
- package/package.json +42 -0
package/NOTICE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# @kybernesis/identity
|
|
2
|
+
|
|
3
|
+
Give an eve agent its `.agent` name. ARP Cloud holds the identity, the key, the
|
|
4
|
+
permissions and the audit trail; this package is the thin end: it verifies the
|
|
5
|
+
tokens ARP Cloud signs when it delivers a message, serves the document ARP Cloud
|
|
6
|
+
checks when you attach the runtime, and turns your paired peers into tools.
|
|
7
|
+
|
|
8
|
+
No daemon. No socket. No private key in your deployment.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
eve add @kybernesis/identity-channel # agent/channels/arp.ts
|
|
14
|
+
eve add @kybernesis/identity-peers # agent/tools/arp-peers.ts
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Then, in the ARP console (`cloud.arp.run/names/<name>` → Runtime → Attach), give
|
|
18
|
+
it `https://<your-agent-host>/eve/v1/arp`. The console verifies the document this
|
|
19
|
+
package serves and hands you four variables to set on the deployment:
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
ARP_ISSUER=https://gateway.arp.run
|
|
23
|
+
ARP_AGENT_DID=did:web:<name>.agent
|
|
24
|
+
ARP_AGENT_CREDENTIAL=<shown once>
|
|
25
|
+
AGENTID_CHALLENGE=<from the attach step>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Add `arpAuth()` to your eve channel's auth walk so deliveries are accepted:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
// agent/channels/eve.ts
|
|
32
|
+
import { eveChannel } from "eve/channels/eve";
|
|
33
|
+
import { localDev } from "eve/channels/auth";
|
|
34
|
+
import { arpAuth } from "@kybernesis/identity";
|
|
35
|
+
|
|
36
|
+
export default eveChannel({ auth: [arpAuth(), localDev()] });
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
(With `@kybernesis/dispatch`: `dispatchChannel({ trustedPeers, extraAuth: [arpAuth()] })`.)
|
|
40
|
+
|
|
41
|
+
## What each piece does
|
|
42
|
+
|
|
43
|
+
- `arpAuth()` — route auth. A delivery from ARP Cloud carries an ES256 token
|
|
44
|
+
verified against `https://gateway.arp.run/.well-known/jwks.json`, naming this
|
|
45
|
+
agent as audience and the paired peer as subject. The session principal is
|
|
46
|
+
`principalType: "agent"`, `authenticator: "arp"`, with `peerDid`,
|
|
47
|
+
`connectionId`, `purpose` and `obligations` as attributes.
|
|
48
|
+
- `identityChannel()` — serves `GET /eve/v1/arp/.well-known/agentid-verification`
|
|
49
|
+
(`{ did, challenge }`) and `/eve/v1/arp/health`.
|
|
50
|
+
- `arpPeers()` — on every turn, lists active connections from ARP Cloud and
|
|
51
|
+
exposes `ask_<peer>` tools. Pair or revoke in the console; nothing to redeploy.
|
|
52
|
+
- `ARP_INSTRUCTIONS` — append to your instructions so the model uses the tools well.
|
|
53
|
+
|
|
54
|
+
Degrades, never throws at boot: with no credential there are simply no peer
|
|
55
|
+
tools; with no token the auth entry skips to the next one.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type AuthFn } from "eve/channels/auth";
|
|
2
|
+
export interface ArpAuthOptions {
|
|
3
|
+
/** ARP Cloud gateway origin. Defaults to ARP_ISSUER, then https://gateway.arp.run. */
|
|
4
|
+
issuer?: string;
|
|
5
|
+
/** This agent's identity, e.g. `did:web:samantha.agent`. Defaults to ARP_AGENT_DID. */
|
|
6
|
+
agentDid?: string;
|
|
7
|
+
/** fetch override (tests). */
|
|
8
|
+
fetchImpl?: typeof fetch;
|
|
9
|
+
/** JWKS cache lifetime (ms). Default 5 min. */
|
|
10
|
+
jwksTtlMs?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Route auth for messages ARP Cloud delivers to this agent.
|
|
14
|
+
*
|
|
15
|
+
* ARP Cloud (the gateway) signs every delivery with an ES256 key published at
|
|
16
|
+
* `<issuer>/.well-known/jwks.json`; the token names THIS agent as audience and
|
|
17
|
+
* the paired peer as subject. Policy, obligations and audit were evaluated by
|
|
18
|
+
* ARP Cloud before delivery, so a verified token is the authorization — the
|
|
19
|
+
* same offline-verification shape `@kybernesis/enterprise` uses.
|
|
20
|
+
*
|
|
21
|
+
* Returns `null` (skip to the next auth entry) for requests without an ARP
|
|
22
|
+
* token; throws a structured 401 only when the JWKS is unreachable, so a
|
|
23
|
+
* gateway outage is distinguishable from a bad credential.
|
|
24
|
+
*/
|
|
25
|
+
export declare function arpAuth(options?: ArpAuthOptions): AuthFn<Request>;
|
package/dist/arp-auth.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { createLocalJWKSet, jwtVerify } from "jose";
|
|
2
|
+
import { UnauthenticatedError, extractBearerToken } from "eve/channels/auth";
|
|
3
|
+
/**
|
|
4
|
+
* Route auth for messages ARP Cloud delivers to this agent.
|
|
5
|
+
*
|
|
6
|
+
* ARP Cloud (the gateway) signs every delivery with an ES256 key published at
|
|
7
|
+
* `<issuer>/.well-known/jwks.json`; the token names THIS agent as audience and
|
|
8
|
+
* the paired peer as subject. Policy, obligations and audit were evaluated by
|
|
9
|
+
* ARP Cloud before delivery, so a verified token is the authorization — the
|
|
10
|
+
* same offline-verification shape `@kybernesis/enterprise` uses.
|
|
11
|
+
*
|
|
12
|
+
* Returns `null` (skip to the next auth entry) for requests without an ARP
|
|
13
|
+
* token; throws a structured 401 only when the JWKS is unreachable, so a
|
|
14
|
+
* gateway outage is distinguishable from a bad credential.
|
|
15
|
+
*/
|
|
16
|
+
export function arpAuth(options = {}) {
|
|
17
|
+
const issuer = (options.issuer ?? process.env.ARP_ISSUER ?? "https://gateway.arp.run").replace(/\/+$/, "");
|
|
18
|
+
const agentDid = options.agentDid ?? process.env.ARP_AGENT_DID ?? "";
|
|
19
|
+
const fetchImpl = options.fetchImpl ?? globalThis.fetch;
|
|
20
|
+
const ttl = options.jwksTtlMs ?? 5 * 60_000;
|
|
21
|
+
let cached = null;
|
|
22
|
+
// JWKS via global fetch (stubbable, same as the peers module) with a short
|
|
23
|
+
// cache; one refetch when a key id is unknown (rotation).
|
|
24
|
+
async function keySet(force = false) {
|
|
25
|
+
if (!force && cached && Date.now() - cached.at < ttl)
|
|
26
|
+
return cached.set;
|
|
27
|
+
const res = await fetchImpl(`${issuer}/.well-known/jwks.json`, { signal: AbortSignal.timeout(6_000) });
|
|
28
|
+
if (!res.ok)
|
|
29
|
+
throw Object.assign(new Error(`jwks ${res.status}`), { code: "ERR_JWKS_FETCH" });
|
|
30
|
+
const doc = (await res.json());
|
|
31
|
+
cached = { at: Date.now(), set: createLocalJWKSet(doc) };
|
|
32
|
+
return cached.set;
|
|
33
|
+
}
|
|
34
|
+
return async (request) => {
|
|
35
|
+
const token = extractBearerToken(request.headers.get("authorization"));
|
|
36
|
+
if (!token || !agentDid)
|
|
37
|
+
return null;
|
|
38
|
+
// Only ARP tokens are ours; anything else falls through to the next entry.
|
|
39
|
+
let unverified;
|
|
40
|
+
try {
|
|
41
|
+
unverified = JSON.parse(Buffer.from(token.split(".")[1] ?? "", "base64url").toString("utf8"));
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
if (unverified.kind !== "arp-push" || unverified.iss !== issuer)
|
|
47
|
+
return null;
|
|
48
|
+
let payload;
|
|
49
|
+
try {
|
|
50
|
+
try {
|
|
51
|
+
({ payload } = await jwtVerify(token, await keySet(), { issuer, audience: agentDid }));
|
|
52
|
+
}
|
|
53
|
+
catch (first) {
|
|
54
|
+
const code = first?.code;
|
|
55
|
+
if (code === "ERR_JWKS_NO_MATCHING_KEY") {
|
|
56
|
+
({ payload } = await jwtVerify(token, await keySet(true), { issuer, audience: agentDid }));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
throw first;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
const code = error?.code;
|
|
65
|
+
const name = error?.name;
|
|
66
|
+
if ((typeof code === "string" && code.startsWith("ERR_JWKS")) || name === "TimeoutError" || name === "AbortError") {
|
|
67
|
+
throw new UnauthenticatedError({
|
|
68
|
+
code: "verification_unavailable",
|
|
69
|
+
message: "ARP Cloud's signing keys could not be fetched; try again shortly.",
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
const peerDid = String(payload.sub ?? payload.peer_did ?? "");
|
|
75
|
+
if (!peerDid)
|
|
76
|
+
return null;
|
|
77
|
+
const obligations = Array.isArray(payload.obligations) ? payload.obligations : [];
|
|
78
|
+
return {
|
|
79
|
+
authenticator: "arp",
|
|
80
|
+
issuer,
|
|
81
|
+
principalId: peerDid,
|
|
82
|
+
principalType: "agent",
|
|
83
|
+
subject: `arp:${peerDid}`,
|
|
84
|
+
attributes: {
|
|
85
|
+
kind: "arp-push",
|
|
86
|
+
peerDid,
|
|
87
|
+
peerName: peerDid.replace(/^did:web:/, "").replace(/\.agent$/, ""),
|
|
88
|
+
connectionId: String(payload.connection_id ?? ""),
|
|
89
|
+
msgId: String(payload.msg_id ?? ""),
|
|
90
|
+
thid: String(payload.thid ?? ""),
|
|
91
|
+
...(typeof payload.purpose === "string" ? { purpose: payload.purpose } : {}),
|
|
92
|
+
obligations: JSON.stringify(obligations),
|
|
93
|
+
obligationTypes: obligations
|
|
94
|
+
.map((o) => (o && typeof o === "object" ? String(o.type ?? "") : ""))
|
|
95
|
+
.filter((t) => t.length > 0),
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface IdentityChannelOptions {
|
|
2
|
+
/** This agent's identity, e.g. `did:web:samantha.agent`. Defaults to ARP_AGENT_DID. */
|
|
3
|
+
agentDid?: string;
|
|
4
|
+
/** The challenge ARP Cloud issued when attaching this runtime. Defaults to AGENTID_CHALLENGE. */
|
|
5
|
+
challenge?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const IDENTITY_PREFIX = "/eve/v1/arp";
|
|
8
|
+
/**
|
|
9
|
+
* Serves the identity verification document ARP Cloud fetches when this
|
|
10
|
+
* runtime is attached to a name (`<url>/.well-known/agentid-verification`),
|
|
11
|
+
* plus a health probe. Mount as `agent/channels/arp.ts`; attach the name with
|
|
12
|
+
* URL `https://<host>/eve/v1/arp`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function identityChannel(options?: IdentityChannelOptions): import("eve/channels").Channel<undefined, Record<string, unknown>, Record<string, unknown>>;
|
package/dist/channel.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { defineChannel, GET } from "eve/channels";
|
|
2
|
+
export const IDENTITY_PREFIX = "/eve/v1/arp";
|
|
3
|
+
/**
|
|
4
|
+
* Serves the identity verification document ARP Cloud fetches when this
|
|
5
|
+
* runtime is attached to a name (`<url>/.well-known/agentid-verification`),
|
|
6
|
+
* plus a health probe. Mount as `agent/channels/arp.ts`; attach the name with
|
|
7
|
+
* URL `https://<host>/eve/v1/arp`.
|
|
8
|
+
*/
|
|
9
|
+
export function identityChannel(options = {}) {
|
|
10
|
+
return defineChannel({
|
|
11
|
+
// Deliveries from ARP Cloud arrive on the eve channel (POST /eve/v1/session),
|
|
12
|
+
// not here; this channel only owns the identity's HTTP documents.
|
|
13
|
+
receive: async ({ message, auth }, { from }) => from("arp:inbox").send(message, { auth }),
|
|
14
|
+
routes: [
|
|
15
|
+
GET(IDENTITY_PREFIX + "/.well-known/agentid-verification", async () => {
|
|
16
|
+
const did = options.agentDid ?? process.env.ARP_AGENT_DID ?? "";
|
|
17
|
+
const challenge = options.challenge ?? process.env.AGENTID_CHALLENGE ?? "";
|
|
18
|
+
if (!did || !challenge) {
|
|
19
|
+
return Response.json({ error: "not_configured", hint: "set ARP_AGENT_DID and AGENTID_CHALLENGE" }, { status: 404 });
|
|
20
|
+
}
|
|
21
|
+
return Response.json({ did, challenge }, { headers: { "cache-control": "no-store" } });
|
|
22
|
+
}),
|
|
23
|
+
GET(IDENTITY_PREFIX + "/health", async () => Response.json({ ok: true, did: options.agentDid ?? process.env.ARP_AGENT_DID ?? null })),
|
|
24
|
+
],
|
|
25
|
+
});
|
|
26
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { arpAuth, type ArpAuthOptions } from "./arp-auth.js";
|
|
2
|
+
export { identityChannel, IDENTITY_PREFIX, type IdentityChannelOptions } from "./channel.js";
|
|
3
|
+
export { arpPeers, discoverPeers, askPeer, toolName, type ArpPeersOptions, type ArpPeer } from "./peers.js";
|
|
4
|
+
export { ARP_INSTRUCTIONS } from "./instructions.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Instructions to append to an agent that carries a .agent identity.
|
|
3
|
+
*/
|
|
4
|
+
export const ARP_INSTRUCTIONS = `
|
|
5
|
+
## Your .agent identity
|
|
6
|
+
|
|
7
|
+
You have a registered name on the agent network. Other agents that are paired
|
|
8
|
+
with you appear as \`ask_<name>\` tools; use them when a request belongs to that
|
|
9
|
+
agent rather than to you. When a message arrives from a paired agent, the
|
|
10
|
+
caller's identity has already been verified and the message has already been
|
|
11
|
+
checked against what its owner allowed — answer it as you would a trusted
|
|
12
|
+
colleague, and honour any obligations attached (for example, do not include
|
|
13
|
+
fields you were told to redact).
|
|
14
|
+
`.trim();
|
package/dist/peers.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface ArpPeersOptions {
|
|
2
|
+
/** ARP Cloud gateway origin. Defaults to ARP_ISSUER, then https://gateway.arp.run. */
|
|
3
|
+
issuer?: string;
|
|
4
|
+
/** This agent's credential from "Attach runtime". Defaults to ARP_AGENT_CREDENTIAL. */
|
|
5
|
+
credential?: string;
|
|
6
|
+
/** Cache the connection list this long (ms). Default 60s. */
|
|
7
|
+
cacheMs?: number;
|
|
8
|
+
/** How long to wait for a peer's answer (ms). Default 120s. */
|
|
9
|
+
timeoutMs?: number;
|
|
10
|
+
/** fetch override (tests). */
|
|
11
|
+
fetchImpl?: typeof fetch;
|
|
12
|
+
}
|
|
13
|
+
export interface ArpPeer {
|
|
14
|
+
connectionId: string;
|
|
15
|
+
peerDid: string;
|
|
16
|
+
name: string;
|
|
17
|
+
purpose: string | null;
|
|
18
|
+
}
|
|
19
|
+
/** Active ARP connections for this agent, from the gateway's agent-API. Degrades to [] on any failure. */
|
|
20
|
+
export declare function discoverPeers(options?: ArpPeersOptions): Promise<ArpPeer[]>;
|
|
21
|
+
/** Send one message to a paired peer through ARP Cloud and return its reply. */
|
|
22
|
+
export declare function askPeer(options: ArpPeersOptions, peer: ArpPeer, message: string): Promise<string>;
|
|
23
|
+
export declare function toolName(peerName: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Every agent this one is PAIRED with on ARP, as tools — resolved from ARP
|
|
26
|
+
* Cloud at the start of each turn. Pair or revoke in the console and the tool
|
|
27
|
+
* appears or disappears on the next turn; nothing to redeploy.
|
|
28
|
+
*/
|
|
29
|
+
export declare function arpPeers(options?: ArpPeersOptions): import("eve/tools").DynamicSentinel<Record<string, unknown> | null>;
|
package/dist/peers.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { defineDynamic, defineTool } from "eve/tools";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const cache = new Map();
|
|
4
|
+
function config(options) {
|
|
5
|
+
return {
|
|
6
|
+
issuer: (options.issuer ?? process.env.ARP_ISSUER ?? "https://gateway.arp.run").replace(/\/+$/, ""),
|
|
7
|
+
credential: options.credential ?? process.env.ARP_AGENT_CREDENTIAL ?? "",
|
|
8
|
+
cacheMs: options.cacheMs ?? 60_000,
|
|
9
|
+
timeoutMs: options.timeoutMs ?? 120_000,
|
|
10
|
+
fetchImpl: options.fetchImpl ?? globalThis.fetch,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** Active ARP connections for this agent, from the gateway's agent-API. Degrades to [] on any failure. */
|
|
14
|
+
export async function discoverPeers(options = {}) {
|
|
15
|
+
const c = config(options);
|
|
16
|
+
if (!c.credential)
|
|
17
|
+
return [];
|
|
18
|
+
const key = `${c.issuer}|${c.credential.slice(0, 8)}`;
|
|
19
|
+
const hit = cache.get(key);
|
|
20
|
+
if (hit && Date.now() - hit.at < c.cacheMs)
|
|
21
|
+
return hit.peers;
|
|
22
|
+
try {
|
|
23
|
+
const res = await c.fetchImpl(`${c.issuer}/agent-api/connections`, {
|
|
24
|
+
headers: { authorization: `Bearer ${c.credential}` },
|
|
25
|
+
signal: AbortSignal.timeout(6_000),
|
|
26
|
+
});
|
|
27
|
+
if (!res.ok)
|
|
28
|
+
return hit?.peers ?? [];
|
|
29
|
+
const body = (await res.json());
|
|
30
|
+
const peers = (body.connections ?? []).map((k) => ({
|
|
31
|
+
connectionId: k.connection_id,
|
|
32
|
+
peerDid: k.peer_did,
|
|
33
|
+
name: k.peer_name,
|
|
34
|
+
purpose: k.purpose ?? null,
|
|
35
|
+
}));
|
|
36
|
+
cache.set(key, { at: Date.now(), peers });
|
|
37
|
+
return peers;
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return hit?.peers ?? [];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Send one message to a paired peer through ARP Cloud and return its reply. */
|
|
44
|
+
export async function askPeer(options, peer, message) {
|
|
45
|
+
const c = config(options);
|
|
46
|
+
const res = await c.fetchImpl(`${c.issuer}/agent-api/send`, {
|
|
47
|
+
method: "POST",
|
|
48
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${c.credential}` },
|
|
49
|
+
body: JSON.stringify({ connection_id: peer.connectionId, text: message, wait_ms: c.timeoutMs }),
|
|
50
|
+
signal: AbortSignal.timeout(c.timeoutMs + 10_000),
|
|
51
|
+
});
|
|
52
|
+
const body = (await res.json().catch(() => ({})));
|
|
53
|
+
if (res.status === 403)
|
|
54
|
+
return `${peer.name} declined: ${body.reason ?? "the message is outside what this connection allows."}`;
|
|
55
|
+
if (!res.ok || body.ok === false)
|
|
56
|
+
throw new Error(`${peer.name} could not be reached (${body.error ?? res.status}).`);
|
|
57
|
+
if (body.timed_out || !body.reply)
|
|
58
|
+
return `${peer.name} received the message but has not replied yet.`;
|
|
59
|
+
return body.reply;
|
|
60
|
+
}
|
|
61
|
+
export function toolName(peerName) {
|
|
62
|
+
return `ask_${peerName.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "")}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Every agent this one is PAIRED with on ARP, as tools — resolved from ARP
|
|
66
|
+
* Cloud at the start of each turn. Pair or revoke in the console and the tool
|
|
67
|
+
* appears or disappears on the next turn; nothing to redeploy.
|
|
68
|
+
*/
|
|
69
|
+
export function arpPeers(options = {}) {
|
|
70
|
+
return defineDynamic({
|
|
71
|
+
events: {
|
|
72
|
+
"turn.started": async () => {
|
|
73
|
+
const peers = await discoverPeers(options);
|
|
74
|
+
if (peers.length === 0)
|
|
75
|
+
return null;
|
|
76
|
+
const tools = {};
|
|
77
|
+
for (const peer of peers) {
|
|
78
|
+
tools[toolName(peer.name)] = defineTool({
|
|
79
|
+
description: `Send a message to ${peer.name}, a separate agent paired with you, and get its reply. ` +
|
|
80
|
+
(peer.purpose ? `Paired for: ${peer.purpose}. ` : "") +
|
|
81
|
+
`Every message is checked against the permissions its owner granted and is logged for both sides.`,
|
|
82
|
+
inputSchema: z.object({
|
|
83
|
+
message: z.string().describe("What to ask or tell it. It has no view of this conversation."),
|
|
84
|
+
}),
|
|
85
|
+
execute: (input) => askPeer(options, peer, input.message),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return tools;
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kybernesis/identity",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Give an eve agent its .agent identity: verify ARP Cloud push tokens, serve the verification document, and reach paired peers as tools — no daemon, no socket, no key in the bundle.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./package.json": "./package.json"
|
|
13
|
+
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"eve": ">=0.51.0 <0.52.0"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"jose": "^5.9.6",
|
|
19
|
+
"zod": "^3.23.8"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/node": "24.x",
|
|
23
|
+
"eve": "^0.51.1",
|
|
24
|
+
"typescript": "7.0.2"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "tsc -p tsconfig.build.json",
|
|
28
|
+
"prepack": "tsc -p tsconfig.build.json",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"prepublishOnly": "node ../../scripts/prepublish.mjs",
|
|
31
|
+
"test": "node --test \"test/**/*.test.mjs\""
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"NOTICE"
|
|
36
|
+
],
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/KybernesisAI/platform",
|
|
40
|
+
"directory": "packages/identity"
|
|
41
|
+
}
|
|
42
|
+
}
|