evolcore 0.0.31 → 0.0.33
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 +35 -0
- package/bin/install-codex-managed-hooks.mjs +124 -37
- package/dist/agents/claude-runner.js +29 -2
- package/dist/agents/codex/app-server-client.js +3 -0
- package/dist/agents/codex/diagnostics.js +76 -44
- package/dist/agents/codex-runner.js +51 -24
- package/dist/agents/ecagent-runner.js +9 -13
- package/dist/agents/gemini-runner.js +4 -0
- package/dist/aun/aid/store.js +0 -81
- package/dist/aun/group/fs-download.js +1 -10
- package/dist/aun/group/operations.js +0 -1
- package/dist/aun/msg/history.js +1 -0
- package/dist/aun/msg/managed-operation.js +130 -32
- package/dist/aun/msg/p2p.js +0 -1
- package/dist/aun/outbox.js +50 -1
- package/dist/aun/service-proxy.js +12 -18
- package/dist/aun/storage/index.js +29 -0
- package/dist/channels/aun.js +38 -137
- package/dist/channels/daemon.js +257 -2
- package/dist/cli/agent-command.js +64 -31
- package/dist/cli/agent-create.js +43 -24
- package/dist/cli/agent.js +16 -70
- package/dist/cli/aun-commands.js +512 -32
- package/dist/cli/contact.js +8 -2
- package/dist/cli/ctl-command.js +1 -2
- package/dist/cli/daemon-commands.js +82 -13
- package/dist/cli/debug-mode.js +154 -0
- package/dist/cli/diag.js +2 -2
- package/dist/cli/handoff-command.js +18 -5
- package/dist/cli/index.js +81 -64
- package/dist/cli/init.js +2 -2
- package/dist/cli/managed-command-guard.js +5 -0
- package/dist/cli/memory-command.js +93 -12
- package/dist/cli/model.js +14 -138
- package/dist/cli/queue-command.js +51 -0
- package/dist/cli/response.js +5 -54
- package/dist/cli/session-command.js +194 -0
- package/dist/cli/skill-command.js +85 -3
- package/dist/cli/stats.js +10 -4
- package/dist/cli/task-command.js +1 -0
- package/dist/cli/task-context.js +16 -0
- package/dist/cli/thread-command.js +620 -0
- package/dist/cli/trigger-command.js +76 -50
- package/dist/config/builtin-roles.js +9 -7
- package/dist/config/config-field-policy.js +2 -3
- package/dist/config/config-manager.js +7 -2
- package/dist/config/resolved-config-op.js +3 -0
- package/dist/config-store.js +15 -0
- package/dist/core/agent-ipc-registration.js +65 -22
- package/dist/core/auth/agent-delegation.js +42 -2
- package/dist/core/auth/debug-context.js +139 -0
- package/dist/core/auth/delegation-authorization.js +1 -0
- package/dist/core/auth/operation-authorizer.js +24 -1
- package/dist/core/auth/operation-catalog.js +44 -3
- package/dist/core/background-session/session-cleanup.js +212 -0
- package/dist/core/background-session/types.js +10 -0
- package/dist/core/bootstrap-messages.js +1 -1
- package/dist/core/bootstrap-service.js +6 -3
- package/dist/core/command/command-handler.js +224 -45
- package/dist/core/command/diag-service.js +5 -1
- package/dist/core/command/memory-slash.js +6 -2
- package/dist/core/command/menu-catalog.js +48 -1
- package/dist/core/command/menu-handler.js +92 -16
- package/dist/core/command/menu-protocol.js +24 -1
- package/dist/core/command/skill-slash.js +322 -0
- package/dist/core/command/slash-gate.js +6 -4
- package/dist/core/command/slash-handler.js +193 -13
- package/dist/core/command/topic-slash.js +528 -0
- package/dist/core/evolagent-registry.js +20 -5
- package/dist/core/handoff/ipc-registration.js +38 -0
- package/dist/core/handoff/runtime.js +5 -11
- package/dist/core/handoff/store.js +5 -0
- package/dist/core/ipc-registration.js +210 -9
- package/dist/core/memory/consolidation-context.js +49 -16
- package/dist/core/memory/consolidation-ops-records.js +35 -0
- package/dist/core/memory/consolidation-queue-format.js +21 -0
- package/dist/core/memory/consolidation.js +174 -180
- package/dist/core/message/aun-ipc-sender.js +207 -8
- package/dist/core/message/im-renderer.js +149 -6
- package/dist/core/message/message-bridge.js +13 -3
- package/dist/core/message/message-log.js +1 -0
- package/dist/core/message/message-queue.js +131 -3
- package/dist/core/message/peer-mode.js +6 -1
- package/dist/core/message/response-engine.js +379 -69
- package/dist/core/message/subtask-tool-projection.js +140 -0
- package/dist/core/model/catalog-service.js +17 -12
- package/dist/core/permission/ec-command-parser.js +126 -7
- package/dist/core/permission/sandbox-runtime.js +14 -1
- package/dist/core/session/session-idle-monitor.js +249 -22
- package/dist/core/session/session-manager.js +54 -9
- package/dist/core/skill/command-parser.js +13 -0
- package/dist/core/skill/index-generator.js +4 -1
- package/dist/core/skill/startup.js +41 -0
- package/dist/core/skill/switch-resolver.js +55 -29
- package/dist/core/task/task-recovery-service.js +2 -0
- package/dist/core/task/task-resume-operation.js +11 -0
- package/dist/core/thread/command-parser.js +125 -0
- package/dist/core/thread/index.js +1 -0
- package/dist/core/thread/ipc-operation.js +95 -0
- package/dist/core/thread/thread-context-storage.js +131 -0
- package/dist/core/thread/thread-operation.js +258 -0
- package/dist/core/thread/thread-route.js +33 -0
- package/dist/core/thread/thread-service.js +777 -0
- package/dist/core/thread/types.js +1 -0
- package/dist/eck/message-renderer.js +35 -0
- package/dist/index.js +10 -7
- package/dist/ipc.js +234 -17
- package/dist/paths.js +23 -0
- package/dist/response-system/engines/v1/proactive-flow.js +169 -80
- package/dist/trigger/authorization.js +59 -29
- package/dist/trigger/feedback.js +7 -1
- package/dist/trigger/ipc-service.js +49 -35
- package/dist/trigger/parser.js +63 -1
- package/dist/trigger/script-sandbox.js +58 -77
- package/dist/trigger/validation.js +14 -0
- package/dist/utils/error-utils.js +22 -1
- package/kits/docs/AUTHORING.md +1 -1
- package/kits/docs/channels/aun.md +8 -0
- package/kits/docs/context-assembly.md +1 -0
- package/kits/docs/evolcore/INDEX.md +3 -2
- package/kits/docs/evolcore/agent-create.md +39 -28
- package/kits/docs/evolcore/agent.md +19 -4
- package/kits/docs/evolcore/ec-capabilities.md +4 -0
- package/kits/docs/evolcore/group-collaboration.md +3 -5
- package/kits/docs/evolcore/group.md +3 -4
- package/kits/docs/evolcore/memory-consolidation.md +1 -1
- package/kits/docs/evolcore/menu-exec-schema-commands.md +2 -2
- package/kits/docs/evolcore/menu-protocol.md +7 -0
- package/kits/docs/evolcore/msg.md +5 -8
- package/kits/docs/evolcore/task.md +2 -0
- package/kits/docs/evolcore/thread-chain.md +267 -0
- package/kits/docs/evolcore/trigger.md +2 -2
- package/kits/docs/prompt-loading-architecture.md +1 -0
- package/kits/eck_manifest.json +61 -26
- package/kits/eck_message_manifest.json +169 -10
- package/kits/rules/01-overview.md +0 -9
- package/kits/rules/05-venue.md +1 -1
- package/kits/rules/06-channel.md +7 -1
- package/kits/rules/07-memory-and-thread.md +202 -0
- package/kits/schemas/relation-config.schema.9.json +18 -3
- package/kits/schemas/role-config.schema.1.json +6 -6
- package/kits/schemas/single-session.schema.1.json +6 -6
- package/kits/schemas/single-session.schema.2.json +6 -6
- package/kits/schemas/single-session.schema.3.json +6 -6
- package/kits/skills/.switches.json +12 -1
- package/kits/skills/ec-group/SKILL.md +234 -0
- package/kits/skills/ec-skill/SKILL.md +10 -1
- package/kits/skills/ec-skill/scripts/cli.mjs +15 -1
- package/kits/skills/scrapling-article-fetch/SKILL.md +128 -0
- package/kits/skills/scrapling-article-fetch/scripts/check_python_env.py +54 -0
- package/kits/skills/scrapling-article-fetch/scripts/render_markdown_reply.py +35 -0
- package/kits/skills/scrapling-article-fetch/scripts/run_pipeline.sh +16 -0
- package/kits/skills/scrapling-article-fetch/scripts/scrapling_fetch.py +344 -0
- package/kits/skills/thread-ops/SKILL.md +492 -0
- package/kits/skills/wechat-article-media-download/SKILL.md +65 -0
- package/kits/skills/wechat-article-media-download/scripts/download.py +163 -0
- package/kits/skills/wechat-article-reader/SKILL.md +97 -0
- package/kits/skills/wechat-article-reader/scripts/fetch.mjs +256 -0
- package/kits/templates/bootstrap-welcome.md +7 -7
- package/kits/templates/memory-consolidation/forget.md +5 -0
- package/kits/templates/memory-consolidation/generalize.md +5 -0
- package/kits/templates/memory-consolidation/profile.md +5 -0
- package/kits/templates/memory-consolidation/promote.md +5 -0
- package/kits/templates/message-fragments/item.md +2 -1
- package/kits/templates/message-fragments/thread-context.md +6 -0
- package/kits/templates/message-fragments/trigger-session.md +2 -0
- package/kits/templates/message-fragments/trigger-thread-check.md +2 -0
- package/kits/templates/roles/member.json +2 -0
- package/kits/templates/roles/visitor.json +2 -0
- package/kits/templates/system-fragments/bootstrap.md +66 -72
- package/kits/templates/system-fragments/channel.md +3 -6
- package/kits/templates/system-fragments/commands.md +2 -1
- package/kits/templates/system-fragments/managed-runtime.md +15 -0
- package/kits/templates/system-fragments/reply.md +3 -2
- package/kits/templates/system-fragments/session.md +5 -14
- package/package.json +3 -1
- package/kits/docs/evolcore/group-fs.md +0 -17
- package/kits/docs/venues/aun-group.md +0 -45
- package/kits/docs/venues/group.md +0 -43
package/dist/cli/contact.js
CHANGED
|
@@ -11,8 +11,14 @@ export async function cmdContact(args) {
|
|
|
11
11
|
}
|
|
12
12
|
const json = getArgValue(args, '--format') === 'json';
|
|
13
13
|
if (process.env.EVOLCORE_SESSION_ID) {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
try {
|
|
15
|
+
const result = await runManaged(args, json);
|
|
16
|
+
output(result, json);
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
console.error(`❌ ${err.message ?? String(err)}`);
|
|
20
|
+
process.exitCode = 1;
|
|
21
|
+
}
|
|
16
22
|
return;
|
|
17
23
|
}
|
|
18
24
|
if (!args.includes('--self') && isListCommand(args) && !process.env.EVOLCORE_SELF_AID?.trim()) {
|
package/dist/cli/ctl-command.js
CHANGED
|
@@ -41,11 +41,10 @@ export async function cmdCtl(args) {
|
|
|
41
41
|
console.error('错误: EVOLCORE_SESSION_ID 未设置(仅在 evolcore 托管环境中可用)');
|
|
42
42
|
process.exit(1);
|
|
43
43
|
}
|
|
44
|
-
const cmd = '/' + args.join(' ');
|
|
45
44
|
const socketPath = resolvePaths().socket;
|
|
46
45
|
const result = await ipcQuery(socketPath, {
|
|
47
46
|
type: 'ctl',
|
|
48
|
-
|
|
47
|
+
argv: ['ctl', ...args],
|
|
49
48
|
sessionId,
|
|
50
49
|
delegationToken: readDelegationCredential(),
|
|
51
50
|
}, 10_000);
|
|
@@ -25,7 +25,7 @@ import { isNonAgentSessionChannel } from '../core/system-channels.js';
|
|
|
25
25
|
import { printCodeStats } from './code-stats.js';
|
|
26
26
|
import { getProcessStartTime, startTimeMatches } from '../utils/process-introspect.js';
|
|
27
27
|
import { AGENT_DELEGATION_TOKEN_ENV, readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
28
|
-
import { RUNTIME_HOME_ENV, WEB_CLI_BIN, WEB_PACKAGE_LATEST, WEB_PACKAGE_NAME } from '../product.js';
|
|
28
|
+
import { MAIN_CLI_BIN, RUNTIME_HOME_ENV, WEB_CLI_BIN, WEB_PACKAGE_LATEST, WEB_PACKAGE_NAME } from '../product.js';
|
|
29
29
|
import { rotateStdoutLog } from '../utils/log-writer.js';
|
|
30
30
|
import { inspectDataMigrationRequirement } from '../core/data-migration.js';
|
|
31
31
|
import { isInitCancelledError, printInitCancelHint } from './init-cancel.js';
|
|
@@ -34,8 +34,34 @@ import { listCodexAppServerProcesses, unregisterCodexAppServerProcess } from '..
|
|
|
34
34
|
import { DEFAULT_ECWEB_PORT, ecwebService, setEcwebEnabled } from '../config/daemon-services.js';
|
|
35
35
|
import { checkCodexProjectPath, inspectCodexManagedHook, ensureCodexManagedHook, runCodexHookLaunchDiagnostic, } from '../agents/codex/diagnostics.js';
|
|
36
36
|
const execFileAsync = promisify(execFile);
|
|
37
|
+
export async function confirmCodexHookRebind(state, packageRoot) {
|
|
38
|
+
console.log('⚠️ Codex 受管 Hook 绑定的另一套 EvolCore/Node 路径仍存在,需确认是否切换:');
|
|
39
|
+
console.log(` 现有包: ${state.managedPackageRoot}`);
|
|
40
|
+
console.log(` 现有 Node: ${state.managedNodePath}`);
|
|
41
|
+
console.log(` 当前包: ${packageRoot}`);
|
|
42
|
+
console.log(` 当前 Node: ${process.execPath}`);
|
|
43
|
+
console.log(' 切换会更新机器级 Hook,影响共享此策略的 Codex 会话;不会执行数据迁移。');
|
|
44
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
45
|
+
console.warn(` 非交互模式不自动选择。请在交互式终端运行 ${MAIN_CLI_BIN} start 确认;也可使用现有安装的 CLI。`);
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const terminal = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
49
|
+
return new Promise(resolve => {
|
|
50
|
+
let settled = false;
|
|
51
|
+
const finish = (confirmed) => {
|
|
52
|
+
if (settled)
|
|
53
|
+
return;
|
|
54
|
+
settled = true;
|
|
55
|
+
terminal.close();
|
|
56
|
+
resolve(confirmed);
|
|
57
|
+
};
|
|
58
|
+
terminal.once('close', () => finish(false));
|
|
59
|
+
terminal.once('SIGINT', () => finish(false));
|
|
60
|
+
terminal.question(' [1] 切换到当前包/Node 并修复 [2] 保留原绑定并取消本次启动 [1/2,默认 2]: ', answer => finish(answer.trim() === '1'));
|
|
61
|
+
});
|
|
62
|
+
}
|
|
37
63
|
/** Run before launch, and before restart stops any existing daemon. */
|
|
38
|
-
export function ensureCodexHookBeforeLifecycle(onRepaired) {
|
|
64
|
+
export async function ensureCodexHookBeforeLifecycle(onRepaired) {
|
|
39
65
|
if (!platform.isWindows)
|
|
40
66
|
return true;
|
|
41
67
|
try {
|
|
@@ -53,19 +79,31 @@ export function ensureCodexHookBeforeLifecycle(onRepaired) {
|
|
|
53
79
|
});
|
|
54
80
|
if (!usesCodex)
|
|
55
81
|
return true;
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
82
|
+
const packageRoot = getPackageRoot();
|
|
83
|
+
const result = await ensureCodexManagedHook({
|
|
84
|
+
packageRoot,
|
|
85
|
+
repairDecision: state => confirmCodexHookRebind(state, packageRoot),
|
|
86
|
+
onInstallRequired: state => console.log(state.status === 'stale'
|
|
87
|
+
? '🔧 Codex 受管 Hook 路径已过期,正在修复;Windows 提示管理员授权时请选择“是”。'
|
|
88
|
+
: '🔧 Codex 运行组件缺失,正在自动安装;Windows 提示管理员授权时请选择“是”。'),
|
|
59
89
|
});
|
|
60
90
|
if (result.status === 'installed') {
|
|
61
91
|
if (result.repaired) {
|
|
62
|
-
console.log('✅ Codex Windows managed hook
|
|
92
|
+
console.log('✅ Codex Windows managed hook 已修复并验证');
|
|
63
93
|
onRepaired?.();
|
|
64
94
|
}
|
|
65
95
|
return true;
|
|
66
96
|
}
|
|
67
|
-
|
|
68
|
-
|
|
97
|
+
if (result.cancelled) {
|
|
98
|
+
console.warn('ℹ 未确认切换 Codex 受管 Hook,保留原绑定;本次启动/重启已取消,现有服务未停止。');
|
|
99
|
+
process.exitCode = 1;
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
console.error(`❌ Codex Windows managed hook 启动检查未通过:${result.error || result.reason || result.status}`);
|
|
103
|
+
if (result.status === 'stale') {
|
|
104
|
+
console.error(` 本次操作已停止,现有服务未停止。请在交互式终端运行 ${MAIN_CLI_BIN} start 确认修复,或使用原安装的 CLI。`);
|
|
105
|
+
}
|
|
106
|
+
else if (result.status === 'missing') {
|
|
69
107
|
console.error(' 本次操作已停止。下次启动或重启会再次自动尝试安装,需要允许 Windows 管理员授权。');
|
|
70
108
|
}
|
|
71
109
|
else {
|
|
@@ -154,7 +192,7 @@ async function tryDelegatedDaemonRestart(socketPath) {
|
|
|
154
192
|
return false;
|
|
155
193
|
const response = await ipcQuery(socketPath, {
|
|
156
194
|
type: 'ctl',
|
|
157
|
-
|
|
195
|
+
argv: ['ctl', 'restart'],
|
|
158
196
|
sessionId,
|
|
159
197
|
delegationToken,
|
|
160
198
|
}, 15_000);
|
|
@@ -192,6 +230,7 @@ function buildDaemonEnv(p, opts) {
|
|
|
192
230
|
EVENT_LOG: process.env.EVENT_LOG || 'true',
|
|
193
231
|
...(opts.diagnose ? { EVOLCORE_DIAGNOSE: '1' } : {}),
|
|
194
232
|
...(opts.bindBootstrap ? { EVOLCORE_BIND_BOOTSTRAP: '1' } : {}),
|
|
233
|
+
...(opts.debug ? { EVOLCORE_DEBUG_MODE: '1' } : {}),
|
|
195
234
|
};
|
|
196
235
|
}
|
|
197
236
|
function latestSourceMtime(dir) {
|
|
@@ -474,10 +513,10 @@ export async function cmdStart(opts = {}) {
|
|
|
474
513
|
const existingDaemon = await probeDaemon(p.socket);
|
|
475
514
|
if (existingDaemon) {
|
|
476
515
|
let hookRepaired = false;
|
|
477
|
-
if (!ensureCodexHookBeforeLifecycle(() => { hookRepaired = true; }))
|
|
516
|
+
if (!await ensureCodexHookBeforeLifecycle(() => { hookRepaired = true; }))
|
|
478
517
|
return;
|
|
479
518
|
if (hookRepaired) {
|
|
480
|
-
console.log('🔄 Codex
|
|
519
|
+
console.log('🔄 Codex 运行组件已修复,正在自动重启服务以加载策略...');
|
|
481
520
|
await cmdRestart({ diagnose: opts.diagnose });
|
|
482
521
|
return;
|
|
483
522
|
}
|
|
@@ -524,7 +563,7 @@ export async function cmdStart(opts = {}) {
|
|
|
524
563
|
// The initialization path can create the first Codex agent, so perform the
|
|
525
564
|
// machine-hook check after config migration/auto-init and before any daemon
|
|
526
565
|
// process is launched.
|
|
527
|
-
if (!ensureCodexHookBeforeLifecycle())
|
|
566
|
+
if (!await ensureCodexHookBeforeLifecycle())
|
|
528
567
|
return;
|
|
529
568
|
// 控制 AID 门禁:缺 aid 且交互式 → 只补全控制 AID + owners(不重走 baseagent 向导)。
|
|
530
569
|
// 非 TTY(restart-monitor/systemd/管道)不补全(无法交互),只提示后继续启动,daemon 侧 warn 兜底。
|
|
@@ -666,6 +705,21 @@ export async function cmdStart(opts = {}) {
|
|
|
666
705
|
console.log(` EVOLCORE_HOME: ${resolveRoot()}`);
|
|
667
706
|
console.log(` Logs: ${p.logs}/`);
|
|
668
707
|
console.log(`⏱ ready in ${((Date.now() - cmdStartedAt) / 1000).toFixed(1)}s`);
|
|
708
|
+
if (opts.debug) {
|
|
709
|
+
console.log('');
|
|
710
|
+
console.log('🔧 调试模式已启用(EVOLCORE_DEBUG_MODE=1)');
|
|
711
|
+
console.log(' 在宿主终端以任意 session 身份执行命令:');
|
|
712
|
+
console.log('');
|
|
713
|
+
console.log(' ec msg send "消息内容" --as-session <sessionId>');
|
|
714
|
+
console.log(' ec trigger list --as-session <sessionId>');
|
|
715
|
+
console.log(' ec memory list --as-session <sessionId>');
|
|
716
|
+
console.log('');
|
|
717
|
+
console.log(' 查看可用会话(运行后将在此处列出):');
|
|
718
|
+
console.log(' ec msg send "test" --as-session # 不带 sessionId 自动列出');
|
|
719
|
+
console.log('');
|
|
720
|
+
console.log(' 注意:重启 daemon(ec restart)会清除调试模式,');
|
|
721
|
+
console.log(' 需重新执行 ec start --debug 才能恢复。');
|
|
722
|
+
}
|
|
669
723
|
void waitForExistingEcweb(p).then((ecweb) => {
|
|
670
724
|
if (shouldPrintNoSelfAgentHints) {
|
|
671
725
|
printNoSelfAgentHints({ daemonConfig: loadDaemonConfig(), ecwebStarted: ecweb !== null, skipped });
|
|
@@ -769,6 +823,21 @@ export async function cmdStart(opts = {}) {
|
|
|
769
823
|
printCodeStats(getPackageRoot(), p.logs);
|
|
770
824
|
}
|
|
771
825
|
console.log(`⏱ done in ${((Date.now() - cmdStartedAt) / 1000).toFixed(1)}s`);
|
|
826
|
+
if (opts.debug) {
|
|
827
|
+
console.log('');
|
|
828
|
+
console.log('🔧 调试模式已启用(EVOLCORE_DEBUG_MODE=1)');
|
|
829
|
+
console.log(' 在宿主终端以任意 session 身份执行命令:');
|
|
830
|
+
console.log('');
|
|
831
|
+
console.log(' ec msg send "消息内容" --as-session <sessionId>');
|
|
832
|
+
console.log(' ec trigger list --as-session <sessionId>');
|
|
833
|
+
console.log(' ec memory list --as-session <sessionId>');
|
|
834
|
+
console.log('');
|
|
835
|
+
console.log(' 查看可用会话(运行后将在此处列出):');
|
|
836
|
+
console.log(' ec msg send "test" --as-session # 不带 sessionId 自动列出');
|
|
837
|
+
console.log('');
|
|
838
|
+
console.log(' 注意:重启 daemon(ec restart)会清除调试模式,');
|
|
839
|
+
console.log(' 需重新执行 ec start --debug 才能恢复。');
|
|
840
|
+
}
|
|
772
841
|
// ECWeb lifecycle belongs to the daemon; the CLI only reports whether
|
|
773
842
|
// the supervised instance became healthy.
|
|
774
843
|
const ecwebStarted = await waitForExistingEcweb(p) !== null;
|
|
@@ -904,7 +973,7 @@ export async function cmdStop() {
|
|
|
904
973
|
export async function cmdRestart(opts = {}) {
|
|
905
974
|
const cmdStartedAt = Date.now();
|
|
906
975
|
console.log('🔄 Restarting EvolCore...');
|
|
907
|
-
if (!ensureCodexHookBeforeLifecycle())
|
|
976
|
+
if (!await ensureCodexHookBeforeLifecycle())
|
|
908
977
|
return;
|
|
909
978
|
const initialStatus = scanInstances();
|
|
910
979
|
const socketPath = resolvePaths().socket;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* debug-mode.ts — `--as-session <sessionId>` 调试路径
|
|
3
|
+
*
|
|
4
|
+
* 在外部终端(宿主 CC 终端)以任意 agent 身份执行托管命令。
|
|
5
|
+
* 调用方在检查 EVOLCORE_SESSION_ID 之前先调用 resolveDebugContext(args);
|
|
6
|
+
* 注入完成后 process.env.EVOLCORE_SESSION_ID 已设好,后续走统一托管路径。
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { resolvePaths, debugSessionsDir } from '../paths.js';
|
|
11
|
+
import { ipcQuery } from '../ipc.js';
|
|
12
|
+
import { AGENT_DELEGATION_TOKEN_ENV } from '../core/auth/agent-delegation.js';
|
|
13
|
+
import { buildTaskRuntimeEnv } from './task-context.js';
|
|
14
|
+
const AS_SESSION_FLAG = '--as-session';
|
|
15
|
+
function formatTimeAgo(ms) {
|
|
16
|
+
const s = Math.floor(ms / 1000);
|
|
17
|
+
if (s < 60)
|
|
18
|
+
return `${s}秒前`;
|
|
19
|
+
const m = Math.floor(s / 60);
|
|
20
|
+
if (m < 60)
|
|
21
|
+
return `${m}分钟前`;
|
|
22
|
+
const h = Math.floor(m / 60);
|
|
23
|
+
if (h < 24)
|
|
24
|
+
return `${h}小时前`;
|
|
25
|
+
return `${Math.floor(h / 24)}天前`;
|
|
26
|
+
}
|
|
27
|
+
function listAvailableSessions() {
|
|
28
|
+
const dir = debugSessionsDir();
|
|
29
|
+
if (!fs.existsSync(dir))
|
|
30
|
+
return { sessions: [], dirExists: false };
|
|
31
|
+
try {
|
|
32
|
+
const sessions = fs.readdirSync(dir)
|
|
33
|
+
.filter(f => f.endsWith('.json'))
|
|
34
|
+
.map(f => {
|
|
35
|
+
try {
|
|
36
|
+
return JSON.parse(fs.readFileSync(path.join(dir, f), 'utf-8'));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
.filter((s) => s !== null && !!s.sessionId)
|
|
43
|
+
.sort((a, b) => b.writtenAt - a.writtenAt)
|
|
44
|
+
.slice(0, 20);
|
|
45
|
+
return { sessions, dirExists: true };
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return { sessions: [], dirExists: true };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function printSessionList(result) {
|
|
52
|
+
const { sessions, dirExists } = result;
|
|
53
|
+
if (!dirExists) {
|
|
54
|
+
console.error('❌ 调试模式未启用。请先执行:ec start --debug');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (sessions.length === 0) {
|
|
58
|
+
console.error('ℹ️ 调试模式已启用,但暂无可用会话。');
|
|
59
|
+
console.error(' 请等待 agent 收到至少一条消息后再试。');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
console.error('\n可用会话(最近 20 个):');
|
|
63
|
+
for (const s of sessions) {
|
|
64
|
+
const age = formatTimeAgo(Date.now() - s.writtenAt);
|
|
65
|
+
console.error(` ${s.sessionId} ${s.selfAid} → ${s.channelId} ${age}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* 检测命令行参数中是否包含 --as-session,若有则执行调试路径:
|
|
70
|
+
* 1. 互斥检查(托管会话中拒绝)
|
|
71
|
+
* 2. 读临时文件
|
|
72
|
+
* 3. 调 debug-issue-token IPC 现取 token
|
|
73
|
+
* 4. 注入 process.env,后续命令走统一托管路径
|
|
74
|
+
*
|
|
75
|
+
* 不带 --as-session 时直接返回,不做任何事。
|
|
76
|
+
*/
|
|
77
|
+
export async function resolveDebugContext(args) {
|
|
78
|
+
const flagIdx = args.indexOf(AS_SESSION_FLAG);
|
|
79
|
+
if (flagIdx === -1)
|
|
80
|
+
return;
|
|
81
|
+
// 互斥检查:托管会话里不允许 --as-session
|
|
82
|
+
if (process.env.EVOLCORE_SESSION_ID) {
|
|
83
|
+
console.error('❌ --as-session 仅限外部终端使用,托管会话中不可用');
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
const sessionId = args[flagIdx + 1];
|
|
87
|
+
// 不带 sessionId 或 sessionId 以 - 开头(下一个 flag)
|
|
88
|
+
if (!sessionId || sessionId.startsWith('-')) {
|
|
89
|
+
console.error('❌ --as-session 需要指定 sessionId\n');
|
|
90
|
+
console.error(`使用:ec <命令> --as-session <sessionId>`);
|
|
91
|
+
printSessionList(listAvailableSessions());
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9_.-]*$/.test(sessionId)) {
|
|
95
|
+
console.error('❌ 无效 sessionId');
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
// 读临时文件(session bind 时已写入)
|
|
99
|
+
const snapshotPath = path.join(debugSessionsDir(), `${sessionId}.json`);
|
|
100
|
+
if (!fs.existsSync(snapshotPath)) {
|
|
101
|
+
const result = listAvailableSessions();
|
|
102
|
+
if (!result.dirExists) {
|
|
103
|
+
console.error('❌ 调试模式未启用。请先执行:ec start --debug');
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
console.error(`❌ 调试会话不存在:${sessionId}\n`);
|
|
107
|
+
printSessionList(result);
|
|
108
|
+
}
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
// 调 debug-issue-token IPC 现取 token
|
|
112
|
+
let response;
|
|
113
|
+
try {
|
|
114
|
+
response = await ipcQuery(resolvePaths().socket, { type: 'debug-issue-token', sessionId }, 5000);
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
console.error(`❌ 无法连接 daemon:${err instanceof Error ? err.message : String(err)}`);
|
|
118
|
+
console.error('请确认 daemon 正在以 debug 模式运行:ec start --debug');
|
|
119
|
+
process.exit(1);
|
|
120
|
+
}
|
|
121
|
+
if (!response) {
|
|
122
|
+
console.error('❌ daemon 无响应,请确认 daemon 正在以 debug 模式运行:ec start --debug');
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
if (!response.ok) {
|
|
126
|
+
console.error(`❌ 无法获取调试 token:${response.error}`);
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
const { token, runtimeContext } = response;
|
|
130
|
+
// 注入 process.env,后续代码走统一托管路径
|
|
131
|
+
// 注意:去掉 daemonRuntimeEpoch——debug session 不是真实任务,
|
|
132
|
+
// 不应该受 ipc.ts 里的 daemon epoch 检查约束,否则 msg send --thread 后续命令会报
|
|
133
|
+
// "The task delegation token belongs to a previous daemon runtime"
|
|
134
|
+
const ctxWithoutEpoch = { ...runtimeContext, daemonRuntimeEpoch: undefined };
|
|
135
|
+
Object.assign(process.env, buildTaskRuntimeEnv(ctxWithoutEpoch));
|
|
136
|
+
process.env[AGENT_DELEGATION_TOKEN_ENV] = token;
|
|
137
|
+
// thread 命令从 EVOLCORE_SELF_AID 读 selfAid(不走 taskRuntimeContext),单独注入
|
|
138
|
+
if (runtimeContext.selfAid)
|
|
139
|
+
process.env.EVOLCORE_SELF_AID = runtimeContext.selfAid;
|
|
140
|
+
}
|
|
141
|
+
/** 从 args 中去掉 --as-session <sessionId> 两个元素,返回净化后的参数列表 */
|
|
142
|
+
export function stripAsSessionArgs(args) {
|
|
143
|
+
const result = [];
|
|
144
|
+
let i = 0;
|
|
145
|
+
while (i < args.length) {
|
|
146
|
+
if (args[i] === AS_SESSION_FLAG) {
|
|
147
|
+
i += 2; // 跳过 flag 和 sessionId
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
result.push(args[i++]);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return result;
|
|
154
|
+
}
|
package/dist/cli/diag.js
CHANGED
|
@@ -8,11 +8,11 @@ export async function cmdDiag(args) {
|
|
|
8
8
|
console.log('用法:ec diag <问题描述> [--owner <daemonOwner-aid>] [--format json]\n ec diag stop [--format json]\n未指定 --owner 时联系本机 daemon.json.owners[0];有效诊断期间再次执行会追加到原 case。');
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
|
+
const argv = ['diag', ...args];
|
|
11
12
|
const json = args.at(-2) === '--format' && args.at(-1) === 'json';
|
|
12
|
-
const argv = json ? args.slice(0, -2) : args;
|
|
13
13
|
let result;
|
|
14
14
|
try {
|
|
15
|
-
parseDiagArgs(
|
|
15
|
+
parseDiagArgs(args);
|
|
16
16
|
result = await ipcQuery(resolvePaths().socket, {
|
|
17
17
|
type: 'diag', argv,
|
|
18
18
|
...(process.env.EVOLCORE_SESSION_ID ? {
|
|
@@ -6,6 +6,7 @@ import { HANDOFF_ID_RE } from '../core/handoff/store.js';
|
|
|
6
6
|
import { isHelpFlag, wantsHelp } from './help.js';
|
|
7
7
|
import { readDelegationCredential } from '../core/auth/agent-delegation.js';
|
|
8
8
|
import { canonicalizeEvolcoreCommandArgv } from '../core/permission/ec-command-parser.js';
|
|
9
|
+
import { MAIN_CLI_BIN } from '../product.js';
|
|
9
10
|
function parseLimit(value) {
|
|
10
11
|
const limit = Number(value);
|
|
11
12
|
if (!value || !Number.isInteger(limit) || limit < 1 || limit > HANDOFF_QUERY_MAX_LIMIT) {
|
|
@@ -70,8 +71,9 @@ export function parseTrace(args) {
|
|
|
70
71
|
}
|
|
71
72
|
return parsed;
|
|
72
73
|
}
|
|
73
|
-
export function parseReturn(args) {
|
|
74
|
-
|
|
74
|
+
export function parseReturn(args, options = {}) {
|
|
75
|
+
if (!options.canonical)
|
|
76
|
+
args = canonicalizeEvolcoreCommandArgv([MAIN_CLI_BIN, 'handoff', 'return', ...args]).slice(3);
|
|
75
77
|
const dash = args.indexOf('--');
|
|
76
78
|
if (dash >= 0) {
|
|
77
79
|
const beforeDash = args.slice(0, dash);
|
|
@@ -96,8 +98,10 @@ export function parseReturn(args) {
|
|
|
96
98
|
if (filePath && contentArgs.length > 0)
|
|
97
99
|
throw new Error('HANDOFF_CONTENT_FILE_CONFLICT');
|
|
98
100
|
if (filePath) {
|
|
101
|
+
if (options.deferFileRead)
|
|
102
|
+
return { handoffId, content: '' };
|
|
99
103
|
try {
|
|
100
|
-
return { handoffId, content: fs.readFileSync(filePath, 'utf8') };
|
|
104
|
+
return { handoffId, content: options.readFile ? options.readFile(filePath) : fs.readFileSync(filePath, 'utf8') };
|
|
101
105
|
}
|
|
102
106
|
catch {
|
|
103
107
|
throw new Error('HANDOFF_CONTENT_FILE_READ_FAILED');
|
|
@@ -153,10 +157,14 @@ function formatTimestamp(value) {
|
|
|
153
157
|
return new Date(value).toISOString();
|
|
154
158
|
}
|
|
155
159
|
export async function cmdHandoff(args) {
|
|
160
|
+
args = canonicalizeEvolcoreCommandArgv([MAIN_CLI_BIN, 'handoff', ...args]).slice(2);
|
|
156
161
|
const sub = args[0];
|
|
157
162
|
if (!sub || isHelpFlag(sub) || wantsHelp(args)) {
|
|
158
163
|
console.log(`用法: ec handoff <command> [args]
|
|
159
164
|
|
|
165
|
+
⚠ ec handoff 已废弃,请改用话题链(ec thread + ec msg send --thread)。
|
|
166
|
+
本命令保留以兼容现有脚本,将在 P2 后续版本中移除。
|
|
167
|
+
|
|
160
168
|
Commands:
|
|
161
169
|
return [handoff-id] [content] 提交一个回流结果;required 可用同一 ID 追加多个结果
|
|
162
170
|
return [handoff-id] --text-from-file <path>
|
|
@@ -170,7 +178,7 @@ Commands:
|
|
|
170
178
|
if (sub === 'return') {
|
|
171
179
|
let parsed;
|
|
172
180
|
try {
|
|
173
|
-
parsed = parseReturn(args.slice(1));
|
|
181
|
+
parsed = parseReturn(args.slice(1), { canonical: true, deferFileRead: !!process.env.EVOLCORE_SESSION_ID });
|
|
174
182
|
}
|
|
175
183
|
catch (error) {
|
|
176
184
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -185,6 +193,7 @@ Commands:
|
|
|
185
193
|
}
|
|
186
194
|
const result = await ipcQuery(resolvePaths().socket, {
|
|
187
195
|
type: 'handoff-return',
|
|
196
|
+
argv: ['handoff', ...args],
|
|
188
197
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
189
198
|
handoffId: parsed.handoffId,
|
|
190
199
|
content: parsed.content,
|
|
@@ -201,7 +210,7 @@ Commands:
|
|
|
201
210
|
if (sub === 'recover-return') {
|
|
202
211
|
let parsed;
|
|
203
212
|
try {
|
|
204
|
-
parsed = parseReturn(args.slice(1));
|
|
213
|
+
parsed = parseReturn(args.slice(1), { canonical: true, deferFileRead: !!process.env.EVOLCORE_SESSION_ID });
|
|
205
214
|
}
|
|
206
215
|
catch (error) {
|
|
207
216
|
console.error(`✗ ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -215,6 +224,7 @@ Commands:
|
|
|
215
224
|
}
|
|
216
225
|
const result = await ipcQuery(resolvePaths().socket, {
|
|
217
226
|
type: 'handoff-recover-return',
|
|
227
|
+
argv: ['handoff', ...args],
|
|
218
228
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
219
229
|
handoffId: parsed.handoffId,
|
|
220
230
|
content: parsed.content,
|
|
@@ -237,6 +247,7 @@ Commands:
|
|
|
237
247
|
}
|
|
238
248
|
const result = await ipcQuery(resolvePaths().socket, {
|
|
239
249
|
type: 'handoff-status', sessionId: process.env.EVOLCORE_SESSION_ID, handoffId,
|
|
250
|
+
argv: ['handoff', ...args],
|
|
240
251
|
delegationToken: readDelegationCredential(),
|
|
241
252
|
}, 5000);
|
|
242
253
|
if (!result) {
|
|
@@ -264,6 +275,7 @@ Commands:
|
|
|
264
275
|
}
|
|
265
276
|
const result = await ipcQuery(resolvePaths().socket, {
|
|
266
277
|
type: 'handoff-list',
|
|
278
|
+
argv: ['handoff', ...args],
|
|
267
279
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
268
280
|
agent: parsed.agent,
|
|
269
281
|
state: parsed.state,
|
|
@@ -308,6 +320,7 @@ Commands:
|
|
|
308
320
|
}
|
|
309
321
|
const result = await ipcQuery(resolvePaths().socket, {
|
|
310
322
|
type: 'handoff-trace',
|
|
323
|
+
argv: ['handoff', ...args],
|
|
311
324
|
sessionId: process.env.EVOLCORE_SESSION_ID,
|
|
312
325
|
agent: parsed.agent,
|
|
313
326
|
handoffId: parsed.handoffId,
|