evolcore 0.0.32 → 0.0.34
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 +61 -0
- package/bin/ec.js +3 -2
- package/bin/install-codex-managed-hooks.mjs +135 -37
- package/dist/agents/baseagent-availability.js +20 -36
- package/dist/agents/claude-runner.js +111 -15
- package/dist/agents/codex/app-server-client.js +3 -0
- package/dist/agents/codex/diagnostics.js +112 -54
- package/dist/agents/codex-runner.js +241 -63
- package/dist/agents/ecagent-runner.js +78 -33
- package/dist/agents/runner-types.js +5 -6
- package/dist/aun/aid/identity.js +1 -1
- package/dist/aun/group/operations.js +0 -1
- package/dist/aun/msg/history.js +1 -0
- package/dist/aun/msg/p2p.js +0 -1
- package/dist/aun/outbox.js +50 -1
- package/dist/channels/aun.js +44 -8
- package/dist/channels/daemon.js +261 -3
- package/dist/cli/agent-command.js +58 -24
- package/dist/cli/agent.js +1 -1
- package/dist/cli/aun-commands.js +368 -31
- package/dist/cli/contact.js +8 -2
- package/dist/cli/ctl-command.js +3 -1
- package/dist/cli/daemon-commands.js +197 -27
- package/dist/cli/debug-mode.js +154 -0
- package/dist/cli/fs-command.js +2 -1
- package/dist/cli/handoff-command.js +3 -0
- package/dist/cli/index.js +98 -67
- package/dist/cli/init.js +2 -2
- package/dist/cli/integrity-command.js +196 -0
- package/dist/cli/managed-command-guard.js +5 -0
- package/dist/cli/memory-command.js +166 -146
- package/dist/cli/queue-command.js +9 -4
- package/dist/cli/session-command.js +194 -0
- package/dist/cli/skill-command.js +78 -2
- package/dist/cli/task-context.js +1 -0
- package/dist/cli/thread-command.js +622 -0
- package/dist/cli/trigger-command.js +10 -3
- package/dist/config/builtin-roles.js +1 -0
- package/dist/config/config-field-policy.js +6 -3
- package/dist/config/config-manager.js +26 -2
- package/dist/config/contact-book-store.js +5 -0
- package/dist/config/resolved-config-op.js +3 -0
- package/dist/config/role-service.js +13 -0
- package/dist/config/runtime-env.js +16 -0
- package/dist/config-store.js +45 -0
- package/dist/core/audit/log-integrity.js +3 -1
- package/dist/core/auth/agent-delegation.js +133 -36
- package/dist/core/auth/debug-context.js +139 -0
- package/dist/core/auth/delegation-diagnostics.js +414 -0
- package/dist/core/auth/operation-authorizer.js +25 -2
- package/dist/core/auth/operation-catalog.js +49 -0
- 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/agent-control.js +18 -26
- package/dist/core/command/command-handler.js +197 -27
- package/dist/core/command/daemon-diagnostics.js +1 -0
- package/dist/core/command/memory-slash.js +6 -2
- package/dist/core/command/menu-catalog.js +51 -1
- package/dist/core/command/menu-handler.js +114 -23
- package/dist/core/command/menu-protocol.js +25 -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 +195 -13
- package/dist/core/command/topic-slash.js +528 -0
- package/dist/core/daemon-bootstrap.js +4 -7
- package/dist/core/evolagent-registry.js +20 -5
- package/dist/core/file-integrity/read.js +61 -0
- package/dist/core/file-integrity/store.js +262 -0
- package/dist/core/handoff/runtime.js +5 -11
- package/dist/core/handoff/store.js +5 -0
- package/dist/core/ipc-registration.js +175 -3
- package/dist/core/memory/batch-meta.js +132 -0
- package/dist/core/memory/consolidation-context.js +83 -29
- package/dist/core/memory/consolidation-ops-records.js +49 -16
- package/dist/core/memory/consolidation-queue-format.js +21 -0
- package/dist/core/memory/consolidation.js +264 -205
- package/dist/core/memory/index-manager.js +19 -28
- package/dist/core/memory/memory-admin.js +19 -14
- package/dist/core/memory/memory-document.js +53 -9
- package/dist/core/memory/memory-writer.js +30 -15
- package/dist/core/message/aun-ipc-sender.js +161 -6
- package/dist/core/message/im-renderer.js +169 -10
- package/dist/core/message/message-bridge.js +15 -4
- package/dist/core/message/message-log.js +1 -0
- package/dist/core/message/peer-mode.js +6 -1
- package/dist/core/message/response-engine.js +929 -110
- 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 +217 -9
- package/dist/core/permission/protected-paths.js +5 -1
- package/dist/core/permission/readonly-shell-query.js +43 -5
- package/dist/core/permission/session-path-grants.js +334 -0
- package/dist/core/permission/tool-canonical.js +226 -0
- package/dist/core/permission/tool-policy.js +30 -62
- package/dist/core/role/runtime-policy.js +21 -10
- package/dist/core/session/session-fs-store.js +123 -8
- package/dist/core/session/session-idle-monitor.js +249 -22
- package/dist/core/session/session-manager.js +129 -14
- package/dist/core/skill/command-parser.js +13 -0
- package/dist/core/skill/index-generator.js +21 -4
- package/dist/core/skill/startup.js +41 -0
- package/dist/core/skill/switch-resolver.js +55 -29
- package/dist/core/system-session/grants.js +40 -0
- package/dist/core/system-session/memory.js +222 -0
- package/dist/core/system-session/registry.js +74 -0
- package/dist/core/system-session/types.js +14 -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 +770 -0
- package/dist/core/thread/types.js +1 -0
- package/dist/eck/kit-renderer.js +7 -2
- package/dist/eck/manifest-engine.js +24 -4
- package/dist/eck/message-renderer.js +35 -0
- package/dist/index.js +19 -7
- package/dist/ipc.js +140 -50
- package/dist/paths.js +93 -0
- package/dist/response-system/engines/v1/proactive-flow.js +169 -80
- package/dist/stats/billing.js +20 -8
- package/dist/trigger/authorization.js +57 -28
- package/dist/trigger/feedback.js +13 -2
- package/dist/trigger/parser.js +70 -1
- package/dist/trigger/system-definitions.js +3 -3
- package/dist/trigger/validation.js +14 -0
- package/dist/utils/cross-platform.js +11 -2
- package/dist/utils/error-dict.json +18 -4
- package/dist/utils/error-utils.js +143 -1
- package/dist/utils/instance-registry.js +13 -8
- package/dist/utils/log-writer.js +12 -0
- package/dist/utils/process-introspect.js +11 -0
- package/kits/docs/context-assembly.md +1 -1
- package/kits/docs/evolcore/INDEX.md +1 -0
- package/kits/docs/evolcore/agent-create.md +40 -28
- package/kits/docs/evolcore/agent.md +21 -6
- package/kits/docs/evolcore/config.md +2 -2
- package/kits/docs/evolcore/ctl.md +2 -2
- package/kits/docs/evolcore/ec-capabilities.md +5 -1
- package/kits/docs/evolcore/fs-architecture.md +4 -5
- package/kits/docs/evolcore/fs.md +1 -1
- package/kits/docs/evolcore/group-collaboration.md +4 -6
- package/kits/docs/evolcore/group.md +11 -12
- package/kits/docs/evolcore/memory-architecture.md +4 -5
- package/kits/docs/evolcore/memory-consolidation.md +19 -15
- package/kits/docs/evolcore/memory-tags.md +3 -1
- package/kits/docs/evolcore/memory.md +24 -12
- package/kits/docs/evolcore/menu-exec-schema-commands.md +2 -2
- package/kits/docs/evolcore/menu-protocol.md +7 -0
- package/kits/docs/evolcore/model.md +16 -0
- package/kits/docs/evolcore/msg.md +8 -11
- package/kits/docs/evolcore/thread-chain.md +267 -0
- package/kits/docs/prompt-loading-architecture.md +1 -1
- package/kits/eck_manifest.json +55 -40
- package/kits/eck_manifest.memory.json +0 -12
- package/kits/eck_message_manifest.json +169 -10
- package/kits/rules/01-overview.md +11 -0
- package/kits/rules/03-identity.md +6 -3
- package/kits/rules/05-venue.md +1 -1
- package/kits/rules/06-channel.md +1 -1
- package/kits/rules/07-memory-and-thread.md +199 -0
- package/kits/schemas/_meta.json +7 -1
- package/kits/schemas/agent-config.schema.13.json +1 -1
- package/kits/schemas/daemon.schema.7.json +140 -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 +16 -2
- package/kits/skills/ec-skill/scripts/skill.mjs +1 -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 +7 -2
- package/kits/templates/memory-consolidation/generalize.md +9 -4
- package/kits/templates/memory-consolidation/notes.md +11 -11
- package/kits/templates/memory-consolidation/profile.md +8 -3
- package/kits/templates/memory-consolidation/promote.md +8 -3
- package/kits/templates/memory-consolidation/workflow.md +6 -6
- package/kits/templates/message-fragments/handoff-request-to-target.md +1 -1
- 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 +67 -72
- package/kits/templates/system-fragments/channel.md +3 -6
- package/kits/templates/system-fragments/commands.md +1 -0
- package/kits/templates/system-fragments/managed-runtime.md +15 -0
- package/kits/templates/system-fragments/memory.md +16 -9
- package/kits/templates/system-fragments/reply.md +7 -6
- package/kits/templates/system-fragments/session.md +5 -14
- package/package.json +6 -3
- package/dist/core/memory/memory-session-policy.js +0 -41
- package/dist/core/memory/memory-signature.js +0 -257
- 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
|
@@ -4,7 +4,7 @@ import os from 'os';
|
|
|
4
4
|
import { spawn, execFile } from 'child_process';
|
|
5
5
|
import { promisify } from 'util';
|
|
6
6
|
import readline from 'readline';
|
|
7
|
-
import { resolveRoot, resolvePaths, ensureDataDirs, getPackageRoot, agentMdPath } from '../paths.js';
|
|
7
|
+
import { resolveRoot, resolvePaths, ensureDataDirs, getPackageRoot, agentMdPath, asModeOverridePath } from '../paths.js';
|
|
8
8
|
import { loadDefaults, loadAllAgents, loadDaemonConfig, saveDaemonConfig } from '../config-store.js';
|
|
9
9
|
import { resolveEffective } from '../config/config-manager.js';
|
|
10
10
|
import { resolveAnthropicConfig } from '../agents/baseagent.js';
|
|
@@ -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 {
|
|
@@ -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) {
|
|
@@ -419,7 +458,73 @@ function resolveRunningDuration(pid, uptime) {
|
|
|
419
458
|
const instance = scanInstances().mains.find(entry => entry.alive && entry.record.pid === pid);
|
|
420
459
|
return instance ? formatRunningDuration(Date.now() - instance.record.startedAt) : '未知';
|
|
421
460
|
}
|
|
422
|
-
|
|
461
|
+
/**
|
|
462
|
+
* 渲染"运行模式"那一行。
|
|
463
|
+
*
|
|
464
|
+
* `daemonMode` 有值时用 daemon 实例记录里的模式(`ec status` 看的是正在跑的进程);
|
|
465
|
+
* 没有时按当前进程判断(`ec start` 时就是这一份 CLI 即将拉起的模式)。
|
|
466
|
+
*/
|
|
467
|
+
/**
|
|
468
|
+
* CLI 侧按包路径判断模式。**不能用 isDevMode()**:它首次求值会读走并删除
|
|
469
|
+
* `--as-mode` 覆盖文件,那份文件只该由 daemon 消费。
|
|
470
|
+
*/
|
|
471
|
+
function packageIsDevMode() {
|
|
472
|
+
return !getPackageRoot().includes('node_modules');
|
|
473
|
+
}
|
|
474
|
+
export function describeRunMode(daemonMode, cliIsDevMode = packageIsDevMode()) {
|
|
475
|
+
const effective = daemonMode ?? (cliIsDevMode ? 'dev' : 'install');
|
|
476
|
+
const label = effective === 'install' ? '安装模式' : '开发模式';
|
|
477
|
+
const note = effective === 'install'
|
|
478
|
+
? '(校验随包文件,篡改自动恢复)'
|
|
479
|
+
: '(不校验随包文件,可随意改动)';
|
|
480
|
+
return `运行模式: ${label}${note}`;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* 把本次 `--as-mode` 写进一次性覆盖文件,daemon 启动时读走并删除。
|
|
484
|
+
*
|
|
485
|
+
* 不走环境变量:环境变量会被 `ec restart` 全量继承,模式会在操作者不知情的
|
|
486
|
+
* 情况下被带到新进程。文件是一次性的,daemon 读过即删;若 daemon 最终没起来,
|
|
487
|
+
* 文件还留着,会在下一次启动时被读到——所以启动真实失败时此处清理。
|
|
488
|
+
*/
|
|
489
|
+
function writeAsModeOverride(asMode) {
|
|
490
|
+
const file = asModeOverridePath();
|
|
491
|
+
if (!asMode) {
|
|
492
|
+
// 没带 --as-mode:清掉上次失败启动可能残留的文件,保证这次按包路径判断
|
|
493
|
+
clearAsModeOverride(file);
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
497
|
+
fs.writeFileSync(file, `${asMode}\n`, 'utf-8');
|
|
498
|
+
return file;
|
|
499
|
+
}
|
|
500
|
+
function clearAsModeOverride(file) {
|
|
501
|
+
if (!file)
|
|
502
|
+
return;
|
|
503
|
+
try {
|
|
504
|
+
fs.rmSync(file, { force: true });
|
|
505
|
+
}
|
|
506
|
+
catch { /* ignore */ }
|
|
507
|
+
}
|
|
508
|
+
/** daemon 已在运行时 `--as-mode` 不会生效,明说,别让人以为切过去了。 */
|
|
509
|
+
function warnAsModeNotApplied(asMode) {
|
|
510
|
+
if (!asMode)
|
|
511
|
+
return;
|
|
512
|
+
console.log(` ⚠ --as-mode ${asMode} 未生效:daemon 已在运行,模式只在启动时确定。`);
|
|
513
|
+
console.log(` 需要切换请先 ec stop,再 ec start --as-mode ${asMode}。`);
|
|
514
|
+
}
|
|
515
|
+
function printAsModeNotice(asMode) {
|
|
516
|
+
if (!asMode)
|
|
517
|
+
return;
|
|
518
|
+
console.log('');
|
|
519
|
+
console.log(`🧪 本次运行模式已设为${asMode === 'install' ? '安装模式' : '开发模式'}(ec start --as-mode ${asMode})`);
|
|
520
|
+
if (asMode === 'install') {
|
|
521
|
+
console.log(' 随包发布的 kits/技能文件将按台账校验,带外改动会被自动恢复。');
|
|
522
|
+
console.log(' 开发仓里请勿长期使用:本机 kits 文件会被登记进真实台账,');
|
|
523
|
+
console.log(' 之后再按开发模式修改它们,会在下次以安装模式启动时被回滚。');
|
|
524
|
+
}
|
|
525
|
+
console.log(' 只影响这一次启动;ec restart 不带该参数,会恢复按包路径判断。');
|
|
526
|
+
}
|
|
527
|
+
function printStartupInfo(opts = {}, asMode) {
|
|
423
528
|
const pkgRoot = getPackageRoot();
|
|
424
529
|
const isNpmInstall = pkgRoot.includes('node_modules');
|
|
425
530
|
const cliRunsSource = !import.meta.url.includes('/dist/');
|
|
@@ -463,25 +568,33 @@ function printStartupInfo(opts = {}) {
|
|
|
463
568
|
console.log(`${prefix}${version}${pidPart}${aunPart}`);
|
|
464
569
|
console.log(` 包路径: ${pkgRoot}`);
|
|
465
570
|
console.log(` 安装类型: ${isNpmInstall ? 'npm全局安装' : '开发仓(link)'}`);
|
|
571
|
+
// asMode 只是"本次请求",是否生效要看 daemon 是否真的由这次启动拉起,标清楚别和实际模式混淆
|
|
572
|
+
const modeLine = describeRunMode(opts.runMode ?? asMode, !isNpmInstall);
|
|
573
|
+
console.log(` ${asMode && !opts.runMode ? `${modeLine}(--as-mode 请求)` : modeLine}`);
|
|
466
574
|
console.log(` CLI执行: ${cliRunsSource ? '源码(tsx)' : '编译产物(dist)'}`);
|
|
467
575
|
console.log(` Daemon执行: ${daemonRunsDist ? '编译产物(dist)' : '未知'}`);
|
|
468
576
|
console.log(` 代码时间: ${latestMtime ? formatLocalTime(latestMtime) : '?'}`);
|
|
469
577
|
}
|
|
470
578
|
export async function cmdStart(opts = {}) {
|
|
471
|
-
|
|
472
|
-
|
|
579
|
+
// Measure from process start so the reported time includes CLI bootstrap
|
|
580
|
+
// (tsx compilation in a dev checkout), which is what the operator waits for.
|
|
581
|
+
const cmdStartedAt = Math.min(Date.now(), Math.round(performance.timeOrigin));
|
|
582
|
+
printStartupInfo(undefined, opts.asMode);
|
|
473
583
|
const p = resolvePaths();
|
|
474
584
|
const existingDaemon = await probeDaemon(p.socket);
|
|
475
585
|
if (existingDaemon) {
|
|
476
586
|
let hookRepaired = false;
|
|
477
|
-
if (!ensureCodexHookBeforeLifecycle(() => { hookRepaired = true; }))
|
|
587
|
+
if (!await ensureCodexHookBeforeLifecycle(() => { hookRepaired = true; }))
|
|
478
588
|
return;
|
|
479
589
|
if (hookRepaired) {
|
|
480
|
-
console.log('🔄 Codex
|
|
590
|
+
console.log('🔄 Codex 运行组件已修复,正在自动重启服务以加载策略...');
|
|
481
591
|
await cmdRestart({ diagnose: opts.diagnose });
|
|
482
592
|
return;
|
|
483
593
|
}
|
|
484
594
|
console.log(` EvolCore is already running (PID: ${existingDaemon.pid}, IPC reachable)`);
|
|
595
|
+
const runningRecord = scanInstances().mains.find(m => m.alive && m.record.pid === existingDaemon.pid)?.record;
|
|
596
|
+
console.log(` 当前 daemon ${describeRunMode(runningRecord?.runMode)}`);
|
|
597
|
+
warnAsModeNotApplied(opts.asMode);
|
|
485
598
|
console.log(` 已在运行;已运行时长: ${resolveRunningDuration(existingDaemon.pid, existingDaemon.uptime)};部署/脚本可直接复用当前实例`);
|
|
486
599
|
return;
|
|
487
600
|
}
|
|
@@ -524,7 +637,7 @@ export async function cmdStart(opts = {}) {
|
|
|
524
637
|
// The initialization path can create the first Codex agent, so perform the
|
|
525
638
|
// machine-hook check after config migration/auto-init and before any daemon
|
|
526
639
|
// process is launched.
|
|
527
|
-
if (!ensureCodexHookBeforeLifecycle())
|
|
640
|
+
if (!await ensureCodexHookBeforeLifecycle())
|
|
528
641
|
return;
|
|
529
642
|
// 控制 AID 门禁:缺 aid 且交互式 → 只补全控制 AID + owners(不重走 baseagent 向导)。
|
|
530
643
|
// 非 TTY(restart-monitor/systemd/管道)不补全(无法交互),只提示后继续启动,daemon 侧 warn 兜底。
|
|
@@ -582,6 +695,8 @@ export async function cmdStart(opts = {}) {
|
|
|
582
695
|
console.log(` EvolCore is already running (PID: ${aliveMains.map(m => m.record.pid).join(', ')})`);
|
|
583
696
|
console.log(` 启动于: ${new Date(first.record.startedAtIso).toLocaleString()}`);
|
|
584
697
|
console.log(` 启动方式: ${first.record.launchedBy}`);
|
|
698
|
+
console.log(` 当前 daemon ${describeRunMode(first.record.runMode)}`);
|
|
699
|
+
warnAsModeNotApplied(opts.asMode);
|
|
585
700
|
// 报告 AID 状态
|
|
586
701
|
if (status.aidLastActivity.size > 0) {
|
|
587
702
|
console.log(' AID 状态:');
|
|
@@ -608,7 +723,9 @@ export async function cmdStart(opts = {}) {
|
|
|
608
723
|
// On Windows/macOS the process environment may be unavailable, so an
|
|
609
724
|
// unregistered process from this package is conservatively treated as a
|
|
610
725
|
// blocker when its HOME cannot be identified.
|
|
611
|
-
|
|
726
|
+
// No live main reached this point, so the registry snapshot above is still
|
|
727
|
+
// the authoritative "known PID" set; avoid a second scan.
|
|
728
|
+
const orphans = findOrphanProcesses(status);
|
|
612
729
|
const blockingOrphans = orphans.filter(o => isRuntimeOrphan(o));
|
|
613
730
|
if (blockingOrphans.length > 0) {
|
|
614
731
|
console.error(`❌ 检测到未登记的 EvolCore 进程(PID: ${blockingOrphans.map(o => o.pid).join(', ')}),已停止启动以避免重复连接 AUN。`);
|
|
@@ -619,10 +736,13 @@ export async function cmdStart(opts = {}) {
|
|
|
619
736
|
reportOrphans(orphans);
|
|
620
737
|
if (versionInfo.some(result => result.hasUpdate)) {
|
|
621
738
|
cleanEnv();
|
|
739
|
+
// 这条路由 restart-monitor 拉起 daemon,同样靠覆盖文件把 --as-mode 带过去
|
|
740
|
+
const overrideFile = writeAsModeOverride(opts.asMode);
|
|
622
741
|
const launched = await launchPackageLifecycle('start', console.log, {
|
|
623
742
|
prepared: true, foreground: opts.foreground, env: buildDaemonEnv(p, opts),
|
|
624
743
|
});
|
|
625
744
|
if (!launched.ok) {
|
|
745
|
+
clearAsModeOverride(overrideFile);
|
|
626
746
|
console.error(`❌ 启动事务未能建立:${launched.reason}`);
|
|
627
747
|
process.exitCode = 1;
|
|
628
748
|
}
|
|
@@ -645,6 +765,7 @@ export async function cmdStart(opts = {}) {
|
|
|
645
765
|
const appMain = path.join(getPackageRoot(), 'dist', 'index.js');
|
|
646
766
|
const daemonEnv = buildDaemonEnv(p, opts);
|
|
647
767
|
if (opts.foreground) {
|
|
768
|
+
const overrideFile = writeAsModeOverride(opts.asMode);
|
|
648
769
|
const child = spawn('node', ['--no-warnings=ExperimentalWarning', appMain], {
|
|
649
770
|
detached: false,
|
|
650
771
|
stdio: 'inherit',
|
|
@@ -653,6 +774,7 @@ export async function cmdStart(opts = {}) {
|
|
|
653
774
|
});
|
|
654
775
|
const childPid = child.pid;
|
|
655
776
|
if (!childPid) {
|
|
777
|
+
clearAsModeOverride(overrideFile);
|
|
656
778
|
console.error('❌ Failed to start EvolCore (process creation failed)');
|
|
657
779
|
process.exit(1);
|
|
658
780
|
return;
|
|
@@ -666,6 +788,22 @@ export async function cmdStart(opts = {}) {
|
|
|
666
788
|
console.log(` EVOLCORE_HOME: ${resolveRoot()}`);
|
|
667
789
|
console.log(` Logs: ${p.logs}/`);
|
|
668
790
|
console.log(`⏱ ready in ${((Date.now() - cmdStartedAt) / 1000).toFixed(1)}s`);
|
|
791
|
+
if (opts.debug) {
|
|
792
|
+
console.log('');
|
|
793
|
+
console.log('🔧 调试模式已启用(EVOLCORE_DEBUG_MODE=1)');
|
|
794
|
+
console.log(' 在宿主终端以任意 session 身份执行命令:');
|
|
795
|
+
console.log('');
|
|
796
|
+
console.log(` ec msg send '<消息内容>' --as-session <sessionId>`);
|
|
797
|
+
console.log(' ec trigger list --as-session <sessionId>');
|
|
798
|
+
console.log(' ec memory list --as-session <sessionId>');
|
|
799
|
+
console.log('');
|
|
800
|
+
console.log(' 查看可用会话(运行后将在此处列出):');
|
|
801
|
+
console.log(` ec msg send 'test' --as-session # 不带 sessionId 自动列出`);
|
|
802
|
+
console.log('');
|
|
803
|
+
console.log(' 注意:重启 daemon(ec restart)会清除调试模式,');
|
|
804
|
+
console.log(' 需重新执行 ec start --debug 才能恢复。');
|
|
805
|
+
}
|
|
806
|
+
printAsModeNotice(opts.asMode);
|
|
669
807
|
void waitForExistingEcweb(p).then((ecweb) => {
|
|
670
808
|
if (shouldPrintNoSelfAgentHints) {
|
|
671
809
|
printNoSelfAgentHints({ daemonConfig: loadDaemonConfig(), ecwebStarted: ecweb !== null, skipped });
|
|
@@ -712,6 +850,7 @@ export async function cmdStart(opts = {}) {
|
|
|
712
850
|
const stdoutLog = path.join(p.logs, 'stdout.log');
|
|
713
851
|
const out = fs.openSync(stdoutLog, 'a');
|
|
714
852
|
const err = fs.openSync(stdoutLog, 'a');
|
|
853
|
+
const overrideFile = writeAsModeOverride(opts.asMode);
|
|
715
854
|
const child = spawn('node', ['--no-warnings=ExperimentalWarning', appMain], {
|
|
716
855
|
detached: true,
|
|
717
856
|
stdio: ['ignore', out, err],
|
|
@@ -719,6 +858,12 @@ export async function cmdStart(opts = {}) {
|
|
|
719
858
|
env: daemonEnv,
|
|
720
859
|
});
|
|
721
860
|
const childPid = child.pid;
|
|
861
|
+
// daemon 已在启动时读走该文件;若未能起来(pid 丢失/提前退出),清掉避免影响下次启动
|
|
862
|
+
child.once('error', () => clearAsModeOverride(overrideFile));
|
|
863
|
+
// Track liveness from the spawn handle instead of launching tasklist on
|
|
864
|
+
// every poll; the poll interval below is short enough that it matters.
|
|
865
|
+
let childExited = false;
|
|
866
|
+
child.once('exit', () => { childExited = true; });
|
|
722
867
|
child.unref();
|
|
723
868
|
// 等待 ready signal(最多 30 秒,AUN sidecar 超时 15s + 其他通道连接)
|
|
724
869
|
const startTime = Date.now();
|
|
@@ -769,10 +914,27 @@ export async function cmdStart(opts = {}) {
|
|
|
769
914
|
printCodeStats(getPackageRoot(), p.logs);
|
|
770
915
|
}
|
|
771
916
|
console.log(`⏱ done in ${((Date.now() - cmdStartedAt) / 1000).toFixed(1)}s`);
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
917
|
+
printAsModeNotice(opts.asMode);
|
|
918
|
+
if (opts.debug) {
|
|
919
|
+
console.log('');
|
|
920
|
+
console.log('🔧 调试模式已启用(EVOLCORE_DEBUG_MODE=1)');
|
|
921
|
+
console.log(' 在宿主终端以任意 session 身份执行命令:');
|
|
922
|
+
console.log('');
|
|
923
|
+
console.log(` ec msg send '<消息内容>' --as-session <sessionId>`);
|
|
924
|
+
console.log(' ec trigger list --as-session <sessionId>');
|
|
925
|
+
console.log(' ec memory list --as-session <sessionId>');
|
|
926
|
+
console.log('');
|
|
927
|
+
console.log(' 查看可用会话(运行后将在此处列出):');
|
|
928
|
+
console.log(` ec msg send 'test' --as-session # 不带 sessionId 自动列出`);
|
|
929
|
+
console.log('');
|
|
930
|
+
console.log(' 注意:重启 daemon(ec restart)会清除调试模式,');
|
|
931
|
+
console.log(' 需重新执行 ec start --debug 才能恢复。');
|
|
932
|
+
}
|
|
933
|
+
// ECWeb lifecycle belongs to the daemon; the CLI only needs its health
|
|
934
|
+
// for the no-agent hints. Waiting otherwise just holds the prompt for
|
|
935
|
+
// up to the probe timeout after the daemon is already ready.
|
|
775
936
|
if (shouldPrintNoSelfAgentHints) {
|
|
937
|
+
const ecwebStarted = await waitForExistingEcweb(p) !== null;
|
|
776
938
|
printNoSelfAgentHints({ daemonConfig: loadDaemonConfig(), ecwebStarted, skipped });
|
|
777
939
|
}
|
|
778
940
|
return;
|
|
@@ -791,7 +953,7 @@ export async function cmdStart(opts = {}) {
|
|
|
791
953
|
return;
|
|
792
954
|
}
|
|
793
955
|
// 进程已退出且无 ready signal
|
|
794
|
-
if (
|
|
956
|
+
if (childExited) {
|
|
795
957
|
// 给进程一点时间写 ready signal(可能刚好在写入中)
|
|
796
958
|
if (Date.now() - startTime > 3000) {
|
|
797
959
|
console.log('❌ Failed to start EvolCore');
|
|
@@ -806,9 +968,9 @@ export async function cmdStart(opts = {}) {
|
|
|
806
968
|
return;
|
|
807
969
|
}
|
|
808
970
|
}
|
|
809
|
-
setTimeout(checkReady,
|
|
971
|
+
setTimeout(checkReady, 200);
|
|
810
972
|
};
|
|
811
|
-
setTimeout(checkReady,
|
|
973
|
+
setTimeout(checkReady, 200);
|
|
812
974
|
}
|
|
813
975
|
function isPidReused(pid, expectedStartedAt) {
|
|
814
976
|
if (expectedStartedAt === undefined)
|
|
@@ -821,7 +983,10 @@ function reportPidReused(pid) {
|
|
|
821
983
|
}
|
|
822
984
|
async function stopPid(pid, gracefulRequested = false, expectedStartedAt) {
|
|
823
985
|
console.log(`🛑 Stopping EvolCore (PID: ${pid})...`);
|
|
824
|
-
|
|
986
|
+
// A graceful request was accepted by the daemon that answered for this exact
|
|
987
|
+
// PID over IPC, so its identity is already proven; the start-time probe (a
|
|
988
|
+
// PowerShell launch on Windows) only guards the kill path.
|
|
989
|
+
if (!gracefulRequested && isPidReused(pid, expectedStartedAt)) {
|
|
825
990
|
reportPidReused(pid);
|
|
826
991
|
return true;
|
|
827
992
|
}
|
|
@@ -870,7 +1035,7 @@ function isRuntimeOrphan(orphan, currentHome = resolveRoot()) {
|
|
|
870
1035
|
export async function cmdStop() {
|
|
871
1036
|
const status = scanInstances();
|
|
872
1037
|
const p = resolvePaths();
|
|
873
|
-
const initialOrphans = findOrphanProcesses();
|
|
1038
|
+
const initialOrphans = findOrphanProcesses(status);
|
|
874
1039
|
const runtimeOrphans = initialOrphans.filter(orphan => isRuntimeOrphan(orphan, p.root));
|
|
875
1040
|
const ping = await probeDaemon(p.socket);
|
|
876
1041
|
if (ping && !hasVisibleDaemonPid(status, ping) && runtimeOrphans.length === 0) {
|
|
@@ -895,7 +1060,8 @@ export async function cmdStop() {
|
|
|
895
1060
|
process.exitCode = 1;
|
|
896
1061
|
return;
|
|
897
1062
|
}
|
|
898
|
-
|
|
1063
|
+
// stopPid already observed every process leave the process table, so the
|
|
1064
|
+
// records can be cleaned immediately (same reasoning as restart-monitor).
|
|
899
1065
|
cleanupInstances();
|
|
900
1066
|
if (aliveMains.length > 1) {
|
|
901
1067
|
console.log(`⚠ 停止了 ${aliveMains.length} 个 main 实例: ${aliveMains.map(m => m.record.pid).join(', ')}`);
|
|
@@ -904,7 +1070,10 @@ export async function cmdStop() {
|
|
|
904
1070
|
export async function cmdRestart(opts = {}) {
|
|
905
1071
|
const cmdStartedAt = Date.now();
|
|
906
1072
|
console.log('🔄 Restarting EvolCore...');
|
|
907
|
-
|
|
1073
|
+
// 重启不带 --as-mode,模式按包路径重新判定;清掉可能残留的覆盖文件,并显示出来
|
|
1074
|
+
writeAsModeOverride(undefined);
|
|
1075
|
+
console.log(` ${describeRunMode()}`);
|
|
1076
|
+
if (!await ensureCodexHookBeforeLifecycle())
|
|
908
1077
|
return;
|
|
909
1078
|
const initialStatus = scanInstances();
|
|
910
1079
|
const socketPath = resolvePaths().socket;
|
|
@@ -1117,7 +1286,8 @@ export async function cmdStatus() {
|
|
|
1117
1286
|
console.log('');
|
|
1118
1287
|
}
|
|
1119
1288
|
if (pid) {
|
|
1120
|
-
|
|
1289
|
+
const mainRecord = aliveMains.find(m => m.record.pid === pid)?.record;
|
|
1290
|
+
printStartupInfo({ pid, running: true, runMode: mainRecord?.runMode });
|
|
1121
1291
|
if (!ping) {
|
|
1122
1292
|
console.log('⚠ 仅确认 daemon PID 存活,IPC 不可用,不能据此判断服务健康。');
|
|
1123
1293
|
if (ipcFailure)
|
|
@@ -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/fs-command.js
CHANGED
|
@@ -56,7 +56,8 @@ Options:
|
|
|
56
56
|
--content-type <mime> 上传时指定内容类型
|
|
57
57
|
--public 上传后公开可读(personal storage)
|
|
58
58
|
--visibility <public|private> chmod 可见性
|
|
59
|
-
--allow-roles <roles> chmod
|
|
59
|
+
--allow-roles <roles> chmod 角色约束,写法固定为单引号包住、逗号分隔,
|
|
60
|
+
如 --allow-roles 'owner,admin'
|
|
60
61
|
-m aid:<aid>:<perms> setfacl 新增/更新 ACL
|
|
61
62
|
-x aid:<aid> setfacl 移除 ACL
|
|
62
63
|
--source <AID>:<path> mount 虚拟卷来源
|
|
@@ -162,6 +162,9 @@ export async function cmdHandoff(args) {
|
|
|
162
162
|
if (!sub || isHelpFlag(sub) || wantsHelp(args)) {
|
|
163
163
|
console.log(`用法: ec handoff <command> [args]
|
|
164
164
|
|
|
165
|
+
⚠ ec handoff 已废弃,请改用话题链(ec thread + ec msg send --thread)。
|
|
166
|
+
本命令保留以兼容现有脚本,将在 P2 后续版本中移除。
|
|
167
|
+
|
|
165
168
|
Commands:
|
|
166
169
|
return [handoff-id] [content] 提交一个回流结果;required 可用同一 ID 追加多个结果
|
|
167
170
|
return [handoff-id] --text-from-file <path>
|