evolcore 0.0.21 → 0.0.23
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/AGENTS.md +62 -0
- package/CHANGELOG.md +53 -0
- package/README.md +2 -0
- package/bin/codex-managed-acl.ps1 +155 -0
- package/bin/codex-managed-hook.mjs +3 -0
- package/bin/install-codex-managed-hooks.mjs +376 -96
- package/dist/agents/baseagent-availability.js +48 -0
- package/dist/agents/baseagent.js +1 -1
- package/dist/agents/claude-runner.js +44 -226
- package/dist/agents/{codex-app-server-client.js → codex/app-server-client.js} +103 -17
- 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 +154 -0
- package/dist/agents/codex-runner.js +1292 -219
- package/dist/agents/ecagent-runner.js +10 -31
- package/dist/agents/gemini-runner.js +2 -6
- package/dist/aun/aid/store.js +2 -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 +51 -4
- package/dist/aun/outbox.js +7 -0
- package/dist/aun/rpc/client.js +8 -1
- package/dist/channels/aun.js +240 -36
- package/dist/channels/wechat.js +81 -10
- package/dist/cli/aun-commands.js +48 -4
- package/dist/cli/command-log.js +21 -2
- package/dist/cli/daemon-commands.js +169 -51
- package/dist/cli/index.js +20 -0
- package/dist/cli/init.js +2 -10
- package/dist/cli/menu-client.js +95 -0
- package/dist/cli/model.js +23 -8
- package/dist/cli/task-context.js +16 -2
- package/dist/cli/trigger-command.js +22 -5
- package/dist/config/config-field-policy.js +3 -0
- package/dist/config/config-manager.js +32 -5
- package/dist/config/contact-book-store.js +25 -3
- package/dist/config/schema-migration.js +14 -2
- package/dist/core/auth/agent-delegation.js +15 -0
- package/dist/core/auth/auth-gateway.js +8 -0
- package/dist/core/auth/authorization-audit.js +70 -6
- package/dist/core/auth/operation-catalog.js +4 -0
- package/dist/core/auth/remote-access-store.js +135 -0
- package/dist/core/bootstrap-messages.js +8 -0
- package/dist/core/bootstrap-service.js +93 -25
- package/dist/core/command/command-handler.js +62 -5
- package/dist/core/command/daemon-diagnostics.js +448 -0
- package/dist/core/command/menu-catalog.js +3 -0
- package/dist/core/command/menu-handler.js +150 -33
- package/dist/core/command/menu-protocol.js +120 -1
- package/dist/core/command/slash-gate.js +3 -3
- package/dist/core/command/slash-handler.js +83 -40
- package/dist/core/data-migration.js +11 -1
- package/dist/core/event-catalog.js +32 -0
- package/dist/core/handoff/runtime.js +23 -3
- package/dist/core/message/im-renderer.js +7 -3
- package/dist/core/message/message-bridge.js +60 -2
- package/dist/core/message/message-log.js +33 -0
- package/dist/core/message/message-queue.js +41 -15
- package/dist/core/message/response-engine.js +246 -114
- package/dist/core/model/catalog-service.js +308 -0
- package/dist/core/model/model-catalog.js +124 -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 +1 -1
- package/dist/core/permission/approval-gateway.js +16 -1
- package/dist/core/permission/ec-command-parser.js +272 -70
- package/dist/core/permission/protected-paths.js +74 -14
- package/dist/core/permission/sandbox-runtime.js +4 -2
- package/dist/core/permission/tool-error-code.js +12 -0
- package/dist/core/permission/tool-policy.js +290 -30
- package/dist/core/runtime-lock.js +13 -8
- package/dist/core/session/session-manager.js +30 -0
- package/dist/core/session/session-renew.js +18 -1
- package/dist/core/session/session-turn-coordinator.js +5 -1
- package/dist/index.js +104 -34
- package/dist/ipc.js +218 -96
- package/dist/paths.js +18 -0
- package/dist/response-system/engines/v1/proactive-flow.js +7 -2
- package/dist/stats/price-resolver.js +4 -0
- package/dist/trigger/feedback.js +14 -2
- package/dist/trigger/manager.js +3 -1
- package/dist/trigger/parser.js +86 -13
- package/dist/trigger/patch.js +104 -1
- package/dist/trigger/scheduler.js +20 -3
- package/dist/utils/ecweb-supervisor.js +11 -2
- package/dist/utils/ecweb-utils.js +8 -26
- package/dist/utils/error-utils.js +7 -0
- package/dist/utils/logger.js +9 -4
- package/dist/utils/npm-ops.js +47 -15
- package/dist/utils/tool-summary.js +59 -0
- package/dist/utils/windows-shell-trust.js +201 -0
- package/kits/docs/evolcore/INDEX.md +3 -2
- package/kits/docs/evolcore/agent-create.md +159 -0
- package/kits/docs/evolcore/agent.md +6 -0
- package/kits/docs/evolcore/group-collaboration.md +256 -0
- package/kits/docs/evolcore/group-rules.md +1 -19
- package/kits/docs/evolcore/group.md +3 -1
- package/kits/docs/evolcore/menu-client.md +34 -0
- package/kits/docs/evolcore/trigger.md +6 -3
- package/kits/docs/prompt-loading-architecture.md +6 -0
- package/kits/eck_message_manifest.json +6 -6
- 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/schemas/_meta.json +3 -2
- package/kits/schemas/agent-config.schema.12.json +427 -0
- package/kits/templates/message-fragments/item.md +1 -1
- package/kits/templates/roles/visitor.json +1 -0
- package/kits/templates/system-fragments/bootstrap.md +10 -2
- package/kits/templates/system-fragments/commands.md +2 -2
- package/package.json +11 -3
package/dist/cli/aun-commands.js
CHANGED
|
@@ -299,6 +299,14 @@ function renderManagedGroupResult(args, result, formatJson) {
|
|
|
299
299
|
console.log(`✓ 成功 ${result.added?.length ?? 0},失败 ${result.failed?.length ?? 0}`);
|
|
300
300
|
return;
|
|
301
301
|
}
|
|
302
|
+
if (sub === 'invites') {
|
|
303
|
+
console.log(`✓ ${result.invites?.length ?? 0} 个待处理邀请`);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
if (sub === 'accept-invite' || sub === 'reject-invite' || sub === 'revoke-invite') {
|
|
307
|
+
console.log(`✓ group ${sub} 完成`);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
302
310
|
console.log(`✓ group ${sub} 完成`);
|
|
303
311
|
}
|
|
304
312
|
export async function cmdAid(args) {
|
|
@@ -1558,7 +1566,11 @@ export async function cmdGroup(args) {
|
|
|
1558
1566
|
成员:
|
|
1559
1567
|
join <from> <group-id> [--message M] [--answer A] 申请加入
|
|
1560
1568
|
leave <from> <group-id> 退出群
|
|
1561
|
-
invite <from> <group-id> <member-aid> [<member-aid>...]
|
|
1569
|
+
invite <from> <group-id> <member-aid> [<member-aid>...] 创建定向邀请
|
|
1570
|
+
invites <from> [--page N] [--size N] 查看收到的邀请
|
|
1571
|
+
accept-invite <from> <invite-id> 接受邀请
|
|
1572
|
+
reject-invite <from> <invite-id> 拒绝邀请
|
|
1573
|
+
revoke-invite <from> <invite-id> 撤回邀请
|
|
1562
1574
|
kick <from> <group-id> <member-aid> 踢出成员
|
|
1563
1575
|
members <from> <group-id> [--page N] [--size N] 列出群成员
|
|
1564
1576
|
online <from> <group-id> 查看在线成员
|
|
@@ -1582,6 +1594,7 @@ Options:
|
|
|
1582
1594
|
--text <说明> 附件说明文字(仅 --file 模式)
|
|
1583
1595
|
--transcript <text> 语音转写(仅 --as voice)
|
|
1584
1596
|
--group-id <aid> 指定自定义群 AID(仅 create)
|
|
1597
|
+
--member-type <type> 定向邀请成员类型:human|ai(仅 invite)
|
|
1585
1598
|
-- end-of-options:其后所有参数按正文处理
|
|
1586
1599
|
(用于发送恰好等于某 flag 的文本,如 send a g -- --encrypt)
|
|
1587
1600
|
|
|
@@ -1617,7 +1630,7 @@ Options:
|
|
|
1617
1630
|
renderManagedGroupResult(args, result, formatJson);
|
|
1618
1631
|
return;
|
|
1619
1632
|
}
|
|
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');
|
|
1633
|
+
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
1634
|
const commonOpts = { aunPath, slotId: appSlot };
|
|
1622
1635
|
// 通用 group_id 提取(第三参数)
|
|
1623
1636
|
const requireGroupId = () => {
|
|
@@ -1693,6 +1706,31 @@ Options:
|
|
|
1693
1706
|
}
|
|
1694
1707
|
return parsed;
|
|
1695
1708
|
};
|
|
1709
|
+
if (sub === 'invites') {
|
|
1710
|
+
const page = parseNumberFlag('--page', '--page');
|
|
1711
|
+
const size = parseNumberFlag('--size', '--size');
|
|
1712
|
+
const result = await groupInvites({ from, page, size, ...commonOpts });
|
|
1713
|
+
outputResult(result, () => {
|
|
1714
|
+
const r = result;
|
|
1715
|
+
console.log(`✓ ${r.invites.length} 个待处理邀请:`);
|
|
1716
|
+
for (const invite of r.invites) {
|
|
1717
|
+
console.log(` ${invite.invite_id ?? invite.id ?? '-'} ${invite.group_id ?? invite.group_aid ?? '-'} ${invite.inviter_aid ?? invite.from ?? '-'}`);
|
|
1718
|
+
}
|
|
1719
|
+
});
|
|
1720
|
+
return;
|
|
1721
|
+
}
|
|
1722
|
+
if (sub === 'accept-invite' || sub === 'reject-invite' || sub === 'revoke-invite') {
|
|
1723
|
+
const inviteId = args[2];
|
|
1724
|
+
if (!inviteId || inviteId.startsWith('--')) {
|
|
1725
|
+
console.error(`用法: ec group ${sub} <from> <invite-id>`);
|
|
1726
|
+
process.exit(1);
|
|
1727
|
+
}
|
|
1728
|
+
const action = sub === 'accept-invite' ? groupAcceptInvite
|
|
1729
|
+
: sub === 'reject-invite' ? groupRejectInvite : groupRevokeInvite;
|
|
1730
|
+
const result = await action({ from, inviteId, ...commonOpts });
|
|
1731
|
+
outputResult(result, () => console.log(`✓ 已${sub === 'accept-invite' ? '接受' : sub === 'reject-invite' ? '拒绝' : '撤回'}邀请 ${inviteId}`));
|
|
1732
|
+
return;
|
|
1733
|
+
}
|
|
1696
1734
|
const requireFlagValue = (flag, label) => {
|
|
1697
1735
|
const value = getArgValue(args, flag);
|
|
1698
1736
|
if (value === undefined || value.startsWith('--')) {
|
|
@@ -2147,7 +2185,12 @@ Options:
|
|
|
2147
2185
|
process.exit(1);
|
|
2148
2186
|
}
|
|
2149
2187
|
}
|
|
2150
|
-
const
|
|
2188
|
+
const memberType = getArgValue(args, '--member-type');
|
|
2189
|
+
if (memberType !== undefined && memberType !== 'human' && memberType !== 'ai') {
|
|
2190
|
+
console.error('❌ --member-type 必须是 human 或 ai');
|
|
2191
|
+
process.exit(1);
|
|
2192
|
+
}
|
|
2193
|
+
const result = await groupInvite({ from, groupId, members, memberType: memberType, ...commonOpts });
|
|
2151
2194
|
outputResult(result, () => {
|
|
2152
2195
|
const r = result;
|
|
2153
2196
|
console.log(`✓ 成功 ${r.added.length},失败 ${r.failed.length}`);
|
|
@@ -2300,7 +2343,7 @@ Options:
|
|
|
2300
2343
|
});
|
|
2301
2344
|
return;
|
|
2302
2345
|
}
|
|
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]`);
|
|
2346
|
+
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
2347
|
process.exit(1);
|
|
2305
2348
|
}
|
|
2306
2349
|
// ==================== Main ====================
|
|
@@ -2322,6 +2365,7 @@ const VALUE_FLAGS = new Set([
|
|
|
2322
2365
|
'--payload', '--title', '--description', '--text', '--transcript',
|
|
2323
2366
|
'--as', '--content-type', '--mention', '--visibility', '--join-mode',
|
|
2324
2367
|
'--group-id', '--name', '--message', '--answer', '--page', '--size',
|
|
2368
|
+
'--member-type',
|
|
2325
2369
|
'--aun-path', '--thread', '--return',
|
|
2326
2370
|
]);
|
|
2327
2371
|
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();
|
|
@@ -15,7 +15,7 @@ import { cmdInit, needsControlAidInit, initTail } from './init.js';
|
|
|
15
15
|
import * as platform from '../utils/cross-platform.js';
|
|
16
16
|
import { EventBus } from '../core/event-bus.js';
|
|
17
17
|
import { tryUpgrade, tryUpgradeGlobalPkg, resolveGlobalPkg } from '../utils/npm-ops.js';
|
|
18
|
-
import { ecwebVersionRequirementError,
|
|
18
|
+
import { ecwebVersionRequirementError, resolveEcwebLaunchCommand, fetchRemotePairingCode } from '../utils/ecweb-utils.js';
|
|
19
19
|
import { isHostChinese } from '../utils/locale.js';
|
|
20
20
|
import { scanInstances, cleanupInstances, findOrphanProcesses, killOrphans } from '../utils/instance-registry.js';
|
|
21
21
|
import { filterLogFiles, deriveLogTypes, computePreChecked, validateLogTypes, shortLogName as shortLogNameLocal, isWatchLogFile } from './watch-logs.js';
|
|
@@ -28,8 +28,9 @@ import { WEB_CLI_BIN, WEB_PACKAGE_LATEST, WEB_PACKAGE_NAME } from '../product.js
|
|
|
28
28
|
import { rotateStdoutLog } from '../utils/log-writer.js';
|
|
29
29
|
import { inspectDataMigrationRequirement } from '../core/data-migration.js';
|
|
30
30
|
import { isInitCancelledError, printInitCancelHint } from './init-cancel.js';
|
|
31
|
-
import { listCodexAppServerProcesses, unregisterCodexAppServerProcess } from '../
|
|
31
|
+
import { listCodexAppServerProcesses, unregisterCodexAppServerProcess } from '../agents/codex/app-server-registry.js';
|
|
32
32
|
import { DEFAULT_ECWEB_PORT, ecwebService, setEcwebEnabled } from '../config/daemon-services.js';
|
|
33
|
+
import { checkCodexProjectPath, inspectCodexManagedHook } from '../agents/codex/diagnostics.js';
|
|
33
34
|
const execFileAsync = promisify(execFile);
|
|
34
35
|
async function runAutomaticInit(action) {
|
|
35
36
|
try {
|
|
@@ -174,14 +175,40 @@ function sourceBuildNeedsRefresh() {
|
|
|
174
175
|
const sourceMtime = Math.max(latestSourceMtime(path.join(packageRoot, 'src')), latestSourceMtime(path.join(packageRoot, 'ecagent', 'src')));
|
|
175
176
|
return sourceMtime > fs.statSync(daemonEntry).mtimeMs;
|
|
176
177
|
}
|
|
177
|
-
function
|
|
178
|
+
function runSourceBuild() {
|
|
179
|
+
return new Promise(resolve => {
|
|
180
|
+
console.log('🔧 源码比 daemon 编译产物更新,自动重新构建...');
|
|
181
|
+
// Windows cannot spawn a .cmd shim directly with shell:false on recent
|
|
182
|
+
// Node versions. Invoke cmd.exe explicitly instead of using spawn's
|
|
183
|
+
// shell:true mode, which also avoids the DEP0190 warning.
|
|
184
|
+
const command = platform.isWindows ? (process.env.ComSpec ?? process.env.COMSPEC ?? 'cmd.exe') : 'npm';
|
|
185
|
+
const args = platform.isWindows ? ['/d', '/c', 'npm.cmd', 'run', 'build'] : ['run', 'build'];
|
|
186
|
+
const child = spawn(command, args, {
|
|
187
|
+
cwd: getPackageRoot(),
|
|
188
|
+
stdio: 'inherit',
|
|
189
|
+
windowsHide: platform.isWindows,
|
|
190
|
+
});
|
|
191
|
+
child.on('error', err => {
|
|
192
|
+
console.error(`❌ 无法启动构建进程: ${err.message}`);
|
|
193
|
+
resolve(false);
|
|
194
|
+
});
|
|
195
|
+
child.on('exit', code => {
|
|
196
|
+
if (code === 0) {
|
|
197
|
+
console.log('✅ 构建完成');
|
|
198
|
+
resolve(true);
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
console.error(`❌ 自动构建失败 (exit ${code}),服务未启动。`);
|
|
202
|
+
console.error(' 请手动执行: npm run build 排查错误');
|
|
203
|
+
resolve(false);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
async function requireFreshSourceBuild() {
|
|
178
209
|
if (!sourceBuildNeedsRefresh())
|
|
179
210
|
return true;
|
|
180
|
-
|
|
181
|
-
console.error(' 请先执行: ec stop && npm run build');
|
|
182
|
-
console.error(' 然后执行: ec start');
|
|
183
|
-
process.exitCode = 2;
|
|
184
|
-
return false;
|
|
211
|
+
return await runSourceBuild();
|
|
185
212
|
}
|
|
186
213
|
function requireCompletedDataMigration(root) {
|
|
187
214
|
const requirement = inspectDataMigrationRequirement(root);
|
|
@@ -194,6 +221,64 @@ function requireCompletedDataMigration(root) {
|
|
|
194
221
|
process.exitCode = 2;
|
|
195
222
|
return false;
|
|
196
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Check package updates before starting or restarting the daemon.
|
|
226
|
+
* A failed upgrade is reported, but the currently installed version remains
|
|
227
|
+
* usable and the caller continues with its normal lifecycle.
|
|
228
|
+
*/
|
|
229
|
+
export async function runUpgradeChecks(upgradeFn = signal => tryUpgrade({ signal }), ecwebUpgradeFn = signal => tryUpgradeGlobalPkg(() => resolveGlobalPkg(WEB_PACKAGE_NAME), WEB_PACKAGE_NAME, { signal }), timeoutMs = 60_000) {
|
|
230
|
+
console.log('📦 Checking for updates...');
|
|
231
|
+
const runWithTimeout = async (label, fn) => {
|
|
232
|
+
const controller = new AbortController();
|
|
233
|
+
let timer;
|
|
234
|
+
try {
|
|
235
|
+
return await Promise.race([
|
|
236
|
+
fn(controller.signal),
|
|
237
|
+
new Promise(resolve => {
|
|
238
|
+
timer = setTimeout(() => {
|
|
239
|
+
resolve({ status: 'failed', error: `${label} upgrade timed out` });
|
|
240
|
+
controller.abort();
|
|
241
|
+
}, timeoutMs);
|
|
242
|
+
}),
|
|
243
|
+
]);
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
return { status: 'failed', error: error instanceof Error ? error.message : String(error) };
|
|
247
|
+
}
|
|
248
|
+
finally {
|
|
249
|
+
if (timer)
|
|
250
|
+
clearTimeout(timer);
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
const upgrade = await runWithTimeout('EvolCore', upgradeFn);
|
|
254
|
+
switch (upgrade.status) {
|
|
255
|
+
case 'upgraded':
|
|
256
|
+
console.log(`✅ Upgraded: ${upgrade.from} → ${upgrade.to}`);
|
|
257
|
+
break;
|
|
258
|
+
case 'no-update':
|
|
259
|
+
console.log(`✓ Already up to date (${upgrade.from})`);
|
|
260
|
+
break;
|
|
261
|
+
case 'skipped':
|
|
262
|
+
console.log(upgrade.error
|
|
263
|
+
? '⏭ Skipped upgrade (network unavailable)'
|
|
264
|
+
: '⏭ Skipped upgrade check (dev mode)');
|
|
265
|
+
break;
|
|
266
|
+
case 'failed':
|
|
267
|
+
console.log(`⚠ Upgrade failed${upgrade.from && upgrade.to ? ` (${upgrade.from} → ${upgrade.to})` : ''}, continuing with current version${upgrade.error ? `: ${upgrade.error}` : ''}`);
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
const ecwebUpgrade = await runWithTimeout(WEB_PACKAGE_NAME, ecwebUpgradeFn);
|
|
271
|
+
switch (ecwebUpgrade.status) {
|
|
272
|
+
case 'upgraded':
|
|
273
|
+
console.log(`✅ ${WEB_PACKAGE_NAME} upgraded: ${ecwebUpgrade.from} → ${ecwebUpgrade.to}`);
|
|
274
|
+
break;
|
|
275
|
+
case 'no-update':
|
|
276
|
+
break;
|
|
277
|
+
case 'failed':
|
|
278
|
+
console.log(`⚠ ${WEB_PACKAGE_NAME} upgrade failed${ecwebUpgrade.from && ecwebUpgrade.to ? ` (${ecwebUpgrade.from} → ${ecwebUpgrade.to})` : ''}${ecwebUpgrade.error ? `: ${ecwebUpgrade.error}` : ''}`);
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
197
282
|
// ==================== Commands ====================
|
|
198
283
|
/**
|
|
199
284
|
* 检测并展示跨 HOME 残留的 evolcore 主进程。
|
|
@@ -306,8 +391,11 @@ export async function cmdStart(opts = {}) {
|
|
|
306
391
|
return;
|
|
307
392
|
}
|
|
308
393
|
ensureDataDirs();
|
|
309
|
-
if (!requireFreshSourceBuild())
|
|
394
|
+
if (!await requireFreshSourceBuild())
|
|
310
395
|
return;
|
|
396
|
+
// A stopped container may miss the daily upgrade trigger. Check once on
|
|
397
|
+
// every real start so the service does not stay on an old installation.
|
|
398
|
+
await (opts.upgradeChecks ?? runUpgradeChecks)();
|
|
311
399
|
// 旧配置自动迁移(daemon.json → 新结构)
|
|
312
400
|
const { autoMigrateIfNeeded } = await import('../config-store.js');
|
|
313
401
|
autoMigrateIfNeeded();
|
|
@@ -681,39 +769,11 @@ export async function cmdRestart(opts = {}) {
|
|
|
681
769
|
if (initialRuntimeOrphans.length === 0 && rejectPidIsolatedLifecycle('restart', initialStatus, ping))
|
|
682
770
|
return;
|
|
683
771
|
}
|
|
684
|
-
if (!requireFreshSourceBuild())
|
|
772
|
+
if (!await requireFreshSourceBuild())
|
|
685
773
|
return;
|
|
686
|
-
//
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
switch (upgrade.status) {
|
|
690
|
-
case 'upgraded':
|
|
691
|
-
console.log(`✅ Upgraded: ${upgrade.from} → ${upgrade.to}`);
|
|
692
|
-
break;
|
|
693
|
-
case 'no-update':
|
|
694
|
-
console.log(`✓ Already up to date (${upgrade.from})`);
|
|
695
|
-
break;
|
|
696
|
-
case 'skipped':
|
|
697
|
-
console.log(upgrade.error
|
|
698
|
-
? '⏭ Skipped upgrade (network unavailable)'
|
|
699
|
-
: '⏭ Skipped upgrade check (dev mode)');
|
|
700
|
-
break;
|
|
701
|
-
case 'failed':
|
|
702
|
-
console.log(`⚠ Upgrade failed (${upgrade.from} → ${upgrade.to}), continuing with current version`);
|
|
703
|
-
break;
|
|
704
|
-
}
|
|
705
|
-
// EC Web 是独立全局包,已安装时单独检查升级。
|
|
706
|
-
const ecwebUpgrade = await tryUpgradeGlobalPkg(() => resolveGlobalPkg(WEB_PACKAGE_NAME), WEB_PACKAGE_NAME);
|
|
707
|
-
switch (ecwebUpgrade.status) {
|
|
708
|
-
case 'upgraded':
|
|
709
|
-
console.log(`✅ ${WEB_PACKAGE_NAME} upgraded: ${ecwebUpgrade.from} → ${ecwebUpgrade.to}`);
|
|
710
|
-
break;
|
|
711
|
-
case 'no-update':
|
|
712
|
-
break; // silent
|
|
713
|
-
case 'failed':
|
|
714
|
-
console.log(`⚠ ${WEB_PACKAGE_NAME} upgrade failed (${ecwebUpgrade.from} → ${ecwebUpgrade.to})`);
|
|
715
|
-
break;
|
|
716
|
-
}
|
|
774
|
+
// Keep restart behavior identical to startup: both paths use one upgrade
|
|
775
|
+
// check implementation and continue when an upgrade is unavailable.
|
|
776
|
+
await runUpgradeChecks();
|
|
717
777
|
if (!requireCompletedDataMigration(resolveRoot()))
|
|
718
778
|
return;
|
|
719
779
|
// 停止所有活 main 进程(可能不止一个)
|
|
@@ -2646,7 +2706,7 @@ async function stopEcwebIfRunning(p) {
|
|
|
2646
2706
|
throw new Error(`EC Web old process or port ${port} could not be released`);
|
|
2647
2707
|
}
|
|
2648
2708
|
// 清理 pid 文件(仅 ecweb-<pid>.json / watch-web-<pid>.json,
|
|
2649
|
-
// 不碰
|
|
2709
|
+
// 不碰 daemon-owned control-access-tokens.json 等非 pid 文件,否则会清空凭据库导致每次重启都要重新配对)
|
|
2650
2710
|
removeEcwebInstanceFiles(p);
|
|
2651
2711
|
return pids.size > 0;
|
|
2652
2712
|
}
|
|
@@ -2738,23 +2798,32 @@ export async function startEcwebIfEnabled(p, options = {}) {
|
|
|
2738
2798
|
fs.mkdirSync(p.instanceDir, { recursive: true });
|
|
2739
2799
|
const startedAt = getProcessStartTime(pid) ?? Date.now();
|
|
2740
2800
|
fs.writeFileSync(path.join(p.instanceDir, `ecweb-${pid}.json`), JSON.stringify({ pid, port, startedAt, startedAtIso: new Date(startedAt).toISOString() }, null, 2));
|
|
2741
|
-
// 轮询端口确认 HTTP 服务真正就绪(spawn 成功 ≠
|
|
2801
|
+
// 轮询端口确认 HTTP 服务真正就绪(spawn 成功 ≠ 端口绑定成功)。
|
|
2802
|
+
// 配对码由 daemon 提供,daemon 尚未启动时不应把已经就绪的 ECWeb 杀掉。
|
|
2803
|
+
let ready = false;
|
|
2742
2804
|
let pair = null;
|
|
2743
2805
|
for (let i = 0; i < 20; i++) {
|
|
2744
|
-
|
|
2745
|
-
if (
|
|
2806
|
+
ready = await probeEcwebReady(port);
|
|
2807
|
+
if (ready) {
|
|
2808
|
+
pair = await fetchRemotePairingCode();
|
|
2746
2809
|
break;
|
|
2810
|
+
}
|
|
2747
2811
|
await sleep(250);
|
|
2748
2812
|
}
|
|
2749
|
-
if (
|
|
2813
|
+
if (ready) {
|
|
2750
2814
|
const actualStartedAt = getProcessStartTime(pid);
|
|
2751
2815
|
if (actualStartedAt !== null) {
|
|
2752
2816
|
fs.writeFileSync(path.join(p.instanceDir, `ecweb-${pid}.json`), JSON.stringify({ pid, port, startedAt: actualStartedAt, startedAtIso: new Date(actualStartedAt).toISOString() }, null, 2));
|
|
2753
2817
|
}
|
|
2754
|
-
const mins = Math.max(0, Math.round((pair.expiresAt - Date.now()) / 60000));
|
|
2755
2818
|
const actionLabel = wasRunning ? '已重启' : '启动成功';
|
|
2756
2819
|
console.log(`✓ ECWeb ${actionLabel} (PID: ${pid}) http://localhost:${port}`);
|
|
2757
|
-
|
|
2820
|
+
if (pair) {
|
|
2821
|
+
const mins = Math.max(0, Math.round((pair.expiresAt - Date.now()) / 60000));
|
|
2822
|
+
console.log(` 配对码: ${pair.code} (约 ${mins} 分钟内有效,已配对过的浏览器无需重新配对)`);
|
|
2823
|
+
}
|
|
2824
|
+
else {
|
|
2825
|
+
console.log(' daemon 尚未提供配对码;EvolCore 启动后可通过 /pair 或 ECWeb 页面获取');
|
|
2826
|
+
}
|
|
2758
2827
|
return true;
|
|
2759
2828
|
}
|
|
2760
2829
|
console.log(`❌ ECWeb 启动失败:端口 ${port} 未就绪(进程 PID ${pid} 可能已退出,查看 logs/watch-web.log)`);
|
|
@@ -2780,13 +2849,13 @@ async function printEcwebAccess(port) {
|
|
|
2780
2849
|
console.log(`🔭 ECWeb http://localhost:${port}`);
|
|
2781
2850
|
let pair = null;
|
|
2782
2851
|
for (let i = 0; i < 10 && !pair; i++) {
|
|
2783
|
-
pair = await
|
|
2852
|
+
pair = await fetchRemotePairingCode();
|
|
2784
2853
|
if (!pair)
|
|
2785
2854
|
await sleep(300);
|
|
2786
2855
|
}
|
|
2787
2856
|
if (pair) {
|
|
2788
2857
|
const mins = Math.max(0, Math.round((pair.expiresAt - Date.now()) / 60000));
|
|
2789
|
-
console.log(` 配对码: ${pair.code} (约 ${mins}
|
|
2858
|
+
console.log(` 配对码: ${pair.code} (约 ${mins} 分钟内有效,配对后远程访问 token 缓存 30 天)`);
|
|
2790
2859
|
}
|
|
2791
2860
|
else {
|
|
2792
2861
|
console.log(' 配对码: 暂不可用(稍后重试 ec watch web,或查看 logs/watch-web.log)');
|
|
@@ -2903,7 +2972,56 @@ export async function cmdDiagnose() {
|
|
|
2903
2972
|
else {
|
|
2904
2973
|
console.log(`[diagnose] ✓ 已加载 ${agents.length} 个 self-agent`);
|
|
2905
2974
|
}
|
|
2906
|
-
// 3.
|
|
2975
|
+
// 3. 检查实际使用 Codex 的 Agent 项目目录。项目路径属于 Agent 的
|
|
2976
|
+
// effective config,逐个输出 AID,避免只检查第一个 agent 掩盖坏配置。
|
|
2977
|
+
const codexAgents = agents.filter(agent => {
|
|
2978
|
+
try {
|
|
2979
|
+
return resolveEffective({ self: agent.aid }).active_baseagent === 'codex';
|
|
2980
|
+
}
|
|
2981
|
+
catch (error) {
|
|
2982
|
+
console.error(`[diagnose] ❌ Agent ${agent.aid} effective config 解析失败: ${error instanceof Error ? error.message : String(error)}`);
|
|
2983
|
+
hasError = true;
|
|
2984
|
+
return false;
|
|
2985
|
+
}
|
|
2986
|
+
});
|
|
2987
|
+
for (const agent of codexAgents) {
|
|
2988
|
+
try {
|
|
2989
|
+
const effective = resolveEffective({ self: agent.aid });
|
|
2990
|
+
const check = checkCodexProjectPath(effective.projects?.defaultPath);
|
|
2991
|
+
if (check.status === 'ok') {
|
|
2992
|
+
console.log(`[diagnose] ✓ Codex 项目路径 ${agent.aid}: ${check.path}`);
|
|
2993
|
+
}
|
|
2994
|
+
else {
|
|
2995
|
+
console.error(`[diagnose] ❌ Codex 项目路径 ${agent.aid}: ${check.path || '(未配置)'} (${check.reason || check.status})`);
|
|
2996
|
+
hasError = true;
|
|
2997
|
+
}
|
|
2998
|
+
for (const warning of check.warnings)
|
|
2999
|
+
console.warn(`[diagnose] ⚠️ Codex 项目路径 ${agent.aid}: ${warning}`);
|
|
3000
|
+
}
|
|
3001
|
+
catch (error) {
|
|
3002
|
+
console.error(`[diagnose] ❌ Codex 项目路径检查失败 ${agent.aid}: ${error instanceof Error ? error.message : String(error)}`);
|
|
3003
|
+
hasError = true;
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
if (codexAgents.length === 0) {
|
|
3007
|
+
console.log('[diagnose] - Codex managed hook: 跳过(没有 Agent 使用 Codex)');
|
|
3008
|
+
}
|
|
3009
|
+
else {
|
|
3010
|
+
const hook = inspectCodexManagedHook({ packageRoot: getPackageRoot() });
|
|
3011
|
+
if (hook.status === 'installed') {
|
|
3012
|
+
console.log(`[diagnose] ✓ Codex managed hook 已安装: ${hook.hookPath}`);
|
|
3013
|
+
}
|
|
3014
|
+
else if (hook.status === 'skipped') {
|
|
3015
|
+
console.log(`[diagnose] - Codex managed hook: 跳过(${hook.reason})`);
|
|
3016
|
+
}
|
|
3017
|
+
else {
|
|
3018
|
+
const prefix = hook.status === 'missing' ? '⚠️' : '❌';
|
|
3019
|
+
const writer = hook.status === 'missing' ? console.warn : console.error;
|
|
3020
|
+
writer(`[diagnose] ${prefix} Codex managed hook ${hook.status}: ${hook.reason || 'unknown error'}${hook.requirements ? ` (${hook.requirements})` : ''}`);
|
|
3021
|
+
hasError = true;
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
// 4. 检查 Anthropic 配置(用首个 self-agent 的 effective config)
|
|
2907
3025
|
if (agents.length > 0) {
|
|
2908
3026
|
try {
|
|
2909
3027
|
const merged = resolveEffective({ self: agents[0].aid });
|
package/dist/cli/index.js
CHANGED
|
@@ -46,6 +46,7 @@ AUN:
|
|
|
46
46
|
fs AUN 文件系统
|
|
47
47
|
storage 底层对象存储命令
|
|
48
48
|
rpc 调用底层 AUN RPC
|
|
49
|
+
menu-client 向远程 daemon 发送标准 Menu 请求
|
|
49
50
|
contact 联系人黑名单管理
|
|
50
51
|
net AUN 网络链路诊断
|
|
51
52
|
|
|
@@ -350,6 +351,25 @@ export async function main(args) {
|
|
|
350
351
|
await cmdRpc(args.slice(1));
|
|
351
352
|
break;
|
|
352
353
|
}
|
|
354
|
+
case 'menu-client': {
|
|
355
|
+
const { suppressSdkLogs } = await import('../aun/aid/index.js');
|
|
356
|
+
suppressSdkLogs();
|
|
357
|
+
const { cmdMenuClient } = await import('./menu-client.js');
|
|
358
|
+
try {
|
|
359
|
+
await cmdMenuClient(args.slice(1));
|
|
360
|
+
}
|
|
361
|
+
catch (error) {
|
|
362
|
+
const payload = {
|
|
363
|
+
ok: false,
|
|
364
|
+
code: typeof error?.code === 'string' ? error.code : 'MENU_CLIENT_FAILED',
|
|
365
|
+
error: error?.message ?? String(error),
|
|
366
|
+
...(error?.data === undefined ? {} : { data: error.data }),
|
|
367
|
+
};
|
|
368
|
+
console.error(JSON.stringify(payload));
|
|
369
|
+
process.exitCode = 1;
|
|
370
|
+
}
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
353
373
|
case 'storage': {
|
|
354
374
|
const { suppressSdkLogs } = await import('../aun/aid/index.js');
|
|
355
375
|
suppressSdkLogs();
|
package/dist/cli/init.js
CHANGED
|
@@ -14,6 +14,7 @@ import { defaultProjectsRoot } from '../utils/project-path.js';
|
|
|
14
14
|
import { WEB_CLI_BIN, WEB_PACKAGE_LATEST } from '../product.js';
|
|
15
15
|
import { autostartInstalled, autostartPlatformLabel, configureAutostart } from '../utils/autostart.js';
|
|
16
16
|
import { askInit, isInitCancelledError, printInitCancelHint } from './init-cancel.js';
|
|
17
|
+
import { AUTO_BASEAGENT_CANDIDATES, BASEAGENT_CANDIDATES, detectAvailableBaseagents, } from '../agents/baseagent-availability.js';
|
|
17
18
|
// ==================== Helpers ====================
|
|
18
19
|
function ask(rl, question) {
|
|
19
20
|
return askInit(rl, question);
|
|
@@ -27,17 +28,8 @@ export function expandLeadingTildePath(value, homeDir = os.homedir()) {
|
|
|
27
28
|
}
|
|
28
29
|
return value;
|
|
29
30
|
}
|
|
30
|
-
const BASEAGENT_CANDIDATES = ['claude', 'codex', 'gemini', 'ecagent'];
|
|
31
|
-
const AUTO_BASEAGENT_CANDIDATES = ['claude', 'codex', 'gemini'];
|
|
32
|
-
function isBaseagentAvailable(baseagent, codexAvailability) {
|
|
33
|
-
if (baseagent === 'codex')
|
|
34
|
-
return (codexAvailability ?? getCodexAppServerAvailability()).available;
|
|
35
|
-
if (baseagent === 'ecagent')
|
|
36
|
-
return true;
|
|
37
|
-
return commandExists(baseagent);
|
|
38
|
-
}
|
|
39
31
|
function detectAvailable(codexAvailability = getCodexAppServerAvailability()) {
|
|
40
|
-
return
|
|
32
|
+
return detectAvailableBaseagents(codexAvailability);
|
|
41
33
|
}
|
|
42
34
|
/** Offer installation only when the probe positively identified an old CLI. */
|
|
43
35
|
export async function maybeUpgradeCodexForInit(availability, dependencies) {
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import { getArgValue, wantsHelp } from './help.js';
|
|
3
|
+
import { executeMenuClientRequest, MenuClientError } from '../aun/menu-client.js';
|
|
4
|
+
function parseDurationMs(value) {
|
|
5
|
+
if (value === undefined)
|
|
6
|
+
return undefined;
|
|
7
|
+
const match = value.trim().match(/^(\d+(?:\.\d+)?)(ms|s|m|h)$/i);
|
|
8
|
+
if (!match)
|
|
9
|
+
throw new MenuClientError('INVALID_ARGUMENT', `Invalid timeout: ${value}`);
|
|
10
|
+
const amount = Number(match[1]);
|
|
11
|
+
const unit = match[2].toLowerCase();
|
|
12
|
+
return amount * (unit === 'ms' ? 1 : unit === 's' ? 1_000 : unit === 'm' ? 60_000 : 3_600_000);
|
|
13
|
+
}
|
|
14
|
+
function readRequest(args) {
|
|
15
|
+
const file = getArgValue(args, '--request-file');
|
|
16
|
+
const inline = getArgValue(args, '--request-json');
|
|
17
|
+
if (!!file === !!inline)
|
|
18
|
+
throw new MenuClientError('INVALID_ARGUMENT', '--request-file and --request-json are mutually exclusive');
|
|
19
|
+
let raw;
|
|
20
|
+
try {
|
|
21
|
+
raw = file ? fs.readFileSync(file, 'utf8') : inline;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
throw new MenuClientError('INVALID_ARGUMENT', `Unable to read request: ${error?.message ?? String(error)}`);
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const parsed = JSON.parse(raw);
|
|
28
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
29
|
+
throw new Error('request must be a JSON object');
|
|
30
|
+
return parsed;
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
throw new MenuClientError('INVALID_ARGUMENT', `Invalid request JSON: ${error?.message ?? String(error)}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function validateOptions(args) {
|
|
37
|
+
const valueOptions = new Set(['--request-file', '--request-json', '--timeout', '--remote-token', '--ecweb-token', '--app', '--aun-path', '--format']);
|
|
38
|
+
const booleanOptions = new Set(['--encrypt', '--no-encrypt']);
|
|
39
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
40
|
+
const option = args[index];
|
|
41
|
+
if (booleanOptions.has(option))
|
|
42
|
+
continue;
|
|
43
|
+
if (!valueOptions.has(option))
|
|
44
|
+
throw new MenuClientError('INVALID_ARGUMENT', `Unknown menu-client option: ${option}`);
|
|
45
|
+
if (index + 1 >= args.length || args[index + 1].startsWith('--')) {
|
|
46
|
+
throw new MenuClientError('INVALID_ARGUMENT', `${option} requires a value`);
|
|
47
|
+
}
|
|
48
|
+
index += 1;
|
|
49
|
+
}
|
|
50
|
+
if (args.includes('--encrypt') && args.includes('--no-encrypt')) {
|
|
51
|
+
throw new MenuClientError('INVALID_ARGUMENT', '--encrypt and --no-encrypt are mutually exclusive');
|
|
52
|
+
}
|
|
53
|
+
const format = getArgValue(args, '--format');
|
|
54
|
+
if (format !== undefined && format !== 'json')
|
|
55
|
+
throw new MenuClientError('INVALID_ARGUMENT', '--format currently supports only json');
|
|
56
|
+
}
|
|
57
|
+
export async function cmdMenuClient(args) {
|
|
58
|
+
if (wantsHelp(args)) {
|
|
59
|
+
console.log(`用法: ec menu-client request <from-aid> <daemon-aid> [选项]
|
|
60
|
+
|
|
61
|
+
--request-file <path> 从 JSON 文件读取一个 menu.* 请求
|
|
62
|
+
--request-json <json> 直接传入一个 menu.* JSON 请求
|
|
63
|
+
--timeout <时长> 默认 15s,最大 120s
|
|
64
|
+
--encrypt 使用 E2EE(默认)
|
|
65
|
+
--no-encrypt 已拒绝:ec-menu-client 必须使用 E2EE
|
|
66
|
+
--remote-token <token> 使用 daemon 远程访问 token 临时授权
|
|
67
|
+
--ecweb-token <token> --remote-token 的兼容别名
|
|
68
|
+
--app <slot> 覆盖默认 evolcore-menu-client 消费槽位
|
|
69
|
+
--aun-path <path> 覆盖本地 AUN keystore 根目录
|
|
70
|
+
--format json 输出标准 menu.response JSON`);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (args[0] !== 'request')
|
|
74
|
+
throw new MenuClientError('INVALID_ARGUMENT', 'menu-client currently supports only the request subcommand');
|
|
75
|
+
const fromAid = args[1]?.trim();
|
|
76
|
+
const targetAid = args[2]?.trim();
|
|
77
|
+
if (!fromAid || !targetAid)
|
|
78
|
+
throw new MenuClientError('INVALID_ARGUMENT', 'request requires <from-aid> and <daemon-aid>');
|
|
79
|
+
const options = args.slice(3);
|
|
80
|
+
validateOptions(options);
|
|
81
|
+
const request = readRequest(options);
|
|
82
|
+
const timeoutMs = parseDurationMs(getArgValue(args, '--timeout'));
|
|
83
|
+
const encrypt = args.includes('--no-encrypt') ? false : true;
|
|
84
|
+
const response = await executeMenuClientRequest({
|
|
85
|
+
fromAid,
|
|
86
|
+
targetAid,
|
|
87
|
+
request,
|
|
88
|
+
timeoutMs,
|
|
89
|
+
encrypt,
|
|
90
|
+
remoteAccessToken: getArgValue(args, '--remote-token') ?? getArgValue(args, '--ecweb-token'),
|
|
91
|
+
slotId: getArgValue(args, '--app'),
|
|
92
|
+
aunPath: getArgValue(args, '--aun-path'),
|
|
93
|
+
});
|
|
94
|
+
console.log(JSON.stringify(response, null, 2));
|
|
95
|
+
}
|