evolcore 0.0.3 → 0.0.5
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 +83 -0
- package/README.md +45 -10
- package/bin/ec-safe-output.js +89 -24
- package/dist/agents/baseagent.js +46 -0
- package/dist/agents/claude-runner.js +1 -31
- package/dist/agents/codex-app-server-client.js +68 -0
- package/dist/agents/codex-runner.js +157 -5
- package/dist/agents/runner-types.js +2 -2
- package/dist/aun/aid/agentmd.js +79 -0
- package/dist/aun/aid/encryption-seed-policy.js +29 -0
- package/dist/aun/aid/index.js +1 -1
- package/dist/aun/aid/store.js +2 -5
- package/dist/channels/aun.js +220 -112
- package/dist/channels/daemon.js +18 -4
- package/dist/channels/dingtalk.js +52 -137
- package/dist/channels/feishu.js +56 -4
- package/dist/channels/qqbot.js +23 -1
- package/dist/channels/wechat.js +303 -155
- package/dist/channels/wecom.js +383 -7
- package/dist/cli/aun-commands.js +11 -11
- package/dist/cli/daemon-commands.js +46 -15
- package/dist/cli/handoff-command.js +2 -1
- package/dist/cli/init-channel.js +185 -67
- package/dist/cli/init.js +49 -27
- package/dist/cli/trigger-command.js +92 -11
- package/dist/config/access-policy-domain.js +18 -0
- package/dist/config/access-policy.js +110 -0
- package/dist/config/builtin-role-templates.js +27 -14
- package/dist/config/builtin-roles.js +25 -6
- package/dist/config/config-field-policy.js +17 -5
- package/dist/config/config-manager.js +198 -22
- package/dist/config/config-operation-service.js +35 -38
- package/dist/config/contact-bind-code.js +274 -0
- package/dist/config/contact-book-store.js +173 -5
- package/dist/config/contact-book.js +32 -0
- package/dist/config/contact-operation-service.js +9 -3
- package/dist/config/contact-request-service.js +331 -0
- package/dist/config/peer-role-resolver.js +3 -1
- package/dist/config/schema-registry.js +49 -24
- package/dist/config-store.js +14 -2
- package/dist/core/auth/agent-delegation.js +105 -11
- package/dist/core/auth/authorization-audit.js +6 -0
- package/dist/core/auth/operation-authorizer.js +8 -0
- package/dist/core/auth/operation-catalog.js +51 -3
- package/dist/core/auth/trigger-authorization.js +15 -0
- package/dist/core/bootstrap-service.js +2 -9
- package/dist/core/channel-loader.js +6 -2
- package/dist/core/command/command-handler.js +10 -13
- package/dist/core/command/connect-menu.js +229 -26
- package/dist/core/command/evol-menu-version-gate.js +38 -0
- package/dist/core/command/group-menu.js +421 -0
- package/dist/core/command/menu-handler.js +269 -85
- package/dist/core/command/menu-protocol.js +8 -2
- package/dist/core/command/menu-token-store.js +102 -0
- package/dist/core/command/role-menu.js +16 -0
- package/dist/core/command/slash-gate.js +1 -1
- package/dist/core/command/slash-handler.js +158 -31
- package/dist/core/daemon-file-cache.js +28 -0
- package/dist/core/event-catalog.js +29 -0
- package/dist/core/evolagent-registry.js +4 -39
- package/dist/core/handoff/runtime.js +162 -37
- package/dist/core/handoff/store.js +46 -2
- package/dist/core/handoff/types.js +1 -0
- package/dist/core/inference/text-inference.js +16 -74
- package/dist/core/message/file-markers.js +7 -0
- package/dist/core/message/im-renderer.js +18 -14
- package/dist/core/message/inbound-admission.js +134 -0
- package/dist/core/message/message-bridge.js +616 -74
- package/dist/core/message/message-log.js +1 -0
- package/dist/core/message/message-queue.js +185 -10
- package/dist/core/message/peer-mode.js +7 -8
- package/dist/core/message/response-engine.js +381 -79
- package/dist/core/permission/approval-gateway.js +17 -10
- package/dist/core/permission/ec-command-parser.js +101 -46
- package/dist/core/permission/tool-policy.js +69 -24
- package/dist/core/protected-paths.js +36 -11
- package/dist/core/session/session-fs-store.js +19 -4
- package/dist/core/session/session-manager.js +232 -4
- package/dist/core/session/session-mapper.js +2 -0
- package/dist/core/session/session-renew.js +125 -69
- package/dist/core/session/session-turn-coordinator.js +5 -1
- package/dist/eck/kit-renderer.js +12 -1
- package/dist/eck/message-renderer.js +79 -1
- package/dist/index.js +224 -89
- package/dist/ipc.js +81 -4
- package/dist/paths.js +3 -0
- package/dist/response-system/config-resolver.js +29 -0
- package/dist/response-system/coordinator.js +8 -32
- package/dist/response-system/engines/v1/proactive-flow.js +1 -1
- package/dist/response-system/index.js +1 -0
- package/dist/response-system/modes/single-session/index.js +7 -4
- package/dist/trigger/parser.js +55 -15
- package/dist/trigger/patch.js +4 -1
- package/dist/trigger/scheduler.js +441 -39
- package/dist/utils/cross-platform.js +8 -2
- package/dist/utils/error-dict.json +7 -0
- package/dist/utils/evolcore-version.js +21 -0
- package/dist/utils/logger.js +2 -2
- package/dist/utils/process-introspect.js +19 -3
- package/dist/utils/stable-semver.js +21 -0
- package/dist/utils/stats.js +33 -9
- package/kits/docs/channels/aun.md +4 -13
- package/kits/docs/evolcore/INDEX.md +1 -1
- package/kits/docs/evolcore/config.md +47 -2
- package/kits/docs/evolcore/contact.md +8 -3
- package/kits/docs/evolcore/group-rules.md +46 -4
- package/kits/docs/evolcore/group.md +4 -4
- package/kits/docs/evolcore/msg.md +5 -5
- package/kits/docs/evolcore/trigger.md +25 -8
- package/kits/docs/path-registry.md +36 -17
- package/kits/eck_message_manifest.json +12 -1
- package/kits/migrations/migrate-contact-book-v2.mjs +7 -0
- package/kits/rules/01-overview.md +17 -7
- package/kits/rules/02-navigation.md +38 -18
- package/kits/rules/03-identity.md +28 -24
- package/kits/rules/04-relation.md +44 -28
- package/kits/rules/05-venue.md +31 -15
- package/kits/rules/06-channel.md +11 -7
- package/kits/schemas/_meta.json +18 -7
- package/kits/schemas/agent-config.schema.7.json +303 -0
- package/kits/schemas/agent-config.schema.8.json +304 -0
- package/kits/schemas/agent-config.schema.9.json +364 -0
- package/kits/schemas/contact-book.schema.3.json +67 -0
- package/kits/schemas/daemon.schema.1.json +3 -2
- package/kits/schemas/daemon.schema.2.json +101 -0
- package/kits/schemas/daemon.schema.3.json +123 -0
- package/kits/schemas/defaults.schema.2.json +85 -0
- package/kits/schemas/defaults.schema.3.json +73 -0
- package/kits/schemas/relation-config.schema.6.json +46 -0
- package/kits/schemas/relation-config.schema.7.json +59 -0
- package/kits/schemas/single-session.schema.2.json +57 -0
- package/kits/templates/message-fragments/handoff-context-to-target.md +9 -0
- package/kits/templates/message-fragments/handoff-request-to-target.md +14 -8
- package/kits/templates/message-fragments/handoff-response-to-origin.md +5 -6
- package/kits/templates/roles/admin.json +46 -0
- package/kits/templates/roles/member.json +4 -0
- package/kits/templates/roles/visitor.json +4 -0
- package/kits/templates/system-fragments/channel.md +12 -2
- package/kits/templates/system-fragments/identity.md +3 -1
- package/kits/templates/system-fragments/relation.md +1 -1
- package/kits/templates/system-fragments/session.md +6 -2
- package/package.json +4 -2
- package/MIGRATION-0.5.0.md +0 -378
- package/ROLE_ACCESS_CONTROL.md +0 -174
- package/dist/channels/contact-bind-code.js +0 -134
- package/dist/channels/wecom-card.js +0 -101
- package/dist/channels/wecom-onboarding.js +0 -82
- package/dist/channels/wecom-state.js +0 -191
|
@@ -17,6 +17,8 @@ import { isRetryableError } from '../utils/error-utils.js';
|
|
|
17
17
|
import { renderActionAsText } from '../core/interaction-router.js';
|
|
18
18
|
import { buildEnvelope, sendInteractionPayload } from '../core/message/message-utils.js';
|
|
19
19
|
import { resolveCodexCapabilityThreadConfigForProject } from '../core/capability/capability-manager.js';
|
|
20
|
+
import { AGENT_DELEGATION_TOKEN_ENV, hashDelegatedCommandArgv } from '../core/auth/agent-delegation.js';
|
|
21
|
+
import { classifyEvolcoreShellCommand, parseLiteralShellArgv } from '../core/permission/ec-command-parser.js';
|
|
20
22
|
import { compareVersions } from '../utils/npm-ops.js';
|
|
21
23
|
import { resolvePaths, resolveRoot } from '../paths.js';
|
|
22
24
|
import { buildSessionTurnList } from '../core/session/session-turns.js';
|
|
@@ -111,6 +113,7 @@ const CODEX_CATALOG_FALLBACK = [
|
|
|
111
113
|
{ slug: 'gpt-5.3-codex', efforts: ['low', 'medium', 'high', 'xhigh'] },
|
|
112
114
|
{ slug: 'gpt-5.2', efforts: ['low', 'medium', 'high', 'xhigh'] },
|
|
113
115
|
];
|
|
116
|
+
const CODEX_DELEGATION_CARRIER_METADATA_KEY = '__codexDelegationCarrierV1';
|
|
114
117
|
let codexCatalogCache = null;
|
|
115
118
|
// The permission bridge is version-locked to the v2 schema audited below:
|
|
116
119
|
// named profiles, approvalsReviewer, additional/network approval context, and
|
|
@@ -211,6 +214,7 @@ export class CodexRunner {
|
|
|
211
214
|
threadExternalToolFingerprints = new Map();
|
|
212
215
|
threadExternalToolBoundaries = new Map();
|
|
213
216
|
trackedApprovalItems = new Map();
|
|
217
|
+
threadDelegationCarriers = new Map();
|
|
214
218
|
pendingInterrupts = new Map();
|
|
215
219
|
appServerClient = null;
|
|
216
220
|
onSessionIdUpdate;
|
|
@@ -257,12 +261,98 @@ export class CodexRunner {
|
|
|
257
261
|
}
|
|
258
262
|
return this.appServerClient;
|
|
259
263
|
}
|
|
264
|
+
createDelegationCarrier() {
|
|
265
|
+
return randomBytes(32).toString('base64url');
|
|
266
|
+
}
|
|
267
|
+
approvedEvolcoreCommandArgv(toolInput) {
|
|
268
|
+
const explicitArgv = Array.isArray(toolInput.commandArgv)
|
|
269
|
+
&& toolInput.commandArgv.every(value => typeof value === 'string')
|
|
270
|
+
? toolInput.commandArgv
|
|
271
|
+
: undefined;
|
|
272
|
+
if (explicitArgv?.[0] === 'ec')
|
|
273
|
+
return explicitArgv;
|
|
274
|
+
const command = typeof toolInput.command === 'string' ? toolInput.command : '';
|
|
275
|
+
const classification = classifyEvolcoreShellCommand(command);
|
|
276
|
+
if (classification.kind === 'bounded-output')
|
|
277
|
+
return classification.command.argv;
|
|
278
|
+
if (classification.kind !== 'literal')
|
|
279
|
+
return undefined;
|
|
280
|
+
const argv = parseLiteralShellArgv(command);
|
|
281
|
+
return argv?.[0] === 'ec' ? argv : undefined;
|
|
282
|
+
}
|
|
283
|
+
armApprovedDelegationCommand(sessionId, toolInput) {
|
|
284
|
+
const threadId = this.activeSessions.get(sessionId);
|
|
285
|
+
const carrierToken = threadId ? this.threadDelegationCarriers.get(threadId) : undefined;
|
|
286
|
+
const argv = this.approvedEvolcoreCommandArgv(toolInput);
|
|
287
|
+
if (!carrierToken || !argv)
|
|
288
|
+
return false;
|
|
289
|
+
const commandHash = hashDelegatedCommandArgv(argv);
|
|
290
|
+
const arm = this.permissionContexts.get(sessionId)?.armApprovedDelegationCommand;
|
|
291
|
+
if (!commandHash || !arm)
|
|
292
|
+
return false;
|
|
293
|
+
return arm(carrierToken, commandHash);
|
|
294
|
+
}
|
|
295
|
+
async readThreadDelegationCarrier(appServer, threadId) {
|
|
296
|
+
try {
|
|
297
|
+
const result = await appServer.threadShellCommand(threadId, `node -e "process.stdout.write(process.env.${AGENT_DELEGATION_TOKEN_ENV}||String())"`);
|
|
298
|
+
const carrier = result.output.trim();
|
|
299
|
+
if (result.exitCode !== undefined && result.exitCode !== 0)
|
|
300
|
+
return undefined;
|
|
301
|
+
return /^[A-Za-z0-9_-]{32,128}$/.test(carrier) ? carrier : undefined;
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
logger.warn(`[CodexRunner] failed to recover delegation carrier for loaded thread ${threadId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
305
|
+
return undefined;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
async loadPersistedDelegationCarrier(sessionManager, sessionId, threadId) {
|
|
309
|
+
if (typeof sessionManager?.getSessionById !== 'function')
|
|
310
|
+
return undefined;
|
|
311
|
+
try {
|
|
312
|
+
const session = await sessionManager.getSessionById(sessionId);
|
|
313
|
+
const persisted = session?.metadata?.[CODEX_DELEGATION_CARRIER_METADATA_KEY];
|
|
314
|
+
if (!persisted || typeof persisted !== 'object' || Array.isArray(persisted))
|
|
315
|
+
return undefined;
|
|
316
|
+
if (persisted.threadId !== threadId || typeof persisted.carrier !== 'string')
|
|
317
|
+
return undefined;
|
|
318
|
+
return /^[A-Za-z0-9_-]{32,128}$/.test(persisted.carrier)
|
|
319
|
+
? persisted.carrier
|
|
320
|
+
: undefined;
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
logger.debug(`[CodexRunner] failed to load persisted delegation carrier: session=${sessionId} error=${error}`);
|
|
324
|
+
return undefined;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
async persistDelegationCarrier(sessionManager, sessionId, threadId, carrier) {
|
|
328
|
+
if (typeof sessionManager?.getSessionById !== 'function'
|
|
329
|
+
|| typeof sessionManager?.updateSession !== 'function')
|
|
330
|
+
return;
|
|
331
|
+
try {
|
|
332
|
+
const session = await sessionManager.getSessionById(sessionId);
|
|
333
|
+
if (!session)
|
|
334
|
+
return;
|
|
335
|
+
const current = session.metadata?.[CODEX_DELEGATION_CARRIER_METADATA_KEY];
|
|
336
|
+
if (current?.threadId === threadId && current?.carrier === carrier)
|
|
337
|
+
return;
|
|
338
|
+
await sessionManager.updateSession(sessionId, {
|
|
339
|
+
metadata: {
|
|
340
|
+
...(session.metadata ?? {}),
|
|
341
|
+
[CODEX_DELEGATION_CARRIER_METADATA_KEY]: { threadId, carrier },
|
|
342
|
+
},
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
catch (error) {
|
|
346
|
+
logger.warn(`[CodexRunner] failed to persist delegation carrier: session=${sessionId} thread=${threadId} error=${error}`);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
260
349
|
resetAppServerClient() {
|
|
261
350
|
const client = this.appServerClient;
|
|
262
351
|
this.appServerClient = null;
|
|
263
352
|
this.threadExternalToolFingerprints.clear();
|
|
264
353
|
this.threadExternalToolBoundaries.clear();
|
|
265
354
|
this.trackedApprovalItems.clear();
|
|
355
|
+
this.threadDelegationCarriers.clear();
|
|
266
356
|
client?.close().catch(error => {
|
|
267
357
|
logger.debug(`[CodexRunner] Failed to close stale app-server client: ${error}`);
|
|
268
358
|
});
|
|
@@ -656,6 +746,7 @@ export class CodexRunner {
|
|
|
656
746
|
// ── Core: runQuery ──
|
|
657
747
|
async runQuery(sessionId, prompt, projectPath, initialAgentSessionId, images, systemPromptAppend, sessionManager, modelOverride, runtimeEnv) {
|
|
658
748
|
let agentSessionId = initialAgentSessionId || this.activeSessions.get(sessionId);
|
|
749
|
+
const resumingThread = !!agentSessionId;
|
|
659
750
|
const callModel = modelOverride?.model || this.model;
|
|
660
751
|
const callEffort = modelOverride?.effort ?? this.effort;
|
|
661
752
|
// per-call 权限模式:优先 override(message-processor 解析后传入),缺省回落实例级 currentMode。
|
|
@@ -674,13 +765,24 @@ export class CodexRunner {
|
|
|
674
765
|
const externalToolConfig = await this.resolveExternalToolApprovalConfig(appServer, projectPath, capabilityConfig, callMode);
|
|
675
766
|
const managedTempInstruction = this.managedTempInstruction(sessionId);
|
|
676
767
|
const developerInstructions = [systemPromptAppend, managedTempInstruction].filter(Boolean).join('\n\n') || undefined;
|
|
768
|
+
let knownDelegationCarrier = agentSessionId
|
|
769
|
+
? this.threadDelegationCarriers.get(agentSessionId)
|
|
770
|
+
: undefined;
|
|
771
|
+
if (agentSessionId && !knownDelegationCarrier) {
|
|
772
|
+
knownDelegationCarrier = await this.loadPersistedDelegationCarrier(sessionManager, sessionId, agentSessionId);
|
|
773
|
+
if (knownDelegationCarrier) {
|
|
774
|
+
this.threadDelegationCarriers.set(agentSessionId, knownDelegationCarrier);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
const delegationCarrierCandidate = knownDelegationCarrier ?? this.createDelegationCarrier();
|
|
778
|
+
const hasTaskDelegation = typeof runtimeEnv?.[AGENT_DELEGATION_TOKEN_ENV] === 'string';
|
|
677
779
|
const threadOptions = {
|
|
678
780
|
model: callModel,
|
|
679
781
|
effort: callEffort,
|
|
680
782
|
approvalPolicy: effectiveApprovalPolicy,
|
|
681
783
|
approvalsReviewer: 'user',
|
|
682
784
|
...(executionSandbox.sandbox ? { sandbox: executionSandbox.sandbox } : {}),
|
|
683
|
-
config: this.mergeThreadConfig(executionSandbox.permissionProfileConfig, runtimeEnv ? { shell_environment_policy: { set: runtimeEnv } } : undefined, capabilityConfig, externalToolConfig, this.buildEvolcoreShellEnvironmentConfig(sessionId), this.buildLifecycleLockdownConfig()),
|
|
785
|
+
config: this.mergeThreadConfig(executionSandbox.permissionProfileConfig, runtimeEnv ? { shell_environment_policy: { set: runtimeEnv } } : undefined, capabilityConfig, externalToolConfig, this.buildEvolcoreShellEnvironmentConfig(sessionId, delegationCarrierCandidate), this.buildLifecycleLockdownConfig()),
|
|
684
786
|
...(developerInstructions ? { developerInstructions } : {}),
|
|
685
787
|
};
|
|
686
788
|
logger.info(`[CodexRunner] runQuery permMode=${requestedPermissionMode}->${callMode} ` +
|
|
@@ -688,9 +790,39 @@ export class CodexRunner {
|
|
|
688
790
|
const threadResponse = agentSessionId
|
|
689
791
|
? await appServer.threadResume(agentSessionId, projectPath, threadOptions)
|
|
690
792
|
: await appServer.threadStart(projectPath, threadOptions);
|
|
691
|
-
|
|
793
|
+
let threadId = threadResponse.thread?.id || agentSessionId;
|
|
692
794
|
if (!threadId)
|
|
693
795
|
throw new Error('Codex app-server did not return a thread id');
|
|
796
|
+
if (!resumingThread) {
|
|
797
|
+
this.threadDelegationCarriers.set(threadId, delegationCarrierCandidate);
|
|
798
|
+
await this.persistDelegationCarrier(sessionManager, sessionId, threadId, delegationCarrierCandidate);
|
|
799
|
+
}
|
|
800
|
+
else if (hasTaskDelegation && !knownDelegationCarrier) {
|
|
801
|
+
let recoveredCarrier = await this.readThreadDelegationCarrier(appServer, threadId);
|
|
802
|
+
if (!recoveredCarrier) {
|
|
803
|
+
const staleThreadId = threadId;
|
|
804
|
+
logger.warn(`[CodexRunner] loaded thread has no recoverable delegation carrier; forking once to preserve history: thread=${staleThreadId}`);
|
|
805
|
+
const forked = await appServer.threadFork(staleThreadId, projectPath, undefined, {
|
|
806
|
+
model: callModel,
|
|
807
|
+
effort: callEffort,
|
|
808
|
+
approvalPolicy: effectiveApprovalPolicy,
|
|
809
|
+
approvalsReviewer: 'user',
|
|
810
|
+
...(executionSandbox.sandbox ? { sandbox: executionSandbox.sandbox } : {}),
|
|
811
|
+
config: threadOptions.config,
|
|
812
|
+
});
|
|
813
|
+
const forkedThreadId = forked.thread?.id;
|
|
814
|
+
if (!forkedThreadId)
|
|
815
|
+
throw new Error('Codex delegation-carrier recovery fork did not return a thread id');
|
|
816
|
+
threadId = forkedThreadId;
|
|
817
|
+
recoveredCarrier = delegationCarrierCandidate;
|
|
818
|
+
}
|
|
819
|
+
this.threadDelegationCarriers.set(threadId, recoveredCarrier);
|
|
820
|
+
await this.persistDelegationCarrier(sessionManager, sessionId, threadId, recoveredCarrier);
|
|
821
|
+
}
|
|
822
|
+
else if (knownDelegationCarrier) {
|
|
823
|
+
this.threadDelegationCarriers.set(threadId, knownDelegationCarrier);
|
|
824
|
+
await this.persistDelegationCarrier(sessionManager, sessionId, threadId, knownDelegationCarrier);
|
|
825
|
+
}
|
|
694
826
|
agentSessionId = threadId;
|
|
695
827
|
this.activeSessions.set(sessionId, threadId);
|
|
696
828
|
this.threadProjectPaths.set(threadId, path.resolve(projectPath));
|
|
@@ -829,6 +961,7 @@ export class CodexRunner {
|
|
|
829
961
|
const previousThreadId = this.activeSessions.get(sessionId);
|
|
830
962
|
if (previousThreadId && previousThreadId !== agentSessionId) {
|
|
831
963
|
this.threadProjectPaths.delete(previousThreadId);
|
|
964
|
+
this.threadDelegationCarriers.delete(previousThreadId);
|
|
832
965
|
this.unbindExternalToolBoundary(previousThreadId);
|
|
833
966
|
this.clearTrackedApprovalItemsForThread(previousThreadId);
|
|
834
967
|
}
|
|
@@ -852,6 +985,7 @@ export class CodexRunner {
|
|
|
852
985
|
this.cleanupSessionTempDir(sessionId);
|
|
853
986
|
if (threadId) {
|
|
854
987
|
this.threadProjectPaths.delete(threadId);
|
|
988
|
+
this.threadDelegationCarriers.delete(threadId);
|
|
855
989
|
this.unbindExternalToolBoundary(threadId);
|
|
856
990
|
}
|
|
857
991
|
this.clearTrackedApprovalItemsForThread(threadId);
|
|
@@ -884,6 +1018,7 @@ export class CodexRunner {
|
|
|
884
1018
|
this.chatModes.delete(sessionId);
|
|
885
1019
|
this.cleanupSessionTempDir(sessionId);
|
|
886
1020
|
this.threadProjectPaths.delete(threadId);
|
|
1021
|
+
this.threadDelegationCarriers.delete(threadId);
|
|
887
1022
|
this.unbindExternalToolBoundary(threadId);
|
|
888
1023
|
this.clearTrackedApprovalItemsForThread(threadId);
|
|
889
1024
|
this.onSessionIdUpdate?.(sessionId, '');
|
|
@@ -906,15 +1041,18 @@ export class CodexRunner {
|
|
|
906
1041
|
const executionSandbox = this.buildExecutionSandboxOptions(_sessionId, compactMode, _projectPath);
|
|
907
1042
|
const capabilityConfig = await this.resolveCapabilityThreadConfig(_projectPath);
|
|
908
1043
|
const externalToolConfig = await this.resolveExternalToolApprovalConfig(appServer, _projectPath, capabilityConfig, compactMode);
|
|
1044
|
+
const compactDelegationCarrier = this.threadDelegationCarriers.get(agentSessionId)
|
|
1045
|
+
?? this.createDelegationCarrier();
|
|
909
1046
|
await appServer.threadResume(agentSessionId, _projectPath, {
|
|
910
1047
|
model: this.model,
|
|
911
1048
|
effort: this.effort,
|
|
912
1049
|
approvalPolicy: compactPolicy,
|
|
913
1050
|
approvalsReviewer: 'user',
|
|
914
1051
|
...(executionSandbox.sandbox ? { sandbox: executionSandbox.sandbox } : {}),
|
|
915
|
-
config: this.mergeThreadConfig(executionSandbox.permissionProfileConfig, capabilityConfig, externalToolConfig, this.buildEvolcoreShellEnvironmentConfig(_sessionId), this.buildLifecycleLockdownConfig()),
|
|
1052
|
+
config: this.mergeThreadConfig(executionSandbox.permissionProfileConfig, capabilityConfig, externalToolConfig, this.buildEvolcoreShellEnvironmentConfig(_sessionId, compactDelegationCarrier), this.buildLifecycleLockdownConfig()),
|
|
916
1053
|
});
|
|
917
1054
|
this.threadProjectPaths.set(agentSessionId, path.resolve(_projectPath));
|
|
1055
|
+
this.threadDelegationCarriers.set(agentSessionId, compactDelegationCarrier);
|
|
918
1056
|
this.bindExternalToolBoundary(agentSessionId, externalToolConfig);
|
|
919
1057
|
return await this.startAndWaitForCompact(appServer, agentSessionId);
|
|
920
1058
|
}
|
|
@@ -1054,17 +1192,19 @@ export class CodexRunner {
|
|
|
1054
1192
|
const capabilityConfig = await this.resolveCapabilityThreadConfig(projectPath);
|
|
1055
1193
|
const appServer = this.getAppServerClient();
|
|
1056
1194
|
const externalToolConfig = await this.resolveExternalToolApprovalConfig(appServer, projectPath, capabilityConfig, mode);
|
|
1195
|
+
const delegationCarrier = this.createDelegationCarrier();
|
|
1057
1196
|
const response = await appServer.threadFork(agentSessionId, projectPath, title, {
|
|
1058
1197
|
model: this.model,
|
|
1059
1198
|
effort: this.effort,
|
|
1060
1199
|
approvalPolicy: this.toApprovalPolicy(mode),
|
|
1061
1200
|
approvalsReviewer: 'user',
|
|
1062
1201
|
...(executionSandbox.sandbox ? { sandbox: executionSandbox.sandbox } : {}),
|
|
1063
|
-
config: this.mergeThreadConfig(executionSandbox.permissionProfileConfig, capabilityConfig, externalToolConfig, this.buildEvolcoreShellEnvironmentConfig(sessionKey), this.buildLifecycleLockdownConfig()),
|
|
1202
|
+
config: this.mergeThreadConfig(executionSandbox.permissionProfileConfig, capabilityConfig, externalToolConfig, this.buildEvolcoreShellEnvironmentConfig(sessionKey, delegationCarrier), this.buildLifecycleLockdownConfig()),
|
|
1064
1203
|
});
|
|
1065
1204
|
const forkedThreadId = response.thread?.id;
|
|
1066
1205
|
if (!forkedThreadId)
|
|
1067
1206
|
throw new Error('Codex fork did not return a thread id');
|
|
1207
|
+
this.threadDelegationCarriers.set(forkedThreadId, delegationCarrier);
|
|
1068
1208
|
this.threadProjectPaths.set(forkedThreadId, path.resolve(projectPath));
|
|
1069
1209
|
this.bindExternalToolBoundary(forkedThreadId, externalToolConfig);
|
|
1070
1210
|
return forkedThreadId;
|
|
@@ -1227,6 +1367,16 @@ export class CodexRunner {
|
|
|
1227
1367
|
logger.info(`[CodexRunner] app-server approval request id=${request.id} method=${request.method} session=${sessionKey} mode=${sessionMode} tool=${toolName} summary=${summary}`);
|
|
1228
1368
|
try {
|
|
1229
1369
|
const decision = await this.resolvePermissionDecision(sessionKey, toolName, toolInput, summary, reason, workspacePath, operationCwd);
|
|
1370
|
+
if (decision !== 'deny'
|
|
1371
|
+
&& (request.method === 'item/commandExecution/requestApproval' || request.method === 'execCommandApproval')
|
|
1372
|
+
&& this.approvedEvolcoreCommandArgv(toolInput)) {
|
|
1373
|
+
if (!this.armApprovedDelegationCommand(sessionKey, toolInput)) {
|
|
1374
|
+
// Approval policy and delegation authority are separate boundaries.
|
|
1375
|
+
// If no ticket can be armed, the CLI still fails closed at IPC token
|
|
1376
|
+
// validation instead of changing an otherwise valid tool decision.
|
|
1377
|
+
logger.warn(`[CodexRunner] EC command approved without a task-bound delegation ticket: session=${sessionKey}`);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1230
1380
|
const response = this.toAppServerApprovalResponse(request.method, decision, toolInput, unattended);
|
|
1231
1381
|
logger.info(`[CodexRunner] app-server approval response id=${request.id} method=${request.method} decision=${decision} response=${JSON.stringify(response)}`);
|
|
1232
1382
|
return response;
|
|
@@ -2610,13 +2760,14 @@ export class CodexRunner {
|
|
|
2610
2760
|
return undefined;
|
|
2611
2761
|
return '临时文件必须使用环境变量 `$TMPDIR`。它指向当前 EvolCore 会话的受管临时工作区;不要直接使用 `/tmp`,也不要使用其他会话的临时目录。';
|
|
2612
2762
|
}
|
|
2613
|
-
buildEvolcoreShellEnvironmentConfig(sessionId) {
|
|
2763
|
+
buildEvolcoreShellEnvironmentConfig(sessionId, delegationCarrier) {
|
|
2614
2764
|
const managedTempDir = this.ensureSessionTempDir(sessionId);
|
|
2615
2765
|
return {
|
|
2616
2766
|
shell_environment_policy: {
|
|
2617
2767
|
set: {
|
|
2618
2768
|
EVOLCORE_SESSION_ID: sessionId,
|
|
2619
2769
|
EVOLCORE_HOME: resolveRoot(),
|
|
2770
|
+
...(delegationCarrier ? { [AGENT_DELEGATION_TOKEN_ENV]: delegationCarrier } : {}),
|
|
2620
2771
|
...(managedTempDir ? { TMPDIR: managedTempDir } : {}),
|
|
2621
2772
|
},
|
|
2622
2773
|
},
|
|
@@ -2635,6 +2786,7 @@ export class CodexRunner {
|
|
|
2635
2786
|
this.threadExternalToolFingerprints.clear();
|
|
2636
2787
|
this.threadExternalToolBoundaries.clear();
|
|
2637
2788
|
this.trackedApprovalItems.clear();
|
|
2789
|
+
this.threadDelegationCarriers.clear();
|
|
2638
2790
|
this.pendingInterrupts.clear();
|
|
2639
2791
|
this.permissionContexts.clear();
|
|
2640
2792
|
this.chatModes.clear();
|
|
@@ -69,7 +69,7 @@ export function isOneMillionContextModel(model) {
|
|
|
69
69
|
export function realContextWindowForModel(model) {
|
|
70
70
|
return isOneMillionContextModel(model) ? 1000000 : 200000;
|
|
71
71
|
}
|
|
72
|
-
/** autoCompact trigger threshold:
|
|
72
|
+
/** autoCompact trigger threshold: 350000 for all models. */
|
|
73
73
|
export function autoCompactWindowForModel(_model) {
|
|
74
|
-
return
|
|
74
|
+
return 350000;
|
|
75
75
|
}
|
package/dist/aun/aid/agentmd.js
CHANGED
|
@@ -2,6 +2,85 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { getAidStore, loadAid, SLOT } from './store.js';
|
|
4
4
|
import { agentMdPath, aidLocalDir, resolveRoot } from '../../paths.js';
|
|
5
|
+
const displayNameCache = new Map();
|
|
6
|
+
const displayNamePending = new Map();
|
|
7
|
+
const displayNameRevision = new Map();
|
|
8
|
+
function normalizeAid(aid) {
|
|
9
|
+
const value = String(aid || '').trim();
|
|
10
|
+
return value.startsWith('@') ? value.slice(1) : value;
|
|
11
|
+
}
|
|
12
|
+
/** Extract the display name from an agent.md YAML frontmatter block. */
|
|
13
|
+
export function parseAgentDisplayName(content) {
|
|
14
|
+
const frontmatter = content.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/)?.[1];
|
|
15
|
+
if (!frontmatter)
|
|
16
|
+
return undefined;
|
|
17
|
+
const name = frontmatter.match(/^name:\s*["']?(.+?)["']?\s*$/m)?.[1]?.trim();
|
|
18
|
+
return name || undefined;
|
|
19
|
+
}
|
|
20
|
+
function readLocalAgentDisplayName(aid) {
|
|
21
|
+
try {
|
|
22
|
+
return parseAgentDisplayName(fs.readFileSync(agentMdPath(aid), 'utf-8'));
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolve an agent.md display name without blocking on the network.
|
|
30
|
+
* Local content is returned immediately; a missing value starts one shared
|
|
31
|
+
* background refresh and remains undefined until a later lookup.
|
|
32
|
+
*/
|
|
33
|
+
export function resolveAgentDisplayName(aid) {
|
|
34
|
+
const normalizedAid = normalizeAid(aid);
|
|
35
|
+
if (!normalizedAid)
|
|
36
|
+
return undefined;
|
|
37
|
+
const cached = displayNameCache.get(normalizedAid);
|
|
38
|
+
if (cached)
|
|
39
|
+
return cached;
|
|
40
|
+
const localName = readLocalAgentDisplayName(normalizedAid);
|
|
41
|
+
if (localName) {
|
|
42
|
+
displayNameCache.set(normalizedAid, localName);
|
|
43
|
+
return localName;
|
|
44
|
+
}
|
|
45
|
+
void refreshAgentDisplayName(normalizedAid);
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
/** Fetch agent.md once and update the shared display-name cache. */
|
|
49
|
+
export function refreshAgentDisplayName(aid) {
|
|
50
|
+
const normalizedAid = normalizeAid(aid);
|
|
51
|
+
if (!normalizedAid)
|
|
52
|
+
return Promise.resolve(undefined);
|
|
53
|
+
const existing = displayNamePending.get(normalizedAid);
|
|
54
|
+
if (existing)
|
|
55
|
+
return existing;
|
|
56
|
+
const revision = displayNameRevision.get(normalizedAid) ?? 0;
|
|
57
|
+
let pending;
|
|
58
|
+
pending = agentmdGet(normalizedAid)
|
|
59
|
+
.then(content => {
|
|
60
|
+
const name = typeof content === 'string' ? parseAgentDisplayName(content) : undefined;
|
|
61
|
+
if ((displayNameRevision.get(normalizedAid) ?? 0) !== revision)
|
|
62
|
+
return undefined;
|
|
63
|
+
if (name)
|
|
64
|
+
displayNameCache.set(normalizedAid, name);
|
|
65
|
+
return name;
|
|
66
|
+
})
|
|
67
|
+
.catch(() => undefined)
|
|
68
|
+
.finally(() => {
|
|
69
|
+
if (displayNamePending.get(normalizedAid) === pending) {
|
|
70
|
+
displayNamePending.delete(normalizedAid);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
displayNamePending.set(normalizedAid, pending);
|
|
74
|
+
return pending;
|
|
75
|
+
}
|
|
76
|
+
export function invalidateAgentDisplayName(aid) {
|
|
77
|
+
const normalizedAid = normalizeAid(aid);
|
|
78
|
+
if (!normalizedAid)
|
|
79
|
+
return;
|
|
80
|
+
displayNameCache.delete(normalizedAid);
|
|
81
|
+
displayNamePending.delete(normalizedAid);
|
|
82
|
+
displayNameRevision.set(normalizedAid, (displayNameRevision.get(normalizedAid) ?? 0) + 1);
|
|
83
|
+
}
|
|
5
84
|
export function buildInitialAgentMd(opts) {
|
|
6
85
|
const agentName = opts.aid.split('.')[0];
|
|
7
86
|
const agentType = opts.type || 'ai';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const AUN_KEYSTORE_ENCRYPTION_SEED = 'evol';
|
|
2
|
+
export class AunEncryptionSeedPolicyError extends Error {
|
|
3
|
+
code = 'CUSTOM_AUN_ENCRYPTION_SEED_FORBIDDEN';
|
|
4
|
+
constructor(sources) {
|
|
5
|
+
super(`检测到自定义 AUN encryptionSeed(来源:${sources.join('、')})。` +
|
|
6
|
+
'AUN encryptionSeed 由 EvolCore 内置管理,不允许用户自行设置。' +
|
|
7
|
+
'请停止操作并联系管理人员处理后再启动 EvolCore。');
|
|
8
|
+
this.name = 'AunEncryptionSeedPolicyError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Reject values that would make an existing AUN keystore incompatible with
|
|
13
|
+
* EvolCore's fixed application seed. Explicit legacy copies of the fixed value
|
|
14
|
+
* remain readable so users can remove the obsolete setting without migration.
|
|
15
|
+
*/
|
|
16
|
+
export function assertAunEncryptionSeedPolicy(configuredValue, environmentValue) {
|
|
17
|
+
const customSources = [];
|
|
18
|
+
if (configuredValue !== undefined
|
|
19
|
+
&& configuredValue !== null
|
|
20
|
+
&& configuredValue !== AUN_KEYSTORE_ENCRYPTION_SEED) {
|
|
21
|
+
customSources.push('daemon.json aun.encryptionSeed');
|
|
22
|
+
}
|
|
23
|
+
if (environmentValue !== undefined
|
|
24
|
+
&& environmentValue !== AUN_KEYSTORE_ENCRYPTION_SEED) {
|
|
25
|
+
customSources.push('环境变量 AUN_ENCRYPTION_SEED');
|
|
26
|
+
}
|
|
27
|
+
if (customSources.length > 0)
|
|
28
|
+
throw new AunEncryptionSeedPolicyError(customSources);
|
|
29
|
+
}
|
package/dist/aun/aid/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { isValidAid, aidList, aidListVerified, aidCreate, aidShow, aidDelete, aidLookup, verifySignAbility, probePkiRecoverability, appendAidLifecycle, readAidLifecycle } from './identity.js';
|
|
2
|
-
export { buildInitialAgentMd, agentmdGet, agentmdPut, agentmdSync, stripAgentMdSignature, updateAgentMdFrontmatterAvatar, updateAgentMdFrontmatterName } from './agentmd.js';
|
|
2
|
+
export { buildInitialAgentMd, agentmdGet, agentmdPut, agentmdSync, invalidateAgentDisplayName, parseAgentDisplayName, refreshAgentDisplayName, resolveAgentDisplayName, stripAgentMdSignature, updateAgentMdFrontmatterAvatar, updateAgentMdFrontmatterName, } from './agentmd.js';
|
|
3
3
|
export { MIN_AUN_CORE_SDK, AUN_CORE_SDK_PKG, isAunSdkVersionOk, resolveAunCoreSdkPkg, ensureAunSdk, isAunSdkReady, downloadCaRoot, suppressSdkLogs, } from './client.js';
|
|
4
4
|
export { getAidStore, loadClient, loadAid, AidLoadError, SLOT } from './store.js';
|
package/dist/aun/aid/store.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { AUN_KEYSTORE_ENCRYPTION_SEED } from './encryption-seed-policy.js';
|
|
3
4
|
/**
|
|
4
5
|
* Slot 命名约定(基于 fastaun 0.4.3 隔离键语义)。
|
|
5
6
|
*
|
|
@@ -39,16 +40,12 @@ export class AidLoadError extends Error {
|
|
|
39
40
|
*/
|
|
40
41
|
export async function getAidStore(opts) {
|
|
41
42
|
const { aunPath: defaultAunPath } = await import('../../paths.js');
|
|
42
|
-
const { loadDaemonConfig } = await import('../../config-store.js');
|
|
43
43
|
const { AIDStore } = await import('@agentunion/fastaun');
|
|
44
44
|
const aunPath = opts.aunPath ?? defaultAunPath();
|
|
45
|
-
const encryptionSeed = loadDaemonConfig().aun?.encryptionSeed
|
|
46
|
-
?? process.env.AUN_ENCRYPTION_SEED
|
|
47
|
-
?? 'evol';
|
|
48
45
|
const caCertPath = path.join(aunPath, 'CA', 'root', 'root.crt');
|
|
49
46
|
const storeOpts = {
|
|
50
47
|
aunPath,
|
|
51
|
-
encryptionSeed,
|
|
48
|
+
encryptionSeed: AUN_KEYSTORE_ENCRYPTION_SEED,
|
|
52
49
|
slotId: opts.slotId,
|
|
53
50
|
debug: opts.debug ?? false,
|
|
54
51
|
};
|