@agentunion/fastaun-browser 0.5.4 → 0.5.8
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 +177 -67
- package/_packed_docs/AUN/347/246/273/347/272/277/346/216/250/351/200/201/346/216/245/345/205/245/344/270/216/346/274/224/347/244/272/346/214/207/345/215/227.md +290 -0
- package/_packed_docs/AUN/347/246/273/347/272/277/346/216/250/351/200/201/346/234/215/345/212/241/346/236/266/346/236/204/344/270/216/350/257/246/347/273/206/345/256/236/347/216/260/350/256/241/345/210/222-codex.md +994 -0
- package/_packed_docs/AUN/347/246/273/347/272/277/346/216/250/351/200/201/346/234/215/345/212/241/350/277/220/347/273/264/344/270/216/345/217/221/345/270/203/346/214/207/345/215/227.md +144 -0
- package/_packed_docs/CHANGELOG.md +177 -67
- package/_packed_docs/INDEX.md +124 -65
- package/_packed_docs/KITE_DOCS_GUIDE.md +65 -30
- package/_packed_docs/agent.md/SCHEMA.md +83 -58
- package/_packed_docs/agent.md/examples/codeagent-claudecode.md +1 -1
- package/_packed_docs/agent.md/examples/openclaw-lobster.md +1 -1
- package/_packed_docs/agent.md/examples/signed-openclaw-lobster.md +1 -1
- package/_packed_docs/audit/AUN/346/234/215/345/212/241Go/345/214/226/351/207/215/346/236/204/347/262/276/347/273/206/345/214/226/346/272/220/347/240/201/345/256/241/346/237/245-20260718.md +366 -0
- package/_packed_docs/aun/345/205/254/347/275/221/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +234 -0
- package/_packed_docs/aun/345/210/206/345/270/203/345/274/217/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +1095 -0
- package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +1199 -0
- package/_packed_docs/cli/CLI/346/211/213/345/206/214.md +6 -4
- package/_packed_docs/group-message-rpc-alignment-gaps.md +741 -0
- package/_packed_docs/message-online-push-alignment.md +572 -0
- package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +58 -20
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +219 -247
- package/_packed_docs/protocol/12-Stream-/345/255/220/345/215/217/350/256/256.md +14 -14
- package/_packed_docs/protocol/13-Agent/350/241/214/344/270/272/350/247/204/350/214/203.md +3 -3
- package/_packed_docs/protocol/15-/347/246/273/347/272/277/346/216/250/351/200/201/351/200/232/347/237/245/345/215/217/350/256/256.md +165 -421
- package/_packed_docs/protocol/README.md +1 -0
- package/_packed_docs/protocol/aun-docs-guide.md +7 -4
- package/_packed_docs/protocol/index.md +25 -19
- package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +63 -18
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +22 -0
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +93 -84
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +6 -2
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +73 -34
- package/_packed_docs/sdk/07-/351/224/231/350/257/257/345/244/204/347/220/206.md +3 -3
- package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +21 -9
- package/_packed_docs/sdk/09-group-rpc-manual.md +319 -285
- package/_packed_docs/sdk/09-message-rpc-manual.md +144 -103
- package/_packed_docs/sdk/09-payload-reference.md +1 -1
- package/_packed_docs/sdk/09-storage-rpc-manual.md +14 -3
- package/_packed_docs/sdk/09-stream-rpc-manual.md +8 -8
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +34 -23
- package/_packed_docs/sdk/CHANGELOG-0.5.6.md +73 -0
- package/_packed_docs/sdk/INDEX.md +45 -37
- package/_packed_docs/sdk/README.md +11 -9
- package/_packed_docs//345/217/221/345/270/203/346/212/245/345/221/212-0.5.6.md +260 -0
- package/_packed_docs//346/266/210/346/201/257/345/220/214/346/255/245/344/270/216/345/216/206/345/217/262/346/213/211/345/217/226/344/273/243/347/240/201/345/256/241/346/237/245/351/227/256/351/242/230/346/270/205/345/215/225.md +229 -0
- package/_packed_docs//346/266/210/346/201/257/345/220/214/346/255/245/344/270/216/345/216/206/345/217/262/346/213/211/345/217/226/346/224/271/351/200/240/346/226/271/346/241/210.md +750 -0
- package/dist/agent-md-schema.d.ts +14 -0
- package/dist/agent-md-schema.d.ts.map +1 -0
- package/dist/agent-md-schema.js +103 -0
- package/dist/agent-md-schema.js.map +1 -0
- package/dist/agent-md.d.ts +11 -5
- package/dist/agent-md.d.ts.map +1 -1
- package/dist/agent-md.js +295 -53
- package/dist/agent-md.js.map +1 -1
- package/dist/aid-store.d.ts +7 -7
- package/dist/aid-store.d.ts.map +1 -1
- package/dist/aid-store.js +46 -18
- package/dist/aid-store.js.map +1 -1
- package/dist/aid.d.ts +2 -0
- package/dist/aid.d.ts.map +1 -1
- package/dist/aid.js +29 -7
- package/dist/aid.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +31 -11
- package/dist/auth.js.map +1 -1
- package/dist/bundle.js +29920 -19719
- package/dist/cert-utils.d.ts +1 -0
- package/dist/cert-utils.d.ts.map +1 -1
- package/dist/cert-utils.js +36 -16
- package/dist/cert-utils.js.map +1 -1
- package/dist/client/delivery.d.ts +106 -11
- package/dist/client/delivery.d.ts.map +1 -1
- package/dist/client/delivery.js +1925 -374
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/group-state.d.ts.map +1 -1
- package/dist/client/group-state.js +27 -24
- package/dist/client/group-state.js.map +1 -1
- package/dist/client/lifecycle.d.ts +15 -1
- package/dist/client/lifecycle.d.ts.map +1 -1
- package/dist/client/lifecycle.js +477 -132
- package/dist/client/lifecycle.js.map +1 -1
- package/dist/client/mention-mode.d.ts +7 -0
- package/dist/client/mention-mode.d.ts.map +1 -0
- package/dist/client/mention-mode.js +184 -0
- package/dist/client/mention-mode.js.map +1 -0
- package/dist/client/peers.d.ts +1 -1
- package/dist/client/peers.d.ts.map +1 -1
- package/dist/client/peers.js +26 -3
- package/dist/client/peers.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts +34 -2
- package/dist/client/rpc-pipeline.d.ts.map +1 -1
- package/dist/client/rpc-pipeline.js +503 -99
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/runtime.d.ts +1 -3
- package/dist/client/runtime.d.ts.map +1 -1
- package/dist/client/runtime.js +4 -7
- package/dist/client/runtime.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +43 -2
- package/dist/client/v2-e2ee.d.ts.map +1 -1
- package/dist/client/v2-e2ee.js +931 -138
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +46 -15
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +785 -304
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +4 -1
- package/dist/errors.js.map +1 -1
- package/dist/facades.d.ts +26 -1
- package/dist/facades.d.ts.map +1 -1
- package/dist/facades.js +142 -60
- package/dist/facades.js.map +1 -1
- package/dist/group-id.d.ts.map +1 -1
- package/dist/group-id.js +2 -17
- package/dist/group-id.js.map +1 -1
- package/dist/group-index.d.ts +6 -1
- package/dist/group-index.d.ts.map +1 -1
- package/dist/group-index.js +44 -25
- package/dist/group-index.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/keystore/index.d.ts +10 -5
- package/dist/keystore/index.d.ts.map +1 -1
- package/dist/keystore/indexeddb-identity-store.d.ts +0 -12
- package/dist/keystore/indexeddb-identity-store.d.ts.map +1 -1
- package/dist/keystore/indexeddb-identity-store.js +0 -60
- package/dist/keystore/indexeddb-identity-store.js.map +1 -1
- package/dist/keystore/indexeddb-shared.d.ts.map +1 -1
- package/dist/keystore/indexeddb-shared.js +9 -5
- package/dist/keystore/indexeddb-shared.js.map +1 -1
- package/dist/keystore/indexeddb-token-store.d.ts +3 -1
- package/dist/keystore/indexeddb-token-store.d.ts.map +1 -1
- package/dist/keystore/indexeddb-token-store.js +47 -2
- package/dist/keystore/indexeddb-token-store.js.map +1 -1
- package/dist/register-flow.d.ts.map +1 -1
- package/dist/register-flow.js +28 -3
- package/dist/register-flow.js.map +1 -1
- package/dist/seq-tracker.d.ts +28 -8
- package/dist/seq-tracker.d.ts.map +1 -1
- package/dist/seq-tracker.js +224 -61
- package/dist/seq-tracker.js.map +1 -1
- package/dist/storage/vfs.d.ts +1 -0
- package/dist/storage/vfs.d.ts.map +1 -1
- package/dist/storage/vfs.js +26 -2
- package/dist/storage/vfs.js.map +1 -1
- package/dist/tools/cross-sdk-agent.js +399 -11
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +12 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +226 -102
- package/dist/transport.js.map +1 -1
- package/dist/v2/session/session.d.ts.map +1 -1
- package/dist/v2/session/session.js +3 -4
- package/dist/v2/session/session.js.map +1 -1
- package/dist/v2/state/commitment.d.ts.map +1 -1
- package/dist/v2/state/commitment.js +1 -2
- package/dist/v2/state/commitment.js.map +1 -1
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +8 -14
- package/dist/validators.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +11 -9
- package/dist/group-resources.d.ts +0 -98
- package/dist/group-resources.d.ts.map +0 -1
- package/dist/group-resources.js +0 -635
- package/dist/group-resources.js.map +0 -1
- package/dist/keystore/indexeddb.d.ts +0 -179
- package/dist/keystore/indexeddb.d.ts.map +0 -1
- package/dist/keystore/indexeddb.js +0 -2031
- package/dist/keystore/indexeddb.js.map +0 -1
- package/dist/namespaces/auth.d.ts +0 -98
- package/dist/namespaces/auth.d.ts.map +0 -1
- package/dist/namespaces/auth.js +0 -992
- package/dist/namespaces/auth.js.map +0 -1
- package/dist/namespaces/custody.d.ts +0 -51
- package/dist/namespaces/custody.d.ts.map +0 -1
- package/dist/namespaces/custody.js +0 -302
- package/dist/namespaces/custody.js.map +0 -1
- package/dist/namespaces/meta.d.ts +0 -109
- package/dist/namespaces/meta.d.ts.map +0 -1
- package/dist/namespaces/meta.js +0 -549
- package/dist/namespaces/meta.js.map +0 -1
package/dist/agent-md.js
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
import { AID } from './aid.js';
|
|
2
2
|
import { certMatchesFingerprint, parseAgentMdTailSignature } from './cert-utils.js';
|
|
3
|
+
import { validateAgentMdDocument, verifyAgentMdUpload } from './agent-md-schema.js';
|
|
3
4
|
import { AUNError, ClientSignatureError, NotFoundError, StateError, ValidationError } from './errors.js';
|
|
4
5
|
import { isJsonObject } from './types.js';
|
|
5
6
|
const DEFAULT_HTTP_TIMEOUT_MS = 30_000;
|
|
7
|
+
export function buildDefaultAgentMd(aid, options = {}) {
|
|
8
|
+
const target = String(aid ?? '').trim();
|
|
9
|
+
const type = String(options.type ?? 'agent').trim() || 'agent';
|
|
10
|
+
const name = String(options.name ?? '').trim() || target.split('.', 1)[0] || target;
|
|
11
|
+
const normalized = String(options.description ?? '').trim().replace(/\s+/g, ' ') || `AUN ${type} ${name}`;
|
|
12
|
+
const description = Array.from(normalized).slice(0, 100).join('');
|
|
13
|
+
return [
|
|
14
|
+
'---',
|
|
15
|
+
`aid: ${JSON.stringify(target)}`,
|
|
16
|
+
`name: ${JSON.stringify(name)}`,
|
|
17
|
+
`type: ${JSON.stringify(type)}`,
|
|
18
|
+
'version: "1.0.0"',
|
|
19
|
+
`description: ${JSON.stringify(description)}`,
|
|
20
|
+
'---',
|
|
21
|
+
'',
|
|
22
|
+
`# ${name}`,
|
|
23
|
+
'',
|
|
24
|
+
].join('\n');
|
|
25
|
+
}
|
|
6
26
|
const HEAD_HTTP_TIMEOUT_MS = 15_000;
|
|
7
27
|
const noopLogger = {
|
|
8
28
|
error: () => { },
|
|
@@ -10,7 +30,127 @@ const noopLogger = {
|
|
|
10
30
|
info: () => { },
|
|
11
31
|
debug: () => { },
|
|
12
32
|
};
|
|
33
|
+
function nodeBuiltin(name) {
|
|
34
|
+
const processLike = globalThis.process;
|
|
35
|
+
if (typeof processLike?.getBuiltinModule !== 'function')
|
|
36
|
+
return null;
|
|
37
|
+
try {
|
|
38
|
+
return processLike.getBuiltinModule(name);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function requestHeaders(init) {
|
|
45
|
+
const out = {};
|
|
46
|
+
try {
|
|
47
|
+
new Headers(init.headers).forEach((value, key) => {
|
|
48
|
+
out[key] = value;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return out;
|
|
53
|
+
}
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
function requestWithNodeHost(input, init, timeoutMs) {
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
let parsed;
|
|
59
|
+
try {
|
|
60
|
+
parsed = new URL(input);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
reject(error);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const module = parsed.protocol === 'https:'
|
|
67
|
+
? nodeBuiltin('node:https')
|
|
68
|
+
: nodeBuiltin('node:http');
|
|
69
|
+
if (!module) {
|
|
70
|
+
reject(new Error('Node HTTP module is unavailable'));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const headers = requestHeaders(init);
|
|
74
|
+
const options = {
|
|
75
|
+
method: init.method ?? 'GET',
|
|
76
|
+
headers,
|
|
77
|
+
timeout: timeoutMs,
|
|
78
|
+
};
|
|
79
|
+
if (parsed.protocol === 'https:') {
|
|
80
|
+
options.rejectUnauthorized = runtimeEnv('NODE_TLS_REJECT_UNAUTHORIZED') !== '0';
|
|
81
|
+
}
|
|
82
|
+
let settled = false;
|
|
83
|
+
let request = null;
|
|
84
|
+
const onAbort = () => {
|
|
85
|
+
request?.destroy(new Error('agent.md request aborted'));
|
|
86
|
+
finish(() => reject(new AUNError('agent.md request aborted')));
|
|
87
|
+
};
|
|
88
|
+
const finish = (callback) => {
|
|
89
|
+
if (settled)
|
|
90
|
+
return;
|
|
91
|
+
settled = true;
|
|
92
|
+
if (init.signal)
|
|
93
|
+
init.signal.removeEventListener('abort', onAbort);
|
|
94
|
+
callback();
|
|
95
|
+
};
|
|
96
|
+
if (init.signal?.aborted) {
|
|
97
|
+
onAbort();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
request = module.request(input, options, (response) => {
|
|
102
|
+
const chunks = [];
|
|
103
|
+
response.on('data', (chunk) => {
|
|
104
|
+
if (chunk instanceof Uint8Array)
|
|
105
|
+
chunks.push(chunk);
|
|
106
|
+
else
|
|
107
|
+
chunks.push(new TextEncoder().encode(String(chunk ?? '')));
|
|
108
|
+
});
|
|
109
|
+
response.on('error', (error) => {
|
|
110
|
+
finish(() => reject(error instanceof Error ? error : new Error(String(error))));
|
|
111
|
+
});
|
|
112
|
+
response.on('end', () => {
|
|
113
|
+
const total = chunks.reduce((size, chunk) => size + chunk.byteLength, 0);
|
|
114
|
+
const body = new Uint8Array(total);
|
|
115
|
+
let offset = 0;
|
|
116
|
+
for (const chunk of chunks) {
|
|
117
|
+
body.set(chunk, offset);
|
|
118
|
+
offset += chunk.byteLength;
|
|
119
|
+
}
|
|
120
|
+
const responseHeaders = {};
|
|
121
|
+
for (const [key, value] of Object.entries(response.headers)) {
|
|
122
|
+
if (typeof value === 'string')
|
|
123
|
+
responseHeaders[key] = value;
|
|
124
|
+
else if (Array.isArray(value))
|
|
125
|
+
responseHeaders[key] = value[0] ?? '';
|
|
126
|
+
}
|
|
127
|
+
finish(() => resolve(new Response(body, {
|
|
128
|
+
status: response.statusCode ?? 500,
|
|
129
|
+
headers: responseHeaders,
|
|
130
|
+
})));
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
request.on('error', (error) => {
|
|
134
|
+
finish(() => reject(error instanceof Error ? error : new Error(String(error))));
|
|
135
|
+
});
|
|
136
|
+
request.setTimeout(timeoutMs, () => {
|
|
137
|
+
request?.destroy();
|
|
138
|
+
finish(() => reject(new AUNError(`agent.md request timed out after ${timeoutMs}ms`)));
|
|
139
|
+
});
|
|
140
|
+
init.signal?.addEventListener('abort', onAbort, { once: true });
|
|
141
|
+
if (typeof init.body === 'string')
|
|
142
|
+
request.write(init.body);
|
|
143
|
+
request.end();
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
finish(() => reject(error));
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
13
150
|
async function fetchWithTimeout(input, init, timeoutMs = DEFAULT_HTTP_TIMEOUT_MS) {
|
|
151
|
+
if (new Headers(init.headers).has('host')) {
|
|
152
|
+
return await requestWithNodeHost(input, init, timeoutMs);
|
|
153
|
+
}
|
|
14
154
|
const controller = new AbortController();
|
|
15
155
|
const timer = globalThis.setTimeout(() => controller.abort(), timeoutMs);
|
|
16
156
|
try {
|
|
@@ -32,12 +172,54 @@ function headerValue(headers, name) {
|
|
|
32
172
|
function agentMdHttpScheme(gatewayUrl) {
|
|
33
173
|
return String(gatewayUrl ?? '').trim().toLowerCase().startsWith('ws://') ? 'http' : 'https';
|
|
34
174
|
}
|
|
175
|
+
function runtimeEnv(name) {
|
|
176
|
+
const processLike = globalThis.process;
|
|
177
|
+
return String(processLike?.env?.[name] ?? '').trim();
|
|
178
|
+
}
|
|
179
|
+
function nameServiceAgentMdUrl(aid, gatewayUrl) {
|
|
180
|
+
const configuredBase = runtimeEnv('AUN_NAMESERVICE_URL') || runtimeEnv('KITE_NAMESERVICE_URL');
|
|
181
|
+
if (configuredBase) {
|
|
182
|
+
try {
|
|
183
|
+
const parsed = new URL(configuredBase);
|
|
184
|
+
if (parsed.protocol && parsed.host) {
|
|
185
|
+
parsed.pathname = `${parsed.pathname.replace(/\/+$/g, '')}/agent.md`;
|
|
186
|
+
parsed.search = '';
|
|
187
|
+
parsed.hash = '';
|
|
188
|
+
return parsed.toString();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// 无效配置时回退到按 issuer 推导的 NameService 公网地址。
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
const target = String(aid ?? '').trim().toLowerCase();
|
|
196
|
+
const gatewayHost = (() => {
|
|
197
|
+
try {
|
|
198
|
+
return new URL(String(gatewayUrl ?? '').trim()).hostname.toLowerCase();
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
return '';
|
|
202
|
+
}
|
|
203
|
+
})();
|
|
204
|
+
const configuredIssuer = runtimeEnv('AUN_ISSUER_DOMAIN').toLowerCase();
|
|
205
|
+
const issuer = configuredIssuer
|
|
206
|
+
|| (gatewayHost.startsWith('gateway.') ? gatewayHost.slice('gateway.'.length) : '')
|
|
207
|
+
|| (target.includes('.') ? target.slice(target.indexOf('.') + 1) : '');
|
|
208
|
+
const host = runtimeEnv('AUN_SERVICE_PUBLIC_HOST_NAMESERVICE') || issuer;
|
|
209
|
+
if (!host)
|
|
210
|
+
return '';
|
|
211
|
+
const scheme = runtimeEnv('AUN_SERVICE_SCHEME_NAMESERVICE') || agentMdHttpScheme(gatewayUrl);
|
|
212
|
+
const port = runtimeEnv('AUN_SERVICE_PUBLIC_PORT_NAMESERVICE');
|
|
213
|
+
const hostWithPort = port && !host.includes(':') && !host.endsWith(`:${port}`) ? `${host}:${port}` : host;
|
|
214
|
+
return `${scheme}://${hostWithPort}/agent.md`;
|
|
215
|
+
}
|
|
35
216
|
function isRecord(value) {
|
|
36
217
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
37
218
|
}
|
|
38
219
|
export class AgentMdManager {
|
|
39
220
|
_aunPath;
|
|
40
221
|
_agentMdPath;
|
|
222
|
+
_uploadViaGatewayHost;
|
|
41
223
|
_tokenStore;
|
|
42
224
|
_log;
|
|
43
225
|
_ownerAidGetter;
|
|
@@ -49,12 +231,13 @@ export class AgentMdManager {
|
|
|
49
231
|
_cache = new Map();
|
|
50
232
|
_memoryStorage = new Map();
|
|
51
233
|
_fetchInflight = new Set();
|
|
234
|
+
_snapshotLoads = new Map();
|
|
52
235
|
_lock = Promise.resolve();
|
|
53
|
-
|
|
54
|
-
_remoteAgentMdEtag = '';
|
|
236
|
+
_storageGeneration = 0;
|
|
55
237
|
constructor(opts) {
|
|
56
238
|
this._aunPath = String(opts.aunPath ?? '');
|
|
57
239
|
this._agentMdPath = this._defaultRoot();
|
|
240
|
+
this._uploadViaGatewayHost = opts.uploadViaGatewayHost ?? false;
|
|
58
241
|
this._tokenStore = opts.tokenStore;
|
|
59
242
|
this._log = opts.logger ?? noopLogger;
|
|
60
243
|
this._ownerAidGetter = opts.ownerAidGetter;
|
|
@@ -73,11 +256,11 @@ export class AgentMdManager {
|
|
|
73
256
|
}
|
|
74
257
|
setRoot(root) {
|
|
75
258
|
this._agentMdPath = String(root ?? '').trim() || this._defaultRoot();
|
|
259
|
+
this._storageGeneration += 1;
|
|
76
260
|
this._cache.clear();
|
|
77
261
|
this._memoryStorage.clear();
|
|
78
262
|
this._fetchInflight.clear();
|
|
79
|
-
this.
|
|
80
|
-
this._remoteAgentMdEtag = '';
|
|
263
|
+
this._snapshotLoads.clear();
|
|
81
264
|
return this._agentMdPath;
|
|
82
265
|
}
|
|
83
266
|
async upload(content) {
|
|
@@ -103,11 +286,13 @@ export class AgentMdManager {
|
|
|
103
286
|
if (localContent === null || localContent.length === 0) {
|
|
104
287
|
throw new ValidationError('uploadAgentMd requires local agent.md content');
|
|
105
288
|
}
|
|
289
|
+
validateAgentMdDocument(localContent, { expectedAid: target });
|
|
106
290
|
const signedResult = await current.signAgentMd(localContent);
|
|
107
291
|
if (!signedResult.ok) {
|
|
108
292
|
throw new ClientSignatureError(signedResult.error.message || 'agent.md signing failed');
|
|
109
293
|
}
|
|
110
294
|
const signed = signedResult.data.signed;
|
|
295
|
+
await verifyAgentMdUpload(signed, current.certPem, target);
|
|
111
296
|
const result = await this._uploadHttp(target, signed);
|
|
112
297
|
const localEtag = await AgentMdManager.contentEtag(signed);
|
|
113
298
|
const remoteEtag = String(result.etag ?? '').trim();
|
|
@@ -135,6 +320,9 @@ export class AgentMdManager {
|
|
|
135
320
|
const signature = { ...verified.data };
|
|
136
321
|
const statusText = String(signature.status ?? 'invalid');
|
|
137
322
|
const reason = String(signature.reason ?? '').trim();
|
|
323
|
+
if (statusText === 'invalid') {
|
|
324
|
+
throw new ClientSignatureError(`agent.md verification failed for ${target}${reason ? `: ${reason}` : ''}`);
|
|
325
|
+
}
|
|
138
326
|
const verification = { status: statusText };
|
|
139
327
|
if (reason)
|
|
140
328
|
verification.reason = reason;
|
|
@@ -152,7 +340,7 @@ export class AgentMdManager {
|
|
|
152
340
|
last_error: '',
|
|
153
341
|
});
|
|
154
342
|
let inSync = null;
|
|
155
|
-
if (target === this._ownerAid()) {
|
|
343
|
+
if (target.toLowerCase() === this._ownerAid().toLowerCase()) {
|
|
156
344
|
const remote = contentResult.etag || String(saved.remote_etag ?? '');
|
|
157
345
|
inSync = localEtag && remote ? localEtag === remote : false;
|
|
158
346
|
}
|
|
@@ -255,8 +443,6 @@ export class AgentMdManager {
|
|
|
255
443
|
fields.last_modified = remoteLastModified;
|
|
256
444
|
record = await this.saveRecord(target, fields) || record;
|
|
257
445
|
}
|
|
258
|
-
if (target === this._ownerAid() && remoteEtag)
|
|
259
|
-
this._remoteAgentMdEtag = remoteEtag;
|
|
260
446
|
await this._scheduleFetchIfMissing(target, record, source);
|
|
261
447
|
this._log.debug(`agent.md meta observed: aid=${target} etag=${remoteEtag || '-'} last_modified=${remoteLastModified || '-'} source=${source || '-'}`);
|
|
262
448
|
}
|
|
@@ -266,7 +452,6 @@ export class AgentMdManager {
|
|
|
266
452
|
const owner = String(ownerAid ?? this._ownerAid() ?? '').trim();
|
|
267
453
|
const etag = String(meta.agent_md_etag ?? '').trim();
|
|
268
454
|
if (etag && owner) {
|
|
269
|
-
this._remoteAgentMdEtag = etag;
|
|
270
455
|
await this.observeMeta(owner, etag, '', 'rpc.self');
|
|
271
456
|
}
|
|
272
457
|
const etags = meta.agent_md_etags;
|
|
@@ -304,33 +489,64 @@ export class AgentMdManager {
|
|
|
304
489
|
await this.observeMeta(groupAid, String(group.etag ?? '').trim(), String(group.last_modified ?? group.lastModified ?? '').trim(), 'envelope.group');
|
|
305
490
|
}
|
|
306
491
|
}
|
|
307
|
-
eventSnapshot() {
|
|
308
|
-
|
|
492
|
+
async eventSnapshot(aid) {
|
|
493
|
+
const target = String(aid ?? this._ownerAid() ?? '').trim();
|
|
494
|
+
if (!target)
|
|
495
|
+
return null;
|
|
496
|
+
const generation = this._storageGeneration;
|
|
497
|
+
if (!this._cache.has(target)) {
|
|
498
|
+
let load = this._snapshotLoads.get(target);
|
|
499
|
+
if (!load) {
|
|
500
|
+
load = this.loadRecord(target).then((record) => {
|
|
501
|
+
if (generation === this._storageGeneration && !this._cache.has(target)) {
|
|
502
|
+
this._cache.set(target, record ? { ...record } : { aid: target });
|
|
503
|
+
}
|
|
504
|
+
});
|
|
505
|
+
this._snapshotLoads.set(target, load);
|
|
506
|
+
}
|
|
507
|
+
try {
|
|
508
|
+
await load;
|
|
509
|
+
}
|
|
510
|
+
finally {
|
|
511
|
+
if (this._snapshotLoads.get(target) === load)
|
|
512
|
+
this._snapshotLoads.delete(target);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (generation !== this._storageGeneration)
|
|
516
|
+
return null;
|
|
517
|
+
const record = this._cache.get(target) ?? { aid: target };
|
|
518
|
+
const localEtag = String(record.local_etag ?? '').trim();
|
|
519
|
+
const remoteEtag = String(record.remote_etag ?? record.etag ?? '').trim();
|
|
520
|
+
if (!localEtag && !remoteEtag)
|
|
309
521
|
return null;
|
|
310
|
-
return { local_etag:
|
|
522
|
+
return { local_etag: localEtag, remote_etag: remoteEtag };
|
|
311
523
|
}
|
|
312
524
|
async readContent(aid) {
|
|
313
|
-
|
|
525
|
+
const root = this.root;
|
|
526
|
+
return await this._readStorage(this._contentKey(aid), root);
|
|
314
527
|
}
|
|
315
528
|
async writeContent(aid, content) {
|
|
316
|
-
|
|
529
|
+
const root = this.root;
|
|
530
|
+
await this._writeStorage(this._contentKey(aid), String(content ?? ''), root);
|
|
317
531
|
}
|
|
318
532
|
async loadRecord(aid) {
|
|
319
533
|
const target = String(aid ?? '').trim();
|
|
320
534
|
if (!target)
|
|
321
535
|
return null;
|
|
536
|
+
const root = this.root;
|
|
537
|
+
const generation = this._storageGeneration;
|
|
322
538
|
try {
|
|
323
539
|
const loaded = await this._withLock(async () => {
|
|
324
|
-
const record = await this._readRecordUnlocked(target);
|
|
540
|
+
const record = await this._readRecordUnlocked(target, root);
|
|
325
541
|
const next = Object.keys(record).length > 0 ? { ...record, aid: target } : { aid: target };
|
|
326
542
|
try {
|
|
327
|
-
const content = await this.
|
|
543
|
+
const content = await this._readStorage(this._contentKey(target), root);
|
|
328
544
|
if (content !== null) {
|
|
329
545
|
next.content = content;
|
|
330
546
|
next.local_etag = await AgentMdManager.contentEtag(content);
|
|
331
547
|
}
|
|
332
548
|
else {
|
|
333
|
-
const metaRaw = await this._readStorage(this._metaKey(target));
|
|
549
|
+
const metaRaw = await this._readStorage(this._metaKey(target), root);
|
|
334
550
|
if (metaRaw !== null)
|
|
335
551
|
this._log.warn(`agent.md content read failed: aid=${target}`);
|
|
336
552
|
}
|
|
@@ -342,8 +558,8 @@ export class AgentMdManager {
|
|
|
342
558
|
});
|
|
343
559
|
if (Object.keys(loaded).length <= 1)
|
|
344
560
|
return null;
|
|
345
|
-
|
|
346
|
-
|
|
561
|
+
if (generation === this._storageGeneration)
|
|
562
|
+
this._cache.set(target, { ...loaded });
|
|
347
563
|
return { ...loaded };
|
|
348
564
|
}
|
|
349
565
|
catch (err) {
|
|
@@ -355,12 +571,14 @@ export class AgentMdManager {
|
|
|
355
571
|
const target = String(aid ?? '').trim();
|
|
356
572
|
if (!target)
|
|
357
573
|
return {};
|
|
574
|
+
const root = this.root;
|
|
575
|
+
const generation = this._storageGeneration;
|
|
358
576
|
try {
|
|
359
577
|
const inputFields = { ...fields };
|
|
360
578
|
const hasContent = Object.prototype.hasOwnProperty.call(inputFields, 'content') && inputFields.content !== undefined && inputFields.content !== null;
|
|
361
579
|
if (hasContent) {
|
|
362
580
|
const text = String(inputFields.content ?? '');
|
|
363
|
-
await this.
|
|
581
|
+
await this._writeStorage(this._contentKey(target), text, root);
|
|
364
582
|
if (!inputFields.local_etag)
|
|
365
583
|
inputFields.local_etag = await AgentMdManager.contentEtag(text);
|
|
366
584
|
if (!inputFields.fetched_at)
|
|
@@ -368,20 +586,20 @@ export class AgentMdManager {
|
|
|
368
586
|
}
|
|
369
587
|
delete inputFields.content;
|
|
370
588
|
const record = await this._withLock(async () => {
|
|
371
|
-
const next = { ...(await this._readRecordUnlocked(target)), aid: target };
|
|
589
|
+
const next = { ...(await this._readRecordUnlocked(target, root)), aid: target };
|
|
372
590
|
for (const [key, value] of Object.entries(inputFields)) {
|
|
373
591
|
if (value !== undefined && value !== null)
|
|
374
592
|
next[key] = value;
|
|
375
593
|
}
|
|
376
594
|
next.updated_at = Date.now();
|
|
377
|
-
await this._writeRecordUnlocked(target, next);
|
|
595
|
+
await this._writeRecordUnlocked(target, next, root);
|
|
378
596
|
return next;
|
|
379
597
|
});
|
|
380
598
|
const loaded = { ...record };
|
|
381
599
|
if (hasContent)
|
|
382
600
|
loaded.content = String(fields.content ?? '');
|
|
383
|
-
|
|
384
|
-
|
|
601
|
+
if (generation === this._storageGeneration)
|
|
602
|
+
this._cache.set(target, { ...loaded });
|
|
385
603
|
return { ...loaded };
|
|
386
604
|
}
|
|
387
605
|
catch (err) {
|
|
@@ -447,10 +665,9 @@ export class AgentMdManager {
|
|
|
447
665
|
async _resolvePeer(aid, certFingerprint) {
|
|
448
666
|
const expectedFp = String(certFingerprint ?? '').trim().toLowerCase();
|
|
449
667
|
const current = this._currentAid();
|
|
450
|
-
if (current
|
|
668
|
+
if (current && current.aid.toLowerCase() === aid.toLowerCase()) {
|
|
451
669
|
if (!expectedFp || await certMatchesFingerprint(current.certPem, expectedFp))
|
|
452
670
|
return current;
|
|
453
|
-
throw new StateError(`current AID certificate fingerprint mismatch for ${aid}`);
|
|
454
671
|
}
|
|
455
672
|
const peer = await this._peerResolver?.(aid, expectedFp || null);
|
|
456
673
|
if (!(peer instanceof AID)) {
|
|
@@ -470,14 +687,48 @@ export class AgentMdManager {
|
|
|
470
687
|
async _uploadHttp(aid, content) {
|
|
471
688
|
const gatewayUrl = await this._resolveGateway(aid);
|
|
472
689
|
const token = await this._accessToken(aid, gatewayUrl);
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
},
|
|
479
|
-
|
|
480
|
-
|
|
690
|
+
// 浏览器禁止覆盖 Host;动态 AID URL 由浏览器/Docker 的通配解析路由。
|
|
691
|
+
const viaGatewayHost = this._uploadViaGatewayHost && nodeBuiltin('node:http') !== null;
|
|
692
|
+
const headers = {
|
|
693
|
+
Authorization: `Bearer ${token}`,
|
|
694
|
+
'Content-Type': 'text/markdown; charset=utf-8',
|
|
695
|
+
...(viaGatewayHost ? { Host: this._safeAid(aid) } : {}),
|
|
696
|
+
};
|
|
697
|
+
let url = this._url(aid, gatewayUrl);
|
|
698
|
+
if (viaGatewayHost) {
|
|
699
|
+
try {
|
|
700
|
+
const parsedGateway = new URL(String(gatewayUrl ?? '').trim());
|
|
701
|
+
const gatewayHost = parsedGateway.hostname;
|
|
702
|
+
const gatewayPort = parsedGateway.port;
|
|
703
|
+
if (gatewayHost) {
|
|
704
|
+
const host = gatewayPort && gatewayPort !== '443' && gatewayPort !== '20001'
|
|
705
|
+
? `${gatewayHost}:${gatewayPort}`
|
|
706
|
+
: gatewayHost;
|
|
707
|
+
url = `${agentMdHttpScheme(gatewayUrl)}://${host}/agent.md`;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
catch {
|
|
711
|
+
// 无效 Gateway 地址时保留目标 AID URL。
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
let response;
|
|
715
|
+
try {
|
|
716
|
+
response = await fetchWithTimeout(url, { method: 'PUT', headers, body: content });
|
|
717
|
+
}
|
|
718
|
+
catch (error) {
|
|
719
|
+
if (!viaGatewayHost)
|
|
720
|
+
throw error;
|
|
721
|
+
const fallbackUrl = nameServiceAgentMdUrl(aid, gatewayUrl);
|
|
722
|
+
if (!fallbackUrl || fallbackUrl === url)
|
|
723
|
+
throw error;
|
|
724
|
+
response = await fetchWithTimeout(fallbackUrl, { method: 'PUT', headers, body: content });
|
|
725
|
+
}
|
|
726
|
+
if (response.status === 404 && viaGatewayHost) {
|
|
727
|
+
const fallbackUrl = nameServiceAgentMdUrl(aid, gatewayUrl);
|
|
728
|
+
if (fallbackUrl && fallbackUrl !== url) {
|
|
729
|
+
response = await fetchWithTimeout(fallbackUrl, { method: 'PUT', headers, body: content });
|
|
730
|
+
}
|
|
731
|
+
}
|
|
481
732
|
if (response.status === 404) {
|
|
482
733
|
throw new NotFoundError(`agent.md endpoint not found for aid: ${aid}`);
|
|
483
734
|
}
|
|
@@ -567,35 +818,36 @@ export class AgentMdManager {
|
|
|
567
818
|
});
|
|
568
819
|
return data;
|
|
569
820
|
}
|
|
570
|
-
async _readStorage(logicalKey) {
|
|
821
|
+
async _readStorage(logicalKey, root = this.root) {
|
|
571
822
|
const key = String(logicalKey ?? '').trim();
|
|
572
823
|
if (!key)
|
|
573
824
|
return null;
|
|
574
825
|
const load = this._tokenStore?.loadAgentMdCache;
|
|
575
826
|
if (typeof load === 'function') {
|
|
576
|
-
const record = await load.call(this._tokenStore,
|
|
827
|
+
const record = await load.call(this._tokenStore, root, key);
|
|
577
828
|
if (record && Object.prototype.hasOwnProperty.call(record, 'content')) {
|
|
578
829
|
return String(record.content ?? '');
|
|
579
830
|
}
|
|
580
831
|
return null;
|
|
581
832
|
}
|
|
582
|
-
|
|
833
|
+
const memoryKey = `${root}\u0000${key}`;
|
|
834
|
+
return this._memoryStorage.has(memoryKey) ? String(this._memoryStorage.get(memoryKey) ?? '') : null;
|
|
583
835
|
}
|
|
584
|
-
async _writeStorage(logicalKey, content) {
|
|
836
|
+
async _writeStorage(logicalKey, content, root = this.root) {
|
|
585
837
|
const key = String(logicalKey ?? '').trim();
|
|
586
838
|
if (!key)
|
|
587
839
|
return;
|
|
588
840
|
const save = this._tokenStore?.upsertAgentMdCache;
|
|
589
841
|
const text = String(content ?? '');
|
|
590
842
|
if (typeof save === 'function') {
|
|
591
|
-
await save.call(this._tokenStore,
|
|
843
|
+
await save.call(this._tokenStore, root, key, {
|
|
592
844
|
content: text,
|
|
593
845
|
local_etag: await AgentMdManager.contentEtag(text),
|
|
594
846
|
fetched_at: Date.now(),
|
|
595
847
|
});
|
|
596
848
|
return;
|
|
597
849
|
}
|
|
598
|
-
this._memoryStorage.set(key
|
|
850
|
+
this._memoryStorage.set(`${root}\u0000${key}`, text);
|
|
599
851
|
}
|
|
600
852
|
async _withLock(fn) {
|
|
601
853
|
const previous = this._lock.catch(() => undefined);
|
|
@@ -624,17 +876,17 @@ export class AgentMdManager {
|
|
|
624
876
|
}
|
|
625
877
|
return record;
|
|
626
878
|
}
|
|
627
|
-
async _writeRecordUnlocked(aid, record) {
|
|
879
|
+
async _writeRecordUnlocked(aid, record, root = this.root) {
|
|
628
880
|
const payload = {};
|
|
629
881
|
for (const [key, value] of Object.entries(record)) {
|
|
630
882
|
if (key !== 'content' && value !== undefined && value !== null)
|
|
631
883
|
payload[key] = value;
|
|
632
884
|
}
|
|
633
885
|
payload.aid = this._safeAid(aid);
|
|
634
|
-
await this._writeStorage(this._metaKey(aid), `${JSON.stringify(payload, null, 2)}\n
|
|
886
|
+
await this._writeStorage(this._metaKey(aid), `${JSON.stringify(payload, null, 2)}\n`, root);
|
|
635
887
|
}
|
|
636
|
-
async _readRecordUnlocked(aid) {
|
|
637
|
-
const raw = await this._readStorage(this._metaKey(aid));
|
|
888
|
+
async _readRecordUnlocked(aid, root = this.root) {
|
|
889
|
+
const raw = await this._readStorage(this._metaKey(aid), root);
|
|
638
890
|
if (raw === null)
|
|
639
891
|
return {};
|
|
640
892
|
try {
|
|
@@ -676,15 +928,5 @@ export class AgentMdManager {
|
|
|
676
928
|
this._fetchInflight.delete(target);
|
|
677
929
|
}
|
|
678
930
|
}
|
|
679
|
-
_refreshOwnerEtags(aid, record) {
|
|
680
|
-
if (aid !== this._ownerAid())
|
|
681
|
-
return;
|
|
682
|
-
const localEtag = String(record.local_etag ?? '').trim();
|
|
683
|
-
const remoteEtag = String(record.remote_etag ?? '').trim();
|
|
684
|
-
if (localEtag)
|
|
685
|
-
this._localAgentMdEtag = localEtag;
|
|
686
|
-
if (remoteEtag)
|
|
687
|
-
this._remoteAgentMdEtag = remoteEtag;
|
|
688
|
-
}
|
|
689
931
|
}
|
|
690
932
|
//# sourceMappingURL=agent-md.js.map
|