evolclaw 2.8.3 → 3.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/README.md +21 -12
- package/bin/ec.js +29 -0
- package/dist/agents/baseagent-normalize.js +19 -0
- package/dist/agents/claude-runner.js +108 -46
- package/dist/agents/codex-runner.js +13 -14
- package/dist/agents/gemini-runner.js +15 -17
- package/dist/agents/kit-renderer.js +281 -0
- package/dist/agents/resolve.js +134 -0
- package/dist/aun/aid/agentmd.js +186 -0
- package/dist/aun/aid/client.js +134 -0
- package/dist/aun/aid/identity.js +159 -0
- package/dist/aun/aid/index.js +3 -0
- package/dist/aun/aid/lifecycle-log.js +33 -0
- package/dist/aun/aid/types.js +1 -0
- package/dist/aun/aid/validation.js +21 -0
- package/dist/aun/msg/group.js +293 -0
- package/dist/aun/msg/index.js +4 -0
- package/dist/aun/msg/p2p.js +147 -0
- package/dist/aun/msg/payload-type.js +27 -0
- package/dist/aun/msg/upload.js +98 -0
- package/dist/aun/outbox.js +138 -0
- package/dist/aun/rpc/caller.js +42 -0
- package/dist/aun/rpc/connection.js +34 -0
- package/dist/aun/rpc/index.js +2 -0
- package/dist/aun/storage/download.js +29 -0
- package/dist/aun/storage/index.js +3 -0
- package/dist/aun/storage/manage.js +10 -0
- package/dist/aun/storage/upload.js +35 -0
- package/dist/channels/aun.js +1340 -349
- package/dist/channels/dingtalk.js +59 -5
- package/dist/channels/feishu.js +381 -32
- package/dist/channels/qqbot.js +68 -12
- package/dist/channels/wechat.js +63 -4
- package/dist/channels/wecom.js +59 -5
- package/dist/cli/agent.js +800 -0
- package/dist/cli/bench.js +1219 -0
- package/dist/cli/index.js +4513 -0
- package/dist/{utils → cli}/init-channel.js +211 -621
- package/dist/cli/init.js +178 -0
- package/dist/cli/link-rules.js +245 -0
- package/dist/cli/net-check.js +640 -0
- package/dist/cli/watch-msg.js +589 -0
- package/dist/config-store.js +645 -0
- package/dist/core/{agent-loader.js → baseagent-loader.js} +6 -12
- package/dist/core/channel-loader.js +176 -12
- package/dist/core/command-handler.js +883 -848
- package/dist/core/evolagent-registry.js +191 -371
- package/dist/core/evolagent.js +202 -238
- package/dist/core/interaction-router.js +52 -5
- package/dist/core/message/im-renderer.js +486 -0
- package/dist/core/message/items-formatter.js +68 -0
- package/dist/core/message/message-bridge.js +109 -56
- package/dist/core/message/message-log.js +93 -0
- package/dist/core/message/message-processor.js +430 -212
- package/dist/core/message/message-queue.js +13 -6
- package/dist/core/permission.js +116 -11
- package/dist/core/session/adapters/codex-session-file-adapter.js +24 -2
- package/dist/core/session/session-fs-store.js +230 -0
- package/dist/core/session/session-manager.js +740 -777
- package/dist/core/session/session-mapper.js +87 -0
- package/dist/core/trigger/manager.js +122 -0
- package/dist/core/trigger/parser.js +128 -0
- package/dist/core/trigger/scheduler.js +224 -0
- package/dist/data/error-dict.json +118 -0
- package/dist/eck/baseagent-caps.js +18 -0
- package/dist/eck/detect.js +47 -0
- package/dist/eck/init.js +77 -0
- package/dist/eck/rules-loader.js +28 -0
- package/dist/index.js +560 -283
- package/dist/ipc.js +49 -0
- package/dist/net-check.js +640 -0
- package/dist/paths.js +73 -9
- package/dist/types.js +8 -2
- package/dist/utils/aid-lifecycle-log.js +33 -0
- package/dist/utils/atomic-write.js +89 -0
- package/dist/utils/channel-helpers.js +46 -0
- package/dist/utils/cross-platform.js +17 -26
- package/dist/utils/error-utils.js +10 -2
- package/dist/utils/instance-registry.js +434 -0
- package/dist/utils/log-writer.js +217 -0
- package/dist/utils/logger.js +34 -77
- package/dist/utils/media-cache.js +23 -0
- package/dist/utils/npm-ops.js +163 -0
- package/dist/utils/process-introspect.js +122 -0
- package/dist/utils/stats.js +192 -0
- package/dist/watch-msg.js +544 -0
- package/evolclaw-install-aun.md +127 -47
- package/kits/docs/GUIDE.md +20 -0
- package/kits/docs/INDEX.md +52 -0
- package/kits/docs/aun/CHEATSHEET.md +17 -0
- package/kits/docs/aun/SYNC_PROTOCOL.md +15 -0
- package/kits/docs/channels/aun.md +25 -0
- package/kits/docs/channels/feishu.md +27 -0
- package/kits/docs/eck_templates/GUIDE.template.md +22 -0
- package/kits/docs/eck_templates/INDEX.template.md +28 -0
- package/kits/docs/eck_templates/path-registry.template.md +33 -0
- package/kits/docs/eck_templates/runtime.template.md +19 -0
- package/kits/docs/evolclaw/AGENT_CMD.md +31 -0
- package/kits/docs/evolclaw/MSG_GROUP.md +30 -0
- package/kits/docs/evolclaw/MSG_PRIVATE.md +25 -0
- package/kits/docs/evolclaw/self-summary.md +29 -0
- package/kits/docs/evolclaw/tools.md +25 -0
- package/kits/docs/identity/AID_PROFILE_SPEC.md +27 -0
- package/kits/docs/identity/PATH_OPS.md +16 -0
- package/kits/docs/identity/ROLE_DETAIL.md +20 -0
- package/kits/docs/identity/identity-tools.md +26 -0
- package/kits/docs/path-registry.md +43 -0
- package/kits/eck_manifest.json +95 -0
- package/kits/rules/01-overview.md +120 -0
- package/kits/rules/02-navigation.md +75 -0
- package/kits/rules/03-identity.md +34 -0
- package/kits/rules/04-relation.md +49 -0
- package/kits/rules/05-venue.md +45 -0
- package/kits/rules/06-channel.md +43 -0
- package/kits/templates/system-fragments/baseagent.md +2 -0
- package/kits/templates/system-fragments/channel.md +10 -0
- package/kits/templates/system-fragments/identity.md +12 -0
- package/kits/templates/system-fragments/relation.md +9 -0
- package/kits/templates/system-fragments/runtime.md +19 -0
- package/kits/templates/system-fragments/venue.md +5 -0
- package/package.json +10 -6
- package/data/evolclaw.sample.json +0 -60
- package/dist/agents/templates.js +0 -122
- package/dist/channels/aun-ops.js +0 -275
- package/dist/cli.js +0 -2178
- package/dist/config.js +0 -591
- package/dist/core/agent-registry.js +0 -450
- package/dist/core/evolagent-schema.js +0 -72
- package/dist/core/message/stream-flusher.js +0 -238
- package/dist/core/message/thought-emitter.js +0 -162
- package/dist/core/reload-hooks.js +0 -87
- package/dist/prompts/templates.js +0 -122
- package/dist/templates/prompts.md +0 -104
- package/dist/templates/skills.md +0 -66
- package/dist/utils/channel-fingerprint.js +0 -59
- package/dist/utils/error-dict.js +0 -63
- package/dist/utils/format.js +0 -32
- package/dist/utils/init.js +0 -645
- package/dist/utils/migrate-project.js +0 -122
- package/dist/utils/reload-hooks.js +0 -87
- package/dist/utils/stats-collector.js +0 -99
- package/dist/utils/upgrade.js +0 -100
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { execFileSync } from 'child_process';
|
|
6
|
+
import { isWindows } from '../../utils/cross-platform.js';
|
|
7
|
+
/**
|
|
8
|
+
* Suppress SDK console logs (DEBUG/INFO/WARN) in CLI context.
|
|
9
|
+
* Call once at CLI entry point — NOT at module load time, to avoid
|
|
10
|
+
* affecting the daemon process which imports this module for slash commands.
|
|
11
|
+
*/
|
|
12
|
+
export function suppressSdkLogs() {
|
|
13
|
+
process.env.AUN_LOG_INI_DISABLE = '1';
|
|
14
|
+
const _origLog = console.log;
|
|
15
|
+
const _origInfo = console.info;
|
|
16
|
+
const _origWarn = console.warn;
|
|
17
|
+
const _origError = console.error;
|
|
18
|
+
const SDK_LOG_RE = /^\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\]\[(?:DEBUG|INFO|WARN)\]/;
|
|
19
|
+
const SDK_ERROR_RE = /^\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+\]\[ERROR\]/;
|
|
20
|
+
console.log = (...args) => { if (typeof args[0] === 'string') {
|
|
21
|
+
if (SDK_LOG_RE.test(args[0]))
|
|
22
|
+
return;
|
|
23
|
+
if (SDK_ERROR_RE.test(args[0])) {
|
|
24
|
+
_origError(...args);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
} _origLog(...args); };
|
|
28
|
+
console.info = (...args) => { if (typeof args[0] === 'string' && SDK_LOG_RE.test(args[0]))
|
|
29
|
+
return; _origInfo(...args); };
|
|
30
|
+
console.warn = (...args) => { if (typeof args[0] === 'string' && SDK_LOG_RE.test(args[0]))
|
|
31
|
+
return; _origWarn(...args); };
|
|
32
|
+
}
|
|
33
|
+
// ==================== Constants ====================
|
|
34
|
+
export const MIN_AUN_CORE_SDK = [0, 2, 17];
|
|
35
|
+
export const AUN_CORE_SDK_PKG = '@agentunion/fastaun';
|
|
36
|
+
// ==================== SDK & Environment ====================
|
|
37
|
+
function compareVersion(a, min) {
|
|
38
|
+
const parts = a.split('.').map(n => parseInt(n, 10));
|
|
39
|
+
if (parts.length < 3 || parts.some(isNaN))
|
|
40
|
+
return false;
|
|
41
|
+
if (parts[0] !== min[0])
|
|
42
|
+
return parts[0] > min[0];
|
|
43
|
+
if (parts[1] !== min[1])
|
|
44
|
+
return parts[1] > min[1];
|
|
45
|
+
return parts[2] >= min[2];
|
|
46
|
+
}
|
|
47
|
+
export function isAunSdkVersionOk(version) {
|
|
48
|
+
return compareVersion(version, MIN_AUN_CORE_SDK);
|
|
49
|
+
}
|
|
50
|
+
export function resolveAunCoreSdkPkg() {
|
|
51
|
+
try {
|
|
52
|
+
let dir = path.dirname(fileURLToPath(import.meta.url));
|
|
53
|
+
while (true) {
|
|
54
|
+
const candidate = path.join(dir, 'node_modules', AUN_CORE_SDK_PKG, 'package.json');
|
|
55
|
+
if (fs.existsSync(candidate)) {
|
|
56
|
+
const data = JSON.parse(fs.readFileSync(candidate, 'utf-8'));
|
|
57
|
+
if (data.name === AUN_CORE_SDK_PKG)
|
|
58
|
+
return { version: data.version, path: candidate };
|
|
59
|
+
}
|
|
60
|
+
const parent = path.dirname(dir);
|
|
61
|
+
if (parent === dir)
|
|
62
|
+
break;
|
|
63
|
+
dir = parent;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch { /* fall through */ }
|
|
67
|
+
try {
|
|
68
|
+
const npmCmd = isWindows ? 'npm.cmd' : 'npm';
|
|
69
|
+
const globalRoot = execFileSync(npmCmd, ['root', '-g'], {
|
|
70
|
+
encoding: 'utf-8', timeout: 10000, shell: isWindows,
|
|
71
|
+
}).trim();
|
|
72
|
+
const pkgPath = path.join(globalRoot, AUN_CORE_SDK_PKG, 'package.json');
|
|
73
|
+
if (fs.existsSync(pkgPath)) {
|
|
74
|
+
const data = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
75
|
+
return { version: data.version, path: pkgPath };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch { /* not found */ }
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
export async function ensureAunSdk() {
|
|
82
|
+
const installed = resolveAunCoreSdkPkg();
|
|
83
|
+
if (installed && isAunSdkVersionOk(installed.version))
|
|
84
|
+
return;
|
|
85
|
+
const { npmInstallGlobal } = await import('../../utils/npm-ops.js');
|
|
86
|
+
console.log(`正在安装 ${AUN_CORE_SDK_PKG}@latest...`);
|
|
87
|
+
await npmInstallGlobal(`${AUN_CORE_SDK_PKG}@latest`);
|
|
88
|
+
}
|
|
89
|
+
export function isAunSdkReady() {
|
|
90
|
+
const installed = resolveAunCoreSdkPkg();
|
|
91
|
+
return !!(installed && isAunSdkVersionOk(installed.version));
|
|
92
|
+
}
|
|
93
|
+
// ==================== CA Root ====================
|
|
94
|
+
export async function downloadCaRoot(aunPath, gatewayUrl, indent = '') {
|
|
95
|
+
const caDir = path.join(aunPath, 'CA', 'root');
|
|
96
|
+
const caCertPath = path.join(caDir, 'root.crt');
|
|
97
|
+
if (fs.existsSync(caCertPath))
|
|
98
|
+
return true;
|
|
99
|
+
if (!gatewayUrl)
|
|
100
|
+
return false;
|
|
101
|
+
try {
|
|
102
|
+
fs.mkdirSync(caDir, { recursive: true });
|
|
103
|
+
const gwHttp = gatewayUrl.replace(/^wss?:/, 'https:').replace(/\/aun$/, '');
|
|
104
|
+
const resp = await fetch(`${gwHttp}/pki/chain`, { redirect: 'follow' });
|
|
105
|
+
if (!resp.ok) {
|
|
106
|
+
console.warn(`${indent}⚠ CA 根证书下载失败: HTTP ${resp.status}`);
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
const body = await resp.text();
|
|
110
|
+
if (!body.includes('BEGIN CERTIFICATE')) {
|
|
111
|
+
console.warn(`${indent}⚠ CA 根证书响应内容无效,跳过写入`);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
fs.writeFileSync(caCertPath, body);
|
|
115
|
+
console.log(`${indent}✓ CA 根证书已下载`);
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
catch (e) {
|
|
119
|
+
console.warn(`${indent}⚠ CA 根证书下载失败: ${e},可稍后手动下载`);
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// ==================== AUNClient Factory ====================
|
|
124
|
+
export async function getAunClient(aid, opts) {
|
|
125
|
+
const aunPath = opts?.aunPath ?? path.join(os.homedir(), '.aun');
|
|
126
|
+
const caCertPath = path.join(aunPath, 'CA', 'root', 'root.crt');
|
|
127
|
+
const { AUNClient } = await import('@agentunion/fastaun');
|
|
128
|
+
const clientOpts = { aun_path: aunPath, debug: false };
|
|
129
|
+
if (fs.existsSync(caCertPath))
|
|
130
|
+
clientOpts.root_ca_path = caCertPath;
|
|
131
|
+
const client = new AUNClient(clientOpts);
|
|
132
|
+
await client.auth.createAid({ aid });
|
|
133
|
+
return client;
|
|
134
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import crypto from 'crypto';
|
|
5
|
+
import { getAunClient, downloadCaRoot } from './client.js';
|
|
6
|
+
import { resolvePaths } from '../../paths.js';
|
|
7
|
+
// ==================== Validation ====================
|
|
8
|
+
export function isValidAid(name) {
|
|
9
|
+
const labels = name.split('.');
|
|
10
|
+
return labels.length >= 3 && labels.every(l => /^[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?$/.test(l));
|
|
11
|
+
}
|
|
12
|
+
// ==================== AID Operations ====================
|
|
13
|
+
export function aidList(aunPath) {
|
|
14
|
+
const aidsDir = path.join(aunPath ?? path.join(os.homedir(), '.aun'), 'AIDs');
|
|
15
|
+
if (!fs.existsSync(aidsDir))
|
|
16
|
+
return [];
|
|
17
|
+
const entries = fs.readdirSync(aidsDir, { withFileTypes: true });
|
|
18
|
+
return entries
|
|
19
|
+
.filter(e => e.isDirectory())
|
|
20
|
+
.map(e => ({
|
|
21
|
+
aid: e.name,
|
|
22
|
+
hasPrivateKey: fs.existsSync(path.join(aidsDir, e.name, 'private')),
|
|
23
|
+
hasAgentMd: fs.existsSync(path.join(aidsDir, e.name, 'agent.md')),
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
export async function aidCreate(aid, opts) {
|
|
27
|
+
const aunPath = opts?.aunPath ?? path.join(os.homedir(), '.aun');
|
|
28
|
+
const aidDir = path.join(aunPath, 'AIDs', aid);
|
|
29
|
+
if (fs.existsSync(aidDir) && fs.existsSync(path.join(aidDir, 'private'))) {
|
|
30
|
+
const client = await getAunClient(aid, { aunPath });
|
|
31
|
+
return { aid, alreadyExisted: true, gateway: '', client };
|
|
32
|
+
}
|
|
33
|
+
const { AUNClient, GatewayDiscovery } = await import('@agentunion/fastaun');
|
|
34
|
+
let client = new AUNClient({ aun_path: aunPath });
|
|
35
|
+
try {
|
|
36
|
+
const result = await client.auth.createAid({ aid });
|
|
37
|
+
const gateway = result.gateway || '';
|
|
38
|
+
const caDownloaded = await downloadCaRoot(aunPath, gateway);
|
|
39
|
+
const caCertPath = path.join(aunPath, 'CA', 'root', 'root.crt');
|
|
40
|
+
if (caDownloaded && fs.existsSync(caCertPath)) {
|
|
41
|
+
try {
|
|
42
|
+
await client.close();
|
|
43
|
+
}
|
|
44
|
+
catch { /* ignore */ }
|
|
45
|
+
client = new AUNClient({ aun_path: aunPath, root_ca_path: caCertPath });
|
|
46
|
+
await client.auth.createAid({ aid });
|
|
47
|
+
}
|
|
48
|
+
let gatewayUrl = gateway;
|
|
49
|
+
if (!gatewayUrl) {
|
|
50
|
+
try {
|
|
51
|
+
const discovery = new GatewayDiscovery({});
|
|
52
|
+
gatewayUrl = await discovery.discover(`https://${aid}/.well-known/aun-gateway`);
|
|
53
|
+
}
|
|
54
|
+
catch { /* fall through */ }
|
|
55
|
+
}
|
|
56
|
+
if (gatewayUrl) {
|
|
57
|
+
client._gatewayUrl = gatewayUrl;
|
|
58
|
+
}
|
|
59
|
+
return { aid, alreadyExisted: false, gateway: gatewayUrl, client };
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
try {
|
|
63
|
+
await client.close();
|
|
64
|
+
}
|
|
65
|
+
catch { /* ignore */ }
|
|
66
|
+
throw e;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// ==================== Show ====================
|
|
70
|
+
export function aidShow(aid, opts) {
|
|
71
|
+
const aunPath = opts?.aunPath ?? path.join(os.homedir(), '.aun');
|
|
72
|
+
const aidDir = path.join(aunPath, 'AIDs', aid);
|
|
73
|
+
const hasPrivateKey = fs.existsSync(path.join(aidDir, 'private'));
|
|
74
|
+
const hasAgentMd = fs.existsSync(path.join(aidDir, 'agent.md'));
|
|
75
|
+
let certExpiresAt = null;
|
|
76
|
+
let certSubject = null;
|
|
77
|
+
const certPath = path.join(aidDir, 'public', 'cert.pem');
|
|
78
|
+
if (fs.existsSync(certPath)) {
|
|
79
|
+
try {
|
|
80
|
+
const pem = fs.readFileSync(certPath, 'utf-8');
|
|
81
|
+
const x509 = new crypto.X509Certificate(pem);
|
|
82
|
+
certExpiresAt = x509.validTo;
|
|
83
|
+
certSubject = x509.subject;
|
|
84
|
+
}
|
|
85
|
+
catch { /* ignore parse errors */ }
|
|
86
|
+
}
|
|
87
|
+
return { aid, hasPrivateKey, hasAgentMd, certExpiresAt, certSubject };
|
|
88
|
+
}
|
|
89
|
+
// ==================== Delete ====================
|
|
90
|
+
export function aidDelete(aid, opts) {
|
|
91
|
+
const aunPath = opts?.aunPath ?? path.join(os.homedir(), '.aun');
|
|
92
|
+
const aidDir = path.join(aunPath, 'AIDs', aid);
|
|
93
|
+
if (!fs.existsSync(aidDir))
|
|
94
|
+
return false;
|
|
95
|
+
fs.rmSync(aidDir, { recursive: true, force: true });
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
// ==================== Lookup ====================
|
|
99
|
+
export async function aidLookup(aid) {
|
|
100
|
+
let gateway = '';
|
|
101
|
+
try {
|
|
102
|
+
const gwResp = await fetch(`https://${aid}/.well-known/aun-gateway`, { redirect: 'follow' });
|
|
103
|
+
if (gwResp.ok) {
|
|
104
|
+
const text = await gwResp.text();
|
|
105
|
+
// Response may be JSON with gateways array or plain URL
|
|
106
|
+
try {
|
|
107
|
+
const parsed = JSON.parse(text.trim());
|
|
108
|
+
if (parsed.gateways?.[0]?.url) {
|
|
109
|
+
gateway = parsed.gateways[0].url;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
gateway = text.trim();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
gateway = text.trim();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch { /* ignore */ }
|
|
121
|
+
try {
|
|
122
|
+
const resp = await fetch(`https://${aid}/agent.md`, { redirect: 'follow' });
|
|
123
|
+
if (resp.ok) {
|
|
124
|
+
const content = await resp.text();
|
|
125
|
+
return { exists: true, aid, gateway, content };
|
|
126
|
+
}
|
|
127
|
+
return { exists: false, aid, gateway, error: `agent_md_not_found` };
|
|
128
|
+
}
|
|
129
|
+
catch (e) {
|
|
130
|
+
return { exists: false, aid, gateway, error: String(e.message || e) };
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function lifecycleLogPath(aid) {
|
|
134
|
+
const aidName = aid.startsWith('@') ? aid.slice(1) : aid;
|
|
135
|
+
return path.join(resolvePaths().aidLogsDir, `${aidName}.jsonl`);
|
|
136
|
+
}
|
|
137
|
+
export function appendAidLifecycle(event) {
|
|
138
|
+
const filePath = lifecycleLogPath(event.aid);
|
|
139
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
140
|
+
fs.appendFileSync(filePath, JSON.stringify(event) + '\n');
|
|
141
|
+
}
|
|
142
|
+
export function readAidLifecycle(aid, lastN = 50) {
|
|
143
|
+
const filePath = lifecycleLogPath(aid);
|
|
144
|
+
try {
|
|
145
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
146
|
+
const lines = content.trim().split('\n').filter(Boolean);
|
|
147
|
+
const events = [];
|
|
148
|
+
for (const line of lines.slice(-lastN)) {
|
|
149
|
+
try {
|
|
150
|
+
events.push(JSON.parse(line));
|
|
151
|
+
}
|
|
152
|
+
catch { }
|
|
153
|
+
}
|
|
154
|
+
return events;
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { isValidAid, aidList, aidCreate, aidShow, aidDelete, aidLookup, appendAidLifecycle, readAidLifecycle } from './identity.js';
|
|
2
|
+
export { buildInitialAgentMd, agentmdGet, agentmdPut } from './agentmd.js';
|
|
3
|
+
export { MIN_AUN_CORE_SDK, AUN_CORE_SDK_PKG, isAunSdkVersionOk, resolveAunCoreSdkPkg, ensureAunSdk, isAunSdkReady, downloadCaRoot, getAunClient, suppressSdkLogs, } from './client.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { resolvePaths } from '../../paths.js';
|
|
4
|
+
function ensureDir(dir) {
|
|
5
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
6
|
+
}
|
|
7
|
+
function logPath(aid) {
|
|
8
|
+
const aidName = aid.startsWith('@') ? aid.slice(1) : aid;
|
|
9
|
+
return path.join(resolvePaths().aidLogsDir, `${aidName}.jsonl`);
|
|
10
|
+
}
|
|
11
|
+
export function appendAidLifecycle(event) {
|
|
12
|
+
const filePath = logPath(event.aid);
|
|
13
|
+
ensureDir(path.dirname(filePath));
|
|
14
|
+
fs.appendFileSync(filePath, JSON.stringify(event) + '\n');
|
|
15
|
+
}
|
|
16
|
+
export function readAidLifecycle(aid, lastN = 50) {
|
|
17
|
+
const filePath = logPath(aid);
|
|
18
|
+
try {
|
|
19
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
20
|
+
const lines = content.trim().split('\n').filter(Boolean);
|
|
21
|
+
const events = [];
|
|
22
|
+
for (const line of lines.slice(-lastN)) {
|
|
23
|
+
try {
|
|
24
|
+
events.push(JSON.parse(line));
|
|
25
|
+
}
|
|
26
|
+
catch { }
|
|
27
|
+
}
|
|
28
|
+
return events;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { isValidAid } from './identity.js';
|
|
4
|
+
/**
|
|
5
|
+
* `agents/<dirName>` 是否能被当作合法的 self-agent 目录:
|
|
6
|
+
* - 目录名通过 isValidAid(标准多级域名)
|
|
7
|
+
* - 目录下存在 config.json
|
|
8
|
+
*
|
|
9
|
+
* 不满足返回原因字符串,调用方决定是 warn-and-skip 还是 throw。
|
|
10
|
+
*/
|
|
11
|
+
export function checkAgentDir(agentsDir, dirName) {
|
|
12
|
+
if (!isValidAid(dirName)) {
|
|
13
|
+
return `dir name "${dirName}" is not a valid AID`;
|
|
14
|
+
}
|
|
15
|
+
const configPath = path.join(agentsDir, dirName, 'config.json');
|
|
16
|
+
if (!fs.existsSync(configPath)) {
|
|
17
|
+
return `missing ${path.join(dirName, 'config.json')}`;
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
export { isValidAid };
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { createShortConnection } from '../rpc/index.js';
|
|
2
|
+
import { uploadFileAndBuildPayload } from './upload.js';
|
|
3
|
+
export async function groupSend(args) {
|
|
4
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
5
|
+
try {
|
|
6
|
+
let payload;
|
|
7
|
+
switch (args.body.mode) {
|
|
8
|
+
case 'text':
|
|
9
|
+
payload = { type: 'text', text: args.body.text };
|
|
10
|
+
break;
|
|
11
|
+
case 'payload':
|
|
12
|
+
payload = args.body.payload;
|
|
13
|
+
break;
|
|
14
|
+
case 'file': {
|
|
15
|
+
const built = await uploadFileAndBuildPayload(conn, args.from, args.body.filePath, {
|
|
16
|
+
as: args.body.as,
|
|
17
|
+
contentType: args.body.contentType,
|
|
18
|
+
text: args.body.text,
|
|
19
|
+
transcript: args.body.transcript,
|
|
20
|
+
});
|
|
21
|
+
payload = built.payload;
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (args.mentions && args.mentions.length > 0) {
|
|
26
|
+
payload.mentions = args.mentions;
|
|
27
|
+
}
|
|
28
|
+
const sendParams = { group_id: args.groupId, payload };
|
|
29
|
+
sendParams.encrypt = args.encrypt === true;
|
|
30
|
+
const result = await conn.call('group.send', sendParams);
|
|
31
|
+
return {
|
|
32
|
+
ok: true,
|
|
33
|
+
group_id: result?.group_id ?? args.groupId,
|
|
34
|
+
message: result?.message,
|
|
35
|
+
event: result?.event,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
return formatRpcError(e);
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
await conn.close();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export async function groupPull(args) {
|
|
46
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
47
|
+
try {
|
|
48
|
+
const params = { group_id: args.groupId };
|
|
49
|
+
if (args.afterSeq !== undefined)
|
|
50
|
+
params.after_message_seq = args.afterSeq;
|
|
51
|
+
if (args.limit !== undefined)
|
|
52
|
+
params.limit = args.limit;
|
|
53
|
+
const result = await conn.call('group.pull', params);
|
|
54
|
+
return {
|
|
55
|
+
ok: true,
|
|
56
|
+
group_id: result?.group_id ?? args.groupId,
|
|
57
|
+
messages: result?.messages ?? [],
|
|
58
|
+
latest_message_seq: result?.latest_message_seq ?? 0,
|
|
59
|
+
has_more: !!result?.has_more,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
return formatRpcError(e);
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
await conn.close();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export async function groupAck(args) {
|
|
70
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
71
|
+
try {
|
|
72
|
+
const result = await conn.call('group.ack', { group_id: args.groupId, seq: args.seq });
|
|
73
|
+
return {
|
|
74
|
+
ok: true,
|
|
75
|
+
group_id: result?.group_id ?? args.groupId,
|
|
76
|
+
ack_seq: result?.ack_seq ?? args.seq,
|
|
77
|
+
latest_message_seq: result?.latest_message_seq,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
return formatRpcError(e);
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
await conn.close();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export async function groupCreate(args) {
|
|
88
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
89
|
+
try {
|
|
90
|
+
const params = { name: args.name };
|
|
91
|
+
if (args.groupId)
|
|
92
|
+
params.group_id = args.groupId;
|
|
93
|
+
if (args.visibility)
|
|
94
|
+
params.visibility = args.visibility;
|
|
95
|
+
if (args.description)
|
|
96
|
+
params.description = args.description;
|
|
97
|
+
if (args.joinMode)
|
|
98
|
+
params.join_mode = args.joinMode;
|
|
99
|
+
const result = await conn.call('group.create', params);
|
|
100
|
+
return { ok: true, group: result?.group };
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
return formatRpcError(e);
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
await conn.close();
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
export async function groupInfo(args) {
|
|
110
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
111
|
+
try {
|
|
112
|
+
const result = await conn.call('group.get', { group_id: args.groupId });
|
|
113
|
+
return { ok: true, group: result?.group };
|
|
114
|
+
}
|
|
115
|
+
catch (e) {
|
|
116
|
+
return formatRpcError(e);
|
|
117
|
+
}
|
|
118
|
+
finally {
|
|
119
|
+
await conn.close();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export async function groupList(args) {
|
|
123
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
124
|
+
try {
|
|
125
|
+
const params = {};
|
|
126
|
+
if (args.size !== undefined)
|
|
127
|
+
params.size = args.size;
|
|
128
|
+
const result = await conn.call('group.list_my', params);
|
|
129
|
+
return {
|
|
130
|
+
ok: true,
|
|
131
|
+
items: result?.items ?? [],
|
|
132
|
+
total: result?.total ?? 0,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
return formatRpcError(e);
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
await conn.close();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
export async function groupUpdate(args) {
|
|
143
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
144
|
+
try {
|
|
145
|
+
const params = { group_id: args.groupId };
|
|
146
|
+
if (args.name !== undefined)
|
|
147
|
+
params.name = args.name;
|
|
148
|
+
if (args.description !== undefined)
|
|
149
|
+
params.description = args.description;
|
|
150
|
+
const result = await conn.call('group.update', params);
|
|
151
|
+
return { ok: true, group: result?.group };
|
|
152
|
+
}
|
|
153
|
+
catch (e) {
|
|
154
|
+
return formatRpcError(e);
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
await conn.close();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
export async function groupDissolve(args) {
|
|
161
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
162
|
+
try {
|
|
163
|
+
const result = await conn.call('group.dissolve', { group_id: args.groupId });
|
|
164
|
+
return {
|
|
165
|
+
ok: true,
|
|
166
|
+
group_id: result?.group_id ?? args.groupId,
|
|
167
|
+
status: result?.status ?? 'dissolved',
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
catch (e) {
|
|
171
|
+
return formatRpcError(e);
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
await conn.close();
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
export async function groupJoin(args) {
|
|
178
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
179
|
+
try {
|
|
180
|
+
const params = { group_id: args.groupId };
|
|
181
|
+
if (args.message)
|
|
182
|
+
params.message = args.message;
|
|
183
|
+
if (args.answer)
|
|
184
|
+
params.answer = args.answer;
|
|
185
|
+
const result = await conn.call('group.request_join', params);
|
|
186
|
+
return { ok: true, group_id: args.groupId, data: result };
|
|
187
|
+
}
|
|
188
|
+
catch (e) {
|
|
189
|
+
return formatRpcError(e);
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
await conn.close();
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
export async function groupLeave(args) {
|
|
196
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
197
|
+
try {
|
|
198
|
+
const result = await conn.call('group.leave', { group_id: args.groupId });
|
|
199
|
+
return { ok: true, group_id: args.groupId, data: result };
|
|
200
|
+
}
|
|
201
|
+
catch (e) {
|
|
202
|
+
return formatRpcError(e);
|
|
203
|
+
}
|
|
204
|
+
finally {
|
|
205
|
+
await conn.close();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
export async function groupInvite(args) {
|
|
209
|
+
if (args.members.length === 0) {
|
|
210
|
+
return { ok: false, error: '至少需要一个成员 AID' };
|
|
211
|
+
}
|
|
212
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
213
|
+
const added = [];
|
|
214
|
+
const failed = [];
|
|
215
|
+
try {
|
|
216
|
+
for (const memberAid of args.members) {
|
|
217
|
+
try {
|
|
218
|
+
await conn.call('group.add_member', { group_id: args.groupId, aid: memberAid });
|
|
219
|
+
added.push(memberAid);
|
|
220
|
+
}
|
|
221
|
+
catch (e) {
|
|
222
|
+
failed.push({ aid: memberAid, error: String(e?.message ?? e) });
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return { ok: true, group_id: args.groupId, added, failed };
|
|
226
|
+
}
|
|
227
|
+
finally {
|
|
228
|
+
await conn.close();
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
export async function groupKick(args) {
|
|
232
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
233
|
+
try {
|
|
234
|
+
const result = await conn.call('group.kick', { group_id: args.groupId, aid: args.memberAid });
|
|
235
|
+
return { ok: true, group_id: args.groupId, data: result };
|
|
236
|
+
}
|
|
237
|
+
catch (e) {
|
|
238
|
+
return formatRpcError(e);
|
|
239
|
+
}
|
|
240
|
+
finally {
|
|
241
|
+
await conn.close();
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
export async function groupMembers(args) {
|
|
245
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
246
|
+
try {
|
|
247
|
+
const params = { group_id: args.groupId };
|
|
248
|
+
if (args.page !== undefined)
|
|
249
|
+
params.page = args.page;
|
|
250
|
+
if (args.size !== undefined)
|
|
251
|
+
params.size = args.size;
|
|
252
|
+
const result = await conn.call('group.get_members', params);
|
|
253
|
+
return {
|
|
254
|
+
ok: true,
|
|
255
|
+
members: result?.members ?? [],
|
|
256
|
+
total: result?.total ?? 0,
|
|
257
|
+
page: result?.page ?? 1,
|
|
258
|
+
size: result?.size ?? 50,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
catch (e) {
|
|
262
|
+
return formatRpcError(e);
|
|
263
|
+
}
|
|
264
|
+
finally {
|
|
265
|
+
await conn.close();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
export async function groupOnline(args) {
|
|
269
|
+
const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
270
|
+
try {
|
|
271
|
+
const result = await conn.call('group.get_online_members', { group_id: args.groupId });
|
|
272
|
+
return {
|
|
273
|
+
ok: true,
|
|
274
|
+
group_id: result?.group_id ?? args.groupId,
|
|
275
|
+
members: result?.members ?? [],
|
|
276
|
+
online_count: result?.online_count ?? 0,
|
|
277
|
+
total: result?.total ?? 0,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
catch (e) {
|
|
281
|
+
return formatRpcError(e);
|
|
282
|
+
}
|
|
283
|
+
finally {
|
|
284
|
+
await conn.close();
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
// ==================== Internal ====================
|
|
288
|
+
function formatRpcError(e) {
|
|
289
|
+
if (e?.code !== undefined && e?.message !== undefined) {
|
|
290
|
+
return { ok: false, error: String(e.message), code: e.code };
|
|
291
|
+
}
|
|
292
|
+
return { ok: false, error: String(e?.message ?? e) };
|
|
293
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { msgSend, msgPull, msgAck, msgRecall, msgOnline, } from './p2p.js';
|
|
2
|
+
export { groupSend, groupPull, groupAck, groupCreate, groupInfo, groupList, groupUpdate, groupDissolve, groupJoin, groupLeave, groupInvite, groupKick, groupMembers, groupOnline, } from './group.js';
|
|
3
|
+
export { uploadFileAndBuildPayload } from './upload.js';
|
|
4
|
+
export { inferPayloadType, isValidPayloadType } from './payload-type.js';
|