evolcore 0.0.25 → 0.0.27
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 +632 -565
- package/LICENSE +21 -21
- package/README.md +455 -455
- package/bin/codex-managed-acl.ps1 +203 -160
- package/bin/codex-managed-hook.mjs +208 -208
- package/bin/ec-safe-output.js +327 -327
- package/bin/ec.js +40 -29
- package/bin/install-codex-managed-hooks.mjs +582 -555
- package/dist/agents/baseagent-availability.js +68 -0
- package/dist/agents/baseagent.js +96 -46
- package/dist/agents/claude-runner.js +172 -33
- package/dist/agents/codex/app-server-client.js +76 -31
- package/dist/agents/codex/catalog.js +1 -1
- package/dist/agents/codex/diagnostics.js +34 -1
- package/dist/agents/codex-runner.js +434 -446
- package/dist/agents/ecagent-runner.js +174 -34
- package/dist/agents/gemini-runner.js +8 -7
- package/dist/agents/runner-types.js +75 -19
- package/dist/aun/aid/agentmd.js +151 -36
- package/dist/aun/aid/client.js +1 -1
- package/dist/aun/aid/control-aid.js +180 -1
- package/dist/aun/aid/identity.js +4 -4
- package/dist/aun/aid/index.js +1 -1
- package/dist/aun/aid/store.js +17 -13
- package/dist/aun/group/history.js +303 -0
- package/dist/aun/group/identity.js +43 -0
- package/dist/aun/group/index.js +5 -0
- package/dist/aun/{msg/group.js → group/operations.js} +162 -39
- package/dist/aun/{menu-client.js → menu/client.js} +85 -6
- package/dist/aun/menu/index.js +2 -0
- package/dist/aun/menu/transport.js +49 -0
- package/dist/aun/msg/index.js +2 -1
- package/dist/aun/msg/managed-operation.js +85 -19
- package/dist/aun/msg/mention-schema.js +51 -0
- package/dist/aun/msg/p2p.js +19 -9
- package/dist/aun/msg/upload.js +43 -80
- package/dist/aun/outbox.js +29 -7
- package/dist/aun/rpc/client.js +1 -0
- package/dist/aun/storage/client.js +39 -50
- package/dist/channels/aun.js +842 -318
- package/dist/channels/daemon.js +10 -6
- package/dist/cli/agent-command.js +212 -89
- package/dist/cli/agent-create.js +626 -11
- package/dist/cli/agent.js +125 -13
- package/dist/cli/aun-commands.js +487 -337
- package/dist/cli/bench.js +20 -20
- package/dist/cli/config.js +55 -33
- package/dist/cli/contact.js +72 -15
- package/dist/cli/ctl-command.js +24 -24
- package/dist/cli/daemon-commands.js +140 -63
- package/dist/cli/diag.js +31 -0
- package/dist/cli/fs-command.js +70 -70
- package/dist/cli/handoff-command.js +46 -14
- package/dist/cli/index.js +91 -79
- package/dist/cli/init.js +34 -1
- package/dist/cli/link-rules.js +21 -21
- package/dist/cli/managed-command-guard.js +5 -1
- package/dist/cli/menu-client.js +51 -32
- package/dist/cli/model.js +3 -3
- package/dist/cli/net-check.js +22 -22
- package/dist/cli/queue-command.js +31 -31
- package/dist/cli/response.js +32 -32
- package/dist/cli/restart-monitor.js +103 -42
- package/dist/cli/stats.js +51 -51
- package/dist/cli/task-command.js +59 -0
- package/dist/cli/task-context.js +97 -49
- package/dist/cli/trigger-command.js +74 -64
- package/dist/config/builtin-roles.js +11 -0
- package/dist/config/config-field-policy.js +11 -0
- package/dist/config/config-manager.js +32 -4
- package/dist/config/config-operation-service.js +160 -0
- package/dist/config/contact-book-store.js +1 -1
- package/dist/config/contact-book.js +1 -1
- package/dist/config/contact-operation-service.js +97 -8
- package/dist/config/peer-role-resolver.js +1 -1
- package/dist/config/resolved-config-op.js +30 -7
- package/dist/config-store.js +1 -1
- package/dist/core/agent-application-service.js +7 -1
- package/dist/core/audit/event-key.js +17 -2
- package/dist/core/audit/log-integrity.js +34 -8
- package/dist/core/auth/agent-delegation.js +48 -14
- package/dist/core/auth/auth-gateway.js +2 -0
- package/dist/core/auth/authorization-audit.js +53 -49
- package/dist/core/auth/operation-authorizer.js +90 -7
- package/dist/core/auth/operation-catalog.js +145 -4
- package/dist/core/auth/remote-access-store.js +155 -10
- package/dist/core/bootstrap-messages.js +66 -7
- package/dist/core/bootstrap-service.js +111 -20
- package/dist/core/command/agent-control.js +88 -7
- package/dist/core/command/agent-storage-menu.js +443 -0
- package/dist/core/command/cli-intent-parser.js +19 -0
- package/dist/core/command/command-handler.js +159 -65
- package/dist/core/command/data-root-resolver.js +273 -0
- package/dist/core/command/diag-service.js +118 -0
- package/dist/core/command/group-menu.js +7 -2
- package/dist/core/command/menu-catalog.js +46 -7
- package/dist/core/command/menu-handler.js +392 -100
- package/dist/core/command/menu-protocol.js +45 -6
- package/dist/core/command/menu-token-store.js +41 -8
- package/dist/core/command/role-menu.js +2 -2
- package/dist/core/command/slash-gate.js +34 -4
- package/dist/core/command/slash-handler.js +123 -43
- package/dist/core/event-catalog.js +4 -0
- package/dist/core/evolagent-registry.js +28 -2
- package/dist/core/group/invite-service.js +924 -0
- package/dist/core/handoff/runtime.js +205 -27
- package/dist/core/handoff/store.js +193 -4
- package/dist/core/interaction-router.js +22 -8
- package/dist/core/message/im-renderer.js +146 -34
- package/dist/core/message/message-bridge.js +163 -20
- package/dist/core/message/message-log.js +5 -3
- package/dist/core/message/message-queue.js +99 -41
- package/dist/core/message/message-utils.js +1 -0
- package/dist/core/message/response-engine.js +755 -144
- package/dist/core/model/catalog-service.js +79 -49
- package/dist/core/model/context-window-suffix.js +33 -0
- package/dist/core/model/model-catalog.js +1 -1
- package/dist/core/model/model-permission.js +12 -3
- package/dist/core/permission/approval-gateway.js +36 -3
- package/dist/core/permission/ec-command-parser.js +112 -41
- package/dist/core/permission/protected-paths.js +134 -16
- package/dist/core/permission/sandbox-runtime.js +108 -17
- package/dist/core/permission/tool-error-code.js +15 -0
- package/dist/core/permission/tool-policy.js +9 -8
- package/dist/core/relation/peer-identity.js +57 -6
- package/dist/core/relation/shared-data.js +106 -0
- package/dist/core/role/runtime-policy.js +64 -0
- package/dist/core/runtime-lock.js +10 -26
- package/dist/core/session/runner-task-history.js +170 -0
- package/dist/core/session/session-manager.js +34 -6
- package/dist/core/session/session-mapper.js +41 -0
- package/dist/core/session/session-turn-coordinator.js +37 -7
- package/dist/core/session/session-turns.js +48 -7
- package/dist/core/task/task-recovery-service.js +176 -0
- package/dist/core/task/task-resume-operation.js +32 -0
- package/dist/eck/group-rules-sync.js +5 -3
- package/dist/eck/kit-renderer.js +1 -0
- package/dist/index.js +588 -217
- package/dist/ipc.js +193 -15
- package/dist/paths.js +17 -4
- package/dist/product.js +2 -0
- package/dist/response-system/engines/v1/proactive-flow.js +59 -2
- package/dist/stats/billing.js +41 -15
- package/dist/stats/db.js +159 -159
- package/dist/stats/eck-vars.js +9 -9
- package/dist/stats/price-resolver.js +28 -10
- package/dist/stats/query.js +139 -139
- package/dist/stats/role-budget.js +6 -6
- package/dist/stats/writer.js +51 -51
- package/dist/trigger/event-source.js +19 -0
- package/dist/trigger/feedback.js +233 -40
- package/dist/trigger/parser.js +55 -5
- package/dist/trigger/patch.js +9 -0
- package/dist/trigger/scheduler.js +30 -4
- package/dist/trigger/validation.js +20 -3
- package/dist/utils/cross-platform.js +30 -1
- package/dist/utils/ecweb-utils.js +1 -0
- package/dist/utils/error-dict.json +160 -160
- package/dist/utils/error-utils.js +61 -2
- package/dist/utils/evolcore-version.js +129 -0
- package/dist/utils/logger.js +26 -14
- package/dist/utils/macos-autostart.js +22 -22
- package/dist/utils/model-prices.jsonl +23 -23
- package/dist/utils/npm-ops.js +176 -35
- package/dist/utils/tool-summary.js +59 -3
- package/dist/utils/welcome.js +196 -23
- package/ecagent/LICENSE +21 -21
- package/ecagent/NOTICE +11 -11
- package/ecagent/README.md +61 -61
- package/ecagent/dist/harness/agent-harness.js +3 -0
- package/ecagent/dist/harness/compaction/branch-summarization.js +30 -30
- package/ecagent/dist/harness/compaction/compaction.js +83 -83
- package/ecagent/dist/harness/messages.js +7 -7
- package/ecagent/dist/harness/session/jsonl-storage.js +21 -2
- package/kits/docs/GUIDE.md +20 -20
- package/kits/docs/INDEX.md +60 -66
- package/kits/docs/aun/CHEATSHEET.md +19 -19
- package/kits/docs/aun/SYNC_PROTOCOL.md +15 -15
- package/kits/docs/channels/aun.md +69 -56
- package/kits/docs/channels/feishu.md +56 -56
- package/kits/docs/context-assembly.md +379 -367
- package/kits/docs/eck_templates/GUIDE.template.md +22 -22
- package/kits/docs/eck_templates/INDEX.template.md +28 -28
- package/kits/docs/eck_templates/path-registry.template.md +33 -33
- package/kits/docs/eck_templates/runtime.template.md +19 -19
- package/kits/docs/evolcore/INDEX.md +76 -71
- package/kits/docs/evolcore/agent-create.md +202 -165
- package/kits/docs/evolcore/agent.md +99 -67
- package/kits/docs/evolcore/aid.md +68 -60
- package/kits/docs/evolcore/codex-windows-sandbox.md +146 -146
- package/kits/docs/evolcore/config.md +241 -195
- package/kits/docs/evolcore/contact.md +75 -68
- package/kits/docs/evolcore/ctl.md +46 -46
- package/kits/docs/evolcore/event.md +216 -216
- package/kits/docs/evolcore/fs-architecture.md +1215 -1215
- package/kits/docs/evolcore/fs.md +110 -110
- package/kits/docs/evolcore/group-collaboration.md +244 -244
- package/kits/docs/evolcore/group-fs.md +17 -17
- package/kits/docs/evolcore/group-rules.md +251 -251
- package/kits/docs/evolcore/group.md +267 -152
- package/kits/docs/evolcore/menu-client.md +58 -34
- package/kits/docs/evolcore/model.md +50 -50
- package/kits/docs/evolcore/msg.md +169 -165
- package/kits/docs/evolcore/response.md +75 -75
- package/kits/docs/evolcore/rpc.md +37 -37
- package/kits/docs/evolcore/self-summary.md +29 -29
- package/kits/docs/evolcore/stats.md +83 -83
- package/kits/docs/evolcore/storage.md +53 -50
- package/kits/docs/evolcore/task.md +14 -0
- package/kits/docs/evolcore/trigger.md +623 -575
- package/kits/docs/identity/AID_PROFILE_SPEC.md +26 -26
- package/kits/docs/identity/PATH_OPS.md +16 -16
- package/kits/docs/identity/ROLE_DETAIL.md +25 -25
- package/kits/docs/identity/identity-tools.md +26 -26
- package/kits/docs/path-registry.md +62 -62
- package/kits/docs/prompt-loading-architecture.md +269 -269
- package/kits/docs/venues/aun-group.md +45 -45
- package/kits/docs/venues/aun-private.md +10 -10
- package/kits/docs/venues/client-desktop.md +10 -10
- package/kits/docs/venues/client-mobile.md +10 -10
- package/kits/docs/venues/feishu-group.md +13 -13
- package/kits/docs/venues/feishu-private.md +9 -9
- package/kits/docs/venues/group.md +42 -25
- package/kits/docs/venues/private.md +10 -10
- package/kits/eck_manifest.auxiliary.json +43 -43
- package/kits/eck_manifest.json +217 -190
- package/kits/eck_message_manifest.json +74 -74
- package/kits/migrations/README-role-config-v4.md +32 -32
- package/kits/migrations/migrate-contact-book-v2.mjs +748 -748
- package/kits/migrations/migrate-role-config-v4.mjs +614 -614
- package/kits/migrations/migrate-role-config-v5.mjs +365 -365
- package/kits/migrations/rename-config-file.mjs +99 -99
- package/kits/rules/01-overview.md +166 -162
- package/kits/rules/02-navigation.md +96 -96
- package/kits/rules/03-identity.md +36 -36
- package/kits/rules/04-relation.md +76 -75
- package/kits/rules/05-venue.md +60 -60
- package/kits/rules/06-channel.md +65 -63
- package/kits/schemas/_meta.json +53 -53
- package/kits/schemas/agent-config.schema.1.json +177 -177
- package/kits/schemas/agent-config.schema.10.json +395 -395
- package/kits/schemas/agent-config.schema.11.json +421 -421
- package/kits/schemas/agent-config.schema.12.json +451 -427
- package/kits/schemas/agent-config.schema.2.json +239 -239
- package/kits/schemas/agent-config.schema.3.json +119 -119
- package/kits/schemas/agent-config.schema.4.json +208 -208
- package/kits/schemas/agent-config.schema.5.json +326 -326
- package/kits/schemas/agent-config.schema.6.json +322 -322
- package/kits/schemas/agent-config.schema.7.json +303 -303
- package/kits/schemas/agent-config.schema.8.json +304 -304
- package/kits/schemas/agent-config.schema.9.json +364 -364
- package/kits/schemas/contact-book.schema.1.json +36 -36
- package/kits/schemas/contact-book.schema.2.json +43 -43
- package/kits/schemas/contact-book.schema.3.json +67 -67
- package/kits/schemas/daemon.schema.1.json +91 -91
- package/kits/schemas/daemon.schema.2.json +101 -101
- package/kits/schemas/daemon.schema.3.json +123 -123
- package/kits/schemas/daemon.schema.4.json +136 -136
- package/kits/schemas/daemon.schema.5.json +135 -135
- package/kits/schemas/daemon.schema.6.json +131 -131
- package/kits/schemas/defaults.schema.1.json +81 -81
- package/kits/schemas/defaults.schema.2.json +85 -85
- package/kits/schemas/defaults.schema.3.json +73 -73
- package/kits/schemas/defaults.schema.4.json +107 -107
- package/kits/schemas/defaults.schema.5.json +119 -119
- package/kits/schemas/menu-exec-schema-commands.md +208 -208
- package/kits/schemas/migrations/README.md +30 -30
- package/kits/schemas/relation-config.schema.1.json +158 -158
- package/kits/schemas/relation-config.schema.2.json +73 -73
- package/kits/schemas/relation-config.schema.3.json +50 -50
- package/kits/schemas/relation-config.schema.4.json +47 -47
- package/kits/schemas/relation-config.schema.5.json +47 -47
- package/kits/schemas/relation-config.schema.6.json +46 -46
- package/kits/schemas/relation-config.schema.7.json +59 -59
- package/kits/schemas/relation-config.schema.8.json +103 -103
- package/kits/schemas/role-config.schema.1.json +215 -201
- package/kits/schemas/role-registry.schema.1.json +35 -35
- package/kits/schemas/single-session.schema.1.json +31 -31
- package/kits/schemas/single-session.schema.2.json +57 -57
- package/kits/schemas/single-session.schema.3.json +32 -32
- package/kits/templates/bootstrap-welcome.md +17 -17
- package/kits/templates/message-fragments/handoff-context-to-target.md +9 -9
- package/kits/templates/message-fragments/handoff-request-to-target.md +19 -19
- package/kits/templates/message-fragments/handoff-response-to-origin.md +9 -9
- package/kits/templates/message-fragments/inject-default.md +2 -2
- package/kits/templates/message-fragments/item.md +2 -2
- package/kits/templates/roles/admin.json +92 -92
- package/kits/templates/roles/member.json +101 -96
- package/kits/templates/roles/owner.json +9 -9
- package/kits/templates/roles/visitor.json +90 -85
- package/kits/templates/system-fragments/baseagent.md +14 -14
- package/kits/templates/system-fragments/bootstrap.md +53 -34
- package/kits/templates/system-fragments/channel.md +28 -64
- package/kits/templates/system-fragments/commands.md +36 -28
- package/kits/templates/system-fragments/group-unread-history.md +7 -0
- package/kits/templates/system-fragments/identity.md +13 -13
- package/kits/templates/system-fragments/relation.md +19 -19
- package/kits/templates/system-fragments/reply.md +56 -0
- package/kits/templates/system-fragments/session.md +59 -59
- package/kits/templates/system-fragments/venue.md +31 -31
- package/package.json +104 -98
- package/dist/aun/group-identity.js +0 -9
- /package/dist/aun/{group-fs-download.js → group/fs-download.js} +0 -0
- /package/dist/aun/{msg/group-index.js → group/index-rpc.js} +0 -0
package/dist/ipc.js
CHANGED
|
@@ -5,13 +5,14 @@ import fs from 'fs';
|
|
|
5
5
|
import crypto from 'crypto';
|
|
6
6
|
import os from 'os';
|
|
7
7
|
import path from 'path';
|
|
8
|
+
import { execFile } from 'node:child_process';
|
|
8
9
|
import { logger } from './utils/logger.js';
|
|
9
10
|
import { withMenuProcessingTime, logMenuRequestCompleted, logMenuRequestReceived } from './core/command/menu-protocol.js';
|
|
10
11
|
import { fileCache } from './core/daemon-file-cache.js';
|
|
11
12
|
import { DAEMON_RUNTIME_EPOCH_ENV } from './cli/task-context.js';
|
|
12
13
|
import { HANDOFF_QUERY_MAX_LIMIT, HANDOFF_STATES } from './core/handoff/types.js';
|
|
13
14
|
import { AgentReloadBusyError } from './core/agent-reload-coordinator.js';
|
|
14
|
-
import { getWindowsInstanceSocketPathCandidates, normalizeIpcEndpoint, resolvePaths } from './paths.js';
|
|
15
|
+
import { getPackageRoot, getWindowsInstanceSocketPathCandidates, normalizeIpcEndpoint, resolvePaths } from './paths.js';
|
|
15
16
|
import { getProcessStartTime, isSameOrOlderProcess } from './utils/process-introspect.js';
|
|
16
17
|
import { classifyProcessTree, ProcessTreeSampler, readProcessMetrics } from './utils/process-tree-stats.js';
|
|
17
18
|
import { readSystemMemoryUsage } from './utils/system-memory.js';
|
|
@@ -73,10 +74,42 @@ function nextIpcQueryId(cmd) {
|
|
|
73
74
|
return `ipc-${ipcQuerySequence}`;
|
|
74
75
|
}
|
|
75
76
|
function requiresLocalControlToken(cmd) {
|
|
76
|
-
// Managed
|
|
77
|
-
//
|
|
78
|
-
return LOCAL_CONTROL_COMMANDS.has(String(cmd.type ?? ''))
|
|
79
|
-
|| (
|
|
77
|
+
// Managed calls use task delegation. Standalone queries must not gain
|
|
78
|
+
// management scope merely by omitting (or emptying) sessionId.
|
|
79
|
+
return cmd.type === 'evolagent.initialize' || LOCAL_CONTROL_COMMANDS.has(String(cmd.type ?? ''))
|
|
80
|
+
|| (['evolagent.bootstrapComplete', 'diag', 'handoff-status', 'handoff-list', 'handoff-trace', 'task.resume'].includes(String(cmd.type))
|
|
81
|
+
&& !(typeof cmd.sessionId === 'string' && cmd.sessionId.trim()));
|
|
82
|
+
}
|
|
83
|
+
/** Preserve the pipe DACL and grant only the provisioned Codex users data I/O. */
|
|
84
|
+
function grantWindowsSandboxPipeAccess(endpoint) {
|
|
85
|
+
const powershell = path.join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'WindowsPowerShell', 'v1.0', 'powershell.exe');
|
|
86
|
+
const request = Buffer.from(JSON.stringify({ action: 'pipe', path: endpoint })).toString('base64');
|
|
87
|
+
return new Promise((resolve, reject) => {
|
|
88
|
+
// Asynchronous: the ACL helper connects as a client, so Node must keep
|
|
89
|
+
// accepting pipe instances while it runs. Never interpolate shell source.
|
|
90
|
+
execFile(powershell, ['-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass',
|
|
91
|
+
'-File', path.join(getPackageRoot(), 'bin', 'codex-managed-acl.ps1'), '-Request', request], { windowsHide: true, timeout: 15_000, maxBuffer: 64 * 1024 }, (error, stdout, stderr) => {
|
|
92
|
+
if (error) {
|
|
93
|
+
reject(new Error(`Windows IPC sandbox ACL setup failed: ${stderr.trim() || error.message}`));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const result = JSON.parse(stdout.replace(/^\uFEFF/, '').trim());
|
|
98
|
+
if (!Array.isArray(result.granted))
|
|
99
|
+
throw new Error('invalid ACL helper response');
|
|
100
|
+
if (result.granted.length) {
|
|
101
|
+
logger.info(`[IPC] Sandbox pipe access granted to ${result.granted.join(', ')}`);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
logger.info('[IPC] Codex sandbox accounts are not provisioned; restart daemon after Windows sandbox setup');
|
|
105
|
+
}
|
|
106
|
+
resolve();
|
|
107
|
+
}
|
|
108
|
+
catch (parseError) {
|
|
109
|
+
reject(parseError);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
});
|
|
80
113
|
}
|
|
81
114
|
export function summarizeMonitorAgents(agents, aids) {
|
|
82
115
|
const connectedAgents = new Set(aids.filter(aid => aid.status === 'connected').map(aid => aid.agentName || aid.aid));
|
|
@@ -102,21 +135,28 @@ export class IpcServer {
|
|
|
102
135
|
aunAidStatsRecorder;
|
|
103
136
|
menuExecutor;
|
|
104
137
|
agentOperationExecutor;
|
|
138
|
+
initializationExecutor;
|
|
105
139
|
statsProvider;
|
|
106
140
|
agentStatsProvider;
|
|
107
141
|
queueSnapshotProvider;
|
|
108
142
|
queueActionExecutor;
|
|
109
143
|
queueOperationExecutor;
|
|
110
144
|
statusAuthorizationExecutor;
|
|
145
|
+
taskResumeExecutor;
|
|
111
146
|
storageAuthorizationExecutor;
|
|
147
|
+
storageUploadExecutor;
|
|
112
148
|
triggerExecutor;
|
|
113
149
|
bootstrapCompleteExecutor;
|
|
114
150
|
agentReloadExecutor;
|
|
115
151
|
shutdownExecutor;
|
|
116
152
|
taskRuntimeContextProvider;
|
|
153
|
+
taskRuntimeContextAuthorizer;
|
|
117
154
|
codexPreToolUseExecutor;
|
|
118
155
|
aunMsgSender;
|
|
156
|
+
diagExecutor;
|
|
157
|
+
menuClientExecutor;
|
|
119
158
|
handoffReturnExecutor;
|
|
159
|
+
handoffRecoverReturnExecutor;
|
|
120
160
|
handoffStatusExecutor;
|
|
121
161
|
handoffListExecutor;
|
|
122
162
|
handoffTraceExecutor;
|
|
@@ -135,6 +175,8 @@ export class IpcServer {
|
|
|
135
175
|
controlToken;
|
|
136
176
|
daemonRuntimeEpoch;
|
|
137
177
|
remoteAccessService = remoteAccessService;
|
|
178
|
+
/** Current daemon owner used to bind locally issued ECWeb pairing codes. */
|
|
179
|
+
remoteAccessOwnerProvider;
|
|
138
180
|
// CPU 占用追踪:IPC handler 是一次性同步调用,无法在响应里做 200ms 异步采样,
|
|
139
181
|
// 故用后台 1s interval 累积 process.cpuUsage() 增量,handler 直接读最近值。
|
|
140
182
|
// procCpuPercent = 本 daemon 进程占单核的百分比(可 >100% 仅当多核,已 clamp 到 100);
|
|
@@ -189,6 +231,15 @@ export class IpcServer {
|
|
|
189
231
|
setRemoteAccessService(service) {
|
|
190
232
|
this.remoteAccessService = service;
|
|
191
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Supply the live process-level owner for pairing requests that do not carry
|
|
236
|
+
* an explicit owner (for example `ec watch web` and the ECWeb supervisor).
|
|
237
|
+
* The provider is evaluated for every request so owner updates take effect
|
|
238
|
+
* without restarting ECWeb.
|
|
239
|
+
*/
|
|
240
|
+
setRemoteAccessOwnerProvider(provider) {
|
|
241
|
+
this.remoteAccessOwnerProvider = provider;
|
|
242
|
+
}
|
|
192
243
|
/** Set the process-lifetime marker used to reject stale managed children. */
|
|
193
244
|
setDaemonRuntimeEpoch(epoch) {
|
|
194
245
|
this.daemonRuntimeEpoch = epoch;
|
|
@@ -197,6 +248,9 @@ export class IpcServer {
|
|
|
197
248
|
setMenuExecutor(executor) {
|
|
198
249
|
this.menuExecutor = executor;
|
|
199
250
|
}
|
|
251
|
+
setInitializationExecutor(executor) {
|
|
252
|
+
this.initializationExecutor = executor;
|
|
253
|
+
}
|
|
200
254
|
setAgentOperationExecutor(executor) {
|
|
201
255
|
this.agentOperationExecutor = executor;
|
|
202
256
|
}
|
|
@@ -340,9 +394,15 @@ export class IpcServer {
|
|
|
340
394
|
setStatusAuthorizationExecutor(executor) {
|
|
341
395
|
this.statusAuthorizationExecutor = executor;
|
|
342
396
|
}
|
|
397
|
+
setTaskResumeExecutor(executor) {
|
|
398
|
+
this.taskResumeExecutor = executor;
|
|
399
|
+
}
|
|
343
400
|
setStorageAuthorizationExecutor(executor) {
|
|
344
401
|
this.storageAuthorizationExecutor = executor;
|
|
345
402
|
}
|
|
403
|
+
setStorageUploadExecutor(executor) {
|
|
404
|
+
this.storageUploadExecutor = executor;
|
|
405
|
+
}
|
|
346
406
|
/** Inject daemon-level trigger executor for ec trigger. */
|
|
347
407
|
setTriggerExecutor(executor) {
|
|
348
408
|
this.triggerExecutor = executor;
|
|
@@ -355,6 +415,9 @@ export class IpcServer {
|
|
|
355
415
|
setTaskRuntimeContextProvider(provider) {
|
|
356
416
|
this.taskRuntimeContextProvider = provider;
|
|
357
417
|
}
|
|
418
|
+
setTaskRuntimeContextAuthorizer(authorizer) {
|
|
419
|
+
this.taskRuntimeContextAuthorizer = authorizer;
|
|
420
|
+
}
|
|
358
421
|
setCodexPreToolUseExecutor(executor) {
|
|
359
422
|
this.codexPreToolUseExecutor = executor;
|
|
360
423
|
}
|
|
@@ -362,10 +425,15 @@ export class IpcServer {
|
|
|
362
425
|
setAunMsgSender(sender) {
|
|
363
426
|
this.aunMsgSender = sender;
|
|
364
427
|
}
|
|
428
|
+
setDiagExecutor(executor) { this.diagExecutor = executor; }
|
|
429
|
+
setMenuClientExecutor(executor) { this.menuClientExecutor = executor; }
|
|
365
430
|
/** Inject internal handoff result return executor for `ec handoff return`. */
|
|
366
431
|
setHandoffReturnExecutor(executor) {
|
|
367
432
|
this.handoffReturnExecutor = executor;
|
|
368
433
|
}
|
|
434
|
+
setHandoffRecoverReturnExecutor(executor) {
|
|
435
|
+
this.handoffRecoverReturnExecutor = executor;
|
|
436
|
+
}
|
|
369
437
|
setHandoffStatusExecutor(executor) {
|
|
370
438
|
this.handoffStatusExecutor = executor;
|
|
371
439
|
}
|
|
@@ -773,8 +841,17 @@ export class IpcServer {
|
|
|
773
841
|
}
|
|
774
842
|
catch { }
|
|
775
843
|
}
|
|
776
|
-
|
|
777
|
-
|
|
844
|
+
const permissionsReady = isNamedPipe(this.socketPath)
|
|
845
|
+
? grantWindowsSandboxPipeAccess(this.socketPath)
|
|
846
|
+
: Promise.resolve();
|
|
847
|
+
void permissionsReady.then(() => {
|
|
848
|
+
logger.info(`[IPC] Listening on ${this.socketPath}`);
|
|
849
|
+
resolve();
|
|
850
|
+
}, error => {
|
|
851
|
+
this.stop();
|
|
852
|
+
logger.error('[IPC] Unable to configure pipe permissions:', error);
|
|
853
|
+
reject(error);
|
|
854
|
+
});
|
|
778
855
|
});
|
|
779
856
|
});
|
|
780
857
|
}
|
|
@@ -795,11 +872,10 @@ export class IpcServer {
|
|
|
795
872
|
if (requiresLocalControlToken(cmd) && !this.hasValidControlToken(cmd.controlToken)) {
|
|
796
873
|
return { ok: false, code: 'INVALID_CONTROL_TOKEN', error: 'valid local control token is required' };
|
|
797
874
|
}
|
|
798
|
-
if (typeof cmd.
|
|
799
|
-
&& typeof cmd.delegationToken === 'string' && cmd.delegationToken
|
|
875
|
+
if (typeof cmd.delegationToken === 'string' && cmd.delegationToken
|
|
800
876
|
&& this.daemonRuntimeEpoch
|
|
801
877
|
&& cmd.daemonRuntimeEpoch !== this.daemonRuntimeEpoch) {
|
|
802
|
-
logger.warn(`[IPC] stale delegation rejected: session=${ipcLogToken(cmd.sessionId)} type=${ipcLogToken(cmd.type)} cause=daemon_runtime_epoch_mismatch`);
|
|
878
|
+
logger.warn(`[IPC] stale delegation rejected: session=${ipcLogToken(cmd.sessionId ?? cmd.originSessionId ?? cmd.actorSessionId)} type=${ipcLogToken(cmd.type)} cause=daemon_runtime_epoch_mismatch`);
|
|
803
879
|
return {
|
|
804
880
|
ok: false,
|
|
805
881
|
code: 'DAEMON_RESTARTED',
|
|
@@ -807,6 +883,10 @@ export class IpcServer {
|
|
|
807
883
|
};
|
|
808
884
|
}
|
|
809
885
|
switch (cmd.type) {
|
|
886
|
+
case 'diag':
|
|
887
|
+
return this.diagExecutor ? this.diagExecutor(cmd) : { ok: false, code: 'NOT_CONFIGURED', message: '诊断入口未配置' };
|
|
888
|
+
case 'menu-client.request':
|
|
889
|
+
return this.menuClientExecutor ? this.menuClientExecutor(cmd) : { ok: false, code: 'NOT_CONFIGURED', error: 'Managed Menu client is not configured' };
|
|
810
890
|
case 'model.catalog': {
|
|
811
891
|
if ((cmd.self !== undefined && typeof cmd.self !== 'string')
|
|
812
892
|
|| (cmd.baseagent !== undefined && !['claude', 'codex', 'ecagent', 'gemini'].includes(cmd.baseagent))) {
|
|
@@ -887,14 +967,21 @@ export class IpcServer {
|
|
|
887
967
|
});
|
|
888
968
|
}
|
|
889
969
|
case 'remote-auth.pair-code': {
|
|
890
|
-
|
|
970
|
+
// IPC issues local codes. Owner-authenticated /pair and Menu paths
|
|
971
|
+
// supply provenance in-process, never from a caller-supplied source.
|
|
972
|
+
if (cmd.source !== undefined && cmd.source !== 'host-cli' && cmd.source !== 'ecweb-local') {
|
|
973
|
+
return { ok: false, code: 'INVALID_ARGUMENT', error: 'invalid local pairing source' };
|
|
974
|
+
}
|
|
975
|
+
const requestedOwner = typeof cmd.authorizedBy === 'string' ? cmd.authorizedBy.trim() : undefined;
|
|
976
|
+
const authorizedBy = requestedOwner || this.remoteAccessOwnerProvider?.();
|
|
977
|
+
const pair = this.remoteAccessService.getPairingCode(authorizedBy, Date.now(), cmd.source ?? 'host-cli');
|
|
891
978
|
return { ok: true, ...pair };
|
|
892
979
|
}
|
|
893
980
|
case 'remote-auth.issue-local': {
|
|
894
981
|
return this.remoteAccessService.issueLocalToken(cmd.label);
|
|
895
982
|
}
|
|
896
983
|
case 'remote-auth.redeem': {
|
|
897
|
-
return this.remoteAccessService.redeemPairingCode(cmd.code, cmd.label
|
|
984
|
+
return this.remoteAccessService.redeemPairingCode(cmd.code, cmd.label);
|
|
898
985
|
}
|
|
899
986
|
case 'remote-auth.validate': {
|
|
900
987
|
return { ok: true, ...this.remoteAccessService.validateToken(cmd.token) };
|
|
@@ -1068,6 +1155,25 @@ export class IpcServer {
|
|
|
1068
1155
|
delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
|
|
1069
1156
|
});
|
|
1070
1157
|
}
|
|
1158
|
+
case 'storage.upload': {
|
|
1159
|
+
if (!this.storageUploadExecutor)
|
|
1160
|
+
return { ok: false, code: 'NOT_CONFIGURED', error: 'storage upload not configured' };
|
|
1161
|
+
if (typeof cmd.sessionId !== 'string' || !cmd.sessionId
|
|
1162
|
+
|| typeof cmd.aid !== 'string' || !cmd.aid
|
|
1163
|
+
|| typeof cmd.localFile !== 'string' || !cmd.localFile
|
|
1164
|
+
|| typeof cmd.remotePath !== 'string' || !cmd.remotePath) {
|
|
1165
|
+
return { ok: false, code: 'INVALID_REQUEST', error: 'missing sessionId, aid, localFile, or remotePath' };
|
|
1166
|
+
}
|
|
1167
|
+
return await this.storageUploadExecutor({
|
|
1168
|
+
sessionId: cmd.sessionId,
|
|
1169
|
+
aid: cmd.aid,
|
|
1170
|
+
localFile: cmd.localFile,
|
|
1171
|
+
remotePath: cmd.remotePath,
|
|
1172
|
+
isPublic: cmd.isPublic === true,
|
|
1173
|
+
delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
|
|
1174
|
+
delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1071
1177
|
case 'aun-aid-stats-record-outbound': {
|
|
1072
1178
|
if (!this.aunAidStatsRecorder)
|
|
1073
1179
|
return { ok: false, error: 'recorder not configured' };
|
|
@@ -1085,15 +1191,55 @@ export class IpcServer {
|
|
|
1085
1191
|
return { ok: false, error: String(e?.message || e) };
|
|
1086
1192
|
}
|
|
1087
1193
|
}
|
|
1194
|
+
case 'task.resume': {
|
|
1195
|
+
const allowed = new Set(['type', 'targetSessionId', 'sessionId', 'delegationToken',
|
|
1196
|
+
'delegationCommandHash', 'controlToken', 'daemonRuntimeEpoch', 'requestId', 'id']);
|
|
1197
|
+
if (Object.keys(cmd).some(key => !allowed.has(key))
|
|
1198
|
+
|| typeof cmd.targetSessionId !== 'string' || !cmd.targetSessionId.trim()
|
|
1199
|
+
|| (cmd.sessionId !== undefined && (typeof cmd.sessionId !== 'string' || !cmd.sessionId.trim()))) {
|
|
1200
|
+
return { ok: false, code: 'INVALID_REQUEST', error: 'task.resume accepts only a target session and caller credentials' };
|
|
1201
|
+
}
|
|
1202
|
+
if (cmd.sessionId && (typeof cmd.delegationToken !== 'string' || !cmd.delegationToken)) {
|
|
1203
|
+
return { ok: false, code: 'DELEGATION_REQUIRED', error: 'managed task resume requires a delegation token' };
|
|
1204
|
+
}
|
|
1205
|
+
if (!this.taskResumeExecutor)
|
|
1206
|
+
return { ok: false, code: 'NOT_CONFIGURED', error: 'task.resume not configured' };
|
|
1207
|
+
try {
|
|
1208
|
+
return await this.taskResumeExecutor({
|
|
1209
|
+
targetSessionId: cmd.targetSessionId,
|
|
1210
|
+
sessionId: cmd.sessionId,
|
|
1211
|
+
delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
|
|
1212
|
+
delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
|
|
1213
|
+
localControl: !cmd.sessionId && this.hasValidControlToken(cmd.controlToken),
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
catch (error) {
|
|
1217
|
+
return { ok: false, code: 'TASK_RESUME_FAILED', error: error instanceof Error ? error.message : String(error) };
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1088
1220
|
case 'task-runtime-context': {
|
|
1089
1221
|
if (!this.taskRuntimeContextProvider)
|
|
1090
1222
|
return { ok: false, error: 'task runtime context not configured' };
|
|
1091
1223
|
if (!cmd.sessionId || typeof cmd.sessionId !== 'string')
|
|
1092
1224
|
return { ok: false, error: 'missing sessionId' };
|
|
1225
|
+
if (!this.taskRuntimeContextAuthorizer) {
|
|
1226
|
+
return { ok: false, code: 'DELEGATION_REQUIRED', error: 'task runtime context authorization is not configured' };
|
|
1227
|
+
}
|
|
1228
|
+
const authorization = this.taskRuntimeContextAuthorizer({
|
|
1229
|
+
sessionId: cmd.sessionId,
|
|
1230
|
+
delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
|
|
1231
|
+
delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
|
|
1232
|
+
});
|
|
1233
|
+
if (!authorization.ok)
|
|
1234
|
+
return authorization;
|
|
1093
1235
|
const context = this.taskRuntimeContextProvider({ sessionId: cmd.sessionId }) ?? null;
|
|
1094
1236
|
return { ok: true, context };
|
|
1095
1237
|
}
|
|
1096
1238
|
case 'aun-msg-send': {
|
|
1239
|
+
if (cmd.handoffContext !== undefined && (typeof cmd.handoffContext !== 'string'
|
|
1240
|
+
|| !cmd.handoffContext.trim() || cmd.handoffContext.length > 64 * 1024 || cmd.scope === 'group')) {
|
|
1241
|
+
return { ok: false, code: 'INVALID_HANDOFF_CONTEXT', error: 'Private handoff context must contain 1–65536 characters' };
|
|
1242
|
+
}
|
|
1097
1243
|
if (!this.aunMsgSender)
|
|
1098
1244
|
return { ok: false, error: 'aun msg sender not configured' };
|
|
1099
1245
|
if (!cmd.aid || typeof cmd.aid !== 'string')
|
|
@@ -1148,6 +1294,7 @@ export class IpcServer {
|
|
|
1148
1294
|
encrypt: typeof cmd.encrypt === 'boolean' ? cmd.encrypt : undefined,
|
|
1149
1295
|
thread: typeof cmd.thread === 'string' ? cmd.thread : undefined,
|
|
1150
1296
|
returnPolicy: cmd.returnPolicy === 'required' || cmd.returnPolicy === 'none' ? cmd.returnPolicy : undefined,
|
|
1297
|
+
handoffContext: cmd.handoffContext,
|
|
1151
1298
|
originSessionId: typeof cmd.originSessionId === 'string' ? cmd.originSessionId : undefined,
|
|
1152
1299
|
originMessageId: typeof cmd.originMessageId === 'string' ? cmd.originMessageId : undefined,
|
|
1153
1300
|
delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
|
|
@@ -1177,6 +1324,28 @@ export class IpcServer {
|
|
|
1177
1324
|
return { ok: false, error: e?.message || String(e) };
|
|
1178
1325
|
}
|
|
1179
1326
|
}
|
|
1327
|
+
case 'handoff-recover-return': {
|
|
1328
|
+
if (!this.handoffRecoverReturnExecutor)
|
|
1329
|
+
return { ok: false, error: 'handoff recovery not configured' };
|
|
1330
|
+
if (typeof cmd.sessionId !== 'string' || !cmd.sessionId)
|
|
1331
|
+
return { ok: false, code: 'HANDOFF_CALL_SESSION_INVALID', error: 'missing sessionId' };
|
|
1332
|
+
if (typeof cmd.handoffId !== 'string' || !cmd.handoffId)
|
|
1333
|
+
return { ok: false, code: 'INVALID_HANDOFF_ID', error: 'missing handoff_id' };
|
|
1334
|
+
if (typeof cmd.content !== 'string')
|
|
1335
|
+
return { ok: false, code: 'HANDOFF_RETURN_CONTENT_REQUIRED', error: 'missing content' };
|
|
1336
|
+
try {
|
|
1337
|
+
return await this.handoffRecoverReturnExecutor({
|
|
1338
|
+
sessionId: cmd.sessionId,
|
|
1339
|
+
handoffId: cmd.handoffId,
|
|
1340
|
+
content: cmd.content,
|
|
1341
|
+
delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
|
|
1342
|
+
delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
catch (e) {
|
|
1346
|
+
return { ok: false, error: e?.message || String(e) };
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1180
1349
|
case 'handoff-status': {
|
|
1181
1350
|
if (!this.handoffStatusExecutor)
|
|
1182
1351
|
return { ok: false, code: 'HANDOFF_STATUS_UNAVAILABLE', error: 'handoff status not configured' };
|
|
@@ -1309,6 +1478,13 @@ export class IpcServer {
|
|
|
1309
1478
|
}
|
|
1310
1479
|
return await this.fsOperationExecutor(argv, sessionId, delegationToken, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
|
|
1311
1480
|
}
|
|
1481
|
+
case 'evolagent.initialize': {
|
|
1482
|
+
if (cmd.sessionId || cmd.delegationToken)
|
|
1483
|
+
return { ok: false, code: 'NOT_ALLOWED', error: 'Managed callers must use agent.op' };
|
|
1484
|
+
if (!this.initializationExecutor)
|
|
1485
|
+
return { ok: false, code: 'NOT_CONFIGURED', error: 'Initialization service unavailable' };
|
|
1486
|
+
return this.initializationExecutor(cmd);
|
|
1487
|
+
}
|
|
1312
1488
|
case 'agent.op': {
|
|
1313
1489
|
if (!this.agentOperationExecutor)
|
|
1314
1490
|
return { ok: false, code: 'NOT_CONFIGURED', error: 'agent.op not configured' };
|
|
@@ -1376,12 +1552,13 @@ export class IpcServer {
|
|
|
1376
1552
|
if (!this.bootstrapCompleteExecutor)
|
|
1377
1553
|
return { ok: false, error: 'bootstrap complete executor not configured' };
|
|
1378
1554
|
try {
|
|
1379
|
-
|
|
1555
|
+
const auth = {
|
|
1380
1556
|
sessionId: typeof cmd.sessionId === 'string' ? cmd.sessionId : undefined,
|
|
1381
1557
|
delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
|
|
1382
1558
|
delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
|
|
1383
1559
|
controlToken: typeof cmd.controlToken === 'string' ? cmd.controlToken : undefined,
|
|
1384
|
-
}
|
|
1560
|
+
};
|
|
1561
|
+
return await this.bootstrapCompleteExecutor(aid, auth);
|
|
1385
1562
|
}
|
|
1386
1563
|
catch (e) {
|
|
1387
1564
|
return { ok: false, error: e?.message || String(e) };
|
|
@@ -1548,7 +1725,7 @@ export class IpcTransportError extends Error {
|
|
|
1548
1725
|
endpoint;
|
|
1549
1726
|
constructor(code, endpoint) {
|
|
1550
1727
|
const hint = code === 'EPERM' || code === 'EACCES'
|
|
1551
|
-
? '
|
|
1728
|
+
? '权限被拒绝;请检查 IPC 端点权限及沙箱隔离。Windows 下同用户进程也可能因受限令牌无法连接命名管道。'
|
|
1552
1729
|
: code === 'ETIMEDOUT'
|
|
1553
1730
|
? '等待 daemon 响应超时;请求可能已执行,请先检查状态再重试。'
|
|
1554
1731
|
: code === 'ENOENT' || code === 'ECONNREFUSED'
|
|
@@ -1619,6 +1796,7 @@ function ipcQueryOnce(socketPath, cmd, timeoutMs = 3000) {
|
|
|
1619
1796
|
const request = {
|
|
1620
1797
|
...(delegationCommandHash ? { ...authenticatedCmd, delegationCommandHash } : authenticatedCmd),
|
|
1621
1798
|
...(process.env[DAEMON_RUNTIME_EPOCH_ENV]
|
|
1799
|
+
&& authenticatedCmd.daemonRuntimeEpoch === undefined
|
|
1622
1800
|
&& typeof authenticatedCmd.delegationToken === 'string'
|
|
1623
1801
|
? { daemonRuntimeEpoch: process.env[DAEMON_RUNTIME_EPOCH_ENV] }
|
|
1624
1802
|
: {}),
|
package/dist/paths.js
CHANGED
|
@@ -72,11 +72,11 @@ export function aunPath() {
|
|
|
72
72
|
export function aidsDir() {
|
|
73
73
|
return path.join(resolveRoot(), 'AIDs');
|
|
74
74
|
}
|
|
75
|
-
export function aidLocalDir(aid) {
|
|
76
|
-
return path.join(
|
|
75
|
+
export function aidLocalDir(aid, root = resolveRoot()) {
|
|
76
|
+
return path.join(root, 'AIDs', aid);
|
|
77
77
|
}
|
|
78
|
-
export function agentMdPath(aid) {
|
|
79
|
-
return path.join(
|
|
78
|
+
export function agentMdPath(aid, root = resolveRoot()) {
|
|
79
|
+
return path.join(root, 'AIDs', aid, 'agent.md');
|
|
80
80
|
}
|
|
81
81
|
// ── per-agent 路径(参数化,不进 resolvePaths() 的固定 map)──
|
|
82
82
|
export function agentDir(aid) {
|
|
@@ -94,6 +94,10 @@ export function agentContactOperations(aid) {
|
|
|
94
94
|
export function agentPersonalDir(aid) {
|
|
95
95
|
return path.join(agentDir(aid), 'personal');
|
|
96
96
|
}
|
|
97
|
+
/** Agent-owned Bootstrap completion welcome template. */
|
|
98
|
+
export function agentWelcomePath(aid) {
|
|
99
|
+
return path.join(agentPersonalDir(aid), 'welcome.md');
|
|
100
|
+
}
|
|
97
101
|
export function agentRolesDir(aid) {
|
|
98
102
|
return path.join(agentDir(aid), 'roles');
|
|
99
103
|
}
|
|
@@ -106,6 +110,12 @@ export function agentRoleConfig(aid, roleId) {
|
|
|
106
110
|
export function agentRelationsDir(aid) {
|
|
107
111
|
return path.join(agentDir(aid), 'relations');
|
|
108
112
|
}
|
|
113
|
+
export function agentRelationDir(aid, peerKey) {
|
|
114
|
+
return path.join(agentRelationsDir(aid), peerKey);
|
|
115
|
+
}
|
|
116
|
+
export function agentRelationSharedDir(aid, peerKey) {
|
|
117
|
+
return path.join(agentRelationDir(aid, peerKey), 'shared');
|
|
118
|
+
}
|
|
109
119
|
/** @deprecated Use agentRelationsDir instead */
|
|
110
120
|
export function agentIdentitiesDir(aid) {
|
|
111
121
|
return agentRelationsDir(aid);
|
|
@@ -128,6 +138,9 @@ export function agentDataCacheDir(aid) {
|
|
|
128
138
|
export function agentHandoffDir(aid) {
|
|
129
139
|
return path.join(agentDataDir(aid), 'handoff');
|
|
130
140
|
}
|
|
141
|
+
export function agentGroupInviteReviewsPath(aid) {
|
|
142
|
+
return path.join(agentDataDir(aid), 'aun', 'group-invite-reviews.json');
|
|
143
|
+
}
|
|
131
144
|
export function agentOutboxPath(aid) {
|
|
132
145
|
return path.join(resolvePaths().outboxDir, encodeURIComponent(aid), 'outbox.jsonl');
|
|
133
146
|
}
|
package/dist/product.js
CHANGED
|
@@ -14,6 +14,8 @@ export const MIN_ECWEB_VERSION = '0.0.8';
|
|
|
14
14
|
export const DAEMON_CONFIG_FILENAME = 'daemon.json';
|
|
15
15
|
export const DAEMON_SCHEMA_NAME = 'daemon';
|
|
16
16
|
export const RUNTIME_HOME_ENV = 'EVOLCORE_HOME';
|
|
17
|
+
export const SESSION_ID_ENV = 'EVOLCORE_SESSION_ID';
|
|
18
|
+
export const SELF_AID_ENV = 'EVOLCORE_SELF_AID';
|
|
17
19
|
export const DEFAULT_RUNTIME_HOME_DIRNAME = '.evolcore';
|
|
18
20
|
export const INSTANCE_SOCKET_FILENAME = 'daemon.sock';
|
|
19
21
|
export const WINDOWS_PIPE_PREFIX = 'daemon';
|
|
@@ -12,7 +12,18 @@ const STATE_KEY = 'proactive';
|
|
|
12
12
|
const TOOL_REPORT_INTERVAL = 10;
|
|
13
13
|
const SEND_RECEIPT_RE = /["']?(?:message[_ -]?id|handoff[_ -]?id)["']?\s*[:=]\s*["']?([A-Za-z0-9][A-Za-z0-9._:-]*)/gi;
|
|
14
14
|
const HANDOFF_TEXT_RECEIPT_RE = /\bhandoff\s+(h-[A-Za-z0-9._-]+)/i;
|
|
15
|
-
|
|
15
|
+
const RETURN_CONTENT_RE = /["']?(?:return[_ -]?content|returnContent)["']?\s*[:=]\s*["']?([^}\n,]*)/i;
|
|
16
|
+
function hasRequiredReturnFlag(toolInput) {
|
|
17
|
+
if (!toolInput || typeof toolInput !== 'object')
|
|
18
|
+
return false;
|
|
19
|
+
const input = toolInput;
|
|
20
|
+
const commandValues = ['command', 'cmd', 'script'].flatMap(key => {
|
|
21
|
+
const value = input[key];
|
|
22
|
+
return typeof value === 'string' ? [value] : [];
|
|
23
|
+
});
|
|
24
|
+
return commandValues.some(command => /(?:^|\s)--return(?:=|\s+)['"]?required(?:['"]?)(?=\s|$)/i.test(command));
|
|
25
|
+
}
|
|
26
|
+
function hasSuccessfulSendReceipt(result, isError, requiresBusinessReturn = false) {
|
|
16
27
|
if (isError === true)
|
|
17
28
|
return false;
|
|
18
29
|
const hasReceiptValue = (value) => {
|
|
@@ -40,6 +51,41 @@ function hasSuccessfulSendReceipt(result, isError) {
|
|
|
40
51
|
};
|
|
41
52
|
if (hasExplicitFailure(result, new Set()))
|
|
42
53
|
return false;
|
|
54
|
+
const isBusinessReturn = (value) => {
|
|
55
|
+
if (typeof value !== 'string')
|
|
56
|
+
return false;
|
|
57
|
+
const normalized = value.trim();
|
|
58
|
+
if (!normalized || /^(?:null|undefined|-)$/.test(normalized))
|
|
59
|
+
return false;
|
|
60
|
+
// Contact admission/refusal is a real reply, but it is not task completion.
|
|
61
|
+
if (/(?:当前不接受陌生人消息|可发送\s*\/request|contact\s+(?:required|request)|stranger message)/i.test(normalized))
|
|
62
|
+
return false;
|
|
63
|
+
return true;
|
|
64
|
+
};
|
|
65
|
+
const inspectBusinessReturn = (value, seen) => {
|
|
66
|
+
if (!value || typeof value !== 'object')
|
|
67
|
+
return false;
|
|
68
|
+
if (seen.has(value))
|
|
69
|
+
return false;
|
|
70
|
+
seen.add(value);
|
|
71
|
+
if (Array.isArray(value))
|
|
72
|
+
return value.some(item => inspectBusinessReturn(item, seen));
|
|
73
|
+
for (const [key, item] of Object.entries(value)) {
|
|
74
|
+
if ((key === 'return_content' || key === 'returnContent') && isBusinessReturn(item))
|
|
75
|
+
return true;
|
|
76
|
+
if (inspectBusinessReturn(item, seen))
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
};
|
|
81
|
+
if (requiresBusinessReturn) {
|
|
82
|
+
if (inspectBusinessReturn(result, new Set()))
|
|
83
|
+
return true;
|
|
84
|
+
const returnText = typeof result === 'string'
|
|
85
|
+
? result.match(RETURN_CONTENT_RE)?.[1]
|
|
86
|
+
: undefined;
|
|
87
|
+
return isBusinessReturn(returnText);
|
|
88
|
+
}
|
|
43
89
|
const inspect = (value, seen) => {
|
|
44
90
|
if (!value || typeof value !== 'object')
|
|
45
91
|
return false;
|
|
@@ -153,6 +199,11 @@ export const proactiveFlow = {
|
|
|
153
199
|
// Codex only invokes this hook for local tool paths. Hosted tools stay
|
|
154
200
|
// enabled and do not satisfy or clear the pending first-send gate.
|
|
155
201
|
const isSendCommand = ctx.isSendCommand(toolName, toolInput);
|
|
202
|
+
if (!isSendCommand && ((state.firstSendRequired && !state.firstToolDone) || state.toolReportPending)) {
|
|
203
|
+
const sendFailure = ctx.describeSendCommandFailure?.(toolName, toolInput);
|
|
204
|
+
if (sendFailure)
|
|
205
|
+
return { block: true, policyCode: 'proactive_send_invalid', reason: sendFailure };
|
|
206
|
+
}
|
|
156
207
|
if (state.firstSendRequired && !state.firstToolDone) {
|
|
157
208
|
if (!isSendCommand) {
|
|
158
209
|
const cmdHint = state.chatType === 'group' ? 'ec group send' : 'ec msg send';
|
|
@@ -221,7 +272,13 @@ export const proactiveFlow = {
|
|
|
221
272
|
return;
|
|
222
273
|
if (!ctx.isSendCommand(ctx.toolName, ctx.toolInput))
|
|
223
274
|
return;
|
|
224
|
-
|
|
275
|
+
const requiresBusinessReturn = hasRequiredReturnFlag(ctx.toolInput)
|
|
276
|
+
&& (typeof ctx.result === 'string'
|
|
277
|
+
? HANDOFF_TEXT_RECEIPT_RE.test(ctx.result)
|
|
278
|
+
: !!ctx.result && typeof ctx.result === 'object'
|
|
279
|
+
&& ('handoff_id' in ctx.result || 'handoffId' in ctx.result));
|
|
280
|
+
HANDOFF_TEXT_RECEIPT_RE.lastIndex = 0;
|
|
281
|
+
if (!hasSuccessfulSendReceipt(ctx.result, ctx.isError || !!ctx.error, requiresBusinessReturn))
|
|
225
282
|
return;
|
|
226
283
|
if (state.firstSendRequired && !state.firstToolDone)
|
|
227
284
|
state.firstToolDone = true;
|
package/dist/stats/billing.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import fs from 'fs';
|
|
6
6
|
import path from 'path';
|
|
7
7
|
import { getPackageRoot } from '../paths.js';
|
|
8
|
+
import { parseModelId, stripContextWindowSuffix } from '../core/model/context-window-suffix.js';
|
|
8
9
|
// 模型参数缓存(进程内,5 分钟 TTL)
|
|
9
10
|
let _parameterCache = null;
|
|
10
11
|
let _parameterCacheTs = 0;
|
|
@@ -79,21 +80,36 @@ function loadPrices(evolcoreHome) {
|
|
|
79
80
|
_priceCacheTs = now;
|
|
80
81
|
return _priceCache;
|
|
81
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* 按优先级列出一个模型 ID 的查表候选键。
|
|
85
|
+
*
|
|
86
|
+
* 上下文窗口变体(`claude-opus-5[1m]`)与基础模型同价,价表只需一条基础条目;
|
|
87
|
+
* 但仍先试精确匹配,好让用户能给某个变体单独定价。
|
|
88
|
+
*/
|
|
89
|
+
export function modelLookupKeys(evolcoreHome, model) {
|
|
90
|
+
const keys = [];
|
|
91
|
+
const push = (key) => { if (key && !keys.includes(key))
|
|
92
|
+
keys.push(key); };
|
|
93
|
+
push(model);
|
|
94
|
+
push(resolveCanonicalModel(evolcoreHome, model));
|
|
95
|
+
const base = stripContextWindowSuffix(model);
|
|
96
|
+
if (base !== model) {
|
|
97
|
+
push(base);
|
|
98
|
+
push(resolveCanonicalModel(evolcoreHome, base));
|
|
99
|
+
}
|
|
100
|
+
return keys;
|
|
101
|
+
}
|
|
82
102
|
/** 取 model 在 ts 时刻生效的价格行(effective_from <= ts 中最新的一条)。
|
|
83
|
-
*
|
|
103
|
+
* 精确匹配失败时,依次回落到 alias 规范 ID 和去掉窗口后缀的基础 ID。 */
|
|
84
104
|
export function resolvePriceRow(evolcoreHome, model, ts) {
|
|
85
105
|
const prices = loadPrices(evolcoreHome);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (canonical !== model) {
|
|
91
|
-
candidates = prices.filter(p => p.model === canonical && p.effective_from <= ts);
|
|
106
|
+
for (const key of modelLookupKeys(evolcoreHome, model)) {
|
|
107
|
+
const candidates = prices.filter(p => p.model === key && p.effective_from <= ts);
|
|
108
|
+
if (candidates.length) {
|
|
109
|
+
return candidates.reduce((a, b) => a.effective_from >= b.effective_from ? a : b);
|
|
92
110
|
}
|
|
93
111
|
}
|
|
94
|
-
|
|
95
|
-
return null;
|
|
96
|
-
return candidates.reduce((a, b) => a.effective_from >= b.effective_from ? a : b);
|
|
112
|
+
return null;
|
|
97
113
|
}
|
|
98
114
|
export const BILLING_FNS = {
|
|
99
115
|
// 通用 per-token(Claude / OpenAI 兼容 / Kimi / MiniMax)
|
|
@@ -164,14 +180,24 @@ function loadSpecs(evolcoreHome) {
|
|
|
164
180
|
_specCacheTs = now;
|
|
165
181
|
return _specCache;
|
|
166
182
|
}
|
|
167
|
-
/** 取模型在 ts 时刻的能力参数。找不到时返回默认值。
|
|
183
|
+
/** 取模型在 ts 时刻的能力参数。找不到时返回默认值。
|
|
184
|
+
* 带窗口后缀的 ID 复用基础模型的参数行,但窗口由后缀决定(网关的权威声明)。 */
|
|
168
185
|
export function resolveModelSpec(evolcoreHome, model, ts) {
|
|
169
186
|
const specs = loadSpecs(evolcoreHome);
|
|
170
187
|
const t = ts ?? Date.now();
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
188
|
+
const suffixWindow = parseModelId(model).contextWindow;
|
|
189
|
+
for (const key of modelLookupKeys(evolcoreHome, model)) {
|
|
190
|
+
const candidates = specs.filter(s => s.model === key && s.effective_from <= t);
|
|
191
|
+
if (!candidates.length)
|
|
192
|
+
continue;
|
|
193
|
+
const row = candidates.reduce((a, b) => a.effective_from >= b.effective_from ? a : b);
|
|
194
|
+
if (suffixWindow === undefined || suffixWindow === row.context_window)
|
|
195
|
+
return row;
|
|
196
|
+
// 后缀声明的窗口覆盖基础行,输入上限按原行的预留比例等比缩放。
|
|
197
|
+
const ratio = row.context_window > 0 ? row.max_input_tokens / row.context_window : 0.9;
|
|
198
|
+
return { ...row, model, context_window: suffixWindow, max_input_tokens: Math.floor(suffixWindow * ratio) };
|
|
174
199
|
}
|
|
175
200
|
// 默认值
|
|
176
|
-
|
|
201
|
+
const contextWindow = suffixWindow ?? 200000;
|
|
202
|
+
return { model, effective_from: 0, context_window: contextWindow, max_input_tokens: Math.floor(contextWindow * 0.9), max_output_tokens: 8192 };
|
|
177
203
|
}
|