evolcore 0.0.22 → 0.0.24
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 +74 -14
- package/README.md +4 -0
- package/bin/codex-managed-acl.ps1 +160 -0
- package/bin/codex-managed-hook.mjs +127 -10
- package/bin/ec-safe-output.js +85 -3
- package/bin/install-codex-managed-hooks.mjs +384 -95
- package/dist/agents/baseagent-availability.js +48 -0
- package/dist/agents/baseagent.js +30 -2
- package/dist/agents/claude-runner.js +179 -240
- package/dist/agents/{codex-app-server-client.js → codex/app-server-client.js} +90 -20
- package/dist/{utils/codex-app-server-registry.js → agents/codex/app-server-registry.js} +2 -2
- package/dist/agents/codex/catalog.js +70 -0
- package/dist/agents/codex/diagnostics.js +369 -0
- package/dist/agents/codex-runner.js +839 -192
- package/dist/agents/ecagent-runner.js +27 -34
- package/dist/agents/gemini-runner.js +62 -8
- package/dist/agents/runner-types.js +1 -1
- package/dist/aun/aid/managed-operation.js +28 -6
- package/dist/aun/aid/store.js +43 -0
- package/dist/aun/menu-client.js +272 -0
- package/dist/aun/msg/group.js +65 -4
- package/dist/aun/msg/index.js +1 -1
- package/dist/aun/msg/managed-operation.js +57 -5
- package/dist/aun/outbox.js +56 -18
- package/dist/aun/rpc/client.js +7 -1
- package/dist/channels/aun.js +178 -77
- package/dist/channels/daemon.js +7 -1
- package/dist/channels/dingtalk.js +1 -0
- package/dist/channels/feishu.js +10 -4
- package/dist/channels/wechat.js +81 -10
- package/dist/channels/wecom.js +2 -1
- package/dist/cli/agent-command.js +29 -3
- package/dist/cli/agent-create.js +538 -0
- package/dist/cli/agent.js +26 -675
- package/dist/cli/aun-commands.js +108 -24
- package/dist/cli/command-log.js +21 -2
- package/dist/cli/ctl-command.js +2 -0
- package/dist/cli/daemon-commands.js +289 -61
- package/dist/cli/index.js +22 -2
- package/dist/cli/init.js +2 -10
- package/dist/cli/managed-command-guard.js +3 -0
- package/dist/cli/menu-client.js +95 -0
- package/dist/cli/model.js +23 -8
- package/dist/cli/restart-monitor.js +432 -8
- package/dist/cli/stats.js +110 -0
- package/dist/cli/task-context.js +12 -2
- package/dist/cli/trigger-command.js +9 -1
- package/dist/config/builtin-roles.js +2 -0
- package/dist/config/schema-migration.js +14 -2
- package/dist/core/auth/agent-delegation.js +10 -7
- package/dist/core/auth/auth-gateway.js +3 -2
- package/dist/core/auth/authorization-audit.js +75 -18
- package/dist/core/auth/operation-authorizer.js +63 -3
- package/dist/core/auth/operation-catalog.js +14 -2
- package/dist/core/auth/remote-access-store.js +136 -0
- package/dist/core/baseagent-loader.js +4 -4
- package/dist/core/bootstrap-messages.js +39 -18
- package/dist/core/bootstrap-service.js +32 -26
- package/dist/core/capability/capability-manager.js +8 -4
- package/dist/core/capability/providers/codex-capability-provider.js +1 -1
- package/dist/core/command/agent-control.js +7 -2
- package/dist/core/command/command-handler.js +128 -30
- package/dist/core/command/daemon-diagnostics.js +448 -0
- package/dist/core/command/menu-catalog.js +6 -1
- package/dist/core/command/menu-handler.js +410 -98
- package/dist/core/command/menu-protocol.js +123 -0
- package/dist/core/command/slash-gate.js +4 -6
- package/dist/core/command/slash-handler.js +199 -70
- package/dist/core/data-migration.js +5 -15
- package/dist/core/event-catalog.js +3 -0
- package/dist/core/handoff/runtime.js +3 -1
- package/dist/core/handoff/store.js +7 -1
- package/dist/core/message/im-renderer.js +13 -6
- package/dist/core/message/message-bridge.js +5 -36
- package/dist/core/message/message-queue.js +20 -15
- package/dist/core/message/message-utils.js +6 -3
- package/dist/core/message/response-engine.js +147 -94
- package/dist/core/model/catalog-service.js +310 -0
- package/dist/core/model/model-catalog.js +134 -334
- package/dist/core/model/model-diagnostics.js +4 -5
- package/dist/core/model/model-fallback.js +9 -16
- package/dist/core/model/model-permission.js +5 -2
- package/dist/core/permission/approval-gateway.js +183 -32
- package/dist/core/permission/protected-paths.js +63 -4
- package/dist/core/permission/sandbox-runtime.js +4 -2
- package/dist/core/permission/tool-policy.js +257 -31
- package/dist/core/runtime-lock.js +13 -8
- package/dist/core/session/adapters/codex-session-file-adapter.js +71 -3
- package/dist/core/session/session-manager.js +49 -13
- package/dist/core/session/session-renew.js +1 -0
- package/dist/index.js +214 -57
- package/dist/ipc.js +191 -102
- package/dist/paths.js +23 -1
- package/dist/stats/billing.js +18 -4
- package/dist/trigger/manager.js +3 -1
- package/dist/trigger/parser.js +77 -13
- package/dist/trigger/patch.js +104 -1
- package/dist/utils/atomic-write.js +26 -2
- package/dist/utils/cross-platform.js +436 -1
- package/dist/utils/ecweb-supervisor.js +11 -2
- package/dist/utils/ecweb-utils.js +8 -26
- package/dist/utils/error-utils.js +16 -2
- package/dist/utils/model-prices.jsonl +23 -20
- package/dist/utils/npm-ops.js +70 -15
- package/dist/utils/windows-autostart.js +1 -1
- package/kits/docs/evolcore/INDEX.md +1 -0
- package/kits/docs/evolcore/agent-create.md +13 -0
- package/kits/docs/evolcore/group-collaboration.md +7 -2
- package/kits/docs/evolcore/menu-client.md +34 -0
- package/kits/migrations/migrate-contact-book-v2.mjs +9 -1
- package/kits/migrations/migrate-role-config-v4.mjs +11 -5
- package/kits/migrations/migrate-role-config-v5.mjs +8 -2
- package/kits/templates/roles/admin.json +2 -0
- package/kits/templates/roles/visitor.json +1 -0
- package/kits/templates/system-fragments/bootstrap.md +8 -1
- package/package.json +16 -4
- package/dist/utils/codex-cli.js +0 -43
package/dist/cli/aun-commands.js
CHANGED
|
@@ -5,6 +5,7 @@ import { isExplicitGroupId } from '../aun/group-identity.js';
|
|
|
5
5
|
import { getArgValue, isHelpFlag, wantsHelp } from './help.js';
|
|
6
6
|
import { ipcQuery } from '../ipc.js';
|
|
7
7
|
import { AGENT_DELEGATION_TOKEN_ENV } from '../core/auth/agent-delegation.js';
|
|
8
|
+
import { isManagementRole } from '../config/builtin-roles.js';
|
|
8
9
|
import { readBestTaskRuntimeContext } from './task-context.js';
|
|
9
10
|
// ==================== AID ====================
|
|
10
11
|
function resolveAunPath(args) {
|
|
@@ -13,24 +14,35 @@ function resolveAunPath(args) {
|
|
|
13
14
|
return args[idx + 1];
|
|
14
15
|
return process.env.AUN_HOME || undefined;
|
|
15
16
|
}
|
|
17
|
+
function isRedactedAidShowResult(info) {
|
|
18
|
+
return 'redacted' in info && info.redacted === true;
|
|
19
|
+
}
|
|
16
20
|
function renderAidShow(info, formatJson) {
|
|
17
21
|
if (formatJson) {
|
|
18
22
|
console.log(JSON.stringify(info, null, 2));
|
|
19
23
|
return;
|
|
20
24
|
}
|
|
21
25
|
console.log(`AID: ${info.aid}`);
|
|
22
|
-
|
|
26
|
+
const redacted = isRedactedAidShowResult(info);
|
|
27
|
+
if (!redacted) {
|
|
28
|
+
console.log(` 私钥: ${info.hasPrivateKey ? '有' : '无'}`);
|
|
29
|
+
}
|
|
23
30
|
console.log(` agent.md: ${info.hasAgentMd ? '有' : '无'}`);
|
|
24
31
|
if (info.hasAgentMd) {
|
|
32
|
+
const signatureReason = redacted ? undefined : info.agentMdSignatureReason;
|
|
25
33
|
const sigLabel = info.agentMdSignature === 'verified' ? '✓ 已验签'
|
|
26
34
|
: info.agentMdSignature === 'unsigned' ? '⚠ 未签名'
|
|
27
|
-
: info.agentMdSignature === 'invalid' ? `✗ 签名无效${
|
|
35
|
+
: info.agentMdSignature === 'invalid' ? `✗ 签名无效${signatureReason ? ': ' + signatureReason : ''}`
|
|
28
36
|
: '? 未知';
|
|
29
37
|
console.log(` 签名状态: ${sigLabel}`);
|
|
30
38
|
}
|
|
31
39
|
console.log(` 证书到期: ${info.certExpiresAt ?? '无证书'}${info.certExpired ? ' (已过期!)' : ''}`);
|
|
32
40
|
if (info.certSubject)
|
|
33
41
|
console.log(` 证书主体: ${info.certSubject}`);
|
|
42
|
+
if (redacted) {
|
|
43
|
+
console.log(' 本地密钥状态: 已脱敏');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
34
46
|
if (info.keyMatchesCert === false)
|
|
35
47
|
console.log(' 密钥/证书: ✗ 公钥不匹配(cert.pem 与 key.json 公钥不一致)');
|
|
36
48
|
else if (info.keyMatchesCert === true)
|
|
@@ -104,7 +116,8 @@ async function runManagedAid(args, formatJson) {
|
|
|
104
116
|
if (!parsed.ok)
|
|
105
117
|
failManagedAid(formatJson, parsed.code, parsed.reason);
|
|
106
118
|
const runtime = await readBestTaskRuntimeContext();
|
|
107
|
-
|
|
119
|
+
const requiresSelfAid = parsed.command.kind === 'show' || parsed.command.kind === 'agentmd.put';
|
|
120
|
+
if (requiresSelfAid && runtime?.selfAid && parsed.command.aid !== runtime.selfAid.replace(/^@/, '')) {
|
|
108
121
|
failManagedAid(formatJson, 'SCOPE_MISMATCH', `托管任务只能操作当前 self AID:${runtime.selfAid}`);
|
|
109
122
|
}
|
|
110
123
|
const response = await ipcQuery(resolvePaths().socket, {
|
|
@@ -212,7 +225,12 @@ async function runManagedMsg(args, formatJson) {
|
|
|
212
225
|
if (runtime && (runtime.channel !== 'aun' || runtime.chatType !== 'private')) {
|
|
213
226
|
failManagedGroup(formatJson, 'SCOPE_MISMATCH', 'ec msg history/online 只能读取当前 AUN 私聊关系');
|
|
214
227
|
}
|
|
215
|
-
|
|
228
|
+
// owner/admin 可以跨对端读历史(每次查询仍只针对一个对端)。这里只是快速
|
|
229
|
+
// 预检:角色未知时放行交给 daemon 判定,daemon 侧 handleMsgOperation 才是
|
|
230
|
+
// 权威关卡,member 由 currentRelationOnly 约束、visitor 直接拒绝。
|
|
231
|
+
const mayReadCrossPeer = parsed.command.kind === 'history'
|
|
232
|
+
&& (runtime?.peerRole === undefined || isManagementRole(runtime.peerRole));
|
|
233
|
+
if (!mayReadCrossPeer && runtime?.channelId && parsed.command.target !== runtime.channelId.replace(/^@/, '')) {
|
|
216
234
|
failManagedGroup(formatJson, 'SCOPE_MISMATCH', `只能读取当前 AUN 私聊对端:${runtime.channelId}`);
|
|
217
235
|
}
|
|
218
236
|
}
|
|
@@ -299,6 +317,14 @@ function renderManagedGroupResult(args, result, formatJson) {
|
|
|
299
317
|
console.log(`✓ 成功 ${result.added?.length ?? 0},失败 ${result.failed?.length ?? 0}`);
|
|
300
318
|
return;
|
|
301
319
|
}
|
|
320
|
+
if (sub === 'invites') {
|
|
321
|
+
console.log(`✓ ${result.invites?.length ?? 0} 个待处理邀请`);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
if (sub === 'accept-invite' || sub === 'reject-invite' || sub === 'revoke-invite') {
|
|
325
|
+
console.log(`✓ group ${sub} 完成`);
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
302
328
|
console.log(`✓ group ${sub} 完成`);
|
|
303
329
|
}
|
|
304
330
|
export async function cmdAid(args) {
|
|
@@ -1045,7 +1071,7 @@ Commands:
|
|
|
1045
1071
|
send <from> <to> --file <path> [--as <type>] 发送文件(image|video|voice|file)
|
|
1046
1072
|
send <from> <to> --link <url> [--title T] 发送链接卡片
|
|
1047
1073
|
send <from> <to> --payload <json> 发送自定义 payload
|
|
1048
|
-
pull <from> [--after-seq N] [--limit N]
|
|
1074
|
+
pull <from> [--after-seq N] [--limit N] --app <name> 拉取收件箱(必须使用独立 slot)
|
|
1049
1075
|
ack <from> <seq> [--app <name>] 确认已读
|
|
1050
1076
|
recall <from> <message-id> [<message-id>...] 撤回消息
|
|
1051
1077
|
online <from> <target-aid> [<target-aid>...] 查询在线状态
|
|
@@ -1134,6 +1160,20 @@ Options:
|
|
|
1134
1160
|
}
|
|
1135
1161
|
const { msgSend, msgPull, msgAck, msgRecall, msgOnline, msgHistory } = await import('../aun/msg/index.js');
|
|
1136
1162
|
const commonOpts = { aunPath, slotId: appSlot };
|
|
1163
|
+
const requireConsumerSlot = (operation) => {
|
|
1164
|
+
if (appSlot)
|
|
1165
|
+
return appSlot;
|
|
1166
|
+
const error = {
|
|
1167
|
+
ok: false,
|
|
1168
|
+
code: 'APP_SLOT_REQUIRED',
|
|
1169
|
+
error: `${operation} requires an explicit --app <name> isolated consumer slot; refusing to access the daemon inbox`,
|
|
1170
|
+
};
|
|
1171
|
+
if (formatJson)
|
|
1172
|
+
console.log(JSON.stringify(error));
|
|
1173
|
+
else
|
|
1174
|
+
console.error(`❌ ${error.error}`);
|
|
1175
|
+
process.exit(1);
|
|
1176
|
+
};
|
|
1137
1177
|
if (sub === 'history') {
|
|
1138
1178
|
const target = args[2] && !args[2].startsWith('--') ? args[2] : undefined;
|
|
1139
1179
|
const historyValueFlags = new Set([
|
|
@@ -1381,9 +1421,7 @@ Options:
|
|
|
1381
1421
|
return;
|
|
1382
1422
|
}
|
|
1383
1423
|
if (sub === 'pull') {
|
|
1384
|
-
|
|
1385
|
-
console.warn('⚠ 警告: 未传 --app,当前与 daemon 共享 evolcore 消费通道。pull 会看到/影响 daemon 的消息消费;如需独立消费请用 --app <name>');
|
|
1386
|
-
}
|
|
1424
|
+
const consumerSlot = requireConsumerSlot('ec msg pull');
|
|
1387
1425
|
const afterSeqStr = getArgValue(args, '--after-seq');
|
|
1388
1426
|
const limitStr = getArgValue(args, '--limit');
|
|
1389
1427
|
const afterSeq = afterSeqStr !== undefined ? Number(afterSeqStr) : undefined;
|
|
@@ -1396,7 +1434,7 @@ Options:
|
|
|
1396
1434
|
console.error(`❌ --limit 必须是数字: ${limitStr}`);
|
|
1397
1435
|
process.exit(1);
|
|
1398
1436
|
}
|
|
1399
|
-
const result = await msgPull({ from, afterSeq, limit,
|
|
1437
|
+
const result = await msgPull({ from, afterSeq, limit, aunPath, slotId: consumerSlot });
|
|
1400
1438
|
if (!result.ok) {
|
|
1401
1439
|
if (formatJson) {
|
|
1402
1440
|
console.log(JSON.stringify(result));
|
|
@@ -1432,10 +1470,8 @@ Options:
|
|
|
1432
1470
|
console.error(`❌ seq 必须是数字: ${seqStr}`);
|
|
1433
1471
|
process.exit(1);
|
|
1434
1472
|
}
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
}
|
|
1438
|
-
const result = await msgAck({ from, seq, ...commonOpts });
|
|
1473
|
+
const consumerSlot = requireConsumerSlot('ec msg ack');
|
|
1474
|
+
const result = await msgAck({ from, seq, aunPath, slotId: consumerSlot });
|
|
1439
1475
|
if (!result.ok) {
|
|
1440
1476
|
if (formatJson) {
|
|
1441
1477
|
console.log(JSON.stringify(result));
|
|
@@ -1538,7 +1574,7 @@ export async function cmdGroup(args) {
|
|
|
1538
1574
|
send <from> <group-id> <text> --return <none|required> 发送群文本(跨会话时 --return 必填)
|
|
1539
1575
|
send <from> <group-id> --file <path> [--as <type>] 发送群文件
|
|
1540
1576
|
send <from> <group-id> --payload <json> 发送自定义 payload
|
|
1541
|
-
pull <from> <group-id> [--after-seq N] [--limit N]
|
|
1577
|
+
pull <from> <group-id> [--after-seq N] [--limit N] --app <name> 拉取群消息(必须使用独立 slot)
|
|
1542
1578
|
ack <from> <group-id> <seq> [--app <name>] 确认已读
|
|
1543
1579
|
|
|
1544
1580
|
群管理:
|
|
@@ -1558,7 +1594,11 @@ export async function cmdGroup(args) {
|
|
|
1558
1594
|
成员:
|
|
1559
1595
|
join <from> <group-id> [--message M] [--answer A] 申请加入
|
|
1560
1596
|
leave <from> <group-id> 退出群
|
|
1561
|
-
invite <from> <group-id> <member-aid> [<member-aid>...]
|
|
1597
|
+
invite <from> <group-id> <member-aid> [<member-aid>...] 创建定向邀请
|
|
1598
|
+
invites <from> [--page N] [--size N] 查看收到的邀请
|
|
1599
|
+
accept-invite <from> <invite-id> 接受邀请
|
|
1600
|
+
reject-invite <from> <invite-id> 拒绝邀请
|
|
1601
|
+
revoke-invite <from> <invite-id> 撤回邀请
|
|
1562
1602
|
kick <from> <group-id> <member-aid> 踢出成员
|
|
1563
1603
|
members <from> <group-id> [--page N] [--size N] 列出群成员
|
|
1564
1604
|
online <from> <group-id> 查看在线成员
|
|
@@ -1582,6 +1622,7 @@ Options:
|
|
|
1582
1622
|
--text <说明> 附件说明文字(仅 --file 模式)
|
|
1583
1623
|
--transcript <text> 语音转写(仅 --as voice)
|
|
1584
1624
|
--group-id <aid> 指定自定义群 AID(仅 create)
|
|
1625
|
+
--member-type <type> 定向邀请成员类型:human|ai(仅 invite)
|
|
1585
1626
|
-- end-of-options:其后所有参数按正文处理
|
|
1586
1627
|
(用于发送恰好等于某 flag 的文本,如 send a g -- --encrypt)
|
|
1587
1628
|
|
|
@@ -1617,7 +1658,7 @@ Options:
|
|
|
1617
1658
|
renderManagedGroupResult(args, result, formatJson);
|
|
1618
1659
|
return;
|
|
1619
1660
|
}
|
|
1620
|
-
const { 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, } = await import('../aun/msg/index.js');
|
|
1661
|
+
const { groupSend, groupPull, groupAck, groupCreate, groupInfo, groupList, groupUpdate, groupDissolve, groupSuspend, groupResume, groupJoin, groupLeave, groupInvite, groupInvites, groupAcceptInvite, groupRejectInvite, groupRevokeInvite, groupKick, groupMembers, groupOnline, groupSetRole, groupTransferOwner, groupBan, groupUnban, groupBanlist, groupRules, groupUpdateRules, groupRulesFileGet, groupRulesFileSet, groupRulesFilePublish, } = await import('../aun/msg/index.js');
|
|
1621
1662
|
const commonOpts = { aunPath, slotId: appSlot };
|
|
1622
1663
|
// 通用 group_id 提取(第三参数)
|
|
1623
1664
|
const requireGroupId = () => {
|
|
@@ -1693,6 +1734,31 @@ Options:
|
|
|
1693
1734
|
}
|
|
1694
1735
|
return parsed;
|
|
1695
1736
|
};
|
|
1737
|
+
if (sub === 'invites') {
|
|
1738
|
+
const page = parseNumberFlag('--page', '--page');
|
|
1739
|
+
const size = parseNumberFlag('--size', '--size');
|
|
1740
|
+
const result = await groupInvites({ from, page, size, ...commonOpts });
|
|
1741
|
+
outputResult(result, () => {
|
|
1742
|
+
const r = result;
|
|
1743
|
+
console.log(`✓ ${r.invites.length} 个待处理邀请:`);
|
|
1744
|
+
for (const invite of r.invites) {
|
|
1745
|
+
console.log(` ${invite.invite_id ?? invite.id ?? '-'} ${invite.group_id ?? invite.group_aid ?? '-'} ${invite.inviter_aid ?? invite.from ?? '-'}`);
|
|
1746
|
+
}
|
|
1747
|
+
});
|
|
1748
|
+
return;
|
|
1749
|
+
}
|
|
1750
|
+
if (sub === 'accept-invite' || sub === 'reject-invite' || sub === 'revoke-invite') {
|
|
1751
|
+
const inviteId = args[2];
|
|
1752
|
+
if (!inviteId || inviteId.startsWith('--')) {
|
|
1753
|
+
console.error(`用法: ec group ${sub} <from> <invite-id>`);
|
|
1754
|
+
process.exit(1);
|
|
1755
|
+
}
|
|
1756
|
+
const action = sub === 'accept-invite' ? groupAcceptInvite
|
|
1757
|
+
: sub === 'reject-invite' ? groupRejectInvite : groupRevokeInvite;
|
|
1758
|
+
const result = await action({ from, inviteId, ...commonOpts });
|
|
1759
|
+
outputResult(result, () => console.log(`✓ 已${sub === 'accept-invite' ? '接受' : sub === 'reject-invite' ? '拒绝' : '撤回'}邀请 ${inviteId}`));
|
|
1760
|
+
return;
|
|
1761
|
+
}
|
|
1696
1762
|
const requireFlagValue = (flag, label) => {
|
|
1697
1763
|
const value = getArgValue(args, flag);
|
|
1698
1764
|
if (value === undefined || value.startsWith('--')) {
|
|
@@ -1839,12 +1905,18 @@ Options:
|
|
|
1839
1905
|
}
|
|
1840
1906
|
if (sub === 'pull') {
|
|
1841
1907
|
const groupId = requireGroupId();
|
|
1842
|
-
|
|
1843
|
-
|
|
1908
|
+
const consumerSlot = appSlot;
|
|
1909
|
+
if (!consumerSlot) {
|
|
1910
|
+
const error = 'ec group pull requires an explicit --app <name> isolated consumer slot; refusing to access the daemon inbox';
|
|
1911
|
+
if (formatJson)
|
|
1912
|
+
console.log(JSON.stringify({ ok: false, code: 'APP_SLOT_REQUIRED', error }));
|
|
1913
|
+
else
|
|
1914
|
+
console.error(`❌ ${error}`);
|
|
1915
|
+
process.exit(1);
|
|
1844
1916
|
}
|
|
1845
1917
|
const afterSeq = parseNumberFlag('--after-seq', '--after-seq');
|
|
1846
1918
|
const limit = parseNumberFlag('--limit', '--limit');
|
|
1847
|
-
const result = await groupPull({ from, groupId, afterSeq, limit,
|
|
1919
|
+
const result = await groupPull({ from, groupId, afterSeq, limit, aunPath, slotId: consumerSlot });
|
|
1848
1920
|
outputResult(result, () => {
|
|
1849
1921
|
const r = result;
|
|
1850
1922
|
console.log(`✓ ${r.messages.length} 条消息,latest_seq=${r.latest_message_seq}${r.has_more ? '(还有更多)' : ''}`);
|
|
@@ -1867,10 +1939,16 @@ Options:
|
|
|
1867
1939
|
console.error(`❌ seq 必须是数字: ${seqStr}`);
|
|
1868
1940
|
process.exit(1);
|
|
1869
1941
|
}
|
|
1870
|
-
|
|
1871
|
-
|
|
1942
|
+
const consumerSlot = appSlot;
|
|
1943
|
+
if (!consumerSlot) {
|
|
1944
|
+
const error = 'ec group ack requires an explicit --app <name> isolated consumer slot; refusing to access the daemon inbox';
|
|
1945
|
+
if (formatJson)
|
|
1946
|
+
console.log(JSON.stringify({ ok: false, code: 'APP_SLOT_REQUIRED', error }));
|
|
1947
|
+
else
|
|
1948
|
+
console.error(`❌ ${error}`);
|
|
1949
|
+
process.exit(1);
|
|
1872
1950
|
}
|
|
1873
|
-
const result = await groupAck({ from, groupId, seq,
|
|
1951
|
+
const result = await groupAck({ from, groupId, seq, aunPath, slotId: consumerSlot });
|
|
1874
1952
|
outputResult(result, () => {
|
|
1875
1953
|
const r = result;
|
|
1876
1954
|
console.log(`✓ ack_seq=${r.ack_seq}`);
|
|
@@ -2147,7 +2225,12 @@ Options:
|
|
|
2147
2225
|
process.exit(1);
|
|
2148
2226
|
}
|
|
2149
2227
|
}
|
|
2150
|
-
const
|
|
2228
|
+
const memberType = getArgValue(args, '--member-type');
|
|
2229
|
+
if (memberType !== undefined && memberType !== 'human' && memberType !== 'ai') {
|
|
2230
|
+
console.error('❌ --member-type 必须是 human 或 ai');
|
|
2231
|
+
process.exit(1);
|
|
2232
|
+
}
|
|
2233
|
+
const result = await groupInvite({ from, groupId, members, memberType: memberType, ...commonOpts });
|
|
2151
2234
|
outputResult(result, () => {
|
|
2152
2235
|
const r = result;
|
|
2153
2236
|
console.log(`✓ 成功 ${r.added.length},失败 ${r.failed.length}`);
|
|
@@ -2300,7 +2383,7 @@ Options:
|
|
|
2300
2383
|
});
|
|
2301
2384
|
return;
|
|
2302
2385
|
}
|
|
2303
|
-
console.error(`未知子命令: ${sub}\n用法: ec group [send|pull|ack|create|list|info|update|dissolve|suspend|resume|rules|join|leave|invite|kick|members|online|role|owner|ban|unban]`);
|
|
2386
|
+
console.error(`未知子命令: ${sub}\n用法: ec group [send|pull|ack|create|list|info|update|dissolve|suspend|resume|rules|join|leave|invite|invites|accept-invite|reject-invite|revoke-invite|kick|members|online|role|owner|ban|unban]`);
|
|
2304
2387
|
process.exit(1);
|
|
2305
2388
|
}
|
|
2306
2389
|
// ==================== Main ====================
|
|
@@ -2322,6 +2405,7 @@ const VALUE_FLAGS = new Set([
|
|
|
2322
2405
|
'--payload', '--title', '--description', '--text', '--transcript',
|
|
2323
2406
|
'--as', '--content-type', '--mention', '--visibility', '--join-mode',
|
|
2324
2407
|
'--group-id', '--name', '--message', '--answer', '--page', '--size',
|
|
2408
|
+
'--member-type',
|
|
2325
2409
|
'--aun-path', '--thread', '--return',
|
|
2326
2410
|
]);
|
|
2327
2411
|
const BOOLEAN_FLAGS = new Set([
|
package/dist/cli/command-log.js
CHANGED
|
@@ -59,8 +59,8 @@ export function logCliCommand(cmd, args) {
|
|
|
59
59
|
const line = JSON.stringify({
|
|
60
60
|
ts: localTimestamp(),
|
|
61
61
|
cmd,
|
|
62
|
-
//
|
|
63
|
-
command: `ec ${args.map(shellQuote).join(' ')}`,
|
|
62
|
+
// 可审计命令行(敏感参数掩码;含 ec 前缀,含空格参数自动加引号)
|
|
63
|
+
command: `ec ${loggableArgs(args).map(shellQuote).join(' ')}`,
|
|
64
64
|
selfAid: selfAid || undefined,
|
|
65
65
|
sessionId: process.env.EVOLCORE_SESSION_ID || undefined,
|
|
66
66
|
}) + '\n';
|
|
@@ -82,6 +82,25 @@ function shellQuote(arg) {
|
|
|
82
82
|
return arg;
|
|
83
83
|
return `'${arg.replace(/'/g, `'\\''`)}'`;
|
|
84
84
|
}
|
|
85
|
+
function loggableArgs(args) {
|
|
86
|
+
const output = [];
|
|
87
|
+
let redactNext = false;
|
|
88
|
+
for (const arg of args) {
|
|
89
|
+
if (redactNext) {
|
|
90
|
+
output.push('[REDACTED]');
|
|
91
|
+
redactNext = false;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const flag = arg.replace(/^--?/, '').replace(/=.*$/, '').toLowerCase();
|
|
95
|
+
if (/^(?:remote-token|ecweb-token|menu-token|token|password|secret)$/.test(flag)) {
|
|
96
|
+
output.push(arg.includes('=') ? `${arg.slice(0, arg.indexOf('=') + 1)}[REDACTED]` : arg);
|
|
97
|
+
redactNext = !arg.includes('=');
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
output.push(arg.replace(/((?:"|')?(?:ecweb[_-]?token|menu[_-]?token|access[_-]?token|refresh[_-]?token|password|secret)(?:"|')?\s*[:=]\s*)("(?:[^"\\]|\\.)*"|'[^']*'|[^,}\s]+)/gi, '$1"[REDACTED]"'));
|
|
101
|
+
}
|
|
102
|
+
return output;
|
|
103
|
+
}
|
|
85
104
|
/** 本地日期 tag YYYYMMDD,用于日志文件按天切分(一天一个文件)。 */
|
|
86
105
|
function dayTag() {
|
|
87
106
|
const d = new Date();
|
package/dist/cli/ctl-command.js
CHANGED
|
@@ -7,6 +7,7 @@ const CTL_HELP = `用法: ec ctl <command> [args...]
|
|
|
7
7
|
|
|
8
8
|
查询:
|
|
9
9
|
status 查看会话状态
|
|
10
|
+
status --format json 查看当前任务的结构化运行上下文
|
|
10
11
|
pwd 显示当前项目路径
|
|
11
12
|
help 显示帮助
|
|
12
13
|
|
|
@@ -20,6 +21,7 @@ const CTL_HELP = `用法: ec ctl <command> [args...]
|
|
|
20
21
|
|
|
21
22
|
示例:
|
|
22
23
|
ec ctl status
|
|
24
|
+
ec ctl status --format json
|
|
23
25
|
ec ctl name "新会话名称"
|
|
24
26
|
ec ctl send "任务已完成"
|
|
25
27
|
ec ctl file report.md
|