evolcore 0.0.22 → 0.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +74 -14
- package/README.md +4 -0
- package/bin/codex-managed-acl.ps1 +160 -0
- package/bin/codex-managed-hook.mjs +127 -10
- package/bin/ec-safe-output.js +85 -3
- package/bin/install-codex-managed-hooks.mjs +384 -95
- package/dist/agents/baseagent-availability.js +48 -0
- package/dist/agents/baseagent.js +30 -2
- package/dist/agents/claude-runner.js +179 -240
- package/dist/agents/{codex-app-server-client.js → codex/app-server-client.js} +90 -20
- package/dist/{utils/codex-app-server-registry.js → agents/codex/app-server-registry.js} +2 -2
- package/dist/agents/codex/catalog.js +70 -0
- package/dist/agents/codex/diagnostics.js +369 -0
- package/dist/agents/codex-runner.js +839 -192
- package/dist/agents/ecagent-runner.js +27 -34
- package/dist/agents/gemini-runner.js +62 -8
- package/dist/agents/runner-types.js +1 -1
- package/dist/aun/aid/managed-operation.js +28 -6
- package/dist/aun/aid/store.js +43 -0
- package/dist/aun/menu-client.js +272 -0
- package/dist/aun/msg/group.js +65 -4
- package/dist/aun/msg/index.js +1 -1
- package/dist/aun/msg/managed-operation.js +57 -5
- package/dist/aun/outbox.js +56 -18
- package/dist/aun/rpc/client.js +7 -1
- package/dist/channels/aun.js +178 -77
- package/dist/channels/daemon.js +7 -1
- package/dist/channels/dingtalk.js +1 -0
- package/dist/channels/feishu.js +10 -4
- package/dist/channels/wechat.js +81 -10
- package/dist/channels/wecom.js +2 -1
- package/dist/cli/agent-command.js +29 -3
- package/dist/cli/agent-create.js +538 -0
- package/dist/cli/agent.js +26 -675
- package/dist/cli/aun-commands.js +108 -24
- package/dist/cli/command-log.js +21 -2
- package/dist/cli/ctl-command.js +2 -0
- package/dist/cli/daemon-commands.js +289 -61
- package/dist/cli/index.js +22 -2
- package/dist/cli/init.js +2 -10
- package/dist/cli/managed-command-guard.js +3 -0
- package/dist/cli/menu-client.js +95 -0
- package/dist/cli/model.js +23 -8
- package/dist/cli/restart-monitor.js +432 -8
- package/dist/cli/stats.js +110 -0
- package/dist/cli/task-context.js +12 -2
- package/dist/cli/trigger-command.js +9 -1
- package/dist/config/builtin-roles.js +2 -0
- package/dist/config/schema-migration.js +14 -2
- package/dist/core/auth/agent-delegation.js +10 -7
- package/dist/core/auth/auth-gateway.js +3 -2
- package/dist/core/auth/authorization-audit.js +75 -18
- package/dist/core/auth/operation-authorizer.js +63 -3
- package/dist/core/auth/operation-catalog.js +14 -2
- package/dist/core/auth/remote-access-store.js +136 -0
- package/dist/core/baseagent-loader.js +4 -4
- package/dist/core/bootstrap-messages.js +39 -18
- package/dist/core/bootstrap-service.js +32 -26
- package/dist/core/capability/capability-manager.js +8 -4
- package/dist/core/capability/providers/codex-capability-provider.js +1 -1
- package/dist/core/command/agent-control.js +7 -2
- package/dist/core/command/command-handler.js +128 -30
- package/dist/core/command/daemon-diagnostics.js +448 -0
- package/dist/core/command/menu-catalog.js +6 -1
- package/dist/core/command/menu-handler.js +410 -98
- package/dist/core/command/menu-protocol.js +123 -0
- package/dist/core/command/slash-gate.js +4 -6
- package/dist/core/command/slash-handler.js +199 -70
- package/dist/core/data-migration.js +5 -15
- package/dist/core/event-catalog.js +3 -0
- package/dist/core/handoff/runtime.js +3 -1
- package/dist/core/handoff/store.js +7 -1
- package/dist/core/message/im-renderer.js +13 -6
- package/dist/core/message/message-bridge.js +5 -36
- package/dist/core/message/message-queue.js +20 -15
- package/dist/core/message/message-utils.js +6 -3
- package/dist/core/message/response-engine.js +147 -94
- package/dist/core/model/catalog-service.js +310 -0
- package/dist/core/model/model-catalog.js +134 -334
- package/dist/core/model/model-diagnostics.js +4 -5
- package/dist/core/model/model-fallback.js +9 -16
- package/dist/core/model/model-permission.js +5 -2
- package/dist/core/permission/approval-gateway.js +183 -32
- package/dist/core/permission/protected-paths.js +63 -4
- package/dist/core/permission/sandbox-runtime.js +4 -2
- package/dist/core/permission/tool-policy.js +257 -31
- package/dist/core/runtime-lock.js +13 -8
- package/dist/core/session/adapters/codex-session-file-adapter.js +71 -3
- package/dist/core/session/session-manager.js +49 -13
- package/dist/core/session/session-renew.js +1 -0
- package/dist/index.js +214 -57
- package/dist/ipc.js +191 -102
- package/dist/paths.js +23 -1
- package/dist/stats/billing.js +18 -4
- package/dist/trigger/manager.js +3 -1
- package/dist/trigger/parser.js +77 -13
- package/dist/trigger/patch.js +104 -1
- package/dist/utils/atomic-write.js +26 -2
- package/dist/utils/cross-platform.js +436 -1
- package/dist/utils/ecweb-supervisor.js +11 -2
- package/dist/utils/ecweb-utils.js +8 -26
- package/dist/utils/error-utils.js +16 -2
- package/dist/utils/model-prices.jsonl +23 -20
- package/dist/utils/npm-ops.js +70 -15
- package/dist/utils/windows-autostart.js +1 -1
- package/kits/docs/evolcore/INDEX.md +1 -0
- package/kits/docs/evolcore/agent-create.md +13 -0
- package/kits/docs/evolcore/group-collaboration.md +7 -2
- package/kits/docs/evolcore/menu-client.md +34 -0
- package/kits/migrations/migrate-contact-book-v2.mjs +9 -1
- package/kits/migrations/migrate-role-config-v4.mjs +11 -5
- package/kits/migrations/migrate-role-config-v5.mjs +8 -2
- package/kits/templates/roles/admin.json +2 -0
- package/kits/templates/roles/visitor.json +1 -0
- package/kits/templates/system-fragments/bootstrap.md +8 -1
- package/package.json +16 -4
- package/dist/utils/codex-cli.js +0 -43
|
@@ -4,6 +4,7 @@ import { compareVersions, resolveGlobalPkg } from './npm-ops.js';
|
|
|
4
4
|
import { isWindows as platformIsWindows, resolveCommandPath } from './cross-platform.js';
|
|
5
5
|
import { MIN_ECWEB_VERSION, WEB_CLI_BIN, WEB_PACKAGE_NAME } from '../product.js';
|
|
6
6
|
import { resolvePaths } from '../paths.js';
|
|
7
|
+
import { ipcQuery } from '../ipc.js';
|
|
7
8
|
/** EC Web owns the session-log reader, so older builds cannot safely serve a newer daemon. */
|
|
8
9
|
export function isEcwebVersionSupported(version) {
|
|
9
10
|
const normalized = version?.trim();
|
|
@@ -65,34 +66,15 @@ export function resolveEcwebLaunchCommand(ecwebArgs, opts = {}) {
|
|
|
65
66
|
}
|
|
66
67
|
return { command: commandPath, args: ecwebArgs, source: 'command' };
|
|
67
68
|
}
|
|
68
|
-
|
|
69
|
-
* ECWeb 配对码取码 helper(共享给 daemon 和 CLI)。
|
|
70
|
-
*
|
|
71
|
-
* 配对码是 ecweb 进程自己生成并持有的内部状态。daemon/CLI 通过 ecweb 的
|
|
72
|
-
* localhost-only HTTP 接口 GET /api/pair-code 取当前码(远程访问被 ecweb 403 拒绝)。
|
|
73
|
-
*/
|
|
74
|
-
/** 经 localhost 拉取 ecweb 当前配对码(仅本机可取)。失败返回 null。
|
|
75
|
-
* authorizedBy 仅由 daemon 的 AUN 控制通道传入,用于把配对码换出的 token
|
|
76
|
-
* 绑定到实际批准的 daemon-owner;普通 CLI 取码不携带该字段。 */
|
|
77
|
-
export async function fetchEcwebPairCode(port, authorizedBy) {
|
|
69
|
+
export async function fetchRemotePairingCode(authorizedBy) {
|
|
78
70
|
try {
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const controlToken = fs.readFileSync(resolvePaths().controlToken, 'utf8').trim();
|
|
85
|
-
if (controlToken)
|
|
86
|
-
headers['x-evolcore-control-token'] = controlToken;
|
|
87
|
-
}
|
|
88
|
-
catch { }
|
|
89
|
-
const resp = await fetch(`http://127.0.0.1:${port}/api/pair-code`, {
|
|
90
|
-
headers,
|
|
91
|
-
signal: AbortSignal.timeout(2000),
|
|
92
|
-
});
|
|
93
|
-
if (!resp.ok)
|
|
71
|
+
const response = await ipcQuery(resolvePaths().socket, {
|
|
72
|
+
type: 'remote-auth.pair-code',
|
|
73
|
+
...(authorizedBy?.trim() ? { authorizedBy: authorizedBy.trim() } : {}),
|
|
74
|
+
}, 2_000);
|
|
75
|
+
if (!response?.ok || typeof response.code !== 'string' || typeof response.expiresAt !== 'number')
|
|
94
76
|
return null;
|
|
95
|
-
return
|
|
77
|
+
return { code: response.code, expiresAt: response.expiresAt };
|
|
96
78
|
}
|
|
97
79
|
catch {
|
|
98
80
|
return null;
|
|
@@ -38,6 +38,7 @@ export var ErrorType;
|
|
|
38
38
|
ErrorType["STREAM_ERROR"] = "stream_error";
|
|
39
39
|
ErrorType["CONTEXT_TOO_LONG"] = "context_too_long";
|
|
40
40
|
ErrorType["MODEL_UNAVAILABLE"] = "model_unavailable";
|
|
41
|
+
ErrorType["SESSION_UNAVAILABLE"] = "session_unavailable";
|
|
41
42
|
ErrorType["SANDBOX_INITIALIZATION_FAILED"] = "sandbox_initialization_failed";
|
|
42
43
|
ErrorType["CLAUDE_STARTUP_ARGUMENTS_TOO_LONG"] = "claude_startup_arguments_too_long";
|
|
43
44
|
ErrorType["UNKNOWN"] = "unknown";
|
|
@@ -278,6 +279,9 @@ function hasRetryableHttpStatus(text) {
|
|
|
278
279
|
}
|
|
279
280
|
export function classifyError(error) {
|
|
280
281
|
const msg = (error?.message || '').toLowerCase();
|
|
282
|
+
if (error?.code === 'TOPIC_BACKEND_UNAVAILABLE') {
|
|
283
|
+
return ErrorType.SESSION_UNAVAILABLE;
|
|
284
|
+
}
|
|
281
285
|
// Startup-size failures are deterministic local failures and must win over
|
|
282
286
|
// dictionary rules that would otherwise turn them into generic retries.
|
|
283
287
|
if (isClaudeStartupArgumentsTooLong(error)) {
|
|
@@ -380,13 +384,23 @@ export function getErrorMessage(error, terminalReason, includeEmoji = true) {
|
|
|
380
384
|
}
|
|
381
385
|
// 回退到原有的错误消息匹配逻辑
|
|
382
386
|
const msg = error?.message || String(error);
|
|
387
|
+
const warnPrefix = includeEmoji ? '⚠️ ' : '';
|
|
388
|
+
const errPrefix = includeEmoji ? '❌ ' : '';
|
|
389
|
+
// Codex app-server reports this when another app-server still owns the
|
|
390
|
+
// thread writer. Surface the handoff condition instead of hiding it behind
|
|
391
|
+
// the generic "processing failed" message.
|
|
392
|
+
if (error?.code === 'THREAD_ACTIVE_WRITER' || /already has an active writer/i.test(msg)) {
|
|
393
|
+
return `${warnPrefix}Codex 会话正在由另一个执行通道占用,请稍后重试(THREAD_ACTIVE_WRITER)`;
|
|
394
|
+
}
|
|
395
|
+
if (error?.code === 'TOPIC_BACKEND_UNAVAILABLE'
|
|
396
|
+
|| /bound topic backend is unavailable/i.test(msg)) {
|
|
397
|
+
return `${warnPrefix}当前会话已失效,请发送 /renew。`;
|
|
398
|
+
}
|
|
383
399
|
// 字典优先 — 命中且有自定义消息则直接返回
|
|
384
400
|
const rule = matchErrorRule(msg.toLowerCase());
|
|
385
401
|
if (rule?.message)
|
|
386
402
|
return rule.message;
|
|
387
403
|
// 内置兜底规则(结构性错误)
|
|
388
|
-
const warnPrefix = includeEmoji ? '⚠️ ' : '';
|
|
389
|
-
const errPrefix = includeEmoji ? '❌ ' : '';
|
|
390
404
|
if (msg.includes('CONTEXT_COMPACT_FAILED') || isContextTooLongText(msg)) {
|
|
391
405
|
const detail = msg.match(/^CONTEXT_COMPACT_FAILED:\s*(.+)$/)?.[1]?.trim();
|
|
392
406
|
return detail
|
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
{"model":"claude-opus-4-8","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":15,"price_output":75,"price_cache_creation":18.75,"price_cache_read":1.5}
|
|
2
|
-
{"model":"claude-opus-4-7","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":15,"price_output":75,"price_cache_creation":18.75,"price_cache_read":1.5}
|
|
3
|
-
{"model":"claude-opus-4-6","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":15,"price_output":75,"price_cache_creation":18.75,"price_cache_read":1.5}
|
|
4
|
-
{"model":"claude-sonnet-4-6","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":3,"price_output":15,"price_cache_creation":3.75,"price_cache_read":0.3}
|
|
5
|
-
{"model":"claude-haiku-4-5-20251001","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":0.8,"price_output":4,"price_cache_creation":1,"price_cache_read":0.08}
|
|
6
|
-
{"model":"gpt-5.6-sol","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":5,"price_output":30,"price_cache_creation":6.25,"price_cache_read":0.5,"tiers":[{"up_to_input_tokens":272000,"price_input":5,"price_output":30,"price_cache_creation":6.25,"price_cache_read":0.5},{"up_to_input_tokens":null,"price_input":10,"price_output":45,"price_cache_creation":12.5,"price_cache_read":1}]}
|
|
7
|
-
{"model":"gpt-5.6-terra","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":2.5,"price_output":15,"price_cache_creation":3.125,"price_cache_read":0.25,"tiers":[{"up_to_input_tokens":272000,"price_input":2.5,"price_output":15,"price_cache_creation":3.125,"price_cache_read":0.25},{"up_to_input_tokens":null,"price_input":5,"price_output":22.5,"price_cache_creation":6.25,"price_cache_read":0.5}]}
|
|
8
|
-
{"model":"gpt-5.6-luna","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":1,"price_output":6,"price_cache_creation":1.25,"price_cache_read":0.1,"tiers":[{"up_to_input_tokens":272000,"price_input":1,"price_output":6,"price_cache_creation":1.25,"price_cache_read":0.1},{"up_to_input_tokens":null,"price_input":2,"price_output":9,"price_cache_creation":2.5,"price_cache_read":0.2}]}
|
|
9
|
-
{"model":"gpt-5.5","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":5,"price_output":30,"price_cache_creation":0,"price_cache_read":0.5,"tiers":[{"up_to_input_tokens":272000,"price_input":5,"price_output":30,"price_cache_creation":0,"price_cache_read":0.5},{"up_to_input_tokens":null,"price_input":10,"price_output":45,"price_cache_creation":0,"price_cache_read":1}]}
|
|
10
|
-
{"model":"gpt-5.4","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":2.5,"price_output":15,"price_cache_creation":0,"price_cache_read":0.25,"tiers":[{"up_to_input_tokens":272000,"price_input":2.5,"price_output":15,"price_cache_creation":0,"price_cache_read":0.25},{"up_to_input_tokens":null,"price_input":5,"price_output":22.5,"price_cache_creation":0,"price_cache_read":0.5}]}
|
|
11
|
-
{"model":"gpt-5.3-codex","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":1.75,"price_output":14,"price_cache_creation":0,"price_cache_read":0.175}
|
|
12
|
-
{"model":"deepseek-v4-pro","effective_from":0,"billing_fn":"per_token_deepseek_v1","currency":"CNY","price_cache_hit":0.5,"price_cache_miss":2,"price_output":8}
|
|
13
|
-
{"model":"deepseek-v4-flash","effective_from":0,"billing_fn":"per_token_deepseek_v1","currency":"CNY","price_cache_hit":0.1,"price_cache_miss":0.5,"price_output":2}
|
|
14
|
-
{"model":"deepseek-v3.2","effective_from":0,"billing_fn":"per_token_deepseek_v1","currency":"CNY","price_cache_hit":0.5,"price_cache_miss":2,"price_output":8}
|
|
15
|
-
{"model":"kimi-k2.6","effective_from":0,"billing_fn":"per_token_v1","currency":"CNY","price_input":2,"price_output":8,"price_cache_creation":0,"price_cache_read":0}
|
|
16
|
-
{"model":"kimi-k2.5","effective_from":0,"billing_fn":"per_token_v1","currency":"CNY","price_input":2,"price_output":8,"price_cache_creation":0,"price_cache_read":0}
|
|
17
|
-
{"model":"glm-5.1","effective_from":0,"billing_fn":"per_token_v1","currency":"CNY","price_input":5,"price_output":20,"price_cache_creation":0,"price_cache_read":0}
|
|
18
|
-
{"model":"glm-5","effective_from":0,"billing_fn":"per_token_v1","currency":"CNY","price_input":5,"price_output":20,"price_cache_creation":0,"price_cache_read":0}
|
|
19
|
-
{"model":"glm-4.7","effective_from":0,"billing_fn":"per_token_v1","currency":"CNY","price_input":1,"price_output":5,"price_cache_creation":0,"price_cache_read":0}
|
|
20
|
-
{"model":"MiniMax-M2.7","effective_from":0,"billing_fn":"per_token_v1","currency":"CNY","price_input":1,"price_output":5,"price_cache_creation":0,"price_cache_read":0}
|
|
1
|
+
{"model":"claude-opus-4-8","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":15,"price_output":75,"price_cache_creation":18.75,"price_cache_read":1.5,"context_window":1000000,"max_input_tokens":900000,"max_output_tokens":32768,"supports_cache":true,"supports_vision":true}
|
|
2
|
+
{"model":"claude-opus-4-7","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":15,"price_output":75,"price_cache_creation":18.75,"price_cache_read":1.5,"context_window":1000000,"max_input_tokens":900000,"max_output_tokens":32768,"supports_cache":true,"supports_vision":true}
|
|
3
|
+
{"model":"claude-opus-4-6","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":15,"price_output":75,"price_cache_creation":18.75,"price_cache_read":1.5,"context_window":1000000,"max_input_tokens":900000,"max_output_tokens":32768,"supports_cache":true,"supports_vision":true}
|
|
4
|
+
{"model":"claude-sonnet-4-6","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":3,"price_output":15,"price_cache_creation":3.75,"price_cache_read":0.3,"context_window":200000,"max_input_tokens":180000,"max_output_tokens":16384,"supports_cache":true,"supports_vision":true}
|
|
5
|
+
{"model":"claude-haiku-4-5-20251001","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":0.8,"price_output":4,"price_cache_creation":1,"price_cache_read":0.08,"context_window":200000,"max_input_tokens":180000,"max_output_tokens":16384,"supports_cache":true,"supports_vision":false}
|
|
6
|
+
{"model":"gpt-5.6-sol","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":5,"price_output":30,"price_cache_creation":6.25,"price_cache_read":0.5,"tiers":[{"up_to_input_tokens":272000,"price_input":5,"price_output":30,"price_cache_creation":6.25,"price_cache_read":0.5},{"up_to_input_tokens":null,"price_input":10,"price_output":45,"price_cache_creation":12.5,"price_cache_read":1}],"context_window":200000,"max_input_tokens":180000,"max_output_tokens":16384}
|
|
7
|
+
{"model":"gpt-5.6-terra","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":2.5,"price_output":15,"price_cache_creation":3.125,"price_cache_read":0.25,"tiers":[{"up_to_input_tokens":272000,"price_input":2.5,"price_output":15,"price_cache_creation":3.125,"price_cache_read":0.25},{"up_to_input_tokens":null,"price_input":5,"price_output":22.5,"price_cache_creation":6.25,"price_cache_read":0.5}],"context_window":200000,"max_input_tokens":180000,"max_output_tokens":16384}
|
|
8
|
+
{"model":"gpt-5.6-luna","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":1,"price_output":6,"price_cache_creation":1.25,"price_cache_read":0.1,"tiers":[{"up_to_input_tokens":272000,"price_input":1,"price_output":6,"price_cache_creation":1.25,"price_cache_read":0.1},{"up_to_input_tokens":null,"price_input":2,"price_output":9,"price_cache_creation":2.5,"price_cache_read":0.2}],"context_window":200000,"max_input_tokens":180000,"max_output_tokens":16384}
|
|
9
|
+
{"model":"gpt-5.5","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":5,"price_output":30,"price_cache_creation":0,"price_cache_read":0.5,"tiers":[{"up_to_input_tokens":272000,"price_input":5,"price_output":30,"price_cache_creation":0,"price_cache_read":0.5},{"up_to_input_tokens":null,"price_input":10,"price_output":45,"price_cache_creation":0,"price_cache_read":1}],"context_window":200000,"max_input_tokens":180000,"max_output_tokens":16384}
|
|
10
|
+
{"model":"gpt-5.4","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":2.5,"price_output":15,"price_cache_creation":0,"price_cache_read":0.25,"tiers":[{"up_to_input_tokens":272000,"price_input":2.5,"price_output":15,"price_cache_creation":0,"price_cache_read":0.25},{"up_to_input_tokens":null,"price_input":5,"price_output":22.5,"price_cache_creation":0,"price_cache_read":0.5}],"context_window":200000,"max_input_tokens":180000,"max_output_tokens":16384}
|
|
11
|
+
{"model":"gpt-5.3-codex","effective_from":0,"billing_fn":"per_token_v1","currency":"USD","price_input":1.75,"price_output":14,"price_cache_creation":0,"price_cache_read":0.175,"context_window":200000,"max_input_tokens":180000,"max_output_tokens":16384}
|
|
12
|
+
{"model":"deepseek-v4-pro","effective_from":0,"billing_fn":"per_token_deepseek_v1","currency":"CNY","price_cache_hit":0.5,"price_cache_miss":2,"price_output":8,"context_window":1000000,"max_input_tokens":950000,"max_output_tokens":8192,"supports_cache":true}
|
|
13
|
+
{"model":"deepseek-v4-flash","effective_from":0,"billing_fn":"per_token_deepseek_v1","currency":"CNY","price_cache_hit":0.1,"price_cache_miss":0.5,"price_output":2,"context_window":1000000,"max_input_tokens":950000,"max_output_tokens":8192,"supports_cache":true}
|
|
14
|
+
{"model":"deepseek-v3.2","effective_from":0,"billing_fn":"per_token_deepseek_v1","currency":"CNY","price_cache_hit":0.5,"price_cache_miss":2,"price_output":8,"context_window":128000,"max_input_tokens":120000,"max_output_tokens":8192,"supports_cache":true}
|
|
15
|
+
{"model":"kimi-k2.6","effective_from":0,"billing_fn":"per_token_v1","currency":"CNY","price_input":2,"price_output":8,"price_cache_creation":0,"price_cache_read":0,"context_window":128000,"max_input_tokens":120000,"max_output_tokens":8192}
|
|
16
|
+
{"model":"kimi-k2.5","effective_from":0,"billing_fn":"per_token_v1","currency":"CNY","price_input":2,"price_output":8,"price_cache_creation":0,"price_cache_read":0,"context_window":128000,"max_input_tokens":120000,"max_output_tokens":8192}
|
|
17
|
+
{"model":"glm-5.1","effective_from":0,"billing_fn":"per_token_v1","currency":"CNY","price_input":5,"price_output":20,"price_cache_creation":0,"price_cache_read":0,"context_window":128000,"max_input_tokens":120000,"max_output_tokens":8192}
|
|
18
|
+
{"model":"glm-5","effective_from":0,"billing_fn":"per_token_v1","currency":"CNY","price_input":5,"price_output":20,"price_cache_creation":0,"price_cache_read":0,"context_window":128000,"max_input_tokens":120000,"max_output_tokens":8192}
|
|
19
|
+
{"model":"glm-4.7","effective_from":0,"billing_fn":"per_token_v1","currency":"CNY","price_input":1,"price_output":5,"price_cache_creation":0,"price_cache_read":0,"context_window":128000,"max_input_tokens":120000,"max_output_tokens":8192}
|
|
20
|
+
{"model":"MiniMax-M2.7","effective_from":0,"billing_fn":"per_token_v1","currency":"CNY","price_input":1,"price_output":5,"price_cache_creation":0,"price_cache_read":0,"context_window":128000,"max_input_tokens":120000,"max_output_tokens":8192}
|
|
21
|
+
{"model":"claude-opus-5","effective_from":0,"context_window":1000000,"max_input_tokens":900000,"max_output_tokens":131072,"supports_cache":true,"supports_vision":true}
|
|
22
|
+
{"model":"claude-sonnet-5","effective_from":0,"context_window":1000000,"max_input_tokens":900000,"max_output_tokens":131072,"supports_cache":true,"supports_vision":true}
|
|
23
|
+
{"model":"claude-fable-5","effective_from":0,"context_window":1000000,"max_input_tokens":900000,"max_output_tokens":131072,"supports_cache":true,"supports_vision":true}
|
package/dist/utils/npm-ops.js
CHANGED
|
@@ -14,7 +14,27 @@ import { getPackageRoot } from '../paths.js';
|
|
|
14
14
|
import { isWindows } from './cross-platform.js';
|
|
15
15
|
const execFileAsync = promisify(execFile);
|
|
16
16
|
// ── npm install -g (shared) ────────────────────────────────────────────────
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Can we run sudo without a password prompt?
|
|
19
|
+
*
|
|
20
|
+
* `sudo -n` never prompts: it exits non-zero instead when credentials are
|
|
21
|
+
* needed. That matters because upgrades run inside a detached monitor with no
|
|
22
|
+
* tty — a plain `sudo` there would block until the 180s timeout rather than
|
|
23
|
+
* fail. NOPASSWD rules and an unexpired credential cache both pass this check,
|
|
24
|
+
* so the cases where sudo can actually succeed are preserved.
|
|
25
|
+
*/
|
|
26
|
+
async function canSudoNonInteractively() {
|
|
27
|
+
if (isWindows)
|
|
28
|
+
return false;
|
|
29
|
+
try {
|
|
30
|
+
await execFileAsync('sudo', ['-n', 'true'], { timeout: 5000 });
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export async function npmInstallGlobal(pkg, options = {}) {
|
|
18
38
|
let cmd;
|
|
19
39
|
let args;
|
|
20
40
|
// Windows: run via cmd /c to avoid shell:true deprecation warning on Node 22.
|
|
@@ -28,14 +48,27 @@ export async function npmInstallGlobal(pkg) {
|
|
|
28
48
|
args = ['install', '-g', pkg];
|
|
29
49
|
}
|
|
30
50
|
try {
|
|
31
|
-
await execFileAsync(cmd, args, {
|
|
51
|
+
await execFileAsync(cmd, args, {
|
|
52
|
+
timeout: options.timeoutMs ?? 180000,
|
|
53
|
+
windowsHide: isWindows,
|
|
54
|
+
signal: options.signal,
|
|
55
|
+
});
|
|
32
56
|
}
|
|
33
57
|
catch (e) {
|
|
58
|
+
if (options.signal?.aborted)
|
|
59
|
+
throw e;
|
|
34
60
|
if (e.stderr?.includes('EACCES') || e.message?.includes('EACCES')) {
|
|
35
61
|
if (isWindows) {
|
|
36
62
|
throw new Error('权限不足。请以管理员身份运行 PowerShell 或 CMD,然后重试');
|
|
37
63
|
}
|
|
38
|
-
await
|
|
64
|
+
if (!await canSudoNonInteractively()) {
|
|
65
|
+
throw new Error(`权限不足,且 sudo 需要密码(当前进程无法交互输入)。请手动执行: sudo npm install -g ${pkg}`);
|
|
66
|
+
}
|
|
67
|
+
await execFileAsync('sudo', ['-n', 'npm', 'install', '-g', pkg], {
|
|
68
|
+
timeout: options.timeoutMs ?? 180000,
|
|
69
|
+
windowsHide: false,
|
|
70
|
+
signal: options.signal,
|
|
71
|
+
});
|
|
39
72
|
}
|
|
40
73
|
else {
|
|
41
74
|
throw e;
|
|
@@ -119,15 +152,19 @@ export function resolveGlobalPkg(pkgName) {
|
|
|
119
152
|
* 使用 HTTP fetch 直接查 registry API,不依赖 npm CLI。
|
|
120
153
|
* 超时 10 秒,失败返回 null。
|
|
121
154
|
*/
|
|
122
|
-
export async function checkLatestVersion(pkg = 'evolcore') {
|
|
155
|
+
export async function checkLatestVersion(pkg = 'evolcore', timeoutMs = 10000, signal) {
|
|
156
|
+
const controller = new AbortController();
|
|
157
|
+
const abort = () => controller.abort();
|
|
158
|
+
if (signal?.aborted)
|
|
159
|
+
abort();
|
|
160
|
+
else
|
|
161
|
+
signal?.addEventListener('abort', abort, { once: true });
|
|
162
|
+
const timer = setTimeout(abort, timeoutMs);
|
|
123
163
|
try {
|
|
124
|
-
const controller = new AbortController();
|
|
125
|
-
const timer = setTimeout(() => controller.abort(), 10000);
|
|
126
164
|
const res = await fetch(`https://registry.npmjs.org/${pkg}/latest`, {
|
|
127
165
|
signal: controller.signal,
|
|
128
166
|
headers: { 'Accept': 'application/json' },
|
|
129
167
|
});
|
|
130
|
-
clearTimeout(timer);
|
|
131
168
|
if (!res.ok)
|
|
132
169
|
return null;
|
|
133
170
|
const data = await res.json();
|
|
@@ -136,20 +173,26 @@ export async function checkLatestVersion(pkg = 'evolcore') {
|
|
|
136
173
|
catch {
|
|
137
174
|
return null;
|
|
138
175
|
}
|
|
176
|
+
finally {
|
|
177
|
+
clearTimeout(timer);
|
|
178
|
+
signal?.removeEventListener('abort', abort);
|
|
179
|
+
}
|
|
139
180
|
}
|
|
140
181
|
/**
|
|
141
182
|
* 完整升级流程:检查 → 比较 → 安装(失败重试一次)
|
|
142
183
|
*/
|
|
143
|
-
export async function tryUpgrade() {
|
|
184
|
+
export async function tryUpgrade(options = {}) {
|
|
144
185
|
// 开发模式跳过
|
|
145
186
|
if (isLinkedInstall()) {
|
|
146
187
|
return { status: 'skipped' };
|
|
147
188
|
}
|
|
148
189
|
const localVer = getLocalVersion();
|
|
149
190
|
// 查询 registry
|
|
150
|
-
const remoteVer = await checkLatestVersion();
|
|
191
|
+
const remoteVer = await checkLatestVersion('evolcore', options.checkTimeoutMs, options.signal);
|
|
151
192
|
if (!remoteVer) {
|
|
152
|
-
return
|
|
193
|
+
return options.signal?.aborted
|
|
194
|
+
? { status: 'failed', from: localVer, error: 'Upgrade cancelled or timed out' }
|
|
195
|
+
: { status: 'skipped', error: 'Failed to check remote version' };
|
|
153
196
|
}
|
|
154
197
|
// 版本比较
|
|
155
198
|
if (compareVersions(localVer, remoteVer) >= 0) {
|
|
@@ -159,11 +202,16 @@ export async function tryUpgrade() {
|
|
|
159
202
|
let lastError;
|
|
160
203
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
161
204
|
try {
|
|
162
|
-
await npmInstallGlobal('evolcore@latest'
|
|
205
|
+
await npmInstallGlobal('evolcore@latest', {
|
|
206
|
+
timeoutMs: options.installTimeoutMs,
|
|
207
|
+
signal: options.signal,
|
|
208
|
+
});
|
|
163
209
|
return { status: 'upgraded', from: localVer, to: remoteVer };
|
|
164
210
|
}
|
|
165
211
|
catch (e) {
|
|
166
212
|
lastError = e.stderr || e.message || String(e);
|
|
213
|
+
if (options.signal?.aborted)
|
|
214
|
+
break;
|
|
167
215
|
}
|
|
168
216
|
}
|
|
169
217
|
return { status: 'failed', from: localVer, to: remoteVer, error: lastError };
|
|
@@ -173,7 +221,7 @@ export async function tryUpgrade() {
|
|
|
173
221
|
* 仅在包已安装时检查升级,未安装则跳过(resolveFn 返回 null)。
|
|
174
222
|
* 用于 EC Web 等真正独立于 EvolCore 的全局包。
|
|
175
223
|
*/
|
|
176
|
-
export async function tryUpgradeGlobalPkg(resolveInstalled, pkgName) {
|
|
224
|
+
export async function tryUpgradeGlobalPkg(resolveInstalled, pkgName, options = {}) {
|
|
177
225
|
if (isLinkedInstall()) {
|
|
178
226
|
return { status: 'skipped' };
|
|
179
227
|
}
|
|
@@ -182,9 +230,11 @@ export async function tryUpgradeGlobalPkg(resolveInstalled, pkgName) {
|
|
|
182
230
|
return { status: 'skipped' }; // not installed, skip
|
|
183
231
|
}
|
|
184
232
|
const localVer = installed.version;
|
|
185
|
-
const remoteVer = await checkLatestVersion(pkgName);
|
|
233
|
+
const remoteVer = await checkLatestVersion(pkgName, options.checkTimeoutMs, options.signal);
|
|
186
234
|
if (!remoteVer) {
|
|
187
|
-
return
|
|
235
|
+
return options.signal?.aborted
|
|
236
|
+
? { status: 'failed', from: localVer, error: 'Upgrade cancelled or timed out' }
|
|
237
|
+
: { status: 'skipped', error: 'Failed to check remote version' };
|
|
188
238
|
}
|
|
189
239
|
if (compareVersions(localVer, remoteVer) >= 0) {
|
|
190
240
|
return { status: 'no-update', from: localVer };
|
|
@@ -192,11 +242,16 @@ export async function tryUpgradeGlobalPkg(resolveInstalled, pkgName) {
|
|
|
192
242
|
let lastError;
|
|
193
243
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
194
244
|
try {
|
|
195
|
-
await npmInstallGlobal(`${pkgName}@latest
|
|
245
|
+
await npmInstallGlobal(`${pkgName}@latest`, {
|
|
246
|
+
timeoutMs: options.installTimeoutMs,
|
|
247
|
+
signal: options.signal,
|
|
248
|
+
});
|
|
196
249
|
return { status: 'upgraded', from: localVer, to: remoteVer };
|
|
197
250
|
}
|
|
198
251
|
catch (e) {
|
|
199
252
|
lastError = e.stderr || e.message || String(e);
|
|
253
|
+
if (options.signal?.aborted)
|
|
254
|
+
break;
|
|
200
255
|
}
|
|
201
256
|
}
|
|
202
257
|
return { status: 'failed', from: localVer, to: remoteVer, error: lastError };
|
|
@@ -693,7 +693,7 @@ export function configureWindowsAutostart(enabled, runtimeRoot) {
|
|
|
693
693
|
'/TN', WINDOWS_AUTOSTART_TASK_NAME,
|
|
694
694
|
'/SC', 'ONLOGON',
|
|
695
695
|
'/TR', taskCommand(scriptPath),
|
|
696
|
-
'/RL', '
|
|
696
|
+
'/RL', 'HIGHEST',
|
|
697
697
|
'/F',
|
|
698
698
|
];
|
|
699
699
|
const result = runSchtasks(args);
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
| `ec agent` | EvolAgent 生命周期 | 创建/启停/热重载/改配置 | 管理员(owner/admin) | `agent.md`;完整创建与 Bootstrap 见 `agent-create.md` |
|
|
38
38
|
| `ec contact` | Contact Book 与访问控制 | 申请添加、拉黑/解除拉黑、查拉黑 | Agent 当前私聊可申请添加;管理写操作按角色限制 | `contact.md` |
|
|
39
39
|
| `ec rpc` | 底层 AUN RPC(逃生通道) | 直接调协议方法 | 高级/兜底 | `rpc.md` |
|
|
40
|
+
| `ec menu-client` | 远程 Daemon Menu 请求 | 远程诊断/daemon 日志/监控/原始配置 | 非托管 eclink/运维主机 | `menu-client.md` |
|
|
40
41
|
|
|
41
42
|
## 会话自管理类(不连 AUN,操作当前会话)
|
|
42
43
|
|
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
本手册用于创建一个能正常工作的 EvolAgent。创建者负责创建和观察状态;新 Agent 在自己的 Bootstrap 会话中完成首次设定。不要把创建流水线完成误认为 Agent 已激活。
|
|
4
4
|
|
|
5
|
+
### AID 与 Owner 约定
|
|
6
|
+
|
|
7
|
+
- AID 必须是 `{name}.{issuer}`,例如 `helper.agentid.cn`;不要使用四级域名(如 `helper.team.agentid.cn`),也不要把显示名当作 AID。
|
|
8
|
+
- `--owner` 填写需求提出者或实际责任 Owner 的完整 AID,而不是默认填写当前执行者。创建者只是代办创建流程时,仍应保留需求提出者的 Owner 权限。
|
|
9
|
+
|
|
5
10
|
## 生命周期与完成标准
|
|
6
11
|
|
|
7
12
|
```text
|
|
@@ -18,6 +23,8 @@ active
|
|
|
18
23
|
|
|
19
24
|
## 1. 创建者创建 Agent
|
|
20
25
|
|
|
26
|
+
多个 Agent 必须串行创建和观察。不要并行启动多个 `ec agent new`:证书、热加载和 Bootstrap 会竞争连接与资源,容易造成超时、锁等待或把失败误判为未创建。
|
|
27
|
+
|
|
21
28
|
在独立终端可以使用交互模式:
|
|
22
29
|
|
|
23
30
|
```bash
|
|
@@ -56,6 +63,8 @@ ec agent show helper.agentid.pub
|
|
|
56
63
|
|
|
57
64
|
如果是 menu 创建,`accepted=true` 只表示请求已受理。继续轮询 `createProgress.status` 直到 `ready` 或 `failed`。这里的 `createProgress.status=ready` **只表示后台创建流水线结束,不等于 `lifecycle=active`**。
|
|
58
65
|
|
|
66
|
+
创建者应维护一个最小状态账本(可放在当前任务记录中),每个 Agent 至少记录:`aid`、需求 Owner、项目路径、创建请求是否受理、`createProgress.status`、`lifecycle`、本地 `agent.md` 是否存在/字段是否完整、名片是否已发布、最近错误、下一步和最后检查时间。重启或超时恢复时先按账本逐项核对实际状态,再决定续做,不按“上次命令是否返回”推断结果。
|
|
67
|
+
|
|
59
68
|
## 2. 触发 Bootstrap
|
|
60
69
|
|
|
61
70
|
当任一已启用 channel 可以联系 Owner 时,系统会向 Owner 发送固定的 Bootstrap 首条消息,并把生命周期从 `created` 切换为 `bootstrapping`。
|
|
@@ -136,6 +145,8 @@ ec agent get helper.agentid.pub lifecycle
|
|
|
136
145
|
ec agent show helper.agentid.pub
|
|
137
146
|
```
|
|
138
147
|
|
|
148
|
+
验证其它 Agent 的生命周期、配置和创建进度统一使用 `ec agent get/show/list`;`ec aid` 只用于身份、证书和名片操作,不要用 `ec aid` 代替 Agent 状态验证。
|
|
149
|
+
|
|
139
150
|
验收标准:
|
|
140
151
|
|
|
141
152
|
- `lifecycle` 为 `active`。
|
|
@@ -144,3 +155,5 @@ ec agent show helper.agentid.pub
|
|
|
144
155
|
- 新 Agent 能在新主会话中处理普通任务。
|
|
145
156
|
|
|
146
157
|
如果仍为 `created`,检查 channel 是否已能联系 Owner,必要时由 Owner 主动发送首条消息。如果仍为 `bootstrapping`,回到新 Agent 的 Bootstrap 会话完成字段确认、名片发布和 `ready`,不要由创建者直接绕过引导。
|
|
158
|
+
|
|
159
|
+
失败重试前必须先执行状态检查:若本地 `agent.md` 已存在且远端名片已发布,只向该 Agent 发送 `ready`/续做指令,让它在自己的 Bootstrap 会话中完成收尾;不要重复创建、重复改名片或重复发布。仅在确认创建记录不存在且名片未发布时,才重新发起创建。
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
- `<self-aid>` 是当前 Agent 的 AID。托管 Agent 会话必须使用自己的 AID,不能代替其他 Agent 发起管理操作。
|
|
23
23
|
- 创建群的 Agent 自动成为群 owner。
|
|
24
|
+
- 需求发起者应设置为群 admin(若需求发起者就是创建者,则其已是 owner,无需另设)。
|
|
24
25
|
- owner/admin 负责邀请成员、设置角色、修改入群规则和发布 `/rules.md`。
|
|
25
26
|
- 普通 member 可以读取当前群信息、读取规则并参与协作;需要管理群成员或设置时,应请 owner/admin 操作。
|
|
26
27
|
- `dissolve` 和 `owner` 转让属于 owner 级操作,临时协作结束通常不需要解散群。
|
|
@@ -36,13 +37,13 @@
|
|
|
36
37
|
- 分工:谁负责协调、执行、复核和最终决策。
|
|
37
38
|
- 验收:完成条件、截止时间、交付路径和汇报频率。
|
|
38
39
|
|
|
39
|
-
使用 Owner 明确提供或已经可靠取得的完整 AID
|
|
40
|
+
使用 Owner 明确提供或已经可靠取得的完整 AID;AID 必须是 `{name}.{issuer}`,例如 `coordinator.agentid.cn`,不要使用四级域名或从显示名猜测 AID,也不要邀请尚未确认的对象。如果参与者、可见性或入群方式不明确,先向 Owner 补齐这些信息再创建群。
|
|
40
41
|
|
|
41
42
|
如果已经有合适的群,先用 `ec group list` 和 `ec group info` 检查,不要为每个任务重复建群。
|
|
42
43
|
|
|
43
44
|
## 2. 创建私有协作群
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
群名称必填。创建前根据群名称确定一个简短、唯一的 group AID(同样使用 `{name}.{issuer}`,不要四级域名),并给出一句群简介;名称、AID 和简介应能体现协作目标。推荐默认使用私有群和 `invite_only`,先建群再按名单邀请:
|
|
46
47
|
|
|
47
48
|
```bash
|
|
48
49
|
ec group create coordinator.agentid.pub "Project Alpha 协作" \
|
|
@@ -63,6 +64,8 @@ ec group rules coordinator.agentid.pub <group-id> --format json
|
|
|
63
64
|
|
|
64
65
|
## 3. 邀请成员并设置角色
|
|
65
66
|
|
|
67
|
+
先确认所有待协作 Agent 的 `lifecycle` 都是 `active`(使用 `ec agent get/show`,不要用 `ec aid`)。在此之前不要邀请成员,也不要发送或分派任务;Bootstrap 未完成的 Agent 不能稳定接收协作工作。
|
|
68
|
+
|
|
66
69
|
一次邀请多个成员:
|
|
67
70
|
|
|
68
71
|
```bash
|
|
@@ -100,6 +103,8 @@ ec group rules coordinator.agentid.pub <group-id> \
|
|
|
100
103
|
|
|
101
104
|
### 4.2 编写并发布 `/rules.md`
|
|
102
105
|
|
|
106
|
+
团队群必须先发布一份最小 `/rules.md`。至少明确四类职责:协调(拆解任务、同步状态、最终汇总)、侦察(收集资料和事实)、分析(比较方案、识别风险)、策略(做出取舍和升级决策)。可再补充具体成员映射、交付格式和升级路径。
|
|
107
|
+
|
|
103
108
|
在当前项目中准备一个不超过 4KB 的 UTF-8 Markdown 文件,例如 `project-alpha-rules.md`:
|
|
104
109
|
|
|
105
110
|
```markdown
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# ec menu-client — 远程 Daemon Menu 客户端
|
|
2
|
+
|
|
3
|
+
向另一台主机的 EvolCore Control AID 发送一个标准 `menu.*` 请求,并在同一 AUN 短连接中完成发送、拉取、匹配和 ACK。适合非托管主机上的 eclink/运维工具调用;托管 Agent 会话不应使用它绕过当前 daemon。
|
|
4
|
+
|
|
5
|
+
## 用法
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
ec menu-client request <from-aid> <daemon-aid> \
|
|
9
|
+
--request-file "$TMPDIR/menu-request.json" \
|
|
10
|
+
--timeout 15s \
|
|
11
|
+
--encrypt \
|
|
12
|
+
--format json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- `--request-file` 与 `--request-json` 二选一,内容是现有 Menu request;缺少 `id` 时自动生成 UUID。
|
|
16
|
+
- 默认使用 E2EE,并发送 `client_name=ec-menu-client` 和本机 EvolCore `client_version`。
|
|
17
|
+
- 默认 slot 是 `evolcore-menu-client`;`--app <slot>` 可覆盖,但会切换消费游标,调用方须自行串行化。
|
|
18
|
+
- 默认授权是远端 `daemon.json.owners` 对发送 AID 的校验。
|
|
19
|
+
- `--remote-token <token>` 使用 daemon 签发的远程访问 token,权限与 daemon-owner 一致。CLI 审计日志不会记录 token 明文。
|
|
20
|
+
- `--ecweb-token <token>` 是 `--remote-token` 的兼容别名。
|
|
21
|
+
- `menu.query` / `menu.options` 等待响应超时时自动重发一次相同 request id;写操作不自动重试。
|
|
22
|
+
- 成功时 stdout 是完整 `menu.response` JSON。远端业务错误仍在响应的 `error` 字段中;本地传输/超时/ACK 错误退出码非 0。
|
|
23
|
+
|
|
24
|
+
## 常用请求
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{"type":"menu.query","id":"status-1","name":"system","args":{"view":"status"}}
|
|
28
|
+
{"type":"menu.query","id":"monitor-1","name":"system","args":{"view":"monitor"}}
|
|
29
|
+
{"type":"menu.query","id":"logs-1","name":"system","args":{"view":"logs","source":"daemon","limit":200}}
|
|
30
|
+
{"type":"menu.options","id":"config-options-1","name":"config","args":{"option":"rawFile"}}
|
|
31
|
+
{"type":"menu.query","id":"config-1","name":"config","args":{"view":"rawFile","resource":"daemon"}}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
先用 `menu.list` 的 `args.view=catalog`、`context.kind=process` 获取目标 daemon 实际支持的能力和 wire 参数,不要在适配器中另建一套协议字段。
|
|
@@ -531,7 +531,15 @@ function planMigration(home) {
|
|
|
531
531
|
function assertDaemonStopped(home) {
|
|
532
532
|
const candidates = [];
|
|
533
533
|
const pidFile = path.join(home, 'daemon.pid');
|
|
534
|
-
|
|
534
|
+
try {
|
|
535
|
+
// daemon.pid is a retired legacy marker. Ignore directory/symlink residue
|
|
536
|
+
// so a sandbox-created directory cannot turn migration into EISDIR.
|
|
537
|
+
if (fs.lstatSync(pidFile).isFile()) {
|
|
538
|
+
candidates.push({ pid: Number(fs.readFileSync(pidFile, 'utf8').trim()), source: pidFile });
|
|
539
|
+
}
|
|
540
|
+
} catch (error) {
|
|
541
|
+
if (error?.code !== 'ENOENT') throw error;
|
|
542
|
+
}
|
|
535
543
|
const instanceDir = path.join(home, 'data', 'instance');
|
|
536
544
|
if (fs.existsSync(instanceDir)) {
|
|
537
545
|
for (const name of fs.readdirSync(instanceDir)) {
|
|
@@ -452,11 +452,17 @@ function changeRecord(home, file, kind, beforeText, after) {
|
|
|
452
452
|
function assertDaemonStopped(home) {
|
|
453
453
|
const candidates = [];
|
|
454
454
|
const legacyPidFile = path.join(home, 'daemon.pid');
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
455
|
+
try {
|
|
456
|
+
// daemon.pid is a retired legacy marker. Ignore directory/symlink residue
|
|
457
|
+
// so a sandbox-created directory cannot turn migration into EISDIR.
|
|
458
|
+
if (fs.lstatSync(legacyPidFile).isFile()) {
|
|
459
|
+
candidates.push({
|
|
460
|
+
pid: Number(fs.readFileSync(legacyPidFile, 'utf8').trim()),
|
|
461
|
+
source: legacyPidFile,
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
} catch (error) {
|
|
465
|
+
if (error?.code !== 'ENOENT') throw error;
|
|
460
466
|
}
|
|
461
467
|
|
|
462
468
|
const instanceDir = path.join(home, 'data', 'instance');
|
|
@@ -200,8 +200,14 @@ function planMigration(home) {
|
|
|
200
200
|
function assertDaemonStopped(home) {
|
|
201
201
|
const candidates = [];
|
|
202
202
|
const pidFile = path.join(home, 'daemon.pid');
|
|
203
|
-
|
|
204
|
-
|
|
203
|
+
try {
|
|
204
|
+
// daemon.pid is a retired legacy marker. Ignore directory/symlink residue
|
|
205
|
+
// so a sandbox-created directory cannot turn migration into EISDIR.
|
|
206
|
+
if (fs.lstatSync(pidFile).isFile()) {
|
|
207
|
+
candidates.push({ pid: Number(fs.readFileSync(pidFile, 'utf8').trim()), source: pidFile });
|
|
208
|
+
}
|
|
209
|
+
} catch (error) {
|
|
210
|
+
if (error?.code !== 'ENOENT') throw error;
|
|
205
211
|
}
|
|
206
212
|
const instanceDir = path.join(home, 'data', 'instance');
|
|
207
213
|
if (fs.existsSync(instanceDir)) {
|
|
@@ -58,6 +58,8 @@
|
|
|
58
58
|
"scopes": ["agent"],
|
|
59
59
|
"constraints": { "targetCurrentAgentOnly": true, "requireAgentAdmin": true }
|
|
60
60
|
},
|
|
61
|
+
"ec.aid.lookup": { "allow": true, "scopes": ["agent"] },
|
|
62
|
+
"ec.aid.agentmd.get": { "allow": true, "scopes": ["agent"] },
|
|
61
63
|
"ec.aid.agentmd.put": {
|
|
62
64
|
"allow": true,
|
|
63
65
|
"dangerous": true,
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"model.list": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
|
|
22
22
|
"model.current": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
|
|
23
23
|
"model.info": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
|
|
24
|
+
"model.effort.current": { "allow": true, "scopes": ["relation"], "constraints": { "ownPeerOnly": true, "targetCurrentAgentOnly": true } },
|
|
24
25
|
"model.use": { "allow": false },
|
|
25
26
|
"model.effort": { "allow": false },
|
|
26
27
|
"model.reset": { "allow": false },
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
phase: bootstrapping
|
|
3
3
|
|
|
4
4
|
这是 agent 生命周期的强制门禁。你正在进行首次自我设定;在完成前,唯一目标是和 owner 确认并写入基础名片信息,不处理普通任务。
|
|
5
|
-
|
|
5
|
+
Bootstrap 不另设隐藏状态机;恢复依据是可核对的生命周期和名片状态。每次重启、超时恢复或收到“继续”时,先检查自身 `lifecycle` 以及本地 `agent.md` 是否存在、字段是否完整,再决定续做步骤,不按旧上下文推断尚未完成。
|
|
6
6
|
系统已经在进入本阶段时向 owner 发送过固定的首条引导消息。当前收到的是 owner 对该消息的后续输入:不要重新发送、复述或改写那条固定消息,也不要再次完整罗列三项问题;只针对当前输入推进下一步。
|
|
7
7
|
|
|
8
8
|
需要确认的字段:
|
|
@@ -17,6 +17,13 @@ phase: bootstrapping
|
|
|
17
17
|
- `ec agent ready {{selfAid}}`
|
|
18
18
|
- 除这些 bootstrap 操作及向 owner 回复外,不得调用工具或执行命令。
|
|
19
19
|
|
|
20
|
+
恢复时遵循以下幂等规则:
|
|
21
|
+
- `lifecycle=active`:Bootstrap 已完成,不重复改名片、不重复发布、不重复执行 `ready`,也不处理本轮夹带的普通任务。
|
|
22
|
+
- `lifecycle=created`:尚未进入 Bootstrap,只等待 channel/owner 首条消息;不重复创建 Agent。
|
|
23
|
+
- `lifecycle=bootstrapping` 且本地 `agent.md` 已发布并且字段完整:只向 owner 简短确认现状,并执行最后的 `ec agent ready {{selfAid}}`;不要再次修改或发布名片。
|
|
24
|
+
- `lifecycle=bootstrapping` 但名片未发布或字段不完整:从缺失的确认步骤继续。发布失败时先说明错误,修正后再试,不盲目重试。
|
|
25
|
+
- Bootstrap 期间不执行、不分析、不规划普通任务;普通任务只能留到 `active` 后的新主会话。
|
|
26
|
+
|
|
20
27
|
每轮处理规则:
|
|
21
28
|
1. 首次需要候选值时,读取本地 agent.md 的 YAML frontmatter。已有且格式有效的 `name`、`description`、`tags` 是现有候选值:简短回显并询问保持还是修改,不要求重新输入。空值、占位值或格式无效的字段视为缺失;`tags` 必须为 3 到 6 个非空标签。
|
|
22
29
|
2. 只把 owner 明确提供、修改、选择或确认的 `name`、`description`、`tags` 当作候选信息。普通任务内容、示例值和顺带提及的词语都不是候选信息,不得据此推断字段。
|