evolcore 0.0.11 → 0.0.13
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 +44 -0
- package/bin/codex-managed-hook.mjs +80 -0
- package/bin/ec-safe-output.js +26 -7
- package/dist/agents/claude-runner.js +86 -7
- package/dist/agents/codex-app-server-client.js +174 -20
- package/dist/agents/codex-runner.js +375 -92
- package/dist/agents/ecagent-runner.js +39 -4
- package/dist/agents/gemini-runner.js +1 -0
- package/dist/aun/aid/client.js +11 -21
- package/dist/aun/aid/control-aid.js +36 -13
- package/dist/aun/aid/managed-operation.js +107 -0
- package/dist/aun/aid/store.js +13 -7
- package/dist/aun/group-fs-download.js +56 -0
- package/dist/aun/group-identity.js +1 -2
- package/dist/aun/msg/group.js +91 -44
- package/dist/aun/msg/index.js +1 -2
- package/dist/aun/msg/managed-operation.js +865 -0
- package/dist/aun/msg/mention-schema.js +20 -0
- package/dist/aun/msg/p2p.js +7 -0
- package/dist/aun/msg/upload.js +16 -1
- package/dist/aun/outbox.js +31 -2
- package/dist/aun/rpc/client.js +66 -0
- package/dist/aun/rpc/index.js +1 -2
- package/dist/aun/storage/{upload.js → client.js} +11 -2
- package/dist/aun/storage/index.js +1 -2
- package/dist/channels/aun.js +655 -240
- package/dist/channels/daemon.js +13 -0
- package/dist/cli/agent-command.js +56 -8
- package/dist/cli/agent.js +108 -31
- package/dist/cli/aun-commands.js +270 -69
- package/dist/cli/bench.js +12 -3
- package/dist/cli/cli-argv.js +10 -0
- package/dist/cli/config.js +9 -17
- package/dist/cli/ctl-command.js +1 -1
- package/dist/cli/daemon-commands.js +70 -55
- package/dist/cli/fs-command.js +79 -10
- package/dist/cli/handoff-command.js +3 -0
- package/dist/cli/index.js +30 -2
- package/dist/cli/init.js +77 -8
- package/dist/cli/managed-command-guard.js +41 -0
- package/dist/cli/model.js +11 -4
- package/dist/cli/queue-command.js +53 -1
- package/dist/cli/response.js +71 -0
- package/dist/cli/restart-monitor.js +7 -32
- package/dist/cli/trigger-command.js +11 -0
- package/dist/config/access-policy.js +1 -2
- package/dist/config/builtin-roles.js +9 -0
- package/dist/config/config-manager.js +21 -1
- package/dist/config/contact-book-store.js +11 -3
- package/dist/config/contact-request-service.js +161 -15
- package/dist/config/mention-mode.js +8 -24
- package/dist/config/peer-role-resolver.js +6 -2
- package/dist/config/role-migration-startup.js +53 -0
- package/dist/config/role-store.js +1 -1
- package/dist/core/auth/agent-delegation.js +1 -2
- package/dist/core/auth/auth-gateway.js +29 -1
- package/dist/core/auth/authorization-audit.js +15 -0
- package/dist/core/auth/operation-authorizer.js +31 -7
- package/dist/core/auth/operation-catalog.js +196 -25
- package/dist/core/bootstrap-messages.js +25 -0
- package/dist/core/bootstrap-service.js +64 -4
- package/dist/core/capability/providers/claude-capability-provider.js +9 -31
- package/dist/core/capability/providers/codex-capability-provider.js +4 -15
- package/dist/core/capability/skill-discovery.js +55 -0
- package/dist/core/channel-loader.js +1 -1
- package/dist/core/command/cli-intent-parser.js +9 -0
- package/dist/core/command/command-handler.js +650 -42
- package/dist/core/command/connect-menu.js +15 -0
- package/dist/core/command/group-menu.js +4 -4
- package/dist/core/command/menu-catalog.js +370 -0
- package/dist/core/command/menu-handler.js +230 -51
- package/dist/core/command/menu-protocol.js +94 -2
- package/dist/core/command/slash-gate.js +5 -2
- package/dist/core/command/slash-handler.js +99 -31
- package/dist/core/daemon-file-cache.js +2 -1
- package/dist/core/data-migration.js +9 -2
- package/dist/core/event-catalog.js +6 -0
- package/dist/core/evolagent.js +4 -2
- package/dist/core/handoff/dispatcher.js +5 -2
- package/dist/core/handoff/runtime.js +157 -22
- package/dist/core/handoff/store.js +29 -1
- package/dist/core/handoff/types.js +1 -0
- package/dist/core/interaction-router.js +10 -0
- package/dist/core/message/im-renderer.js +19 -0
- package/dist/core/message/logical-queue-bridge.js +1 -0
- package/dist/core/message/mention-schema.js +126 -0
- package/dist/core/message/message-bridge.js +298 -88
- package/dist/core/message/message-log.js +3 -0
- package/dist/core/message/message-queue.js +268 -39
- package/dist/core/message/message-utils.js +81 -4
- package/dist/core/message/response-engine.js +161 -77
- package/dist/core/message/stream-debouncer.js +10 -2
- package/dist/core/permission/approval-gateway.js +1 -0
- package/dist/core/permission/ec-command-parser.js +243 -18
- package/dist/core/permission/index.js +1 -1
- package/dist/core/permission/mode.js +15 -0
- package/dist/core/permission/readonly-shell-query.js +148 -8
- package/dist/core/permission/sandbox-runtime.js +43 -1
- package/dist/core/permission/tool-policy.js +322 -57
- package/dist/core/protected-paths.js +114 -4
- package/dist/core/session/session-manager.js +42 -4
- package/dist/core/session/session-mapper.js +20 -1
- package/dist/eck/detect.js +18 -1
- package/dist/eck/group-rules-sync.js +15 -44
- package/dist/eck/manifest-engine.js +39 -13
- package/dist/index.js +541 -180
- package/dist/ipc.js +232 -10
- package/dist/paths.js +3 -0
- package/dist/response-system/coordinator.js +6 -4
- package/dist/response-system/engines/v1/proactive-flow.js +26 -8
- package/dist/response-system/modes/single-session/index.js +14 -1
- package/dist/response-system/selector.js +6 -5
- package/dist/trigger/anomaly-store.js +4 -0
- package/dist/trigger/feedback.js +64 -11
- package/dist/trigger/manager.js +21 -1
- package/dist/trigger/parser.js +14 -2
- package/dist/trigger/scheduler.js +1 -0
- package/dist/trigger/script-executor.js +1 -0
- package/dist/trigger/validation.js +67 -6
- package/dist/utils/codex-app-server-registry.js +90 -0
- package/dist/utils/codex-cli.js +5 -1
- package/dist/utils/cross-platform.js +15 -0
- package/dist/utils/ecweb-supervisor.js +332 -0
- package/dist/utils/error-utils.js +10 -0
- package/dist/utils/npm-ops.js +5 -12
- package/dist/utils/tool-summary.js +11 -0
- package/kits/docs/channels/aun.md +1 -1
- package/kits/docs/context-assembly.md +2 -2
- package/kits/docs/evolcore/agent.md +11 -6
- package/kits/docs/evolcore/aid.md +14 -0
- package/kits/docs/evolcore/trigger.md +17 -1
- package/kits/docs/prompt-loading-architecture.md +1 -2
- package/kits/docs/venues/group.md +1 -1
- package/kits/eck_manifest.json +0 -12
- package/kits/migrations/migrate-contact-book-v2.mjs +1 -2
- package/kits/rules/04-relation.md +1 -1
- package/kits/rules/05-venue.md +2 -2
- package/kits/schemas/role-config.schema.1.json +1 -0
- package/kits/schemas/single-session.schema.1.json +3 -3
- package/kits/schemas/single-session.schema.2.json +3 -3
- package/kits/templates/roles/admin.json +27 -0
- package/kits/templates/roles/member.json +34 -1
- package/kits/templates/roles/visitor.json +35 -3
- package/kits/templates/system-fragments/bootstrap.md +1 -1
- package/kits/templates/system-fragments/channel.md +1 -1
- package/kits/templates/system-fragments/session.md +1 -1
- package/package.json +2 -2
- package/dist/aun/msg/payload-type.js +0 -27
- package/dist/aun/rpc/caller.js +0 -42
- package/dist/aun/rpc/connection.js +0 -25
- package/dist/aun/storage/manage.js +0 -10
- package/dist/config/access-policy-domain.js +0 -18
- package/dist/config/config-batch-get.js +0 -11
- package/dist/config/owner-policy.js +0 -4
- package/dist/config/role-config-v4-startup.js +0 -32
- package/dist/config/role-config-v5-startup.js +0 -27
- package/dist/core/auth/trigger-authorization.js +0 -15
- package/dist/core/command/evol-menu-version-gate.js +0 -39
- package/dist/core/interaction-registration.js +0 -10
- package/dist/core/permission/execution-sandbox.js +0 -16
- package/dist/core/relation/peer-key.js +0 -1
- package/dist/core/session/session-key.js +0 -24
- package/dist/eck/baseagent-caps.js +0 -18
- package/dist/eck/rules-loader.js +0 -28
|
@@ -9,6 +9,7 @@ import { requestDangerousCommandPermission } from '../core/permission/approval-g
|
|
|
9
9
|
import { normalizePermissionMode } from '../core/permission/mode.js';
|
|
10
10
|
import { checkDangerousCommand, checkReadonly, evaluateToolPreflight } from '../core/permission/tool-policy.js';
|
|
11
11
|
import { logger } from '../utils/logger.js';
|
|
12
|
+
import { summarizeToolInputForAudit } from '../utils/tool-summary.js';
|
|
12
13
|
import { resolveEcagentConfig } from './baseagent.js';
|
|
13
14
|
import { buildModelRequestHeaders } from './request-identity.js';
|
|
14
15
|
const PROVIDER_ID = 'evolcore-gateway';
|
|
@@ -957,9 +958,31 @@ export class EcagentRunner {
|
|
|
957
958
|
}
|
|
958
959
|
async authorizeTool(sessionId, projectPath, mode, toolName, input) {
|
|
959
960
|
const permissionContext = this.permissionContexts.get(sessionId);
|
|
961
|
+
const recordBlockedOperation = async (policyCode, operationInput = input) => {
|
|
962
|
+
try {
|
|
963
|
+
await permissionContext?.recordExecutionAnomaly?.({
|
|
964
|
+
code: 'operation_blocked',
|
|
965
|
+
severity: 'warning',
|
|
966
|
+
phase: 'execution',
|
|
967
|
+
occurredAt: Date.now(),
|
|
968
|
+
toolName,
|
|
969
|
+
policyCode,
|
|
970
|
+
decisionSource: 'policy',
|
|
971
|
+
agentAid: permissionContext?.selfAid,
|
|
972
|
+
permissionMode: mode,
|
|
973
|
+
summary: summarizeToolInputForAudit(toolName, operationInput).slice(0, 512),
|
|
974
|
+
effect: 'operation_skipped',
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
catch (error) {
|
|
978
|
+
logger.warn(`[EcagentRunner] failed to record blocked operation: session=${sessionId} tool=${toolName} code=${policyCode} error=${error instanceof Error ? error.message : String(error)}`);
|
|
979
|
+
}
|
|
980
|
+
};
|
|
960
981
|
const policy = permissionContext?.policyHook?.(toolName, input);
|
|
961
|
-
if (policy?.block)
|
|
982
|
+
if (policy?.block) {
|
|
983
|
+
await recordBlockedOperation(policy.policyCode ?? 'session_policy_hook');
|
|
962
984
|
return { block: true, reason: policy.reason || '当前会话策略拒绝此工具调用' };
|
|
985
|
+
}
|
|
963
986
|
const preflight = evaluateToolPreflight(toolName, input, {
|
|
964
987
|
sessionId,
|
|
965
988
|
selfAid: permissionContext?.selfAid,
|
|
@@ -969,8 +992,12 @@ export class EcagentRunner {
|
|
|
969
992
|
permissionMode: mode,
|
|
970
993
|
projectPath,
|
|
971
994
|
});
|
|
972
|
-
if (preflight.behavior === 'deny')
|
|
995
|
+
if (preflight.behavior === 'deny') {
|
|
996
|
+
if (preflight.policyCode) {
|
|
997
|
+
await recordBlockedOperation(preflight.policyCode, input);
|
|
998
|
+
}
|
|
973
999
|
return { block: true, reason: preflight.message };
|
|
1000
|
+
}
|
|
974
1001
|
if (preflight.behavior === 'allow')
|
|
975
1002
|
return {};
|
|
976
1003
|
const checkedInput = preflight.input;
|
|
@@ -978,11 +1005,19 @@ export class EcagentRunner {
|
|
|
978
1005
|
const decision = checkReadonly(toolName, checkedInput, projectPath, {
|
|
979
1006
|
sessionId, channel: permissionContext?.channel, peerId: permissionContext?.userId, role: permissionContext?.role,
|
|
980
1007
|
});
|
|
981
|
-
|
|
1008
|
+
if (decision.behavior === 'deny') {
|
|
1009
|
+
await recordBlockedOperation(decision.policyCode ?? 'readonly_mode', checkedInput);
|
|
1010
|
+
return { block: true, reason: decision.message };
|
|
1011
|
+
}
|
|
1012
|
+
return {};
|
|
982
1013
|
}
|
|
983
1014
|
const dangerous = checkDangerousCommand(toolName, checkedInput);
|
|
984
1015
|
if (mode === 'auto') {
|
|
985
|
-
|
|
1016
|
+
if (dangerous.isDangerous) {
|
|
1017
|
+
await recordBlockedOperation('auto_dangerous_command', checkedInput);
|
|
1018
|
+
return { block: true, reason: `危险操作已由 auto 模式拒绝:${dangerous.reason}` };
|
|
1019
|
+
}
|
|
1020
|
+
return {};
|
|
986
1021
|
}
|
|
987
1022
|
const prompt = permissionContext?.sendPrompt ?? this.sendPromptFn;
|
|
988
1023
|
const decision = await requestDangerousCommandPermission(this.permissionGateway, sessionId, toolName, checkedInput, prompt, permissionContext, `ecagent:${mode}`, mode);
|
package/dist/aun/aid/client.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
-
import { execFileSync } from 'child_process';
|
|
5
|
-
import { isWindows } from '../../utils/cross-platform.js';
|
|
6
4
|
/**
|
|
7
5
|
* Suppress SDK console logs (DEBUG/INFO/WARN) in CLI context.
|
|
8
6
|
* Call once at CLI entry point — NOT at module load time, to avoid
|
|
@@ -40,10 +38,9 @@ export function suppressSdkLogs() {
|
|
|
40
38
|
return _origStderrWrite(chunk, encoding, callback);
|
|
41
39
|
};
|
|
42
40
|
}
|
|
43
|
-
// ====================
|
|
44
|
-
export const MIN_AUN_CORE_SDK = [0,
|
|
41
|
+
// ==================== SDK package ====================
|
|
42
|
+
export const MIN_AUN_CORE_SDK = [0, 5, 6];
|
|
45
43
|
export const AUN_CORE_SDK_PKG = '@agentunion/fastaun';
|
|
46
|
-
// ==================== SDK & Environment ====================
|
|
47
44
|
function compareVersion(a, min) {
|
|
48
45
|
const parts = a.split('.').map(n => parseInt(n, 10));
|
|
49
46
|
if (parts.length < 3 || parts.some(isNaN))
|
|
@@ -57,6 +54,7 @@ function compareVersion(a, min) {
|
|
|
57
54
|
export function isAunSdkVersionOk(version) {
|
|
58
55
|
return compareVersion(version, MIN_AUN_CORE_SDK);
|
|
59
56
|
}
|
|
57
|
+
/** Resolve only the SDK bundled in EvolCore's own dependency tree. */
|
|
60
58
|
export function resolveAunCoreSdkPkg() {
|
|
61
59
|
try {
|
|
62
60
|
let dir = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -73,28 +71,20 @@ export function resolveAunCoreSdkPkg() {
|
|
|
73
71
|
dir = parent;
|
|
74
72
|
}
|
|
75
73
|
}
|
|
76
|
-
catch { /*
|
|
77
|
-
try {
|
|
78
|
-
const npmCmd = isWindows ? 'npm.cmd' : 'npm';
|
|
79
|
-
const globalRoot = execFileSync(npmCmd, ['root', '-g'], {
|
|
80
|
-
encoding: 'utf-8', timeout: 10000, shell: isWindows,
|
|
81
|
-
}).trim();
|
|
82
|
-
const pkgPath = path.join(globalRoot, AUN_CORE_SDK_PKG, 'package.json');
|
|
83
|
-
if (fs.existsSync(pkgPath)) {
|
|
84
|
-
const data = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
85
|
-
return { version: data.version, path: pkgPath };
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
catch { /* not found */ }
|
|
74
|
+
catch { /* invalid or missing package metadata */ }
|
|
89
75
|
return null;
|
|
90
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Compatibility guard retained for callers that explicitly check SDK readiness.
|
|
79
|
+
* The SDK is bundled with EvolCore and must never be installed independently.
|
|
80
|
+
*/
|
|
91
81
|
export async function ensureAunSdk() {
|
|
92
82
|
const installed = resolveAunCoreSdkPkg();
|
|
93
83
|
if (installed && isAunSdkVersionOk(installed.version))
|
|
94
84
|
return;
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
85
|
+
const expected = MIN_AUN_CORE_SDK.join('.');
|
|
86
|
+
const detected = installed?.version ?? 'missing';
|
|
87
|
+
throw new Error(`${AUN_CORE_SDK_PKG} ${detected} is not the bundled SDK expected by EvolCore (>= ${expected}); reinstall or upgrade EvolCore`);
|
|
98
88
|
}
|
|
99
89
|
export function isAunSdkReady() {
|
|
100
90
|
const installed = resolveAunCoreSdkPkg();
|
|
@@ -62,7 +62,8 @@ async function candidateExists(store, candidate) {
|
|
|
62
62
|
throw new Error(`Gateway 不可达,无法查重控制 AID:${r.error?.message ?? 'unknown'}`);
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
|
-
* 生成控制 AID:循环候选 → candidateExists 查重(权威 PKI 判据)→ 不冲突则 aidCreate
|
|
65
|
+
* 生成控制 AID:循环候选 → candidateExists 查重(权威 PKI 判据)→ 不冲突则 aidCreate;
|
|
66
|
+
* 查重通过但注册失败时也换候选重试,覆盖查重与注册之间的竞态。
|
|
66
67
|
* - 查重走 GET 证书(见 candidateExists;不拉 agent.md,控制 AID 本就不传 agent.md)
|
|
67
68
|
* - fail-fast:查重探测失败(网关不可达)立即抛错,不掩盖成"均冲突"
|
|
68
69
|
* - agent.md 不上传:aidCreate 仅注册身份 + 写私钥,不调 agentmdPut
|
|
@@ -72,6 +73,7 @@ export async function generateControlAid(aidDomain) {
|
|
|
72
73
|
? resolveControlAidDomain()
|
|
73
74
|
: normalizeAidDomain(aidDomain, 'aidDomain');
|
|
74
75
|
const store = await getAidStore({ slotId: SLOT.cli });
|
|
76
|
+
let lastRegistrationError;
|
|
75
77
|
try {
|
|
76
78
|
for (let i = 0; i < MAX_ATTEMPTS; i++) {
|
|
77
79
|
const candidate = candidateAid(finalAidDomain);
|
|
@@ -79,22 +81,43 @@ export async function generateControlAid(aidDomain) {
|
|
|
79
81
|
logger.info(`[control-aid] ${candidate} 已注册,重试 (${i + 1}/${MAX_ATTEMPTS})`);
|
|
80
82
|
continue;
|
|
81
83
|
}
|
|
82
|
-
const created = await aidCreate(candidate);
|
|
83
|
-
// 清理 aidCreate 内部另开的 client/store——关闭失败不可丢弃已注册的 AID(否则下次 init
|
|
84
|
-
// 会把它当冲突,白白消耗一次重试)。close 异常降级为 warn。
|
|
85
84
|
try {
|
|
86
|
-
await
|
|
85
|
+
const created = await aidCreate(candidate);
|
|
86
|
+
// 清理 aidCreate 内部另开的 client/store——关闭失败不可丢弃已注册的 AID(否则下次 init
|
|
87
|
+
// 会把它当冲突,白白消耗一次重试)。close 异常降级为 warn。
|
|
88
|
+
try {
|
|
89
|
+
await created.client?.close?.();
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
logger.warn(`[control-aid] client.close() 失败(非致命): ${e}`);
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
await created.store?.close?.();
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
logger.warn(`[control-aid] store.close() 失败(非致命): ${e}`);
|
|
99
|
+
}
|
|
100
|
+
return { aid: created.aid, gateway: created.gateway };
|
|
87
101
|
}
|
|
88
102
|
catch (e) {
|
|
89
|
-
|
|
103
|
+
// 查重与实际注册之间存在 TOCTOU 竞态;注册接口也可能因服务端暂时失败而拒绝,
|
|
104
|
+
// 这些情况都换一个候选继续尝试。查重阶段的网关错误仍在 candidateExists 中 fail-fast。
|
|
105
|
+
lastRegistrationError = e;
|
|
106
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
107
|
+
logger.warn(`[control-aid] ${candidate} 注册失败: ${reason},重试 (${i + 1}/${MAX_ATTEMPTS})`);
|
|
90
108
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
109
|
+
}
|
|
110
|
+
if (lastRegistrationError !== undefined) {
|
|
111
|
+
const reason = lastRegistrationError instanceof Error
|
|
112
|
+
? lastRegistrationError.message
|
|
113
|
+
: String(lastRegistrationError);
|
|
114
|
+
const error = new Error(`无法生成控制 AID:连续 ${MAX_ATTEMPTS} 次注册尝试失败;最后错误:${reason}`, {
|
|
115
|
+
cause: lastRegistrationError,
|
|
116
|
+
});
|
|
117
|
+
const code = lastRegistrationError?.code;
|
|
118
|
+
if (typeof code === 'string')
|
|
119
|
+
error.code = code;
|
|
120
|
+
throw error;
|
|
98
121
|
}
|
|
99
122
|
throw new Error(`无法生成控制 AID:连续 ${MAX_ATTEMPTS} 次候选均冲突`);
|
|
100
123
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { resolveRoot } from '../../paths.js';
|
|
4
|
+
import { agentmdGet, agentmdPut } from './agentmd.js';
|
|
5
|
+
import { aidLookup, aidShow } from './identity.js';
|
|
6
|
+
import { isValidAid } from './validation.js';
|
|
7
|
+
export class ManagedAidOperationError extends Error {
|
|
8
|
+
code;
|
|
9
|
+
constructor(code, message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.name = 'ManagedAidOperationError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function normalizeAid(value) {
|
|
16
|
+
const aid = String(value || '').trim();
|
|
17
|
+
return aid.startsWith('@') ? aid.slice(1) : aid;
|
|
18
|
+
}
|
|
19
|
+
function hasOnlyOptionalJsonFormat(args, aidIndex) {
|
|
20
|
+
const suffix = args.slice(aidIndex + 1);
|
|
21
|
+
return suffix.length === 0 || (suffix.length === 2 && suffix[0] === '--format' && suffix[1] === 'json');
|
|
22
|
+
}
|
|
23
|
+
function parseAid(value) {
|
|
24
|
+
const aid = normalizeAid(value);
|
|
25
|
+
if (!aid)
|
|
26
|
+
return { ok: false, code: 'INVALID_ARGUMENT', reason: 'missing AID' };
|
|
27
|
+
if (!isValidAid(aid))
|
|
28
|
+
return { ok: false, code: 'INVALID_AID', reason: `invalid AID: ${aid}` };
|
|
29
|
+
return { ok: true, aid };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The daemon accepts only the self-scoped AID commands exposed to managed
|
|
33
|
+
* tasks. Parsing here is deliberately narrower than the standalone CLI.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveManagedAidOperation(argv) {
|
|
36
|
+
const args = argv[0] === 'aid' ? argv.slice(1) : argv;
|
|
37
|
+
const subcommand = args[0];
|
|
38
|
+
if ((subcommand === 'show' || subcommand === 'lookup') && hasOnlyOptionalJsonFormat(args, 1)) {
|
|
39
|
+
const parsedAid = parseAid(args[1]);
|
|
40
|
+
if (!parsedAid.ok)
|
|
41
|
+
return parsedAid;
|
|
42
|
+
return {
|
|
43
|
+
ok: true,
|
|
44
|
+
command: {
|
|
45
|
+
kind: subcommand,
|
|
46
|
+
aid: parsedAid.aid,
|
|
47
|
+
operationId: `ec.aid.${subcommand}`,
|
|
48
|
+
canonicalArgv: ['aid', subcommand, parsedAid.aid],
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (subcommand === 'agentmd' && (args[1] === 'get' || args[1] === 'put') && hasOnlyOptionalJsonFormat(args, 2)) {
|
|
53
|
+
const parsedAid = parseAid(args[2]);
|
|
54
|
+
if (!parsedAid.ok)
|
|
55
|
+
return parsedAid;
|
|
56
|
+
const kind = `agentmd.${args[1]}`;
|
|
57
|
+
return {
|
|
58
|
+
ok: true,
|
|
59
|
+
command: {
|
|
60
|
+
kind,
|
|
61
|
+
aid: parsedAid.aid,
|
|
62
|
+
operationId: `ec.aid.${kind}`,
|
|
63
|
+
canonicalArgv: ['aid', 'agentmd', args[1], parsedAid.aid],
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
ok: false,
|
|
69
|
+
code: 'NOT_ALLOWED',
|
|
70
|
+
reason: 'Managed AID operations only allow exact self-scoped show, lookup, agentmd get, or agentmd put commands with an optional --format json suffix',
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const defaultDependencies = () => ({
|
|
74
|
+
root: resolveRoot(),
|
|
75
|
+
aidShow,
|
|
76
|
+
aidLookup,
|
|
77
|
+
agentmdGet,
|
|
78
|
+
agentmdPut,
|
|
79
|
+
existsSync: fs.existsSync,
|
|
80
|
+
readFileSync: fs.readFileSync,
|
|
81
|
+
});
|
|
82
|
+
/** Execute a validated AID operation from the daemon-owned host filesystem. */
|
|
83
|
+
export async function executeManagedAidOperation(command, overrides = {}) {
|
|
84
|
+
const deps = { ...defaultDependencies(), ...overrides };
|
|
85
|
+
const aunPath = deps.root;
|
|
86
|
+
switch (command.kind) {
|
|
87
|
+
case 'show':
|
|
88
|
+
return { kind: command.kind, aid: command.aid, value: await deps.aidShow(command.aid, { aunPath }) };
|
|
89
|
+
case 'lookup':
|
|
90
|
+
return { kind: command.kind, aid: command.aid, value: await deps.aidLookup(command.aid) };
|
|
91
|
+
case 'agentmd.get':
|
|
92
|
+
return {
|
|
93
|
+
kind: command.kind,
|
|
94
|
+
aid: command.aid,
|
|
95
|
+
value: await deps.agentmdGet(command.aid, { aunPath, withVerification: true }),
|
|
96
|
+
};
|
|
97
|
+
case 'agentmd.put': {
|
|
98
|
+
const localPath = path.join(aunPath, 'AIDs', command.aid, 'agent.md');
|
|
99
|
+
if (!deps.existsSync(localPath)) {
|
|
100
|
+
throw new ManagedAidOperationError('LOCAL_AGENTMD_MISSING', `local agent.md not found: ${command.aid}`);
|
|
101
|
+
}
|
|
102
|
+
const content = deps.readFileSync(localPath, 'utf-8');
|
|
103
|
+
await deps.agentmdPut(content, { aid: command.aid, aunPath });
|
|
104
|
+
return { kind: command.kind, aid: command.aid, path: localPath };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
package/dist/aun/aid/store.js
CHANGED
|
@@ -7,21 +7,27 @@ import { AUN_KEYSTORE_ENCRYPTION_SEED } from './encryption-seed-policy.js';
|
|
|
7
7
|
* slotIsolationKey 取第一个分隔符(空格/'/'/':')之前的部分作为隔离键,
|
|
8
8
|
* 隔离键相同 = 共享消费通道(token / seq 游标 / 消息过滤)。
|
|
9
9
|
*
|
|
10
|
-
* 'evolcore daemon' → 隔离键 'evolcore'
|
|
11
|
-
* 'evolcore
|
|
12
|
-
* 'evolcore
|
|
10
|
+
* 'evolcore daemon' → 隔离键 'evolcore'
|
|
11
|
+
* 'evolcore-cli' → 隔离键 'evolcore-cli'
|
|
12
|
+
* 'evolcore-netcheck' → 隔离键 'evolcore-netcheck'
|
|
13
|
+
* 'evolcore-group-rules' → 隔离键 'evolcore-group-rules'
|
|
13
14
|
* 'evolcore-bench' → 隔离键 'evolcore-bench'(连字符非分隔符)→ 独立通道
|
|
14
15
|
*
|
|
15
16
|
* 设计意图:
|
|
16
|
-
* - daemon
|
|
17
|
-
* -
|
|
17
|
+
* - daemon 保留历史 slot 值;slot_id 是网关上的消费游标身份,不可改名。
|
|
18
|
+
* - CLI / ecweb 查询使用新的独立 slot,不能共享 daemon 的 token 或 seq 游标。
|
|
19
|
+
* - netcheck 使用独立消费者,不得因诊断连接影响 daemon 的入站顺序。
|
|
20
|
+
* - 群规则同步是短连接 RPC,也必须使用独立 slot,避免触碰 daemon 消费游标。
|
|
18
21
|
* - bench 各并发单元用 evolcore-bench-<N>,各自独立隔离键,互不干扰
|
|
19
22
|
*/
|
|
20
23
|
export const SLOT = {
|
|
24
|
+
// Wire-compatibility contract: changing this creates a new gateway cursor
|
|
25
|
+
// and can replay retained history into the daemon.
|
|
21
26
|
daemon: 'evolcore daemon',
|
|
22
|
-
cli: 'evolcore
|
|
27
|
+
cli: 'evolcore-cli',
|
|
28
|
+
groupRules: 'evolcore-group-rules',
|
|
23
29
|
bench: 'evolcore-bench',
|
|
24
|
-
netcheck: 'evolcore
|
|
30
|
+
netcheck: 'evolcore-netcheck',
|
|
25
31
|
};
|
|
26
32
|
/** 加载身份失败时抛出,携带 SDK 的错误码与消息。 */
|
|
27
33
|
export class AidLoadError extends Error {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
export class GroupFsDownloadError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
constructor(code, message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.code = code;
|
|
7
|
+
this.name = 'GroupFsDownloadError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Download a group file into memory through the ticket/data plane. */
|
|
11
|
+
export async function downloadGroupFsBytes(client, path) {
|
|
12
|
+
const ticketValue = await client.call('group.fs.create_download_ticket', { path });
|
|
13
|
+
if (!isRecord(ticketValue)) {
|
|
14
|
+
throw new GroupFsDownloadError('INVALID_TICKET', 'group.fs.create_download_ticket returned invalid response');
|
|
15
|
+
}
|
|
16
|
+
const downloadUrl = stringField(ticketValue, ['download_url', 'url']);
|
|
17
|
+
if (!downloadUrl) {
|
|
18
|
+
throw new GroupFsDownloadError('MISSING_DOWNLOAD_URL', 'group.fs.create_download_ticket did not return download_url');
|
|
19
|
+
}
|
|
20
|
+
const bytes = await client.group.fs.lowlevel.httpGet(downloadUrl, bearerHeaders(client));
|
|
21
|
+
const expectedSha = stringField(ticketValue, ['sha256']);
|
|
22
|
+
if (expectedSha && sha256Hex(bytes).toLowerCase() !== expectedSha.toLowerCase()) {
|
|
23
|
+
throw new GroupFsDownloadError('HASH_MISMATCH', 'download hash verification failed');
|
|
24
|
+
}
|
|
25
|
+
return { bytes, ticket: ticketValue };
|
|
26
|
+
}
|
|
27
|
+
function isRecord(value) {
|
|
28
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
29
|
+
}
|
|
30
|
+
function stringField(value, keys) {
|
|
31
|
+
for (const key of keys) {
|
|
32
|
+
const field = value[key];
|
|
33
|
+
if (typeof field === 'string' && field.trim())
|
|
34
|
+
return field;
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
function sha256Hex(bytes) {
|
|
39
|
+
return createHash('sha256').update(bytes).digest('hex');
|
|
40
|
+
}
|
|
41
|
+
function bearerHeaders(client) {
|
|
42
|
+
const anyClient = client;
|
|
43
|
+
if (typeof anyClient.getAccessToken === 'function') {
|
|
44
|
+
const token = stringValue(anyClient.getAccessToken());
|
|
45
|
+
if (token)
|
|
46
|
+
return { Authorization: `Bearer ${token}` };
|
|
47
|
+
}
|
|
48
|
+
const token = stringValue(anyClient.accessToken)
|
|
49
|
+
|| stringValue(anyClient.access_token)
|
|
50
|
+
|| stringValue(anyClient._identity?.access_token)
|
|
51
|
+
|| stringValue(anyClient._sessionParams?.access_token);
|
|
52
|
+
return token ? { Authorization: `Bearer ${token}` } : undefined;
|
|
53
|
+
}
|
|
54
|
+
function stringValue(value) {
|
|
55
|
+
return value === undefined || value === null ? '' : String(value).trim();
|
|
56
|
+
}
|
|
@@ -5,6 +5,5 @@ export function isExplicitGroupId(value) {
|
|
|
5
5
|
return (id.startsWith('group.') && id.includes('/'))
|
|
6
6
|
|| /^\d+\.[a-z0-9.-]+$/i.test(id)
|
|
7
7
|
|| /^grp_[a-z0-9_-]+$/i.test(id)
|
|
8
|
-
|| /^g-[a-z0-9_-]+(?:[.@][a-z0-9.-]+)?$/i.test(id)
|
|
9
|
-
|| /(?:^|\.)groupid\.pub$/i.test(id);
|
|
8
|
+
|| /^g-[a-z0-9_-]+(?:[.@][a-z0-9.-]+)?$/i.test(id);
|
|
10
9
|
}
|
package/dist/aun/msg/group.js
CHANGED
|
@@ -13,6 +13,8 @@ import { readBestTaskRuntimeContext } from '../../cli/task-context.js';
|
|
|
13
13
|
import { ipcQuery } from '../../ipc.js';
|
|
14
14
|
import { resolvePaths } from '../../paths.js';
|
|
15
15
|
import { AGENT_DELEGATION_TOKEN_ENV } from '../../core/auth/agent-delegation.js';
|
|
16
|
+
import { normalizeAunMentionEntries } from './mention-schema.js';
|
|
17
|
+
import { downloadGroupFsBytes } from '../group-fs-download.js';
|
|
16
18
|
function buildGroupPayload(body) {
|
|
17
19
|
return body.mode === 'text' ? { type: 'text', text: body.text } : { ...body.payload };
|
|
18
20
|
}
|
|
@@ -129,17 +131,18 @@ async function daemonGroupSendResult(args, payload, runtimeContext, result) {
|
|
|
129
131
|
status: result.status,
|
|
130
132
|
};
|
|
131
133
|
}
|
|
132
|
-
|
|
134
|
+
const messageId = result.message_id
|
|
135
|
+
?? (typeof result.message?.message_id === 'string' ? result.message.message_id : undefined);
|
|
136
|
+
if (!result.group_id || !messageId) {
|
|
133
137
|
return { ok: false, error: 'daemon AUN group send returned no group message' };
|
|
134
138
|
}
|
|
135
|
-
const messageId = result.message_id
|
|
136
|
-
?? (typeof result.message.message_id === 'string' ? result.message.message_id : undefined);
|
|
137
139
|
if (messageId && !result.log_written) {
|
|
138
140
|
appendGroupSendOutboundLog(args, messageId, payload, runtimeContext, result.encrypt ?? resolveAunMessageEncrypt(args.encrypt));
|
|
139
141
|
}
|
|
140
142
|
return {
|
|
141
143
|
ok: true,
|
|
142
144
|
group_id: result.group_id || args.groupId,
|
|
145
|
+
message_id: messageId,
|
|
143
146
|
message: result.message,
|
|
144
147
|
event: result.event,
|
|
145
148
|
};
|
|
@@ -189,8 +192,18 @@ export async function groupSend(args) {
|
|
|
189
192
|
break;
|
|
190
193
|
}
|
|
191
194
|
}
|
|
192
|
-
|
|
193
|
-
payload.mentions
|
|
195
|
+
const payloadMentions = Object.prototype.hasOwnProperty.call(payload, 'mentions')
|
|
196
|
+
? normalizeAunMentionEntries(payload.mentions)
|
|
197
|
+
: undefined;
|
|
198
|
+
if (args.mentions !== undefined) {
|
|
199
|
+
const normalizedMentions = normalizeAunMentionEntries(args.mentions);
|
|
200
|
+
if (normalizedMentions.length > 0)
|
|
201
|
+
payload.mentions = normalizedMentions;
|
|
202
|
+
else if (payloadMentions !== undefined)
|
|
203
|
+
payload.mentions = payloadMentions;
|
|
204
|
+
}
|
|
205
|
+
else if (payloadMentions !== undefined) {
|
|
206
|
+
payload.mentions = payloadMentions;
|
|
194
207
|
}
|
|
195
208
|
applyGroupRoutingPayloadFields(payload, args, runtimeContext);
|
|
196
209
|
const encrypt = resolveAunMessageEncrypt(args.encrypt);
|
|
@@ -305,8 +318,9 @@ export async function groupInfo(args) {
|
|
|
305
318
|
}
|
|
306
319
|
}
|
|
307
320
|
export async function groupList(args) {
|
|
308
|
-
|
|
321
|
+
let conn;
|
|
309
322
|
try {
|
|
323
|
+
conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
|
|
310
324
|
const params = {};
|
|
311
325
|
if (args.size !== undefined)
|
|
312
326
|
params.size = args.size;
|
|
@@ -329,7 +343,8 @@ export async function groupList(args) {
|
|
|
329
343
|
return formatRpcError(e);
|
|
330
344
|
}
|
|
331
345
|
finally {
|
|
332
|
-
|
|
346
|
+
if (conn)
|
|
347
|
+
await conn.close();
|
|
333
348
|
}
|
|
334
349
|
}
|
|
335
350
|
export async function groupUpdate(args) {
|
|
@@ -675,7 +690,7 @@ export async function groupUpdateRules(args) {
|
|
|
675
690
|
}
|
|
676
691
|
}
|
|
677
692
|
const GROUP_RULES_FILE_PATH = '/rules.md';
|
|
678
|
-
const MAX_GROUP_RULES_BYTES = 4 * 1024;
|
|
693
|
+
export const MAX_GROUP_RULES_BYTES = 4 * 1024;
|
|
679
694
|
const MTIME_TOLERANCE_MS = 1;
|
|
680
695
|
export async function groupRulesFileGet(args) {
|
|
681
696
|
return withAunClient(args.from, args, async (client) => {
|
|
@@ -742,13 +757,26 @@ export async function groupRulesFileGet(args) {
|
|
|
742
757
|
}
|
|
743
758
|
export async function groupRulesFileSet(args) {
|
|
744
759
|
return withAunClient(args.from, args, async (client) => {
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
760
|
+
if ((args.filePath === undefined) === (args.content === undefined)) {
|
|
761
|
+
throw new Error('规则文件必须且只能提供 filePath 或 content');
|
|
762
|
+
}
|
|
763
|
+
let upload;
|
|
764
|
+
if (args.content !== undefined) {
|
|
765
|
+
const bytes = Buffer.from(args.content, 'utf8');
|
|
766
|
+
if (!args.content || bytes.byteLength > MAX_GROUP_RULES_BYTES || bytes.toString('utf8') !== args.content) {
|
|
767
|
+
throw new Error(`规则内容必须是非空 UTF-8,且不超过 ${MAX_GROUP_RULES_BYTES} bytes`);
|
|
768
|
+
}
|
|
769
|
+
upload = await uploadGroupRulesBytes(client, args.groupId, bytes);
|
|
770
|
+
}
|
|
771
|
+
else {
|
|
772
|
+
assertLocalRulesFile(args.filePath);
|
|
773
|
+
upload = await client.group.fs.cp(args.filePath, `${args.groupId}:${GROUP_RULES_FILE_PATH}`, {
|
|
774
|
+
force: true,
|
|
775
|
+
overwrite: true,
|
|
776
|
+
parents: true,
|
|
777
|
+
contentType: 'text/markdown; charset=utf-8',
|
|
778
|
+
});
|
|
779
|
+
}
|
|
752
780
|
const published = await publishCurrentRulesFile(client, args.groupId, args.from);
|
|
753
781
|
return { ...published, upload };
|
|
754
782
|
});
|
|
@@ -984,22 +1012,52 @@ function assertLocalRulesFile(filePath) {
|
|
|
984
1012
|
throw new Error(`规则文件不是有效 UTF-8: ${errorMessage(e)}`);
|
|
985
1013
|
}
|
|
986
1014
|
}
|
|
987
|
-
async function
|
|
988
|
-
const
|
|
989
|
-
const
|
|
990
|
-
|
|
991
|
-
|
|
1015
|
+
async function uploadGroupRulesBytes(client, groupId, bytes) {
|
|
1016
|
+
const remotePath = `${groupId}:${GROUP_RULES_FILE_PATH}`;
|
|
1017
|
+
const base = {
|
|
1018
|
+
path: remotePath,
|
|
1019
|
+
size_bytes: bytes.byteLength,
|
|
1020
|
+
sha256: sha256Hex(bytes),
|
|
1021
|
+
content_type: 'text/markdown; charset=utf-8',
|
|
1022
|
+
force: true,
|
|
1023
|
+
parents: true,
|
|
1024
|
+
};
|
|
1025
|
+
const check = await client.call('group.fs.check_upload', base);
|
|
1026
|
+
if (isRecord(check) && check.within_limit === false) {
|
|
1027
|
+
throw new Error('规则文件超过 group.fs 上传限制');
|
|
1028
|
+
}
|
|
1029
|
+
if (isRecord(check) && (check.instant === true || check.dedup_hit === true || check.skip_upload === true)) {
|
|
1030
|
+
return client.call('group.fs.complete_upload', {
|
|
1031
|
+
...base,
|
|
1032
|
+
skip_blob: true,
|
|
1033
|
+
...(check.session_id !== undefined ? { session_id: check.session_id } : {}),
|
|
1034
|
+
});
|
|
992
1035
|
}
|
|
993
|
-
const
|
|
994
|
-
if (!
|
|
995
|
-
throw new Error('group.fs.
|
|
1036
|
+
const session = await client.call('group.fs.create_upload_session', base);
|
|
1037
|
+
if (!isRecord(session))
|
|
1038
|
+
throw new Error('group.fs.create_upload_session returned invalid response');
|
|
1039
|
+
const uploadUrl = stringField(session, ['upload_url', 'url']);
|
|
1040
|
+
if (!uploadUrl)
|
|
1041
|
+
throw new Error('group.fs.create_upload_session did not return upload_url');
|
|
1042
|
+
const headers = {};
|
|
1043
|
+
if (isRecord(session.headers)) {
|
|
1044
|
+
for (const [key, value] of Object.entries(session.headers)) {
|
|
1045
|
+
if (value !== undefined && value !== null)
|
|
1046
|
+
headers[key] = String(value);
|
|
1047
|
+
}
|
|
996
1048
|
}
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
if (expectedSha && sha256Hex(bytes).toLowerCase() !== expectedSha.toLowerCase()) {
|
|
1000
|
-
throw new Error('download hash verification failed');
|
|
1049
|
+
if (!Object.keys(headers).some(key => key.toLowerCase() === 'content-type')) {
|
|
1050
|
+
headers['Content-Type'] = base.content_type;
|
|
1001
1051
|
}
|
|
1002
|
-
|
|
1052
|
+
await client.group.fs.lowlevel.httpPut(uploadUrl, bytes, headers);
|
|
1053
|
+
return client.call('group.fs.complete_upload', {
|
|
1054
|
+
...base,
|
|
1055
|
+
...((session.session_id ?? session.id) !== undefined ? { session_id: session.session_id ?? session.id } : {}),
|
|
1056
|
+
});
|
|
1057
|
+
}
|
|
1058
|
+
async function readGroupRulesBytes(client, groupId) {
|
|
1059
|
+
const remoteRef = `${groupId}:${GROUP_RULES_FILE_PATH}`;
|
|
1060
|
+
return (await downloadGroupFsBytes(client, remoteRef)).bytes;
|
|
1003
1061
|
}
|
|
1004
1062
|
function decodeRulesText(bytes) {
|
|
1005
1063
|
return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
@@ -1057,22 +1115,6 @@ function groupIndexEtagFromUpdate(result, groupId) {
|
|
|
1057
1115
|
function sha256Hex(bytes) {
|
|
1058
1116
|
return createHash('sha256').update(bytes).digest('hex');
|
|
1059
1117
|
}
|
|
1060
|
-
function bearerHeaders(client) {
|
|
1061
|
-
const token = accessTokenFromClient(client);
|
|
1062
|
-
return token ? { Authorization: `Bearer ${token}` } : undefined;
|
|
1063
|
-
}
|
|
1064
|
-
function accessTokenFromClient(client) {
|
|
1065
|
-
const anyClient = client;
|
|
1066
|
-
if (typeof anyClient.getAccessToken === 'function') {
|
|
1067
|
-
const token = stringValue(anyClient.getAccessToken());
|
|
1068
|
-
if (token)
|
|
1069
|
-
return token;
|
|
1070
|
-
}
|
|
1071
|
-
return stringValue(anyClient.accessToken)
|
|
1072
|
-
|| stringValue(anyClient.access_token)
|
|
1073
|
-
|| stringValue(anyClient._identity?.access_token)
|
|
1074
|
-
|| stringValue(anyClient._sessionParams?.access_token);
|
|
1075
|
-
}
|
|
1076
1118
|
function stringField(obj, keys) {
|
|
1077
1119
|
for (const key of keys) {
|
|
1078
1120
|
const value = obj[key];
|
|
@@ -1120,6 +1162,11 @@ function rulesFileStatusFromError(error) {
|
|
|
1120
1162
|
if (tagged)
|
|
1121
1163
|
return tagged;
|
|
1122
1164
|
const haystack = errorHaystack(error);
|
|
1165
|
+
// A peer cache miss means signer discovery failed; it does not establish
|
|
1166
|
+
// that the group's rules file is absent.
|
|
1167
|
+
if (/peer\s+not\s+found\s+in\s+cache/i.test(haystack)) {
|
|
1168
|
+
return 'unreadable';
|
|
1169
|
+
}
|
|
1123
1170
|
if (/(forbidden|unauthorized|permission|denied|no_permission|permission_denied|无权限|权限|拒绝|\b401\b|\b403\b)/i.test(haystack)) {
|
|
1124
1171
|
return 'forbidden';
|
|
1125
1172
|
}
|
package/dist/aun/msg/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { msgSend, msgPull, msgAck, msgRecall, msgOnline, } from './p2p.js';
|
|
2
2
|
export { msgHistory, MAX_MSG_HISTORY_LIMIT } from './history.js';
|
|
3
3
|
export { groupSend, groupPull, groupAck, groupCreate, groupInfo, groupList, groupUpdate, groupDissolve, groupSuspend, groupResume, groupJoin, groupLeave, groupInvite, groupKick, groupMembers, groupOnline, groupSetRole, groupTransferOwner, groupBan, groupUnban, groupBanlist, groupRules, groupUpdateRules, groupRulesFileGet, groupRulesFileSet, groupRulesFilePublish, } from './group.js';
|
|
4
|
-
export { uploadFileAndBuildPayload } from './upload.js';
|
|
5
|
-
export { inferPayloadType, isValidPayloadType } from './payload-type.js';
|
|
4
|
+
export { uploadFileAndBuildPayload, inferPayloadType, isValidPayloadType } from './upload.js';
|