@agentfield/sdk 0.1.42 → 0.1.43-rc.1
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/dist/index.d.ts +37 -3
- package/dist/index.js +590 -56
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
|
-
import
|
|
2
|
+
import rateLimit from 'express-rate-limit';
|
|
3
|
+
import crypto2, { randomUUID, createHash } from 'crypto';
|
|
3
4
|
import { AsyncLocalStorage } from 'async_hooks';
|
|
4
5
|
import { generateObject, generateText, streamText, embed, embedMany } from 'ai';
|
|
5
6
|
import { createOpenAI } from '@ai-sdk/openai';
|
|
@@ -11,11 +12,11 @@ import { createXai } from '@ai-sdk/xai';
|
|
|
11
12
|
import { createDeepSeek } from '@ai-sdk/deepseek';
|
|
12
13
|
import { createCohere } from '@ai-sdk/cohere';
|
|
13
14
|
import os from 'os';
|
|
14
|
-
import
|
|
15
|
+
import axios5, { isAxiosError } from 'axios';
|
|
15
16
|
import http from 'http';
|
|
16
17
|
import https from 'https';
|
|
17
18
|
import WebSocket from 'ws';
|
|
18
|
-
import { Buffer } from 'buffer';
|
|
19
|
+
import { Buffer as Buffer$1 } from 'buffer';
|
|
19
20
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
20
21
|
|
|
21
22
|
// src/agent/Agent.ts
|
|
@@ -248,7 +249,7 @@ var StatelessRateLimiter = class {
|
|
|
248
249
|
}
|
|
249
250
|
_getContainerSeed() {
|
|
250
251
|
const identifier = `${os.hostname()}-${process.pid}`;
|
|
251
|
-
const hash =
|
|
252
|
+
const hash = crypto2.createHash("md5").update(identifier).digest("hex");
|
|
252
253
|
return parseInt(hash.slice(0, 8), 16);
|
|
253
254
|
}
|
|
254
255
|
_isRateLimitError(error) {
|
|
@@ -634,15 +635,97 @@ var httpsAgent = new https.Agent({
|
|
|
634
635
|
maxTotalSockets: 50,
|
|
635
636
|
maxFreeSockets: 5
|
|
636
637
|
});
|
|
638
|
+
var HEADER_CALLER_DID = "X-Caller-DID";
|
|
639
|
+
var HEADER_DID_SIGNATURE = "X-DID-Signature";
|
|
640
|
+
var HEADER_DID_TIMESTAMP = "X-DID-Timestamp";
|
|
641
|
+
var HEADER_DID_NONCE = "X-DID-Nonce";
|
|
642
|
+
var ED25519_PKCS8_PREFIX = Buffer.from([
|
|
643
|
+
48,
|
|
644
|
+
46,
|
|
645
|
+
2,
|
|
646
|
+
1,
|
|
647
|
+
0,
|
|
648
|
+
48,
|
|
649
|
+
5,
|
|
650
|
+
6,
|
|
651
|
+
3,
|
|
652
|
+
43,
|
|
653
|
+
101,
|
|
654
|
+
112,
|
|
655
|
+
4,
|
|
656
|
+
34,
|
|
657
|
+
4,
|
|
658
|
+
32
|
|
659
|
+
]);
|
|
660
|
+
var DIDAuthenticator = class {
|
|
661
|
+
_did;
|
|
662
|
+
_privateKey;
|
|
663
|
+
constructor(did, privateKeyJwk) {
|
|
664
|
+
if (did && privateKeyJwk) {
|
|
665
|
+
this.setCredentials(did, privateKeyJwk);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
get isConfigured() {
|
|
669
|
+
return this._did !== void 0 && this._privateKey !== void 0;
|
|
670
|
+
}
|
|
671
|
+
get did() {
|
|
672
|
+
return this._did;
|
|
673
|
+
}
|
|
674
|
+
signRequest(body) {
|
|
675
|
+
if (!this.isConfigured) {
|
|
676
|
+
return {};
|
|
677
|
+
}
|
|
678
|
+
const timestamp = Math.floor(Date.now() / 1e3).toString();
|
|
679
|
+
const nonce = crypto2.randomBytes(16).toString("hex");
|
|
680
|
+
const bodyHash = crypto2.createHash("sha256").update(body).digest("hex");
|
|
681
|
+
const payload = `${timestamp}:${nonce}:${bodyHash}`;
|
|
682
|
+
const signature = crypto2.sign(null, Buffer.from(payload), this._privateKey);
|
|
683
|
+
const signatureB64 = signature.toString("base64");
|
|
684
|
+
return {
|
|
685
|
+
[HEADER_CALLER_DID]: this._did,
|
|
686
|
+
[HEADER_DID_SIGNATURE]: signatureB64,
|
|
687
|
+
[HEADER_DID_TIMESTAMP]: timestamp,
|
|
688
|
+
[HEADER_DID_NONCE]: nonce
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
setCredentials(did, privateKeyJwk) {
|
|
692
|
+
this._privateKey = parsePrivateKeyJWK(privateKeyJwk);
|
|
693
|
+
this._did = did;
|
|
694
|
+
}
|
|
695
|
+
};
|
|
696
|
+
function parsePrivateKeyJWK(jwkJSON) {
|
|
697
|
+
let key;
|
|
698
|
+
try {
|
|
699
|
+
key = JSON.parse(jwkJSON);
|
|
700
|
+
} catch {
|
|
701
|
+
throw new Error("Invalid JWK format: failed to parse JSON");
|
|
702
|
+
}
|
|
703
|
+
if (key.kty !== "OKP" || key.crv !== "Ed25519") {
|
|
704
|
+
throw new Error("Invalid key type: expected Ed25519 OKP key");
|
|
705
|
+
}
|
|
706
|
+
if (!key.d) {
|
|
707
|
+
throw new Error("Missing 'd' (private key) in JWK");
|
|
708
|
+
}
|
|
709
|
+
const seedBytes = Buffer.from(key.d, "base64url");
|
|
710
|
+
if (seedBytes.length !== 32) {
|
|
711
|
+
throw new Error(`Invalid private key length: expected 32 bytes, got ${seedBytes.length}`);
|
|
712
|
+
}
|
|
713
|
+
return crypto2.createPrivateKey({
|
|
714
|
+
key: Buffer.concat([ED25519_PKCS8_PREFIX, seedBytes]),
|
|
715
|
+
format: "der",
|
|
716
|
+
type: "pkcs8"
|
|
717
|
+
});
|
|
718
|
+
}
|
|
637
719
|
|
|
638
720
|
// src/client/AgentFieldClient.ts
|
|
639
721
|
var AgentFieldClient = class {
|
|
640
722
|
http;
|
|
641
723
|
config;
|
|
642
724
|
defaultHeaders;
|
|
725
|
+
didAuthenticator;
|
|
643
726
|
constructor(config) {
|
|
644
727
|
const baseURL = (config.agentFieldUrl ?? "http://localhost:8080").replace(/\/$/, "");
|
|
645
|
-
this.http =
|
|
728
|
+
this.http = axios5.create({
|
|
646
729
|
baseURL,
|
|
647
730
|
timeout: 3e4,
|
|
648
731
|
httpAgent,
|
|
@@ -654,19 +737,30 @@ var AgentFieldClient = class {
|
|
|
654
737
|
mergedHeaders["X-API-Key"] = config.apiKey;
|
|
655
738
|
}
|
|
656
739
|
this.defaultHeaders = this.sanitizeHeaders(mergedHeaders);
|
|
740
|
+
this.didAuthenticator = new DIDAuthenticator(config.did, config.privateKeyJwk);
|
|
657
741
|
}
|
|
658
742
|
async register(payload) {
|
|
659
|
-
|
|
743
|
+
const bodyStr = JSON.stringify(payload);
|
|
744
|
+
const authHeaders = this.didAuthenticator.signRequest(Buffer.from(bodyStr));
|
|
745
|
+
const res = await this.http.post("/api/v1/nodes/register", bodyStr, {
|
|
746
|
+
headers: this.mergeHeaders({ "Content-Type": "application/json", ...authHeaders })
|
|
747
|
+
});
|
|
748
|
+
return res.data;
|
|
749
|
+
}
|
|
750
|
+
async getNode(nodeId) {
|
|
751
|
+
const res = await this.http.get(`/api/v1/nodes/${encodeURIComponent(nodeId)}`, {
|
|
752
|
+
headers: this.mergeHeaders({})
|
|
753
|
+
});
|
|
754
|
+
return res.data;
|
|
660
755
|
}
|
|
661
756
|
async heartbeat(status = "ready") {
|
|
662
757
|
const nodeId = this.config.nodeId;
|
|
758
|
+
const bodyStr = JSON.stringify({ status, version: this.config.version ?? "", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
759
|
+
const authHeaders = this.didAuthenticator.signRequest(Buffer.from(bodyStr));
|
|
663
760
|
const res = await this.http.post(
|
|
664
761
|
`/api/v1/nodes/${nodeId}/heartbeat`,
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
668
|
-
},
|
|
669
|
-
{ headers: this.mergeHeaders() }
|
|
762
|
+
bodyStr,
|
|
763
|
+
{ headers: this.mergeHeaders({ "Content-Type": "application/json", ...authHeaders }) }
|
|
670
764
|
);
|
|
671
765
|
return res.data;
|
|
672
766
|
}
|
|
@@ -681,14 +775,27 @@ var AgentFieldClient = class {
|
|
|
681
775
|
if (metadata?.targetDid) headers["X-Target-DID"] = metadata.targetDid;
|
|
682
776
|
if (metadata?.agentNodeDid) headers["X-Agent-Node-DID"] = metadata.agentNodeDid;
|
|
683
777
|
if (metadata?.agentNodeId) headers["X-Agent-Node-ID"] = metadata.agentNodeId;
|
|
684
|
-
const
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
778
|
+
const bodyStr = JSON.stringify({ input });
|
|
779
|
+
const authHeaders = this.didAuthenticator.signRequest(Buffer.from(bodyStr));
|
|
780
|
+
try {
|
|
781
|
+
const res = await this.http.post(
|
|
782
|
+
`/api/v1/execute/${target}`,
|
|
783
|
+
bodyStr,
|
|
784
|
+
{ headers: this.mergeHeaders({ "Content-Type": "application/json", ...headers, ...authHeaders }) }
|
|
785
|
+
);
|
|
786
|
+
return res.data?.result ?? res.data;
|
|
787
|
+
} catch (err) {
|
|
788
|
+
const respData = err?.response?.data;
|
|
789
|
+
if (respData) {
|
|
790
|
+
const status = err.response.status;
|
|
791
|
+
const msg = respData.message || respData.error || JSON.stringify(respData);
|
|
792
|
+
const enriched = new Error(`execute ${target} failed (${status}): ${msg}`);
|
|
793
|
+
enriched.status = status;
|
|
794
|
+
enriched.responseData = respData;
|
|
795
|
+
throw enriched;
|
|
796
|
+
}
|
|
797
|
+
throw err;
|
|
798
|
+
}
|
|
692
799
|
}
|
|
693
800
|
async publishWorkflowEvent(event) {
|
|
694
801
|
const payload = {
|
|
@@ -706,8 +813,10 @@ var AgentFieldClient = class {
|
|
|
706
813
|
error: event.error,
|
|
707
814
|
duration_ms: event.durationMs
|
|
708
815
|
};
|
|
709
|
-
|
|
710
|
-
|
|
816
|
+
const bodyStr = JSON.stringify(payload);
|
|
817
|
+
const authHeaders = this.didAuthenticator.signRequest(Buffer.from(bodyStr));
|
|
818
|
+
this.http.post("/api/v1/workflow/executions/events", bodyStr, {
|
|
819
|
+
headers: this.mergeHeaders({ "Content-Type": "application/json", ...authHeaders }),
|
|
711
820
|
timeout: this.config.devMode ? 1e3 : void 0
|
|
712
821
|
}).catch(() => {
|
|
713
822
|
});
|
|
@@ -723,7 +832,11 @@ var AgentFieldClient = class {
|
|
|
723
832
|
duration_ms: update.durationMs,
|
|
724
833
|
progress: update.progress !== void 0 ? Math.round(update.progress) : void 0
|
|
725
834
|
};
|
|
726
|
-
|
|
835
|
+
const bodyStr = JSON.stringify(payload);
|
|
836
|
+
const authHeaders = this.didAuthenticator.signRequest(Buffer.from(bodyStr));
|
|
837
|
+
await this.http.post(`/api/v1/executions/${executionId}/status`, bodyStr, {
|
|
838
|
+
headers: this.mergeHeaders({ "Content-Type": "application/json", ...authHeaders })
|
|
839
|
+
});
|
|
727
840
|
}
|
|
728
841
|
async discoverCapabilities(options = {}) {
|
|
729
842
|
const format = (options.format ?? "json").toLowerCase();
|
|
@@ -864,6 +977,15 @@ var AgentFieldClient = class {
|
|
|
864
977
|
if (metadata.agentNodeId) headers["x-agent-node-id"] = metadata.agentNodeId;
|
|
865
978
|
return headers;
|
|
866
979
|
}
|
|
980
|
+
setDIDCredentials(did, privateKeyJwk) {
|
|
981
|
+
this.didAuthenticator.setCredentials(did, privateKeyJwk);
|
|
982
|
+
}
|
|
983
|
+
get didAuthConfigured() {
|
|
984
|
+
return this.didAuthenticator.isConfigured;
|
|
985
|
+
}
|
|
986
|
+
getDID() {
|
|
987
|
+
return this.didAuthenticator.did;
|
|
988
|
+
}
|
|
867
989
|
sendNote(message, tags, agentNodeId, metadata, uiApiBaseUrl, devMode) {
|
|
868
990
|
const payload = {
|
|
869
991
|
message,
|
|
@@ -872,11 +994,14 @@ var AgentFieldClient = class {
|
|
|
872
994
|
agent_node_id: agentNodeId
|
|
873
995
|
};
|
|
874
996
|
const executionHeaders = this.buildExecutionHeaders({ ...metadata, agentNodeId });
|
|
997
|
+
const bodyStr = JSON.stringify(payload);
|
|
998
|
+
const authHeaders = this.didAuthenticator.signRequest(Buffer.from(bodyStr));
|
|
875
999
|
const headers = this.mergeHeaders({
|
|
876
|
-
"
|
|
877
|
-
...executionHeaders
|
|
1000
|
+
"Content-Type": "application/json",
|
|
1001
|
+
...executionHeaders,
|
|
1002
|
+
...authHeaders
|
|
878
1003
|
});
|
|
879
|
-
|
|
1004
|
+
axios5.post(`${uiApiBaseUrl}/executions/note`, bodyStr, {
|
|
880
1005
|
headers,
|
|
881
1006
|
timeout: devMode ? 5e3 : 1e4,
|
|
882
1007
|
httpAgent,
|
|
@@ -889,7 +1014,7 @@ var MemoryClient = class {
|
|
|
889
1014
|
http;
|
|
890
1015
|
defaultHeaders;
|
|
891
1016
|
constructor(baseUrl, defaultHeaders) {
|
|
892
|
-
this.http =
|
|
1017
|
+
this.http = axios5.create({
|
|
893
1018
|
baseURL: baseUrl.replace(/\/$/, ""),
|
|
894
1019
|
timeout: 3e4,
|
|
895
1020
|
httpAgent,
|
|
@@ -1271,7 +1396,7 @@ var DidClient = class {
|
|
|
1271
1396
|
http;
|
|
1272
1397
|
defaultHeaders;
|
|
1273
1398
|
constructor(baseUrl, defaultHeaders) {
|
|
1274
|
-
this.http =
|
|
1399
|
+
this.http = axios5.create({
|
|
1275
1400
|
baseURL: baseUrl.replace(/\/$/, ""),
|
|
1276
1401
|
timeout: 3e4,
|
|
1277
1402
|
httpAgent,
|
|
@@ -1308,7 +1433,7 @@ var DidClient = class {
|
|
|
1308
1433
|
parseIdentityPackage(pkg) {
|
|
1309
1434
|
const parseIdentity = (data) => ({
|
|
1310
1435
|
did: data?.did ?? "",
|
|
1311
|
-
privateKeyJwk: data?.private_key_jwk
|
|
1436
|
+
privateKeyJwk: data?.private_key_jwk,
|
|
1312
1437
|
publicKeyJwk: data?.public_key_jwk ?? "",
|
|
1313
1438
|
derivationPath: data?.derivation_path ?? "",
|
|
1314
1439
|
componentType: data?.component_type ?? "",
|
|
@@ -1397,7 +1522,7 @@ var DidClient = class {
|
|
|
1397
1522
|
if (typeof data === "string") {
|
|
1398
1523
|
value = data;
|
|
1399
1524
|
} else if (data instanceof Uint8Array) {
|
|
1400
|
-
value = Buffer.from(data).toString("utf-8");
|
|
1525
|
+
value = Buffer$1.from(data).toString("utf-8");
|
|
1401
1526
|
} else if (typeof data === "object") {
|
|
1402
1527
|
try {
|
|
1403
1528
|
value = JSON.stringify(data, Object.keys(data).sort());
|
|
@@ -1407,7 +1532,7 @@ var DidClient = class {
|
|
|
1407
1532
|
} else {
|
|
1408
1533
|
value = String(data);
|
|
1409
1534
|
}
|
|
1410
|
-
return Buffer.from(value, "utf-8").toString("base64");
|
|
1535
|
+
return Buffer$1.from(value, "utf-8").toString("base64");
|
|
1411
1536
|
}
|
|
1412
1537
|
mapExecutionCredential(data) {
|
|
1413
1538
|
return {
|
|
@@ -1660,7 +1785,7 @@ var MCPClient = class {
|
|
|
1660
1785
|
this.alias = config.alias;
|
|
1661
1786
|
this.transport = config.transport ?? "http";
|
|
1662
1787
|
this.baseUrl = (config.url ?? `http://localhost:${config.port}`).replace(/\/$/, "");
|
|
1663
|
-
this.http =
|
|
1788
|
+
this.http = axios5.create({
|
|
1664
1789
|
baseURL: this.baseUrl,
|
|
1665
1790
|
headers: config.headers,
|
|
1666
1791
|
timeout: 3e4,
|
|
@@ -1874,6 +1999,227 @@ var MCPToolRegistrar = class {
|
|
|
1874
1999
|
return collapsed || "mcp_tool";
|
|
1875
2000
|
}
|
|
1876
2001
|
};
|
|
2002
|
+
var LocalVerifier = class {
|
|
2003
|
+
agentFieldUrl;
|
|
2004
|
+
refreshInterval;
|
|
2005
|
+
timestampWindow;
|
|
2006
|
+
apiKey;
|
|
2007
|
+
policies = [];
|
|
2008
|
+
revokedDids = /* @__PURE__ */ new Set();
|
|
2009
|
+
registeredDids = /* @__PURE__ */ new Set();
|
|
2010
|
+
adminPublicKeyBytes = null;
|
|
2011
|
+
issuerDid = null;
|
|
2012
|
+
lastRefresh = 0;
|
|
2013
|
+
initialized = false;
|
|
2014
|
+
constructor(agentFieldUrl, refreshInterval = 300, timestampWindow = 300, apiKey) {
|
|
2015
|
+
this.agentFieldUrl = agentFieldUrl.replace(/\/+$/, "");
|
|
2016
|
+
this.refreshInterval = refreshInterval;
|
|
2017
|
+
this.timestampWindow = timestampWindow;
|
|
2018
|
+
this.apiKey = apiKey;
|
|
2019
|
+
}
|
|
2020
|
+
get needsRefresh() {
|
|
2021
|
+
return Date.now() / 1e3 - this.lastRefresh > this.refreshInterval;
|
|
2022
|
+
}
|
|
2023
|
+
async refresh() {
|
|
2024
|
+
const headers = {};
|
|
2025
|
+
if (this.apiKey) {
|
|
2026
|
+
headers["X-API-Key"] = this.apiKey;
|
|
2027
|
+
}
|
|
2028
|
+
let success = true;
|
|
2029
|
+
try {
|
|
2030
|
+
const resp = await axios5.get(`${this.agentFieldUrl}/api/v1/policies`, {
|
|
2031
|
+
headers,
|
|
2032
|
+
timeout: 1e4
|
|
2033
|
+
});
|
|
2034
|
+
if (resp.status !== 200) {
|
|
2035
|
+
success = false;
|
|
2036
|
+
} else {
|
|
2037
|
+
this.policies = resp.data?.policies ?? [];
|
|
2038
|
+
}
|
|
2039
|
+
} catch {
|
|
2040
|
+
success = false;
|
|
2041
|
+
}
|
|
2042
|
+
try {
|
|
2043
|
+
const resp = await axios5.get(`${this.agentFieldUrl}/api/v1/revocations`, {
|
|
2044
|
+
headers,
|
|
2045
|
+
timeout: 1e4
|
|
2046
|
+
});
|
|
2047
|
+
if (resp.status !== 200) {
|
|
2048
|
+
success = false;
|
|
2049
|
+
} else {
|
|
2050
|
+
this.revokedDids = new Set(resp.data?.revoked_dids ?? []);
|
|
2051
|
+
}
|
|
2052
|
+
} catch {
|
|
2053
|
+
success = false;
|
|
2054
|
+
}
|
|
2055
|
+
try {
|
|
2056
|
+
const resp = await axios5.get(`${this.agentFieldUrl}/api/v1/registered-dids`, {
|
|
2057
|
+
headers,
|
|
2058
|
+
timeout: 1e4
|
|
2059
|
+
});
|
|
2060
|
+
if (resp.status !== 200) {
|
|
2061
|
+
success = false;
|
|
2062
|
+
} else {
|
|
2063
|
+
this.registeredDids = new Set(resp.data?.registered_dids ?? []);
|
|
2064
|
+
}
|
|
2065
|
+
} catch {
|
|
2066
|
+
success = false;
|
|
2067
|
+
}
|
|
2068
|
+
try {
|
|
2069
|
+
const resp = await axios5.get(`${this.agentFieldUrl}/api/v1/admin/public-key`, {
|
|
2070
|
+
headers,
|
|
2071
|
+
timeout: 1e4
|
|
2072
|
+
});
|
|
2073
|
+
if (resp.status !== 200) {
|
|
2074
|
+
success = false;
|
|
2075
|
+
} else {
|
|
2076
|
+
const jwk = resp.data?.public_key_jwk;
|
|
2077
|
+
this.issuerDid = resp.data?.issuer_did ?? null;
|
|
2078
|
+
if (jwk?.x) {
|
|
2079
|
+
this.adminPublicKeyBytes = new Uint8Array(Buffer.from(jwk.x, "base64url"));
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2082
|
+
} catch {
|
|
2083
|
+
success = false;
|
|
2084
|
+
}
|
|
2085
|
+
if (success) {
|
|
2086
|
+
this.lastRefresh = Date.now() / 1e3;
|
|
2087
|
+
this.initialized = true;
|
|
2088
|
+
}
|
|
2089
|
+
return success;
|
|
2090
|
+
}
|
|
2091
|
+
checkRevocation(callerDid) {
|
|
2092
|
+
return this.revokedDids.has(callerDid);
|
|
2093
|
+
}
|
|
2094
|
+
/**
|
|
2095
|
+
* Check if a caller DID is registered with the control plane.
|
|
2096
|
+
* Returns true if registered (known), false if unknown.
|
|
2097
|
+
* When the cache is empty (not yet loaded), returns true to avoid
|
|
2098
|
+
* blocking requests before the first refresh completes.
|
|
2099
|
+
*/
|
|
2100
|
+
checkRegistration(callerDid) {
|
|
2101
|
+
if (this.registeredDids.size === 0) {
|
|
2102
|
+
return true;
|
|
2103
|
+
}
|
|
2104
|
+
return this.registeredDids.has(callerDid);
|
|
2105
|
+
}
|
|
2106
|
+
/**
|
|
2107
|
+
* Resolve the public key bytes from a DID.
|
|
2108
|
+
*
|
|
2109
|
+
* For did:key, the public key is self-contained in the identifier:
|
|
2110
|
+
* did:key:z<base64url(0xed01 + 32-byte-pubkey)>
|
|
2111
|
+
*
|
|
2112
|
+
* For other DID methods, falls back to the admin public key.
|
|
2113
|
+
*/
|
|
2114
|
+
resolvePublicKey(callerDid) {
|
|
2115
|
+
if (callerDid.startsWith("did:key:z")) {
|
|
2116
|
+
try {
|
|
2117
|
+
const encoded = callerDid.slice("did:key:z".length);
|
|
2118
|
+
const decoded = Buffer.from(encoded, "base64url");
|
|
2119
|
+
if (decoded.length >= 34 && decoded[0] === 237 && decoded[1] === 1) {
|
|
2120
|
+
return new Uint8Array(decoded.subarray(2, 34));
|
|
2121
|
+
}
|
|
2122
|
+
return null;
|
|
2123
|
+
} catch {
|
|
2124
|
+
return null;
|
|
2125
|
+
}
|
|
2126
|
+
}
|
|
2127
|
+
return this.adminPublicKeyBytes;
|
|
2128
|
+
}
|
|
2129
|
+
async verifySignature(callerDid, signatureB64, timestamp, body, nonce) {
|
|
2130
|
+
const ts = parseInt(timestamp, 10);
|
|
2131
|
+
if (isNaN(ts)) return false;
|
|
2132
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
2133
|
+
if (Math.abs(now - ts) > this.timestampWindow) return false;
|
|
2134
|
+
const publicKeyBytes = this.resolvePublicKey(callerDid);
|
|
2135
|
+
if (!publicKeyBytes || publicKeyBytes.length !== 32) {
|
|
2136
|
+
return false;
|
|
2137
|
+
}
|
|
2138
|
+
try {
|
|
2139
|
+
const { createPublicKey, verify } = await import('crypto');
|
|
2140
|
+
const bodyHash = createHash("sha256").update(body).digest("hex");
|
|
2141
|
+
const payloadStr = nonce ? `${timestamp}:${nonce}:${bodyHash}` : `${timestamp}:${bodyHash}`;
|
|
2142
|
+
const payload = Buffer.from(payloadStr, "utf-8");
|
|
2143
|
+
const signatureBytes = Buffer.from(signatureB64, "base64");
|
|
2144
|
+
const publicKey = createPublicKey({
|
|
2145
|
+
key: Buffer.concat([
|
|
2146
|
+
// Ed25519 DER prefix for a 32-byte public key
|
|
2147
|
+
Buffer.from("302a300506032b6570032100", "hex"),
|
|
2148
|
+
Buffer.from(publicKeyBytes)
|
|
2149
|
+
]),
|
|
2150
|
+
format: "der",
|
|
2151
|
+
type: "spki"
|
|
2152
|
+
});
|
|
2153
|
+
return verify(null, payload, publicKey, signatureBytes);
|
|
2154
|
+
} catch {
|
|
2155
|
+
return false;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
evaluatePolicy(callerTags, targetTags, functionName, inputParams) {
|
|
2159
|
+
if (!this.policies || this.policies.length === 0) {
|
|
2160
|
+
return false;
|
|
2161
|
+
}
|
|
2162
|
+
const sorted = [...this.policies].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
2163
|
+
for (const policy of sorted) {
|
|
2164
|
+
if (policy.enabled === false) continue;
|
|
2165
|
+
if (policy.caller_tags?.length > 0) {
|
|
2166
|
+
if (!policy.caller_tags.some((t) => callerTags.includes(t))) continue;
|
|
2167
|
+
}
|
|
2168
|
+
if (policy.target_tags?.length > 0) {
|
|
2169
|
+
if (!policy.target_tags.some((t) => targetTags.includes(t))) continue;
|
|
2170
|
+
}
|
|
2171
|
+
if (policy.deny_functions?.length > 0 && functionMatches(functionName, policy.deny_functions)) {
|
|
2172
|
+
return false;
|
|
2173
|
+
}
|
|
2174
|
+
if (policy.allow_functions?.length > 0 && !functionMatches(functionName, policy.allow_functions)) {
|
|
2175
|
+
continue;
|
|
2176
|
+
}
|
|
2177
|
+
if (policy.constraints && inputParams) {
|
|
2178
|
+
if (!evaluateConstraints(policy.constraints, inputParams)) {
|
|
2179
|
+
return false;
|
|
2180
|
+
}
|
|
2181
|
+
}
|
|
2182
|
+
const action = policy.action || "allow";
|
|
2183
|
+
return action === "allow";
|
|
2184
|
+
}
|
|
2185
|
+
return true;
|
|
2186
|
+
}
|
|
2187
|
+
};
|
|
2188
|
+
function functionMatches(name, patterns) {
|
|
2189
|
+
for (const pattern of patterns) {
|
|
2190
|
+
if (pattern === "*") return true;
|
|
2191
|
+
if (pattern.endsWith("*") && name.startsWith(pattern.slice(0, -1))) return true;
|
|
2192
|
+
if (pattern.startsWith("*") && name.endsWith(pattern.slice(1))) return true;
|
|
2193
|
+
if (name === pattern) return true;
|
|
2194
|
+
}
|
|
2195
|
+
return false;
|
|
2196
|
+
}
|
|
2197
|
+
function evaluateConstraints(constraints, inputParams) {
|
|
2198
|
+
for (const [paramName, constraint] of Object.entries(constraints)) {
|
|
2199
|
+
if (!(paramName in inputParams)) continue;
|
|
2200
|
+
const value = Number(inputParams[paramName]);
|
|
2201
|
+
const threshold = Number(constraint.value);
|
|
2202
|
+
if (isNaN(value) || isNaN(threshold)) return false;
|
|
2203
|
+
switch (constraint.operator) {
|
|
2204
|
+
case "<=":
|
|
2205
|
+
if (value > threshold) return false;
|
|
2206
|
+
break;
|
|
2207
|
+
case ">=":
|
|
2208
|
+
if (value < threshold) return false;
|
|
2209
|
+
break;
|
|
2210
|
+
case "<":
|
|
2211
|
+
if (value >= threshold) return false;
|
|
2212
|
+
break;
|
|
2213
|
+
case ">":
|
|
2214
|
+
if (value <= threshold) return false;
|
|
2215
|
+
break;
|
|
2216
|
+
case "==":
|
|
2217
|
+
if (Math.abs(value - threshold) > 1e-9) return false;
|
|
2218
|
+
break;
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
return true;
|
|
2222
|
+
}
|
|
1877
2223
|
|
|
1878
2224
|
// src/agent/Agent.ts
|
|
1879
2225
|
var TargetNotFoundError = class extends Error {
|
|
@@ -1894,6 +2240,8 @@ var Agent = class {
|
|
|
1894
2240
|
memoryWatchers = [];
|
|
1895
2241
|
mcpClientRegistry;
|
|
1896
2242
|
mcpToolRegistrar;
|
|
2243
|
+
localVerifier;
|
|
2244
|
+
realtimeValidationFunctions = /* @__PURE__ */ new Set();
|
|
1897
2245
|
constructor(config) {
|
|
1898
2246
|
const mcp = config.mcp ? {
|
|
1899
2247
|
autoRegisterTools: config.mcp.autoRegisterTools ?? true,
|
|
@@ -1926,14 +2274,28 @@ var Agent = class {
|
|
|
1926
2274
|
});
|
|
1927
2275
|
this.mcpToolRegistrar.registerServers(this.config.mcp.servers);
|
|
1928
2276
|
}
|
|
2277
|
+
if (this.config.localVerification && this.config.agentFieldUrl) {
|
|
2278
|
+
this.localVerifier = new LocalVerifier(
|
|
2279
|
+
this.config.agentFieldUrl,
|
|
2280
|
+
this.config.verificationRefreshInterval ?? 300,
|
|
2281
|
+
300,
|
|
2282
|
+
this.config.apiKey
|
|
2283
|
+
);
|
|
2284
|
+
}
|
|
1929
2285
|
this.registerDefaultRoutes();
|
|
1930
2286
|
}
|
|
1931
2287
|
reasoner(name, handler, options) {
|
|
1932
2288
|
this.reasoners.register(name, handler, options);
|
|
2289
|
+
if (options?.requireRealtimeValidation) {
|
|
2290
|
+
this.realtimeValidationFunctions.add(name);
|
|
2291
|
+
}
|
|
1933
2292
|
return this;
|
|
1934
2293
|
}
|
|
1935
2294
|
skill(name, handler, options) {
|
|
1936
2295
|
this.skills.register(name, handler, options);
|
|
2296
|
+
if (options?.requireRealtimeValidation) {
|
|
2297
|
+
this.realtimeValidationFunctions.add(name);
|
|
2298
|
+
}
|
|
1937
2299
|
return this;
|
|
1938
2300
|
}
|
|
1939
2301
|
includeRouter(router) {
|
|
@@ -2035,6 +2397,16 @@ var Agent = class {
|
|
|
2035
2397
|
}
|
|
2036
2398
|
}
|
|
2037
2399
|
await this.registerWithControlPlane();
|
|
2400
|
+
if (this.localVerifier) {
|
|
2401
|
+
try {
|
|
2402
|
+
const ok = await this.localVerifier.refresh();
|
|
2403
|
+
if (!ok) {
|
|
2404
|
+
console.warn("[LocalVerifier] Initial refresh partially failed \u2014 some verification data may be stale");
|
|
2405
|
+
}
|
|
2406
|
+
} catch (err) {
|
|
2407
|
+
console.warn("[LocalVerifier] Initial refresh failed:", err);
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2038
2410
|
const port = this.config.port ?? 8001;
|
|
2039
2411
|
const host = this.config.host ?? "0.0.0.0";
|
|
2040
2412
|
await this.agentFieldClient.heartbeat("starting");
|
|
@@ -2179,6 +2551,111 @@ var Agent = class {
|
|
|
2179
2551
|
this.app.get("/skills", (_req, res) => {
|
|
2180
2552
|
res.json(this.skills.all().map((s) => s.name));
|
|
2181
2553
|
});
|
|
2554
|
+
if (this.localVerifier) {
|
|
2555
|
+
const verifier = this.localVerifier;
|
|
2556
|
+
const realtimeFunctions = this.realtimeValidationFunctions;
|
|
2557
|
+
const authRateLimiter = rateLimit({
|
|
2558
|
+
windowMs: 6e4,
|
|
2559
|
+
max: 30,
|
|
2560
|
+
standardHeaders: true,
|
|
2561
|
+
legacyHeaders: false,
|
|
2562
|
+
keyGenerator: (req) => {
|
|
2563
|
+
const callerDID = req.headers["x-caller-did"];
|
|
2564
|
+
if (typeof callerDID === "string" && callerDID.length > 0) {
|
|
2565
|
+
return callerDID;
|
|
2566
|
+
}
|
|
2567
|
+
return req.ip ?? "unknown";
|
|
2568
|
+
},
|
|
2569
|
+
message: { error: "rate_limit_exceeded", message: "Too many authentication attempts. Try again later." },
|
|
2570
|
+
skip: (req) => {
|
|
2571
|
+
const path = req.path;
|
|
2572
|
+
if (!path.startsWith("/reasoners/") && !path.startsWith("/skills/") && !path.startsWith("/execute") && !path.startsWith("/api/v1/reasoners/") && !path.startsWith("/api/v1/skills/")) {
|
|
2573
|
+
return true;
|
|
2574
|
+
}
|
|
2575
|
+
const parts = path.replace(/^\/+/, "").split("/");
|
|
2576
|
+
const funcName = parts[parts.length - 1] ?? "";
|
|
2577
|
+
return realtimeFunctions.has(funcName);
|
|
2578
|
+
}
|
|
2579
|
+
});
|
|
2580
|
+
this.app.use(authRateLimiter);
|
|
2581
|
+
this.app.use(async (req, res, next) => {
|
|
2582
|
+
const path = req.path;
|
|
2583
|
+
if (!path.startsWith("/reasoners/") && !path.startsWith("/skills/") && !path.startsWith("/execute") && !path.startsWith("/api/v1/reasoners/") && !path.startsWith("/api/v1/skills/")) {
|
|
2584
|
+
return next();
|
|
2585
|
+
}
|
|
2586
|
+
const parts = path.replace(/^\/+/, "").split("/");
|
|
2587
|
+
const funcName = parts[parts.length - 1] ?? "";
|
|
2588
|
+
if (realtimeFunctions.has(funcName)) {
|
|
2589
|
+
return next();
|
|
2590
|
+
}
|
|
2591
|
+
if (verifier.needsRefresh) {
|
|
2592
|
+
try {
|
|
2593
|
+
await verifier.refresh();
|
|
2594
|
+
} catch (err) {
|
|
2595
|
+
console.warn("[LocalVerifier] Cache refresh failed:", err);
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
const callerDid = req.headers["x-caller-did"];
|
|
2599
|
+
const signature = req.headers["x-did-signature"];
|
|
2600
|
+
const timestamp = req.headers["x-did-timestamp"];
|
|
2601
|
+
const nonce = req.headers["x-did-nonce"];
|
|
2602
|
+
if (!callerDid) {
|
|
2603
|
+
return res.status(401).json({
|
|
2604
|
+
error: "did_auth_required",
|
|
2605
|
+
message: "DID authentication required"
|
|
2606
|
+
});
|
|
2607
|
+
}
|
|
2608
|
+
if (verifier.checkRevocation(callerDid)) {
|
|
2609
|
+
return res.status(403).json({
|
|
2610
|
+
error: "did_revoked",
|
|
2611
|
+
message: `Caller DID ${callerDid} has been revoked`
|
|
2612
|
+
});
|
|
2613
|
+
}
|
|
2614
|
+
if (!verifier.checkRegistration(callerDid)) {
|
|
2615
|
+
return res.status(403).json({
|
|
2616
|
+
error: "did_not_registered",
|
|
2617
|
+
message: `Caller DID ${callerDid} is not registered with the control plane`
|
|
2618
|
+
});
|
|
2619
|
+
}
|
|
2620
|
+
if (!signature) {
|
|
2621
|
+
return res.status(401).json({
|
|
2622
|
+
error: "signature_required",
|
|
2623
|
+
message: "DID signature required"
|
|
2624
|
+
});
|
|
2625
|
+
}
|
|
2626
|
+
if (timestamp) {
|
|
2627
|
+
const body = Buffer.isBuffer(req.body) ? req.body : Buffer.from(JSON.stringify(req.body));
|
|
2628
|
+
const valid = await verifier.verifySignature(callerDid, signature, timestamp, body, nonce);
|
|
2629
|
+
if (!valid) {
|
|
2630
|
+
return res.status(401).json({
|
|
2631
|
+
error: "signature_invalid",
|
|
2632
|
+
message: "DID signature verification failed"
|
|
2633
|
+
});
|
|
2634
|
+
}
|
|
2635
|
+
} else {
|
|
2636
|
+
return res.status(401).json({
|
|
2637
|
+
error: "signature_invalid",
|
|
2638
|
+
message: "DID signature verification failed: missing timestamp"
|
|
2639
|
+
});
|
|
2640
|
+
}
|
|
2641
|
+
const agentTags = this.config.tags ?? [];
|
|
2642
|
+
const allowed = verifier.evaluatePolicy(
|
|
2643
|
+
[],
|
|
2644
|
+
// caller tags (not resolvable without control plane)
|
|
2645
|
+
agentTags,
|
|
2646
|
+
// target tags (this agent's own tags)
|
|
2647
|
+
funcName,
|
|
2648
|
+
typeof req.body === "object" && req.body !== null ? req.body : {}
|
|
2649
|
+
);
|
|
2650
|
+
if (!allowed) {
|
|
2651
|
+
return res.status(403).json({
|
|
2652
|
+
error: "policy_denied",
|
|
2653
|
+
message: "Access denied by policy"
|
|
2654
|
+
});
|
|
2655
|
+
}
|
|
2656
|
+
next();
|
|
2657
|
+
});
|
|
2658
|
+
}
|
|
2182
2659
|
this.app.post("/api/v1/reasoners/*", (req, res) => this.executeReasoner(req, res, req.params[0]));
|
|
2183
2660
|
this.app.post("/reasoners/:name", (req, res) => this.executeReasoner(req, res, req.params.name));
|
|
2184
2661
|
this.app.post("/api/v1/skills/*", (req, res) => this.executeSkill(req, res, req.params[0]));
|
|
@@ -2201,7 +2678,10 @@ var Agent = class {
|
|
|
2201
2678
|
if (err instanceof TargetNotFoundError) {
|
|
2202
2679
|
res.status(404).json({ error: err.message });
|
|
2203
2680
|
} else {
|
|
2204
|
-
|
|
2681
|
+
const body = { error: err?.message ?? "Execution failed" };
|
|
2682
|
+
if (err?.responseData) body.error_details = err.responseData;
|
|
2683
|
+
const statusCode = err?.status >= 400 ? err.status : 500;
|
|
2684
|
+
res.status(statusCode).json(body);
|
|
2205
2685
|
}
|
|
2206
2686
|
}
|
|
2207
2687
|
}
|
|
@@ -2220,7 +2700,10 @@ var Agent = class {
|
|
|
2220
2700
|
if (err instanceof TargetNotFoundError) {
|
|
2221
2701
|
res.status(404).json({ error: err.message });
|
|
2222
2702
|
} else {
|
|
2223
|
-
|
|
2703
|
+
const body = { error: err?.message ?? "Execution failed" };
|
|
2704
|
+
if (err?.responseData) body.error_details = err.responseData;
|
|
2705
|
+
const statusCode = err?.status >= 400 ? err.status : 500;
|
|
2706
|
+
res.status(statusCode).json(body);
|
|
2224
2707
|
}
|
|
2225
2708
|
}
|
|
2226
2709
|
}
|
|
@@ -2255,7 +2738,10 @@ var Agent = class {
|
|
|
2255
2738
|
if (err instanceof TargetNotFoundError) {
|
|
2256
2739
|
res.status(404).json({ error: err.message });
|
|
2257
2740
|
} else {
|
|
2258
|
-
|
|
2741
|
+
const body = { error: err?.message ?? "Execution failed" };
|
|
2742
|
+
if (err?.responseData) body.error_details = err.responseData;
|
|
2743
|
+
const statusCode = err?.status >= 400 ? err.status : 500;
|
|
2744
|
+
res.status(statusCode).json(body);
|
|
2259
2745
|
}
|
|
2260
2746
|
}
|
|
2261
2747
|
}
|
|
@@ -2440,24 +2926,32 @@ var Agent = class {
|
|
|
2440
2926
|
return void 0;
|
|
2441
2927
|
}
|
|
2442
2928
|
reasonerDefinitions() {
|
|
2443
|
-
return this.reasoners.all().map((r) =>
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2929
|
+
return this.reasoners.all().map((r) => {
|
|
2930
|
+
const tags = r.options?.tags ?? [];
|
|
2931
|
+
return {
|
|
2932
|
+
id: r.name,
|
|
2933
|
+
input_schema: toJsonSchema(r.options?.inputSchema),
|
|
2934
|
+
output_schema: toJsonSchema(r.options?.outputSchema),
|
|
2935
|
+
memory_config: r.options?.memoryConfig ?? {
|
|
2936
|
+
auto_inject: [],
|
|
2937
|
+
memory_retention: "",
|
|
2938
|
+
cache_results: false
|
|
2939
|
+
},
|
|
2940
|
+
tags,
|
|
2941
|
+
proposed_tags: tags
|
|
2942
|
+
};
|
|
2943
|
+
});
|
|
2454
2944
|
}
|
|
2455
2945
|
skillDefinitions() {
|
|
2456
|
-
return this.skills.all().map((s) =>
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2946
|
+
return this.skills.all().map((s) => {
|
|
2947
|
+
const tags = s.options?.tags ?? [];
|
|
2948
|
+
return {
|
|
2949
|
+
id: s.name,
|
|
2950
|
+
input_schema: toJsonSchema(s.options?.inputSchema),
|
|
2951
|
+
tags,
|
|
2952
|
+
proposed_tags: tags
|
|
2953
|
+
};
|
|
2954
|
+
});
|
|
2461
2955
|
}
|
|
2462
2956
|
discoveryPayload(deploymentType) {
|
|
2463
2957
|
return {
|
|
@@ -2526,7 +3020,10 @@ var Agent = class {
|
|
|
2526
3020
|
return result;
|
|
2527
3021
|
} catch (err) {
|
|
2528
3022
|
if (params.respond && params.res) {
|
|
2529
|
-
|
|
3023
|
+
const body = { error: err?.message ?? "Execution failed" };
|
|
3024
|
+
if (err?.responseData) body.error_details = err.responseData;
|
|
3025
|
+
const statusCode = err?.status >= 400 ? err.status : err?.statusCode >= 400 ? err.statusCode : 500;
|
|
3026
|
+
params.res.status(statusCode).json(body);
|
|
2530
3027
|
return;
|
|
2531
3028
|
}
|
|
2532
3029
|
throw err;
|
|
@@ -2565,7 +3062,10 @@ var Agent = class {
|
|
|
2565
3062
|
return result;
|
|
2566
3063
|
} catch (err) {
|
|
2567
3064
|
if (params.respond && params.res) {
|
|
2568
|
-
|
|
3065
|
+
const body = { error: err?.message ?? "Execution failed" };
|
|
3066
|
+
if (err?.responseData) body.error_details = err.responseData;
|
|
3067
|
+
const statusCode = err?.status >= 400 ? err.status : err?.statusCode >= 400 ? err.statusCode : 500;
|
|
3068
|
+
params.res.status(statusCode).json(body);
|
|
2569
3069
|
return;
|
|
2570
3070
|
}
|
|
2571
3071
|
throw err;
|
|
@@ -2579,15 +3079,24 @@ var Agent = class {
|
|
|
2579
3079
|
const port = this.config.port ?? 8001;
|
|
2580
3080
|
const hostForUrl = this.config.publicUrl ? void 0 : this.config.host && this.config.host !== "0.0.0.0" ? this.config.host : "127.0.0.1";
|
|
2581
3081
|
const publicUrl = this.config.publicUrl ?? `http://${hostForUrl ?? "127.0.0.1"}:${port}`;
|
|
2582
|
-
|
|
3082
|
+
const agentTags = this.config.tags ?? [];
|
|
3083
|
+
const regResponse = await this.agentFieldClient.register({
|
|
2583
3084
|
id: this.config.nodeId,
|
|
2584
|
-
version: this.config.version,
|
|
3085
|
+
version: this.config.version ?? "",
|
|
2585
3086
|
base_url: publicUrl,
|
|
2586
3087
|
public_url: publicUrl,
|
|
2587
3088
|
deployment_type: this.config.deploymentType ?? "long_running",
|
|
2588
3089
|
reasoners,
|
|
2589
|
-
skills
|
|
3090
|
+
skills,
|
|
3091
|
+
proposed_tags: agentTags,
|
|
3092
|
+
tags: agentTags
|
|
2590
3093
|
});
|
|
3094
|
+
if (regResponse?.status === "pending_approval") {
|
|
3095
|
+
const pendingTags = regResponse.pending_tags ?? [];
|
|
3096
|
+
console.log(`[AgentField] Node ${this.config.nodeId} registered but awaiting tag approval (pending tags: ${pendingTags.join(", ")})`);
|
|
3097
|
+
await this.waitForApproval();
|
|
3098
|
+
console.log(`[AgentField] Node ${this.config.nodeId} tag approval granted`);
|
|
3099
|
+
}
|
|
2591
3100
|
if (this.config.didEnabled) {
|
|
2592
3101
|
try {
|
|
2593
3102
|
const didRegistered = await this.didManager.registerAgent(reasoners, skills);
|
|
@@ -2595,6 +3104,10 @@ var Agent = class {
|
|
|
2595
3104
|
const summary = this.didManager.getIdentitySummary();
|
|
2596
3105
|
console.log(`[DID] Agent registered with DID: ${summary.agentDid}`);
|
|
2597
3106
|
console.log(`[DID] Reasoner DIDs: ${summary.reasonerCount}, Skill DIDs: ${summary.skillCount}`);
|
|
3107
|
+
const pkg = this.didManager.getIdentityPackage();
|
|
3108
|
+
if (pkg?.agentDid?.did && pkg?.agentDid?.privateKeyJwk) {
|
|
3109
|
+
this.agentFieldClient.setDIDCredentials(pkg.agentDid.did, pkg.agentDid.privateKeyJwk);
|
|
3110
|
+
}
|
|
2598
3111
|
}
|
|
2599
3112
|
} catch (didErr) {
|
|
2600
3113
|
if (!this.config.devMode) {
|
|
@@ -2609,6 +3122,27 @@ var Agent = class {
|
|
|
2609
3122
|
console.warn("Control plane registration failed (devMode=true), continuing locally", err);
|
|
2610
3123
|
}
|
|
2611
3124
|
}
|
|
3125
|
+
async waitForApproval() {
|
|
3126
|
+
const pollInterval = 5e3;
|
|
3127
|
+
const timeoutMs = 5 * 60 * 1e3;
|
|
3128
|
+
const deadline = Date.now() + timeoutMs;
|
|
3129
|
+
while (Date.now() < deadline) {
|
|
3130
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
3131
|
+
try {
|
|
3132
|
+
const node = await this.agentFieldClient.getNode(this.config.nodeId);
|
|
3133
|
+
const status = node?.lifecycle_status;
|
|
3134
|
+
if (status && status !== "pending_approval") {
|
|
3135
|
+
return;
|
|
3136
|
+
}
|
|
3137
|
+
console.log(`[AgentField] Node ${this.config.nodeId} still pending approval...`);
|
|
3138
|
+
} catch (err) {
|
|
3139
|
+
console.warn("[AgentField] Polling for approval status failed:", err);
|
|
3140
|
+
}
|
|
3141
|
+
}
|
|
3142
|
+
throw new Error(
|
|
3143
|
+
`[AgentField] Node ${this.config.nodeId} approval timed out after ${timeoutMs / 1e3}s`
|
|
3144
|
+
);
|
|
3145
|
+
}
|
|
2612
3146
|
startHeartbeat() {
|
|
2613
3147
|
const interval = this.config.heartbeatIntervalMs ?? 3e4;
|
|
2614
3148
|
if (interval <= 0) return;
|
|
@@ -2685,6 +3219,6 @@ function sanitize(value) {
|
|
|
2685
3219
|
return value.replace(/[^0-9a-zA-Z]+/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
|
|
2686
3220
|
}
|
|
2687
3221
|
|
|
2688
|
-
export { AIClient, Agent, AgentRouter, DidClient, DidInterface, DidManager, ExecutionContext, MCPClient, MCPClientRegistry, MCPToolRegistrar, MemoryClient, MemoryEventClient, MemoryInterface, RateLimitError, ReasonerContext, SkillContext, StatelessRateLimiter, WorkflowReporter, getCurrentContext, getCurrentSkillContext };
|
|
3222
|
+
export { AIClient, Agent, AgentRouter, DIDAuthenticator, DidClient, DidInterface, DidManager, ExecutionContext, HEADER_CALLER_DID, HEADER_DID_NONCE, HEADER_DID_SIGNATURE, HEADER_DID_TIMESTAMP, MCPClient, MCPClientRegistry, MCPToolRegistrar, MemoryClient, MemoryEventClient, MemoryInterface, RateLimitError, ReasonerContext, SkillContext, StatelessRateLimiter, WorkflowReporter, getCurrentContext, getCurrentSkillContext };
|
|
2689
3223
|
//# sourceMappingURL=index.js.map
|
|
2690
3224
|
//# sourceMappingURL=index.js.map
|