evolcore 0.0.5 → 0.0.7
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 +49 -0
- package/README.md +4 -12
- package/dist/agents/baseagent.js +39 -0
- package/dist/agents/claude-runner.js +10 -2
- package/dist/agents/codex-runner.js +37 -8
- package/dist/agents/ecagent-runner.js +1159 -0
- package/dist/agents/gemini-runner.js +4 -1
- package/dist/agents/runner-types.js +20 -4
- package/dist/aun/msg/history.js +32 -9
- package/dist/aun/outbox.js +4 -9
- package/dist/channels/aun.js +32 -6
- package/dist/channels/daemon.js +7 -4
- package/dist/channels/dingtalk.js +3 -5
- package/dist/channels/feishu.js +16 -108
- package/dist/channels/wechat.js +4 -4
- package/dist/channels/wecom.js +4 -6
- package/dist/cli/agent-command.js +1 -1
- package/dist/cli/agent.js +42 -11
- package/dist/cli/aun-commands.js +50 -3
- package/dist/cli/daemon-commands.js +88 -8
- package/dist/cli/data-command.js +132 -0
- package/dist/cli/index.js +11 -3
- package/dist/cli/init.js +76 -17
- package/dist/cli/net-check.js +9 -20
- package/dist/cli/restart-monitor.js +25 -2
- package/dist/cli/trigger-command.js +1 -1
- package/dist/cli/watch-msg.js +12 -25
- package/dist/config/builtin-roles.js +3 -1
- package/dist/config/config-field-policy.js +1 -1
- package/dist/config/gateway-config.js +21 -4
- package/dist/config/resolved-config-op.js +10 -0
- package/dist/core/command/command-handler.js +2 -2
- package/dist/core/command/menu-handler.js +11 -9
- package/dist/core/command/role-menu.js +11 -0
- package/dist/core/command/slash-handler.js +18 -14
- package/dist/core/data-migration.js +1434 -0
- package/dist/core/handoff/store.js +14 -4
- package/dist/core/inference/text-inference.js +42 -1
- package/dist/core/message/pending-hints.js +1 -1
- package/dist/core/message/response-engine.js +406 -167
- package/dist/core/message/retry-scheduler.js +71 -0
- package/dist/core/model/model-catalog.js +7 -2
- package/dist/core/model/model-fallback.js +81 -0
- package/dist/core/protected-paths.js +41 -8
- package/dist/core/session/adapters/ecagent-session-file-adapter.js +112 -0
- package/dist/core/session/session-fs-store.js +283 -59
- package/dist/core/session/session-manager.js +19 -21
- package/dist/core/session/session-title.js +1 -0
- package/dist/core/session/session-turn-coordinator.js +8 -1
- package/dist/core/system-channels.js +1 -0
- package/dist/index.js +13 -10
- package/dist/paths.js +35 -27
- package/dist/trigger/feedback.js +16 -0
- package/dist/trigger/legacy-session-history.js +19 -0
- package/dist/trigger/manager.js +12 -1
- package/dist/trigger/parser.js +4 -2
- package/dist/trigger/scheduler.js +185 -15
- package/dist/trigger/session-lock.js +62 -0
- package/dist/trigger/state.js +64 -0
- package/dist/trigger/validation.js +32 -2
- package/dist/utils/aid-bind.js +1 -1
- package/dist/utils/error-utils.js +9 -0
- package/dist/utils/instance-registry.js +2 -2
- package/dist/utils/welcome.js +2 -3
- package/ecagent/LICENSE +21 -0
- package/ecagent/NOTICE +11 -0
- package/ecagent/README.md +61 -0
- package/ecagent/dist/agent-loop.d.ts +24 -0
- package/ecagent/dist/agent-loop.d.ts.map +1 -0
- package/ecagent/dist/agent-loop.js +547 -0
- package/ecagent/dist/agent-loop.js.map +1 -0
- package/ecagent/dist/agent.d.ts +127 -0
- package/ecagent/dist/agent.d.ts.map +1 -0
- package/ecagent/dist/agent.js +386 -0
- package/ecagent/dist/agent.js.map +1 -0
- package/ecagent/dist/harness/agent-harness.d.ts +95 -0
- package/ecagent/dist/harness/agent-harness.d.ts.map +1 -0
- package/ecagent/dist/harness/agent-harness.js +926 -0
- package/ecagent/dist/harness/agent-harness.js.map +1 -0
- package/ecagent/dist/harness/compaction/branch-summarization.d.ts +51 -0
- package/ecagent/dist/harness/compaction/branch-summarization.d.ts.map +1 -0
- package/ecagent/dist/harness/compaction/branch-summarization.js +174 -0
- package/ecagent/dist/harness/compaction/branch-summarization.js.map +1 -0
- package/ecagent/dist/harness/compaction/compaction.d.ts +95 -0
- package/ecagent/dist/harness/compaction/compaction.d.ts.map +1 -0
- package/ecagent/dist/harness/compaction/compaction.js +528 -0
- package/ecagent/dist/harness/compaction/compaction.js.map +1 -0
- package/ecagent/dist/harness/compaction/utils.d.ts +25 -0
- package/ecagent/dist/harness/compaction/utils.d.ts.map +1 -0
- package/ecagent/dist/harness/compaction/utils.js +131 -0
- package/ecagent/dist/harness/compaction/utils.js.map +1 -0
- package/ecagent/dist/harness/env/nodejs.d.ts +51 -0
- package/ecagent/dist/harness/env/nodejs.d.ts.map +1 -0
- package/ecagent/dist/harness/env/nodejs.js +513 -0
- package/ecagent/dist/harness/env/nodejs.js.map +1 -0
- package/ecagent/dist/harness/messages.d.ts +51 -0
- package/ecagent/dist/harness/messages.d.ts.map +1 -0
- package/ecagent/dist/harness/messages.js +102 -0
- package/ecagent/dist/harness/messages.js.map +1 -0
- package/ecagent/dist/harness/prompt-templates.d.ts +48 -0
- package/ecagent/dist/harness/prompt-templates.d.ts.map +1 -0
- package/ecagent/dist/harness/prompt-templates.js +230 -0
- package/ecagent/dist/harness/prompt-templates.js.map +1 -0
- package/ecagent/dist/harness/session/jsonl-repo.d.ts +26 -0
- package/ecagent/dist/harness/session/jsonl-repo.d.ts.map +1 -0
- package/ecagent/dist/harness/session/jsonl-repo.js +100 -0
- package/ecagent/dist/harness/session/jsonl-repo.js.map +1 -0
- package/ecagent/dist/harness/session/jsonl-storage.d.ts +34 -0
- package/ecagent/dist/harness/session/jsonl-storage.d.ts.map +1 -0
- package/ecagent/dist/harness/session/jsonl-storage.js +234 -0
- package/ecagent/dist/harness/session/jsonl-storage.js.map +1 -0
- package/ecagent/dist/harness/session/memory-repo.d.ts +18 -0
- package/ecagent/dist/harness/session/memory-repo.d.ts.map +1 -0
- package/ecagent/dist/harness/session/memory-repo.js +44 -0
- package/ecagent/dist/harness/session/memory-repo.js.map +1 -0
- package/ecagent/dist/harness/session/memory-storage.d.ts +25 -0
- package/ecagent/dist/harness/session/memory-storage.d.ts.map +1 -0
- package/ecagent/dist/harness/session/memory-storage.js +111 -0
- package/ecagent/dist/harness/session/memory-storage.js.map +1 -0
- package/ecagent/dist/harness/session/repo-utils.d.ts +11 -0
- package/ecagent/dist/harness/session/repo-utils.d.ts.map +1 -0
- package/ecagent/dist/harness/session/repo-utils.js +39 -0
- package/ecagent/dist/harness/session/repo-utils.js.map +1 -0
- package/ecagent/dist/harness/session/session.d.ts +47 -0
- package/ecagent/dist/harness/session/session.d.ts.map +1 -0
- package/ecagent/dist/harness/session/session.js +245 -0
- package/ecagent/dist/harness/session/session.js.map +1 -0
- package/ecagent/dist/harness/session/uuid.d.ts +2 -0
- package/ecagent/dist/harness/session/uuid.d.ts.map +1 -0
- package/ecagent/dist/harness/session/uuid.js +50 -0
- package/ecagent/dist/harness/session/uuid.js.map +1 -0
- package/ecagent/dist/harness/skills.d.ts +44 -0
- package/ecagent/dist/harness/skills.d.ts.map +1 -0
- package/ecagent/dist/harness/skills.js +311 -0
- package/ecagent/dist/harness/skills.js.map +1 -0
- package/ecagent/dist/harness/system-prompt.d.ts +3 -0
- package/ecagent/dist/harness/system-prompt.d.ts.map +1 -0
- package/ecagent/dist/harness/system-prompt.js +30 -0
- package/ecagent/dist/harness/system-prompt.js.map +1 -0
- package/ecagent/dist/harness/types.d.ts +619 -0
- package/ecagent/dist/harness/types.d.ts.map +1 -0
- package/ecagent/dist/harness/types.js +81 -0
- package/ecagent/dist/harness/types.js.map +1 -0
- package/ecagent/dist/harness/utils/shell-output.d.ts +14 -0
- package/ecagent/dist/harness/utils/shell-output.d.ts.map +1 -0
- package/ecagent/dist/harness/utils/shell-output.js +126 -0
- package/ecagent/dist/harness/utils/shell-output.js.map +1 -0
- package/ecagent/dist/harness/utils/truncate.d.ts +70 -0
- package/ecagent/dist/harness/utils/truncate.d.ts.map +1 -0
- package/ecagent/dist/harness/utils/truncate.js +290 -0
- package/ecagent/dist/harness/utils/truncate.js.map +1 -0
- package/ecagent/dist/index.d.ts +22 -0
- package/ecagent/dist/index.d.ts.map +1 -0
- package/ecagent/dist/index.js +27 -0
- package/ecagent/dist/index.js.map +1 -0
- package/ecagent/dist/node.d.ts +3 -0
- package/ecagent/dist/node.d.ts.map +1 -0
- package/ecagent/dist/node.js +3 -0
- package/ecagent/dist/node.js.map +1 -0
- package/ecagent/dist/proxy.d.ts +69 -0
- package/ecagent/dist/proxy.d.ts.map +1 -0
- package/ecagent/dist/proxy.js +278 -0
- package/ecagent/dist/proxy.js.map +1 -0
- package/ecagent/dist/runtime/api/lazy.d.ts +15 -0
- package/ecagent/dist/runtime/api/lazy.d.ts.map +1 -0
- package/ecagent/dist/runtime/api/lazy.js +59 -0
- package/ecagent/dist/runtime/api/lazy.js.map +1 -0
- package/ecagent/dist/runtime/api/pi-messages.d.ts +97 -0
- package/ecagent/dist/runtime/api/pi-messages.d.ts.map +1 -0
- package/ecagent/dist/runtime/api/pi-messages.js +307 -0
- package/ecagent/dist/runtime/api/pi-messages.js.map +1 -0
- package/ecagent/dist/runtime/api/pi-messages.lazy.d.ts +3 -0
- package/ecagent/dist/runtime/api/pi-messages.lazy.d.ts.map +1 -0
- package/ecagent/dist/runtime/api/pi-messages.lazy.js +3 -0
- package/ecagent/dist/runtime/api/pi-messages.lazy.js.map +1 -0
- package/ecagent/dist/runtime/auth/context.d.ts +7 -0
- package/ecagent/dist/runtime/auth/context.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/context.js +42 -0
- package/ecagent/dist/runtime/auth/context.js.map +1 -0
- package/ecagent/dist/runtime/auth/credential-store.d.ts +16 -0
- package/ecagent/dist/runtime/auth/credential-store.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/credential-store.js +39 -0
- package/ecagent/dist/runtime/auth/credential-store.js.map +1 -0
- package/ecagent/dist/runtime/auth/helpers.d.ts +20 -0
- package/ecagent/dist/runtime/auth/helpers.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/helpers.js +46 -0
- package/ecagent/dist/runtime/auth/helpers.js.map +1 -0
- package/ecagent/dist/runtime/auth/resolve.d.ts +26 -0
- package/ecagent/dist/runtime/auth/resolve.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/resolve.js +100 -0
- package/ecagent/dist/runtime/auth/resolve.js.map +1 -0
- package/ecagent/dist/runtime/auth/types.d.ts +180 -0
- package/ecagent/dist/runtime/auth/types.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/types.js +2 -0
- package/ecagent/dist/runtime/auth/types.js.map +1 -0
- package/ecagent/dist/runtime/compat.d.ts +28 -0
- package/ecagent/dist/runtime/compat.d.ts.map +1 -0
- package/ecagent/dist/runtime/compat.js +86 -0
- package/ecagent/dist/runtime/compat.js.map +1 -0
- package/ecagent/dist/runtime/index.d.ts +20 -0
- package/ecagent/dist/runtime/index.d.ts.map +1 -0
- package/ecagent/dist/runtime/index.js +17 -0
- package/ecagent/dist/runtime/index.js.map +1 -0
- package/ecagent/dist/runtime/models.d.ts +142 -0
- package/ecagent/dist/runtime/models.d.ts.map +1 -0
- package/ecagent/dist/runtime/models.js +245 -0
- package/ecagent/dist/runtime/models.js.map +1 -0
- package/ecagent/dist/runtime/oauth.d.ts +2 -0
- package/ecagent/dist/runtime/oauth.d.ts.map +1 -0
- package/ecagent/dist/runtime/oauth.js +2 -0
- package/ecagent/dist/runtime/oauth.js.map +1 -0
- package/ecagent/dist/runtime/providers/faux.d.ts +97 -0
- package/ecagent/dist/runtime/providers/faux.d.ts.map +1 -0
- package/ecagent/dist/runtime/providers/faux.js +395 -0
- package/ecagent/dist/runtime/providers/faux.js.map +1 -0
- package/ecagent/dist/runtime/types.d.ts +607 -0
- package/ecagent/dist/runtime/types.d.ts.map +1 -0
- package/ecagent/dist/runtime/types.js +2 -0
- package/ecagent/dist/runtime/types.js.map +1 -0
- package/ecagent/dist/runtime/utils/diagnostics.d.ts +19 -0
- package/ecagent/dist/runtime/utils/diagnostics.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/diagnostics.js +25 -0
- package/ecagent/dist/runtime/utils/diagnostics.js.map +1 -0
- package/ecagent/dist/runtime/utils/event-stream.d.ts +21 -0
- package/ecagent/dist/runtime/utils/event-stream.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/event-stream.js +77 -0
- package/ecagent/dist/runtime/utils/event-stream.js.map +1 -0
- package/ecagent/dist/runtime/utils/headers.d.ts +4 -0
- package/ecagent/dist/runtime/utils/headers.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/headers.js +18 -0
- package/ecagent/dist/runtime/utils/headers.js.map +1 -0
- package/ecagent/dist/runtime/utils/json-parse.d.ts +16 -0
- package/ecagent/dist/runtime/utils/json-parse.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/json-parse.js +113 -0
- package/ecagent/dist/runtime/utils/json-parse.js.map +1 -0
- package/ecagent/dist/runtime/utils/oauth/types.d.ts +64 -0
- package/ecagent/dist/runtime/utils/oauth/types.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/oauth/types.js +2 -0
- package/ecagent/dist/runtime/utils/oauth/types.js.map +1 -0
- package/ecagent/dist/runtime/utils/overflow.d.ts +58 -0
- package/ecagent/dist/runtime/utils/overflow.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/overflow.js +158 -0
- package/ecagent/dist/runtime/utils/overflow.js.map +1 -0
- package/ecagent/dist/runtime/utils/provider-env.d.ts +7 -0
- package/ecagent/dist/runtime/utils/provider-env.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/provider-env.js +44 -0
- package/ecagent/dist/runtime/utils/provider-env.js.map +1 -0
- package/ecagent/dist/runtime/utils/retry.d.ts +12 -0
- package/ecagent/dist/runtime/utils/retry.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/retry.js +90 -0
- package/ecagent/dist/runtime/utils/retry.js.map +1 -0
- package/ecagent/dist/runtime/utils/typebox-helpers.d.ts +17 -0
- package/ecagent/dist/runtime/utils/typebox-helpers.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/typebox-helpers.js +21 -0
- package/ecagent/dist/runtime/utils/typebox-helpers.js.map +1 -0
- package/ecagent/dist/runtime/utils/validation.d.ts +18 -0
- package/ecagent/dist/runtime/utils/validation.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/validation.js +269 -0
- package/ecagent/dist/runtime/utils/validation.js.map +1 -0
- package/ecagent/dist/types.d.ts +401 -0
- package/ecagent/dist/types.d.ts.map +1 -0
- package/ecagent/dist/types.js +2 -0
- package/ecagent/dist/types.js.map +1 -0
- package/ecagent/package.json +93 -0
- package/ecagent/src/agent-loop.ts +792 -0
- package/ecagent/src/agent.ts +575 -0
- package/ecagent/src/harness/agent-harness.ts +1029 -0
- package/ecagent/src/harness/compaction/branch-summarization.ts +261 -0
- package/ecagent/src/harness/compaction/compaction.ts +753 -0
- package/ecagent/src/harness/compaction/utils.ts +144 -0
- package/ecagent/src/harness/env/nodejs.ts +569 -0
- package/ecagent/src/harness/messages.ts +164 -0
- package/ecagent/src/harness/prompt-templates.ts +267 -0
- package/ecagent/src/harness/session/jsonl-repo.ts +179 -0
- package/ecagent/src/harness/session/jsonl-storage.ts +314 -0
- package/ecagent/src/harness/session/memory-repo.ts +50 -0
- package/ecagent/src/harness/session/memory-storage.ts +133 -0
- package/ecagent/src/harness/session/repo-utils.ts +51 -0
- package/ecagent/src/harness/session/session.ts +338 -0
- package/ecagent/src/harness/session/uuid.ts +54 -0
- package/ecagent/src/harness/skills.ts +375 -0
- package/ecagent/src/harness/system-prompt.ts +34 -0
- package/ecagent/src/harness/types.ts +838 -0
- package/ecagent/src/harness/utils/shell-output.ts +135 -0
- package/ecagent/src/harness/utils/truncate.ts +344 -0
- package/ecagent/src/index.ts +46 -0
- package/ecagent/src/node.ts +2 -0
- package/ecagent/src/proxy.ts +367 -0
- package/ecagent/src/runtime/api/lazy.ts +70 -0
- package/ecagent/src/runtime/api/pi-messages.lazy.ts +4 -0
- package/ecagent/src/runtime/api/pi-messages.ts +436 -0
- package/ecagent/src/runtime/auth/context.ts +45 -0
- package/ecagent/src/runtime/auth/credential-store.ts +47 -0
- package/ecagent/src/runtime/auth/helpers.ts +46 -0
- package/ecagent/src/runtime/auth/resolve.ts +141 -0
- package/ecagent/src/runtime/auth/types.ts +182 -0
- package/ecagent/src/runtime/compat.ts +158 -0
- package/ecagent/src/runtime/index.ts +31 -0
- package/ecagent/src/runtime/models.ts +452 -0
- package/ecagent/src/runtime/oauth.ts +1 -0
- package/ecagent/src/runtime/providers/faux.ts +538 -0
- package/ecagent/src/runtime/types.ts +718 -0
- package/ecagent/src/runtime/utils/diagnostics.ts +45 -0
- package/ecagent/src/runtime/utils/event-stream.ts +88 -0
- package/ecagent/src/runtime/utils/headers.ts +18 -0
- package/ecagent/src/runtime/utils/json-parse.ts +124 -0
- package/ecagent/src/runtime/utils/oauth/types.ts +79 -0
- package/ecagent/src/runtime/utils/overflow.ts +165 -0
- package/ecagent/src/runtime/utils/provider-env.ts +52 -0
- package/ecagent/src/runtime/utils/retry.ts +101 -0
- package/ecagent/src/runtime/utils/typebox-helpers.ts +24 -0
- package/ecagent/src/runtime/utils/validation.ts +310 -0
- package/ecagent/src/types.ts +430 -0
- package/ecagent/tsconfig.build.json +32 -0
- package/kits/schemas/_meta.json +7 -4
- package/kits/schemas/agent-config.schema.10.json +370 -0
- package/kits/schemas/defaults.schema.4.json +93 -0
- package/kits/schemas/relation-config.schema.8.json +69 -0
- package/kits/templates/roles/admin.json +1 -1
- package/package.json +22 -6
- package/skills/eclink/SKILL.md +70 -0
- package/skills/eclink/agents/openai.yaml +4 -0
- package/assets/.env.template +0 -4
package/dist/cli/init.js
CHANGED
|
@@ -8,6 +8,7 @@ import { scanInstances } from '../utils/instance-registry.js';
|
|
|
8
8
|
import { saveDefaultsSafe, loadAllAgents, loadDaemonConfig, saveDaemonConfig } from '../config-store.js';
|
|
9
9
|
import { generateControlAid, resolveControlIssuer } from '../aun/aid/control-aid.js';
|
|
10
10
|
import { getCodexAppServerAvailability, isCodexAppServerAvailable } from '../agents/codex-runner.js';
|
|
11
|
+
import { resolveEcagentConfig } from '../agents/baseagent.js';
|
|
11
12
|
import { defaultProjectsRoot } from '../utils/project-path.js';
|
|
12
13
|
import { WEB_CLI_BIN, WEB_PACKAGE_LATEST } from '../product.js';
|
|
13
14
|
// ==================== Helpers ====================
|
|
@@ -23,22 +24,38 @@ export function expandLeadingTildePath(value, homeDir = os.homedir()) {
|
|
|
23
24
|
}
|
|
24
25
|
return value;
|
|
25
26
|
}
|
|
26
|
-
const BASEAGENT_CANDIDATES = ['claude', 'codex', 'gemini'];
|
|
27
|
+
const BASEAGENT_CANDIDATES = ['claude', 'codex', 'gemini', 'ecagent'];
|
|
28
|
+
const AUTO_BASEAGENT_CANDIDATES = ['claude', 'codex', 'gemini'];
|
|
27
29
|
function isBaseagentAvailable(baseagent) {
|
|
28
30
|
if (baseagent === 'codex')
|
|
29
31
|
return isCodexAppServerAvailable();
|
|
32
|
+
if (baseagent === 'ecagent')
|
|
33
|
+
return true;
|
|
30
34
|
return commandExists(baseagent);
|
|
31
35
|
}
|
|
32
36
|
function detectAvailable() {
|
|
33
37
|
return BASEAGENT_CANDIDATES.filter(isBaseagentAvailable);
|
|
34
38
|
}
|
|
35
39
|
function pickDefault(available) {
|
|
36
|
-
return (available.includes(
|
|
40
|
+
return AUTO_BASEAGENT_CANDIDATES.find(candidate => available.includes(candidate));
|
|
41
|
+
}
|
|
42
|
+
function ecagentUnavailableReason() {
|
|
43
|
+
try {
|
|
44
|
+
resolveEcagentConfig({ agents: { ecagent: {} } });
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
return error instanceof Error ? error.message : String(error);
|
|
49
|
+
}
|
|
37
50
|
}
|
|
38
51
|
function buildDefaults(chosen, available, projectsDefaultPath) {
|
|
39
52
|
const baseagents = {};
|
|
40
|
-
for (const b of available)
|
|
53
|
+
for (const b of available) {
|
|
54
|
+
// ecagent is bundled but opt-in; do not declare it merely because it is available.
|
|
55
|
+
if (b === 'ecagent' && chosen !== 'ecagent')
|
|
56
|
+
continue;
|
|
41
57
|
baseagents[b] = {};
|
|
58
|
+
}
|
|
42
59
|
return {
|
|
43
60
|
$schema_version: 1,
|
|
44
61
|
active_baseagent: chosen,
|
|
@@ -104,7 +121,7 @@ export async function cmdInit(options) {
|
|
|
104
121
|
// 云部署非交互式路径:当带 --owner 或 --format json 时走结构化分支,与交互式 tail 完全隔离。
|
|
105
122
|
// 预留方案 B:当 daemon 支持 Control Plane 无 agent 启动时,可在此分支跳过 agent new 预创建。
|
|
106
123
|
if (options?.nonInteractive && (options.owner || options.format === 'json' || options.projectpath || options.ecweb)) {
|
|
107
|
-
|
|
124
|
+
await cmdInitNonInteractive({
|
|
108
125
|
owner: options.owner,
|
|
109
126
|
baseagent: options.baseagent,
|
|
110
127
|
projectpath: options.projectpath,
|
|
@@ -112,6 +129,7 @@ export async function cmdInit(options) {
|
|
|
112
129
|
force: options.force,
|
|
113
130
|
format: options.format,
|
|
114
131
|
});
|
|
132
|
+
return true;
|
|
115
133
|
}
|
|
116
134
|
const p = resolvePaths();
|
|
117
135
|
ensureDataDirs();
|
|
@@ -120,17 +138,17 @@ export async function cmdInit(options) {
|
|
|
120
138
|
if (aliveMains.length > 0) {
|
|
121
139
|
const pids = aliveMains.map(m => m.record.pid).join(', ');
|
|
122
140
|
console.log(`❌ EvolCore 正在运行 (PID: ${pids}),请先执行 ec stop`);
|
|
123
|
-
return;
|
|
141
|
+
return false;
|
|
124
142
|
}
|
|
125
143
|
// ── 2. 探测 baseagent ──
|
|
126
144
|
const available = detectAvailable();
|
|
127
|
-
if (available.length === 0) {
|
|
145
|
+
if (available.length === 0 || (available.length === 1 && available[0] === 'ecagent' && ecagentUnavailableReason())) {
|
|
128
146
|
console.log('❌ 未检测到可用 baseagent。请安装至少一款:');
|
|
129
147
|
console.log(' - claude CLI');
|
|
130
148
|
console.log(' - gemini CLI');
|
|
131
149
|
console.log(' - codex CLI with app-server');
|
|
132
150
|
console.log('\n安装后重新运行 ec init');
|
|
133
|
-
return;
|
|
151
|
+
return false;
|
|
134
152
|
}
|
|
135
153
|
console.log('检测到可用的 baseagent:');
|
|
136
154
|
for (const b of available)
|
|
@@ -152,19 +170,31 @@ export async function cmdInit(options) {
|
|
|
152
170
|
if (options.baseagent) {
|
|
153
171
|
if (!BASEAGENT_CANDIDATES.includes(options.baseagent)) {
|
|
154
172
|
console.log(`❌ 无效 baseagent: ${options.baseagent}(可选: ${BASEAGENT_CANDIDATES.join('/')})`);
|
|
155
|
-
return; // 硬错误:不落 tail
|
|
173
|
+
return false; // 硬错误:不落 tail
|
|
156
174
|
}
|
|
157
175
|
if (!available.includes(options.baseagent)) {
|
|
158
176
|
const reason = options.baseagent === 'codex'
|
|
159
177
|
? getCodexAppServerAvailability().reason
|
|
160
178
|
: undefined;
|
|
161
179
|
console.log(`❌ ${options.baseagent} 当前环境不可用${reason ? `:${reason}` : `(可用: ${available.join('/')})`}`);
|
|
162
|
-
return; // 硬错误:不落 tail
|
|
180
|
+
return false; // 硬错误:不落 tail
|
|
181
|
+
}
|
|
182
|
+
if (options.baseagent === 'ecagent') {
|
|
183
|
+
const reason = ecagentUnavailableReason();
|
|
184
|
+
if (reason) {
|
|
185
|
+
console.log(`❌ ecagent 当前环境不可用:${reason}`);
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
163
188
|
}
|
|
164
189
|
chosen = options.baseagent;
|
|
165
190
|
}
|
|
166
191
|
else {
|
|
167
|
-
|
|
192
|
+
const defaultBaseagent = pickDefault(available);
|
|
193
|
+
if (!defaultBaseagent) {
|
|
194
|
+
console.log('❌ ecagent 为可选 baseagent,请显式使用 --baseagent ecagent,并配置 API key');
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
chosen = defaultBaseagent;
|
|
168
198
|
}
|
|
169
199
|
writeDefaults(chosen, available);
|
|
170
200
|
console.log(`✓ 已${defaultsExisted ? '覆盖' : '创建'}: ${defaultsPath}`);
|
|
@@ -177,19 +207,24 @@ export async function cmdInit(options) {
|
|
|
177
207
|
await runInteractive();
|
|
178
208
|
}
|
|
179
209
|
// ── 共享 tail(单一出口):提示创建 agent + 生成控制 AID ──
|
|
180
|
-
|
|
210
|
+
return initTail({ invokedByStart: options?.invokedByStart });
|
|
181
211
|
// ── 内部函数 ──
|
|
182
212
|
async function runInteractive() {
|
|
183
213
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
184
214
|
async function askBaseagent() {
|
|
185
215
|
const defaultBa = pickDefault(available);
|
|
186
|
-
if (available.length === 1) {
|
|
216
|
+
if (available.length === 1 && defaultBa) {
|
|
187
217
|
console.log(` baseagent: ${defaultBa}`);
|
|
188
218
|
return defaultBa;
|
|
189
219
|
}
|
|
190
220
|
let chosen = null;
|
|
191
221
|
while (chosen === null) {
|
|
192
|
-
const
|
|
222
|
+
const defaultHint = defaultBa ? ` [${defaultBa}]` : '';
|
|
223
|
+
const input = (await ask(rl, `默认 baseagent (${available.join('/')})${defaultHint}: `)).trim() || defaultBa;
|
|
224
|
+
if (!input) {
|
|
225
|
+
console.log(' ecagent 为可选项,请显式输入 ecagent');
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
193
228
|
if (!BASEAGENT_CANDIDATES.includes(input)) {
|
|
194
229
|
console.log(` 无效选择,可选: ${BASEAGENT_CANDIDATES.join('/')}`);
|
|
195
230
|
continue;
|
|
@@ -198,6 +233,13 @@ export async function cmdInit(options) {
|
|
|
198
233
|
console.log(` ${input} 当前环境不可用(可用: ${available.join('/')})`);
|
|
199
234
|
continue;
|
|
200
235
|
}
|
|
236
|
+
if (input === 'ecagent') {
|
|
237
|
+
const reason = ecagentUnavailableReason();
|
|
238
|
+
if (reason) {
|
|
239
|
+
console.log(` ecagent 当前环境不可用:${reason}`);
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
201
243
|
chosen = input;
|
|
202
244
|
}
|
|
203
245
|
return chosen;
|
|
@@ -275,6 +317,7 @@ export async function initTail(options = {}) {
|
|
|
275
317
|
}
|
|
276
318
|
// 控制 AID:daemon 进程身份。缺失则生成并写回 daemon.json(幂等:已存在则跳过)。
|
|
277
319
|
const daemonConfig = loadDaemonConfig();
|
|
320
|
+
let controlAidReady = !!daemonConfig.aid;
|
|
278
321
|
if (daemonConfig.aid) {
|
|
279
322
|
const targetIssuer = resolveControlIssuer();
|
|
280
323
|
const currentIssuer = daemonConfig.aid.split('.').slice(1).join('.');
|
|
@@ -288,10 +331,12 @@ export async function initTail(options = {}) {
|
|
|
288
331
|
try {
|
|
289
332
|
const { aid } = await generateControlAid();
|
|
290
333
|
saveDaemonConfig({ ...daemonConfig, $schema_version: daemonConfig.$schema_version ?? 1, aid });
|
|
334
|
+
controlAidReady = true;
|
|
291
335
|
console.log(`✓ 已生成控制 AID: ${aid}`);
|
|
292
336
|
}
|
|
293
337
|
catch (e) {
|
|
294
338
|
console.error(`⚠️ 控制 AID 生成失败(Gateway 不可达?联网后重跑 ec init 补全): ${e?.message || e}`);
|
|
339
|
+
controlAidReady = false;
|
|
295
340
|
}
|
|
296
341
|
}
|
|
297
342
|
// 交互式询问:使用单一 readline 实例避免 stdin 状态混乱
|
|
@@ -387,7 +432,11 @@ export async function initTail(options = {}) {
|
|
|
387
432
|
}
|
|
388
433
|
// ec start 会接着启动 daemon,并在其 ready 后给出可用的 Agent 创建入口。
|
|
389
434
|
if (options.invokedByStart)
|
|
390
|
-
return;
|
|
435
|
+
return controlAidReady;
|
|
436
|
+
if (!controlAidReady) {
|
|
437
|
+
console.error('\n❌ EvolCore 初始化未完成:控制 AID 未配置。联网后重新运行 ec init。');
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
391
440
|
// 初始化完成总结
|
|
392
441
|
console.log('\n✓ EvolCore 初始化完成');
|
|
393
442
|
const finalCfg = loadDaemonConfig();
|
|
@@ -405,6 +454,7 @@ export async function initTail(options = {}) {
|
|
|
405
454
|
console.log(`\n✓ 已有 ${finalAgents.length} 个 agent,可直接运行:`);
|
|
406
455
|
console.log(' ec start');
|
|
407
456
|
}
|
|
457
|
+
return controlAidReady;
|
|
408
458
|
}
|
|
409
459
|
/**
|
|
410
460
|
* Present instance selection menu when existing instances are found.
|
|
@@ -500,8 +550,8 @@ export async function cmdInitNonInteractive(opts, dependencies = {}) {
|
|
|
500
550
|
}
|
|
501
551
|
// ── 3. baseagent 探测 + 校验 ──
|
|
502
552
|
const available = dependencies.availableBaseagents ?? detectAvailable();
|
|
503
|
-
if (available.length === 0) {
|
|
504
|
-
fail('BASEAGENT_UNAVAILABLE', 'no baseagent
|
|
553
|
+
if (available.length === 0 || (available.length === 1 && available[0] === 'ecagent' && ecagentUnavailableReason())) {
|
|
554
|
+
fail('BASEAGENT_UNAVAILABLE', 'no usable baseagent detected (install claude/codex/gemini or configure bundled ecagent)', EXIT_USAGE, format);
|
|
505
555
|
}
|
|
506
556
|
let chosenBaseagent;
|
|
507
557
|
if (opts.baseagent) {
|
|
@@ -512,10 +562,19 @@ export async function cmdInitNonInteractive(opts, dependencies = {}) {
|
|
|
512
562
|
const reason = opts.baseagent === 'codex' ? getCodexAppServerAvailability().reason : undefined;
|
|
513
563
|
fail('BASEAGENT_UNAVAILABLE', `${opts.baseagent} not available${reason ? `: ${reason}` : ''}`, EXIT_USAGE, format);
|
|
514
564
|
}
|
|
565
|
+
if (opts.baseagent === 'ecagent') {
|
|
566
|
+
const reason = ecagentUnavailableReason();
|
|
567
|
+
if (reason)
|
|
568
|
+
fail('BASEAGENT_UNAVAILABLE', reason, EXIT_USAGE, format);
|
|
569
|
+
}
|
|
515
570
|
chosenBaseagent = opts.baseagent;
|
|
516
571
|
}
|
|
517
572
|
else {
|
|
518
|
-
|
|
573
|
+
const defaultBaseagent = pickDefault(available);
|
|
574
|
+
if (!defaultBaseagent) {
|
|
575
|
+
fail('BASEAGENT_UNAVAILABLE', 'ecagent is optional; pass --baseagent ecagent after configuring its API key', EXIT_USAGE, format);
|
|
576
|
+
}
|
|
577
|
+
chosenBaseagent = defaultBaseagent;
|
|
519
578
|
}
|
|
520
579
|
// ── 4. projectpath 校验 + 创建 ──
|
|
521
580
|
let projectsDefaultPath;
|
package/dist/cli/net-check.js
CHANGED
|
@@ -307,31 +307,20 @@ async function runCheck(aid, formatJson, kickTest) {
|
|
|
307
307
|
// 统计每个 AID 的总消息活跃度(遍历所有本地 AID 的 sessions)
|
|
308
308
|
const { resolvePaths } = await import('../paths.js');
|
|
309
309
|
const p = resolvePaths();
|
|
310
|
-
const
|
|
311
|
-
const encode = (s) => s.replace(/[/%\\:*?"<>|]/g, ch => '%' + ch.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0'));
|
|
312
|
-
const decode = (s) => s.replace(/%([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)));
|
|
310
|
+
const { scanChatDirs } = await import('../core/session/session-fs-store.js');
|
|
313
311
|
function getGlobalMessageCounts() {
|
|
314
312
|
const counts = new Map();
|
|
315
313
|
try {
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
if (!localDir.isDirectory())
|
|
314
|
+
for (const chat of scanChatDirs(p.sessionsDir)) {
|
|
315
|
+
if (chat.channelType !== 'aun')
|
|
319
316
|
continue;
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
const peerId = decode(peerDir.name);
|
|
326
|
-
const msgFile = path.join(sessAunDir, localDir.name, peerDir.name, 'messages.jsonl');
|
|
327
|
-
try {
|
|
328
|
-
const content = fs.readFileSync(msgFile, 'utf-8');
|
|
329
|
-
const lineCount = content.split('\n').filter(l => l.trim()).length;
|
|
330
|
-
counts.set(peerId, (counts.get(peerId) ?? 0) + lineCount);
|
|
331
|
-
counts.set(localAid, (counts.get(localAid) ?? 0) + lineCount);
|
|
332
|
-
}
|
|
333
|
-
catch { }
|
|
317
|
+
const msgFile = path.join(chat.dirPath, 'messages.jsonl');
|
|
318
|
+
try {
|
|
319
|
+
const lineCount = fs.readFileSync(msgFile, 'utf-8').split('\n').filter(l => l.trim()).length;
|
|
320
|
+
counts.set(chat.channelId, (counts.get(chat.channelId) ?? 0) + lineCount);
|
|
321
|
+
counts.set(chat.selfAID, (counts.get(chat.selfAID) ?? 0) + lineCount);
|
|
334
322
|
}
|
|
323
|
+
catch { }
|
|
335
324
|
}
|
|
336
325
|
}
|
|
337
326
|
catch { }
|
|
@@ -2,7 +2,7 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { spawn, execFile } from 'child_process';
|
|
4
4
|
import { promisify } from 'util';
|
|
5
|
-
import { resolvePaths, getPackageRoot } from '../paths.js';
|
|
5
|
+
import { resolvePaths, getPackageRoot, daemonControlDir } from '../paths.js';
|
|
6
6
|
import { loadDaemonConfig } from '../config-store.js';
|
|
7
7
|
import * as platform from '../utils/cross-platform.js';
|
|
8
8
|
import { EventBus } from '../core/event-bus.js';
|
|
@@ -14,6 +14,8 @@ import { scanInstances, cleanupInstances, writeRestartMonitor, removeRestartMoni
|
|
|
14
14
|
import { WEB_PACKAGE_NAME } from '../product.js';
|
|
15
15
|
import { shouldSuppressRealRestart } from '../utils/restart-safety.js';
|
|
16
16
|
import { rotateStdoutLog } from '../utils/log-writer.js';
|
|
17
|
+
import { inspectDataMigrationRequirement } from '../core/data-migration.js';
|
|
18
|
+
import { serviceProxyNeedsEcweb, startEcwebIfEnabled } from './daemon-commands.js';
|
|
17
19
|
const execFileAsync = promisify(execFile);
|
|
18
20
|
// 清理 Claude Code 环境变量,防止 SDK 认为是嵌套会话
|
|
19
21
|
function cleanEnv() {
|
|
@@ -72,6 +74,14 @@ export async function cmdRestartMonitor() {
|
|
|
72
74
|
return s.mains.some(m => m.alive);
|
|
73
75
|
};
|
|
74
76
|
log('Restart monitor started');
|
|
77
|
+
const migrationRequirement = inspectDataMigrationRequirement(p.root);
|
|
78
|
+
if (migrationRequirement.required) {
|
|
79
|
+
const message = `Pending user-data migration (${migrationRequirement.operationCount} operations); leaving the current service running. Run ec data migrate --dry-run, then ec data migrate --apply.`;
|
|
80
|
+
log(message);
|
|
81
|
+
console.error(`❌ ${message}`);
|
|
82
|
+
process.exitCode = 2;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
75
85
|
// Test daemons live in one temporary HOME per test, so the current HOME's
|
|
76
86
|
// instance registry cannot see them. Their strict environment markers make
|
|
77
87
|
// them safe to reap globally on every real restart.
|
|
@@ -84,7 +94,7 @@ export async function cmdRestartMonitor() {
|
|
|
84
94
|
}
|
|
85
95
|
}
|
|
86
96
|
// restart-pending.json 只留给新主进程发送发起会话内的“重启成功”回执。
|
|
87
|
-
const pendingFile = path.join(
|
|
97
|
+
const pendingFile = path.join(daemonControlDir(), 'restart-pending.json');
|
|
88
98
|
// 等待所有活 main 进程退出(可能不止一个)
|
|
89
99
|
const oldStatus = scanInstances();
|
|
90
100
|
const aliveMains = oldStatus.mains.filter(m => m.alive);
|
|
@@ -168,9 +178,22 @@ export async function cmdRestartMonitor() {
|
|
|
168
178
|
await notifyDaemonOwners(p, `⚠️ ${WEB_PACKAGE_NAME} 升级失败,使用当前版本继续\n${ecwebUpgrade.error ?? ''}`.trim(), log);
|
|
169
179
|
break;
|
|
170
180
|
}
|
|
181
|
+
// source=ecweb 的 Service Proxy 只在 daemon 启动后的短窗口内发现实例。
|
|
182
|
+
// restart-monitor 直接 spawn daemon,必须在此先启动独立的 ec-web,不能绕过
|
|
183
|
+
// cmdStart 的 ECWeb 生命周期逻辑。
|
|
184
|
+
const ecwebStartedBeforeDaemon = serviceProxyNeedsEcweb(loadDaemonConfig())
|
|
185
|
+
? await startEcwebIfEnabled(p)
|
|
186
|
+
: false;
|
|
187
|
+
if (ecwebStartedBeforeDaemon)
|
|
188
|
+
log('ECWeb started before daemon');
|
|
171
189
|
// 启动并检测 ready signal
|
|
172
190
|
let started = await spawnAndWaitReady(p, log, READY_TIMEOUT);
|
|
173
191
|
if (started) {
|
|
192
|
+
// 没有 Service Proxy 时可以等 daemon ready 后再启动;有代理时已在上方启动,
|
|
193
|
+
// 避免重新拉起造成实例记录和反向隧道短暂失配。
|
|
194
|
+
if (!ecwebStartedBeforeDaemon && await startEcwebIfEnabled(p)) {
|
|
195
|
+
log('ECWeb started after daemon');
|
|
196
|
+
}
|
|
174
197
|
log('✓ Service restarted successfully');
|
|
175
198
|
archiveSelfHealLog(p, log);
|
|
176
199
|
// 发起会话内的“重启成功”通知由新进程自行发送,此处只负责失败/自愈告警。
|
|
@@ -110,7 +110,7 @@ Create 参数模式支持:
|
|
|
110
110
|
--tz <时区> (仅 cron)
|
|
111
111
|
--target-channel <channelKey> --target-channel-id <ID> (AUN 可简写为 aun)
|
|
112
112
|
--target-session <main|thread> [--target-thread-id <threadId>]
|
|
113
|
-
--trigger-thread <
|
|
113
|
+
--trigger-thread <by-run|by-trigger> (兼容旧值 per-run)
|
|
114
114
|
--name <名称>
|
|
115
115
|
|
|
116
116
|
通用输出参数:
|
package/dist/cli/watch-msg.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { resolvePaths } from '../paths.js';
|
|
4
|
-
import {
|
|
4
|
+
import { chatDirPath, readAllJsonlLines, scanChatDirs } from '../core/session/session-fs-store.js';
|
|
5
5
|
import { isTransientProtocolMessage } from '../core/message/message-log.js';
|
|
6
6
|
// ==================== ANSI ====================
|
|
7
7
|
const isTTY = !!process.stdout.isTTY;
|
|
@@ -135,36 +135,26 @@ function shortAid(aid) {
|
|
|
135
135
|
// ==================== Data Layer ====================
|
|
136
136
|
export function getSessionsAunDir() {
|
|
137
137
|
const p = resolvePaths();
|
|
138
|
-
return
|
|
138
|
+
return p.sessionsDir;
|
|
139
139
|
}
|
|
140
140
|
export function listLocalAids(aunDir) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
.
|
|
144
|
-
.map(e => decodeDirSegment(e.name));
|
|
145
|
-
}
|
|
146
|
-
catch {
|
|
147
|
-
return [];
|
|
148
|
-
}
|
|
141
|
+
return [...new Set(scanChatDirs(aunDir)
|
|
142
|
+
.filter(chat => chat.channelType === 'aun')
|
|
143
|
+
.map(chat => chat.selfAID))].sort();
|
|
149
144
|
}
|
|
150
145
|
export function listPeers(aunDir, localAid) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
.map(e => decodeDirSegment(e.name));
|
|
156
|
-
}
|
|
157
|
-
catch {
|
|
158
|
-
return [];
|
|
159
|
-
}
|
|
146
|
+
return scanChatDirs(aunDir)
|
|
147
|
+
.filter(chat => chat.channelType === 'aun' && chat.selfAID === localAid)
|
|
148
|
+
.map(chat => chat.channelId)
|
|
149
|
+
.sort();
|
|
160
150
|
}
|
|
161
151
|
export function readMessages(aunDir, localAid, peerId) {
|
|
162
|
-
const msgPath = path.join(aunDir,
|
|
152
|
+
const msgPath = path.join(chatDirPath(aunDir, 'aun', peerId, localAid), 'messages.jsonl');
|
|
163
153
|
return readAllJsonlLines(msgPath)
|
|
164
154
|
.filter(m => !isTransientProtocolMessage(m));
|
|
165
155
|
}
|
|
166
156
|
function readPeerName(aunDir, localAid, peerId) {
|
|
167
|
-
const activePath = path.join(aunDir,
|
|
157
|
+
const activePath = path.join(chatDirPath(aunDir, 'aun', peerId, localAid), 'active.json');
|
|
168
158
|
try {
|
|
169
159
|
const data = JSON.parse(fs.readFileSync(activePath, 'utf-8'));
|
|
170
160
|
return data?.metadata?.peerName || null;
|
|
@@ -173,9 +163,6 @@ function readPeerName(aunDir, localAid, peerId) {
|
|
|
173
163
|
return null;
|
|
174
164
|
}
|
|
175
165
|
}
|
|
176
|
-
function encodeSegment(s) {
|
|
177
|
-
return s.replace(/[/%\\:*?"<>|]/g, ch => '%' + ch.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0'));
|
|
178
|
-
}
|
|
179
166
|
export function loadAidInfo(aunDir, aid) {
|
|
180
167
|
const peers = listPeers(aunDir, aid);
|
|
181
168
|
let totalIn = 0, totalOut = 0;
|
|
@@ -457,7 +444,7 @@ export async function cmdWatchMsg() {
|
|
|
457
444
|
watcher.close();
|
|
458
445
|
watcher = null;
|
|
459
446
|
}
|
|
460
|
-
const aidDir = path.
|
|
447
|
+
const aidDir = path.dirname(path.dirname(chatDirPath(aunDir, 'aun', '__watch__', aid)));
|
|
461
448
|
try {
|
|
462
449
|
watcher = fs.watch(aidDir, { recursive: true }, (_, filename) => {
|
|
463
450
|
if (filename && filename.endsWith('messages.jsonl')) {
|
|
@@ -40,7 +40,9 @@ export function getManagementCommandPermissions(role) {
|
|
|
40
40
|
'config.unset': { allow: true, scopes: ['agent', 'relation'] },
|
|
41
41
|
'role.policy.write': { allow: true, dangerous: true, scopes: ['agent'], constraints: { requireAgentAdmin: true } },
|
|
42
42
|
'*': { allow: true },
|
|
43
|
-
|
|
43
|
+
// Reload is valid from an Agent's own channel and the daemon control plane.
|
|
44
|
+
// The control-channel gate still requires a daemon owner for cross-Agent reloads.
|
|
45
|
+
'agent.reload': { allow: true, dangerous: true, scopes: ['agent', 'control'], constraints: { targetCurrentAgentOnly: true, requireAgentAdmin: true } },
|
|
44
46
|
'dangerous:*': { allow: true, dangerous: true, constraints: { requireDaemonOwner: true } },
|
|
45
47
|
};
|
|
46
48
|
}
|
|
@@ -25,7 +25,7 @@ const BASEAGENT_BEHAVIOR_FIELDS = new Set([
|
|
|
25
25
|
'mode',
|
|
26
26
|
'useVertex',
|
|
27
27
|
]);
|
|
28
|
-
const SUPPORTED_BASEAGENTS = new Set(['claude', 'codex', 'gemini', 'hermes']);
|
|
28
|
+
const SUPPORTED_BASEAGENTS = new Set(['claude', 'codex', 'gemini', 'ecagent', 'hermes']);
|
|
29
29
|
const SENSITIVE_TOP_FIELDS = new Set([
|
|
30
30
|
'$schema_version',
|
|
31
31
|
'aid',
|
|
@@ -15,16 +15,17 @@ import fs from 'fs';
|
|
|
15
15
|
import path from 'path';
|
|
16
16
|
import { resolvePaths } from '../paths.js';
|
|
17
17
|
import { saveDefaultsSafe, saveAgent } from '../config-store.js';
|
|
18
|
-
import { resolveAnthropicConfig, resolveOpenaiConfig } from '../agents/baseagent.js';
|
|
18
|
+
import { resolveAnthropicConfig, resolveEcagentConfig, resolveOpenaiConfig } from '../agents/baseagent.js';
|
|
19
19
|
import { resolvePriceRow } from '../stats/billing.js';
|
|
20
20
|
import { ipcQuery } from '../ipc.js';
|
|
21
21
|
import { logger } from '../utils/logger.js';
|
|
22
22
|
/** 已知 baseagent 类型(网关可管理范围)。 */
|
|
23
|
-
const GATEWAY_TYPES = ['claude', 'codex', 'gemini'];
|
|
23
|
+
const GATEWAY_TYPES = ['claude', 'codex', 'gemini', 'ecagent'];
|
|
24
24
|
const DISPLAY_NAMES = {
|
|
25
25
|
claude: 'Claude',
|
|
26
26
|
codex: 'Codex (OpenAI)',
|
|
27
27
|
gemini: 'Gemini',
|
|
28
|
+
ecagent: 'ecagent (EvolCore)',
|
|
28
29
|
};
|
|
29
30
|
// ── 掩码 ──
|
|
30
31
|
const ENV_PREFIX = '$ENV:';
|
|
@@ -362,7 +363,7 @@ function buildPatch(type, patch) {
|
|
|
362
363
|
else
|
|
363
364
|
return { error: 'apiKey 仅接受 "$ENV:NAME" 环境变量引用,不接受明文' };
|
|
364
365
|
}
|
|
365
|
-
if (type === 'claude' || type === 'codex') {
|
|
366
|
+
if (type === 'claude' || type === 'codex' || type === 'ecagent') {
|
|
366
367
|
if (patch.effort !== undefined)
|
|
367
368
|
f.effort = String(patch.effort).trim() || undefined;
|
|
368
369
|
}
|
|
@@ -383,6 +384,16 @@ function buildPatch(type, patch) {
|
|
|
383
384
|
if (patch.location !== undefined)
|
|
384
385
|
f.location = String(patch.location).trim() || undefined;
|
|
385
386
|
}
|
|
387
|
+
if (type === 'ecagent') {
|
|
388
|
+
for (const key of ['timeoutMs', 'maxRetries', 'maxRetryDelayMs']) {
|
|
389
|
+
if (patch[key] !== undefined) {
|
|
390
|
+
const value = Number(patch[key]);
|
|
391
|
+
if (!Number.isFinite(value) || value < 0)
|
|
392
|
+
return { error: `${key} 必须是非负数字` };
|
|
393
|
+
f[key] = value;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
386
397
|
return { fields: f };
|
|
387
398
|
}
|
|
388
399
|
/** 触发 reload:defaults 改动影响全部 agent(resync),单 agent 改动只 reload 它。 */
|
|
@@ -485,6 +496,10 @@ function resolveGatewayCreds(scope, type) {
|
|
|
485
496
|
const r = resolveAnthropicConfig(synth, expanded);
|
|
486
497
|
return { baseUrl: r.baseUrl, apiKey: r.apiKey };
|
|
487
498
|
}
|
|
499
|
+
else if (type === 'ecagent') {
|
|
500
|
+
const r = resolveEcagentConfig(synth, expanded);
|
|
501
|
+
return { baseUrl: r.baseUrl, apiKey: r.apiKey };
|
|
502
|
+
}
|
|
488
503
|
return { error: 'gemini 暂不支持 HTTP 探测(CLI 后端)', code: 'NOT_SUPPORTED' };
|
|
489
504
|
}
|
|
490
505
|
catch (e) {
|
|
@@ -507,7 +522,9 @@ export async function gatewayTest(args) {
|
|
|
507
522
|
try {
|
|
508
523
|
const controller = new AbortController();
|
|
509
524
|
const timer = setTimeout(() => controller.abort(), 5000);
|
|
510
|
-
const
|
|
525
|
+
const base = baseUrl.replace(/\/+$/, '');
|
|
526
|
+
const modelsUrl = base.endsWith('/v1') ? `${base}/models` : `${base}/v1/models`;
|
|
527
|
+
const resp = await fetch(modelsUrl, {
|
|
511
528
|
headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : {},
|
|
512
529
|
signal: controller.signal,
|
|
513
530
|
});
|
|
@@ -110,6 +110,16 @@ function resolveFieldCommand(argv, subcommand, options = {}) {
|
|
|
110
110
|
reason: 'Agent role policies are managed through the role policy editor',
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
|
+
const canContainFallbackModels = field === 'baseagents'
|
|
114
|
+
|| /^baseagents\.[^.]+$/.test(field)
|
|
115
|
+
|| /^baseagents\.[^.]+\.fallbackModels(?:\.|$)/.test(field);
|
|
116
|
+
if (subcommand !== 'get' && canContainFallbackModels) {
|
|
117
|
+
return {
|
|
118
|
+
ok: false,
|
|
119
|
+
code: 'DEFAULTS_FILE_ONLY',
|
|
120
|
+
reason: 'fallbackModels is configured only by editing agents/defaults.json',
|
|
121
|
+
};
|
|
122
|
+
}
|
|
113
123
|
const fieldRule = resolveConfigFieldRule(field);
|
|
114
124
|
if (subcommand !== 'get' && fieldRule.class === 'safe-readonly-object') {
|
|
115
125
|
return {
|
|
@@ -803,10 +803,10 @@ export class CommandHandler {
|
|
|
803
803
|
};
|
|
804
804
|
if (s.agentSessionId) {
|
|
805
805
|
item.agentSessionId = s.agentSessionId;
|
|
806
|
-
const fileInfo = this.sessionManager.getSessionFileInfo(s.projectPath, s.agentSessionId, s.baseagent);
|
|
806
|
+
const fileInfo = this.sessionManager.getSessionFileInfo(s.projectPath, s.agentSessionId, s.baseagent, s.selfAID);
|
|
807
807
|
if (fileInfo.turns)
|
|
808
808
|
item.turns = fileInfo.turns;
|
|
809
|
-
const firstMsg = this.sessionManager.readSessionFirstMessage(s.projectPath, s.agentSessionId, s.baseagent);
|
|
809
|
+
const firstMsg = this.sessionManager.readSessionFirstMessage(s.projectPath, s.agentSessionId, s.baseagent, s.selfAID);
|
|
810
810
|
if (firstMsg)
|
|
811
811
|
item.preview = firstMsg.length > 80 ? firstMsg.slice(0, 80) + '...' : firstMsg;
|
|
812
812
|
}
|
|
@@ -4,7 +4,7 @@ import { modelMatches } from '../model/model-catalog.js';
|
|
|
4
4
|
import { constrainResolvedModelForRole, filterModelsForRole, validateModelSelectionForRole } from '../model/model-permission.js';
|
|
5
5
|
import { hasModelSwitcher } from '../../agents/runner-types.js';
|
|
6
6
|
import { getCodexEfforts } from '../../agents/codex-runner.js';
|
|
7
|
-
import { resolvePaths, getPackageRoot } from '../../paths.js';
|
|
7
|
+
import { resolvePaths, getPackageRoot, daemonControlDir } from '../../paths.js';
|
|
8
8
|
import { buildEnvelope } from '../message/message-utils.js';
|
|
9
9
|
import path from 'path';
|
|
10
10
|
import fs from 'fs';
|
|
@@ -1038,6 +1038,8 @@ function buildRoleMenuContext(owner, channel, subject) {
|
|
|
1038
1038
|
return {
|
|
1039
1039
|
self,
|
|
1040
1040
|
actorRole: subject.role,
|
|
1041
|
+
actorRoleSource: subject.roleSource,
|
|
1042
|
+
actorAllowAccess: subject.allowAccess,
|
|
1041
1043
|
actorAid: subject.actorId,
|
|
1042
1044
|
chatType: subject.chatType,
|
|
1043
1045
|
aunAvailable,
|
|
@@ -1537,10 +1539,10 @@ export async function getSubMenuItems(cmd, channel, channelId, userId, args, ove
|
|
|
1537
1539
|
};
|
|
1538
1540
|
if (s.agentSessionId) {
|
|
1539
1541
|
item.agentSessionId = s.agentSessionId;
|
|
1540
|
-
const fileInfo = this.sessionManager.getSessionFileInfo(s.projectPath, s.agentSessionId, s.baseagent);
|
|
1542
|
+
const fileInfo = this.sessionManager.getSessionFileInfo(s.projectPath, s.agentSessionId, s.baseagent, s.selfAID);
|
|
1541
1543
|
if (fileInfo.turns)
|
|
1542
1544
|
item.turns = fileInfo.turns;
|
|
1543
|
-
const firstMsg = this.sessionManager.readSessionFirstMessage(s.projectPath, s.agentSessionId, s.baseagent);
|
|
1545
|
+
const firstMsg = this.sessionManager.readSessionFirstMessage(s.projectPath, s.agentSessionId, s.baseagent, s.selfAID);
|
|
1544
1546
|
if (firstMsg)
|
|
1545
1547
|
item.preview = firstMsg.length > 80 ? firstMsg.slice(0, 80) + '…' : firstMsg;
|
|
1546
1548
|
}
|
|
@@ -1903,7 +1905,7 @@ export async function execMenuQuery(cmd, channel, channelId, userId, args, expli
|
|
|
1903
1905
|
}
|
|
1904
1906
|
let turns = 0;
|
|
1905
1907
|
if (session.agentSessionId) {
|
|
1906
|
-
const fileInfo = this.sessionManager.getSessionFileInfo(session.projectPath, session.agentSessionId, session.baseagent);
|
|
1908
|
+
const fileInfo = this.sessionManager.getSessionFileInfo(session.projectPath, session.agentSessionId, session.baseagent, session.selfAID);
|
|
1907
1909
|
turns = fileInfo.turns;
|
|
1908
1910
|
}
|
|
1909
1911
|
const data = {
|
|
@@ -1950,7 +1952,7 @@ export async function execMenuQuery(cmd, channel, channelId, userId, args, expli
|
|
|
1950
1952
|
}
|
|
1951
1953
|
let turns = 0;
|
|
1952
1954
|
if (topic.agentSessionId) {
|
|
1953
|
-
turns = this.sessionManager.getSessionFileInfo(topic.projectPath, topic.agentSessionId, topic.baseagent).turns;
|
|
1955
|
+
turns = this.sessionManager.getSessionFileInfo(topic.projectPath, topic.agentSessionId, topic.baseagent, topic.selfAID).turns;
|
|
1954
1956
|
}
|
|
1955
1957
|
const data = {
|
|
1956
1958
|
threadId: topic.threadId,
|
|
@@ -2878,7 +2880,7 @@ export async function execMenuAction(cmd, action, args, channel, channelId, user
|
|
|
2878
2880
|
return { error: `无效 targetSession: ${targetSession}`, code: 'INVALID_ARGS' };
|
|
2879
2881
|
}
|
|
2880
2882
|
const triggerThread = args.triggerThread;
|
|
2881
|
-
if (triggerThread !== undefined && triggerThread !== 'per_run' && triggerThread !== 'by_trigger') {
|
|
2883
|
+
if (triggerThread !== undefined && triggerThread !== 'per_run' && triggerThread !== 'by_run' && triggerThread !== 'by_trigger') {
|
|
2882
2884
|
return { error: `无效 triggerThread: ${triggerThread}`, code: 'INVALID_ARGS' };
|
|
2883
2885
|
}
|
|
2884
2886
|
const parsed = {
|
|
@@ -3269,9 +3271,9 @@ export async function execMenuAction(cmd, action, args, channel, channelId, user
|
|
|
3269
3271
|
const suppressRealRestart = shouldSuppressRealRestart();
|
|
3270
3272
|
if (!suppressRealRestart) {
|
|
3271
3273
|
const restartInfo = { channel, channelId, timestamp: Date.now() };
|
|
3272
|
-
const
|
|
3273
|
-
fs.mkdirSync(
|
|
3274
|
-
fs.writeFileSync(path.join(
|
|
3274
|
+
const controlDir = daemonControlDir();
|
|
3275
|
+
fs.mkdirSync(controlDir, { recursive: true });
|
|
3276
|
+
fs.writeFileSync(path.join(controlDir, 'restart-pending.json'), JSON.stringify(restartInfo));
|
|
3275
3277
|
const { spawn } = await import('child_process');
|
|
3276
3278
|
spawn('node', [path.join(getPackageRoot(), 'dist', 'cli', 'index.js'), 'restart-monitor'], {
|
|
3277
3279
|
detached: true,
|
|
@@ -785,6 +785,7 @@ async function targetSnapshot(context, args, policyRevision) {
|
|
|
785
785
|
target,
|
|
786
786
|
relationRevision: relation?.revision ?? null,
|
|
787
787
|
...targetRoleView(self, target, relation?.config ?? null),
|
|
788
|
+
...(target.kind === 'group' ? { requesterRole: requesterRoleResult(context) } : {}),
|
|
788
789
|
relationConfig: relationConfigView(context, target, relation?.config ?? null),
|
|
789
790
|
};
|
|
790
791
|
}
|
|
@@ -1157,6 +1158,16 @@ function relationConfigView(context, target, config) {
|
|
|
1157
1158
|
function roleResult(roleId, source, self) {
|
|
1158
1159
|
return { roleId, source: roleId ? source : 'none', allowAccess: roleId ? checkRoleAccess(roleId, self) : false };
|
|
1159
1160
|
}
|
|
1161
|
+
function requesterRoleResult(context) {
|
|
1162
|
+
const roleId = isManagementRole(context.actorRole) ? context.actorRole : null;
|
|
1163
|
+
return {
|
|
1164
|
+
roleId,
|
|
1165
|
+
source: roleId ? context.actorRoleSource ?? 'authenticated' : 'none',
|
|
1166
|
+
allowAccess: roleId
|
|
1167
|
+
? context.actorAllowAccess ?? checkRoleAccess(roleId, context.self)
|
|
1168
|
+
: false,
|
|
1169
|
+
};
|
|
1170
|
+
}
|
|
1160
1171
|
function readAgent(self) {
|
|
1161
1172
|
const agent = read(ConfigTarget.Agent, { self }, { cache: false });
|
|
1162
1173
|
if (!agent)
|