evolcore 0.0.33 → 0.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/bin/ec.js +3 -2
- package/bin/install-codex-managed-hooks.mjs +12 -1
- package/dist/agents/baseagent-availability.js +20 -36
- package/dist/agents/claude-runner.js +82 -13
- package/dist/agents/codex/diagnostics.js +37 -11
- package/dist/agents/codex-runner.js +218 -44
- package/dist/agents/ecagent-runner.js +73 -20
- package/dist/agents/runner-types.js +5 -6
- package/dist/aun/aid/identity.js +1 -1
- package/dist/channels/aun.js +16 -6
- package/dist/channels/daemon.js +6 -3
- package/dist/cli/aun-commands.js +3 -2
- package/dist/cli/ctl-command.js +3 -1
- package/dist/cli/daemon-commands.js +120 -19
- package/dist/cli/fs-command.js +2 -1
- package/dist/cli/index.js +20 -6
- package/dist/cli/integrity-command.js +196 -0
- package/dist/cli/memory-command.js +158 -145
- package/dist/cli/thread-command.js +5 -3
- package/dist/cli/trigger-command.js +6 -1
- package/dist/config/config-field-policy.js +4 -0
- package/dist/config/config-manager.js +19 -0
- package/dist/config/contact-book-store.js +5 -0
- package/dist/config/role-service.js +13 -0
- package/dist/config/runtime-env.js +16 -0
- package/dist/config-store.js +30 -0
- package/dist/core/audit/log-integrity.js +3 -1
- package/dist/core/auth/agent-delegation.js +108 -35
- package/dist/core/auth/delegation-diagnostics.js +414 -0
- package/dist/core/auth/operation-authorizer.js +1 -1
- package/dist/core/auth/operation-catalog.js +16 -0
- package/dist/core/command/agent-control.js +18 -26
- package/dist/core/command/command-handler.js +138 -4
- package/dist/core/command/daemon-diagnostics.js +1 -0
- package/dist/core/command/menu-catalog.js +3 -0
- package/dist/core/command/menu-handler.js +22 -7
- package/dist/core/command/menu-protocol.js +1 -0
- package/dist/core/command/slash-handler.js +2 -0
- package/dist/core/daemon-bootstrap.js +4 -7
- package/dist/core/file-integrity/read.js +61 -0
- package/dist/core/file-integrity/store.js +262 -0
- package/dist/core/ipc-registration.js +36 -1
- package/dist/core/memory/batch-meta.js +132 -0
- package/dist/core/memory/consolidation-context.js +35 -14
- package/dist/core/memory/consolidation-ops-records.js +14 -16
- package/dist/core/memory/consolidation.js +91 -26
- package/dist/core/memory/index-manager.js +19 -28
- package/dist/core/memory/memory-admin.js +19 -14
- package/dist/core/memory/memory-document.js +53 -9
- package/dist/core/memory/memory-writer.js +30 -15
- package/dist/core/message/im-renderer.js +20 -4
- package/dist/core/message/message-bridge.js +2 -1
- package/dist/core/message/response-engine.js +584 -47
- package/dist/core/permission/ec-command-parser.js +93 -4
- package/dist/core/permission/protected-paths.js +5 -1
- package/dist/core/permission/readonly-shell-query.js +43 -5
- package/dist/core/permission/session-path-grants.js +334 -0
- package/dist/core/permission/tool-canonical.js +226 -0
- package/dist/core/permission/tool-policy.js +30 -62
- package/dist/core/role/runtime-policy.js +21 -10
- package/dist/core/session/session-fs-store.js +123 -8
- package/dist/core/session/session-manager.js +75 -5
- package/dist/core/skill/index-generator.js +17 -3
- package/dist/core/system-session/grants.js +40 -0
- package/dist/core/system-session/memory.js +222 -0
- package/dist/core/system-session/registry.js +74 -0
- package/dist/core/system-session/types.js +14 -0
- package/dist/core/thread/thread-service.js +13 -20
- package/dist/eck/kit-renderer.js +7 -2
- package/dist/eck/manifest-engine.js +24 -4
- package/dist/index.js +11 -2
- package/dist/ipc.js +51 -40
- package/dist/paths.js +70 -0
- package/dist/stats/billing.js +20 -8
- package/dist/trigger/feedback.js +6 -1
- package/dist/trigger/parser.js +8 -1
- package/dist/trigger/system-definitions.js +3 -3
- package/dist/utils/cross-platform.js +11 -2
- package/dist/utils/error-dict.json +18 -4
- package/dist/utils/error-utils.js +121 -0
- package/dist/utils/instance-registry.js +13 -8
- package/dist/utils/log-writer.js +12 -0
- package/dist/utils/process-introspect.js +11 -0
- package/kits/docs/context-assembly.md +0 -1
- package/kits/docs/evolcore/agent-create.md +5 -4
- package/kits/docs/evolcore/agent.md +2 -2
- package/kits/docs/evolcore/config.md +2 -2
- package/kits/docs/evolcore/ctl.md +2 -2
- package/kits/docs/evolcore/ec-capabilities.md +1 -1
- package/kits/docs/evolcore/fs-architecture.md +4 -5
- package/kits/docs/evolcore/fs.md +1 -1
- package/kits/docs/evolcore/group-collaboration.md +2 -2
- package/kits/docs/evolcore/group.md +10 -10
- package/kits/docs/evolcore/memory-architecture.md +4 -5
- package/kits/docs/evolcore/memory-consolidation.md +18 -14
- package/kits/docs/evolcore/memory-tags.md +3 -1
- package/kits/docs/evolcore/memory.md +24 -12
- package/kits/docs/evolcore/model.md +16 -0
- package/kits/docs/evolcore/msg.md +7 -7
- package/kits/docs/evolcore/thread-chain.md +5 -5
- package/kits/docs/prompt-loading-architecture.md +0 -1
- package/kits/eck_manifest.json +0 -20
- package/kits/eck_manifest.memory.json +0 -12
- package/kits/rules/01-overview.md +11 -0
- package/kits/rules/03-identity.md +6 -3
- package/kits/rules/06-channel.md +1 -1
- package/kits/rules/07-memory-and-thread.md +12 -15
- package/kits/schemas/_meta.json +7 -1
- package/kits/schemas/agent-config.schema.13.json +1 -1
- package/kits/schemas/daemon.schema.7.json +140 -0
- package/kits/skills/ec-group/SKILL.md +4 -4
- package/kits/skills/ec-skill/scripts/cli.mjs +1 -1
- package/kits/skills/ec-skill/scripts/skill.mjs +1 -1
- package/kits/templates/memory-consolidation/forget.md +2 -2
- package/kits/templates/memory-consolidation/generalize.md +4 -4
- package/kits/templates/memory-consolidation/notes.md +11 -11
- package/kits/templates/memory-consolidation/profile.md +3 -3
- package/kits/templates/memory-consolidation/promote.md +3 -3
- package/kits/templates/memory-consolidation/workflow.md +6 -6
- package/kits/templates/message-fragments/handoff-request-to-target.md +1 -1
- package/kits/templates/system-fragments/bootstrap.md +4 -3
- package/kits/templates/system-fragments/channel.md +2 -2
- package/kits/templates/system-fragments/memory.md +16 -9
- package/kits/templates/system-fragments/reply.md +6 -6
- package/kits/templates/system-fragments/session.md +1 -1
- package/package.json +4 -3
- package/dist/core/memory/memory-session-policy.js +0 -41
- package/dist/core/memory/memory-signature.js +0 -257
|
@@ -18,6 +18,7 @@ import { auditToolPreflightDenial } from '../core/auth/authorization-audit.js';
|
|
|
18
18
|
import { resolveEcagentConfig } from './baseagent.js';
|
|
19
19
|
import { buildModelRequestHeaders } from './request-identity.js';
|
|
20
20
|
import { appendRequestPath } from './request-identity.js';
|
|
21
|
+
import { resolveModelSpec } from '../stats/billing.js';
|
|
21
22
|
import { getManagedTaskTempDir } from '../cli/task-context.js';
|
|
22
23
|
import { unsettledInterruptError, withInterruptDeadline, hasTrustedFullAccessContext } from './runner-types.js';
|
|
23
24
|
const PROVIDER_ID = 'evolcore-gateway';
|
|
@@ -436,18 +437,23 @@ async function consumeOpenAiStream(output, body, model) {
|
|
|
436
437
|
throw new Error('[network] Gateway stream ended without a terminal event');
|
|
437
438
|
}
|
|
438
439
|
function createModel(id, baseUrl) {
|
|
439
|
-
const
|
|
440
|
+
const modelId = stripContextWindowSuffix(id);
|
|
441
|
+
const isClaude = modelId.toLowerCase().startsWith('claude-');
|
|
442
|
+
const fallback = isClaude
|
|
443
|
+
? { context_window: 200_000, max_output_tokens: 8_192 }
|
|
444
|
+
: { context_window: 128_000, max_output_tokens: 16_384 };
|
|
445
|
+
const spec = resolveModelSpec(resolveRoot(), id, undefined, fallback);
|
|
440
446
|
return {
|
|
441
|
-
id,
|
|
442
|
-
name:
|
|
447
|
+
id: modelId,
|
|
448
|
+
name: modelId,
|
|
443
449
|
api: 'openai-completions',
|
|
444
450
|
provider: PROVIDER_ID,
|
|
445
451
|
baseUrl,
|
|
446
452
|
reasoning: true,
|
|
447
453
|
input: ['text', 'image'],
|
|
448
454
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
449
|
-
contextWindow:
|
|
450
|
-
maxTokens:
|
|
455
|
+
contextWindow: spec.context_window,
|
|
456
|
+
maxTokens: spec.max_output_tokens,
|
|
451
457
|
compat: {
|
|
452
458
|
maxTokensField: 'max_tokens',
|
|
453
459
|
supportsUsageInStreaming: true,
|
|
@@ -464,7 +470,11 @@ function isWithin(root, candidate) {
|
|
|
464
470
|
const relative = path.relative(root, candidate);
|
|
465
471
|
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
466
472
|
}
|
|
467
|
-
|
|
473
|
+
/** 路径是否落在任一显式声明的根之下(含根本身)。 */
|
|
474
|
+
function isWithinAny(candidate, roots) {
|
|
475
|
+
return roots.some(root => isWithin(path.resolve(root), candidate));
|
|
476
|
+
}
|
|
477
|
+
export function resolveEcagentToolPath(projectPath, candidate, forWrite = false, bootstrapAgentMdPath, fullaccess = false, personalMdPath, sessionGrants) {
|
|
468
478
|
const root = fs.realpathSync(projectPath);
|
|
469
479
|
const resolved = path.resolve(root, candidate || '.');
|
|
470
480
|
const allowedBootstrapFile = bootstrapAgentMdPath
|
|
@@ -472,7 +482,15 @@ export function resolveEcagentToolPath(projectPath, candidate, forWrite = false,
|
|
|
472
482
|
: undefined;
|
|
473
483
|
const allowedPersonalFile = personalMdPath ? path.resolve(personalMdPath) : undefined;
|
|
474
484
|
const isManagedIdentityFile = resolved === allowedBootstrapFile || resolved === allowedPersonalFile;
|
|
475
|
-
|
|
485
|
+
// 系统会话:模块声明的可读根整体放行,可写文件逐个精确匹配(不含目录)。
|
|
486
|
+
// 声明之外、项目之外的路径仍然拒绝。声明里的路径可能在多个根之间借符号链接互串,
|
|
487
|
+
// 所以放行前统一按真实路径复核,确认真实位置仍落在同一个被授予的边界内。
|
|
488
|
+
// 写只看可写文件(逐个精确匹配),绝不由可读根推导;读只看可读根。
|
|
489
|
+
const sessionWrites = forWrite && (sessionGrants?.writeFiles ?? [])
|
|
490
|
+
.some(file => path.resolve(file) === resolved);
|
|
491
|
+
const sessionReads = !forWrite && isWithinAny(resolved, sessionGrants?.readRoots ?? []);
|
|
492
|
+
const isSessionTarget = sessionReads || sessionWrites;
|
|
493
|
+
if (!fullaccess && !isWithin(root, resolved) && !isManagedIdentityFile && !isSessionTarget) {
|
|
476
494
|
throw new Error(`Path is outside the project: ${candidate}`);
|
|
477
495
|
}
|
|
478
496
|
if (isManagedIdentityFile) {
|
|
@@ -494,7 +512,34 @@ export function resolveEcagentToolPath(projectPath, candidate, forWrite = false,
|
|
|
494
512
|
while (!fs.existsSync(cursor) && cursor !== path.dirname(cursor))
|
|
495
513
|
cursor = path.dirname(cursor);
|
|
496
514
|
const canonical = fs.realpathSync(cursor);
|
|
497
|
-
if (
|
|
515
|
+
if (fullaccess)
|
|
516
|
+
return resolved;
|
|
517
|
+
// 系统会话的写入目标与判定层一致:必须是普通文件,链接一律拒绝。
|
|
518
|
+
// 链接会让 resolved 与真实位置分离,放行等于把洞开到声明之外。
|
|
519
|
+
if (sessionWrites && fs.existsSync(resolved) && fs.lstatSync(resolved).isSymbolicLink()) {
|
|
520
|
+
throw new Error(`Refusing to write through a symbolic link: ${candidate}`);
|
|
521
|
+
}
|
|
522
|
+
// 可写文件尚未创建时,以父目录的真实路径为准;已存在时以文件自身的真实路径为准。
|
|
523
|
+
const canonicalSelf = fs.existsSync(resolved) ? fs.realpathSync(resolved) : canonical;
|
|
524
|
+
if (isSessionTarget) {
|
|
525
|
+
const grantedRoots = [
|
|
526
|
+
...(sessionReads ? sessionGrants?.readRoots ?? [] : []),
|
|
527
|
+
...(sessionWrites ? (sessionGrants?.writeFiles ?? []).filter(file => path.resolve(file) === resolved) : []),
|
|
528
|
+
];
|
|
529
|
+
const canonicalRoots = grantedRoots.flatMap(granted => {
|
|
530
|
+
const inside = fs.existsSync(granted) ? [fs.realpathSync(granted)] : [];
|
|
531
|
+
// 根自身可能尚未创建,或者位于尚未创建的上层目录中;先归到存在的祖先再比。
|
|
532
|
+
let ancestor = granted;
|
|
533
|
+
while (!fs.existsSync(ancestor) && ancestor !== path.dirname(ancestor))
|
|
534
|
+
ancestor = path.dirname(ancestor);
|
|
535
|
+
return [...inside, fs.realpathSync(ancestor)];
|
|
536
|
+
});
|
|
537
|
+
if (!canonicalRoots.some(granted => isWithin(granted, canonical) && isWithin(granted, canonicalSelf))) {
|
|
538
|
+
throw new Error(`Path resolves outside its declared grant: ${candidate}`);
|
|
539
|
+
}
|
|
540
|
+
return resolved;
|
|
541
|
+
}
|
|
542
|
+
if (!isWithin(root, canonical))
|
|
498
543
|
throw new Error(`Path resolves outside the project: ${candidate}`);
|
|
499
544
|
return resolved;
|
|
500
545
|
}
|
|
@@ -547,7 +592,7 @@ async function walkFiles(root, signal) {
|
|
|
547
592
|
function textResult(text, details = {}) {
|
|
548
593
|
return { content: [{ type: 'text', text: truncate(text) }], details };
|
|
549
594
|
}
|
|
550
|
-
function createTools(env, projectPath, runtimeEnv, bootstrapAgentMdPath, fullaccess = false, personalMdPath) {
|
|
595
|
+
function createTools(env, projectPath, runtimeEnv, bootstrapAgentMdPath, fullaccess = false, personalMdPath, sessionGrants) {
|
|
551
596
|
const read = {
|
|
552
597
|
name: 'Read', label: 'Read', description: 'Read a UTF-8 text file from the project.',
|
|
553
598
|
parameters: Type.Object({
|
|
@@ -556,7 +601,7 @@ function createTools(env, projectPath, runtimeEnv, bootstrapAgentMdPath, fullacc
|
|
|
556
601
|
limit: Type.Optional(Type.Number({ minimum: 1 })),
|
|
557
602
|
}),
|
|
558
603
|
async execute(_id, params, signal) {
|
|
559
|
-
const file = resolveEcagentToolPath(projectPath, params.file_path, false, bootstrapAgentMdPath, fullaccess, personalMdPath);
|
|
604
|
+
const file = resolveEcagentToolPath(projectPath, params.file_path, false, bootstrapAgentMdPath, fullaccess, personalMdPath, sessionGrants);
|
|
560
605
|
const stat = await fs.promises.stat(file);
|
|
561
606
|
if (stat.size > MAX_READ_BYTES)
|
|
562
607
|
throw new Error(`File exceeds ${MAX_READ_BYTES} byte read limit`);
|
|
@@ -573,7 +618,7 @@ function createTools(env, projectPath, runtimeEnv, bootstrapAgentMdPath, fullacc
|
|
|
573
618
|
name: 'Glob', label: 'Glob', description: 'Find project files matching a glob pattern.',
|
|
574
619
|
parameters: Type.Object({ pattern: Type.String(), path: Type.Optional(Type.String()) }),
|
|
575
620
|
async execute(_id, params, signal) {
|
|
576
|
-
const root = resolveEcagentToolPath(projectPath, params.path ?? '.', false, undefined, fullaccess);
|
|
621
|
+
const root = resolveEcagentToolPath(projectPath, params.path ?? '.', false, undefined, fullaccess, undefined, sessionGrants);
|
|
577
622
|
const matcher = globRegex(params.pattern.replaceAll('\\', '/'));
|
|
578
623
|
const files = (await walkFiles(root, signal))
|
|
579
624
|
.map(file => path.relative(root, file).replaceAll(path.sep, '/'))
|
|
@@ -589,7 +634,7 @@ function createTools(env, projectPath, runtimeEnv, bootstrapAgentMdPath, fullacc
|
|
|
589
634
|
case_insensitive: Type.Optional(Type.Boolean()), literal: Type.Optional(Type.Boolean()),
|
|
590
635
|
}),
|
|
591
636
|
async execute(_id, params, signal) {
|
|
592
|
-
const root = resolveEcagentToolPath(projectPath, params.path ?? '.', false, undefined, fullaccess);
|
|
637
|
+
const root = resolveEcagentToolPath(projectPath, params.path ?? '.', false, undefined, fullaccess, undefined, sessionGrants);
|
|
593
638
|
const files = (await fs.promises.stat(root)).isFile() ? [root] : await walkFiles(root, signal);
|
|
594
639
|
const fileMatcher = params.glob ? globRegex(params.glob.replaceAll('\\', '/')) : undefined;
|
|
595
640
|
const flags = params.case_insensitive ? 'i' : '';
|
|
@@ -622,7 +667,7 @@ function createTools(env, projectPath, runtimeEnv, bootstrapAgentMdPath, fullacc
|
|
|
622
667
|
name: 'Write', label: 'Write', description: 'Create or completely overwrite a project file.',
|
|
623
668
|
parameters: Type.Object({ file_path: Type.String(), content: Type.String() }), executionMode: 'sequential',
|
|
624
669
|
async execute(_id, params, signal) {
|
|
625
|
-
const file = resolveEcagentToolPath(projectPath, params.file_path, true, bootstrapAgentMdPath, fullaccess, personalMdPath);
|
|
670
|
+
const file = resolveEcagentToolPath(projectPath, params.file_path, true, bootstrapAgentMdPath, fullaccess, personalMdPath, sessionGrants);
|
|
626
671
|
await fs.promises.mkdir(path.dirname(file), { recursive: true });
|
|
627
672
|
await fs.promises.writeFile(file, params.content, { encoding: 'utf8', signal });
|
|
628
673
|
return textResult(`Wrote ${Buffer.byteLength(params.content)} bytes to ${path.relative(projectPath, file)}`, { file });
|
|
@@ -635,7 +680,7 @@ function createTools(env, projectPath, runtimeEnv, bootstrapAgentMdPath, fullacc
|
|
|
635
680
|
replace_all: Type.Optional(Type.Boolean()),
|
|
636
681
|
}), executionMode: 'sequential',
|
|
637
682
|
async execute(_id, params, signal) {
|
|
638
|
-
const file = resolveEcagentToolPath(projectPath, params.file_path,
|
|
683
|
+
const file = resolveEcagentToolPath(projectPath, params.file_path, true, bootstrapAgentMdPath, fullaccess, personalMdPath, sessionGrants);
|
|
639
684
|
const value = await fs.promises.readFile(file, { encoding: 'utf8', signal });
|
|
640
685
|
if (!params.old_string)
|
|
641
686
|
throw new Error('old_string must not be empty');
|
|
@@ -724,7 +769,7 @@ export class EcagentRunner {
|
|
|
724
769
|
configuredHeaders: config.headers,
|
|
725
770
|
}),
|
|
726
771
|
};
|
|
727
|
-
this.model =
|
|
772
|
+
this.model = config.model;
|
|
728
773
|
this.effort = config.effort;
|
|
729
774
|
this.agentAid = runtime?.agentAid;
|
|
730
775
|
this.onSessionIdUpdate = callbacks?.onSessionIdUpdate;
|
|
@@ -734,8 +779,8 @@ export class EcagentRunner {
|
|
|
734
779
|
throw new Error('ecagent requires an EvolCore Agent AID');
|
|
735
780
|
return agentSessionsDir(this.agentAid);
|
|
736
781
|
}
|
|
737
|
-
setModel(model) { this.model =
|
|
738
|
-
getModel() { return this.model; }
|
|
782
|
+
setModel(model) { this.model = model; }
|
|
783
|
+
getModel() { return stripContextWindowSuffix(this.model); }
|
|
739
784
|
resolveModelId(model) { return model; }
|
|
740
785
|
setEffort(effort) { this.effort = effort; }
|
|
741
786
|
getEffort() { return this.effort; }
|
|
@@ -885,7 +930,7 @@ export class EcagentRunner {
|
|
|
885
930
|
models,
|
|
886
931
|
model,
|
|
887
932
|
thinkingLevel: normalizeThinkingLevel(effort),
|
|
888
|
-
tools: createTools(nodeEnv, request.projectPath, request.runtimeEnv, request.modelOverride?.bootstrapAgentMdPath, fullaccess, request.modelOverride?.personalMdPath),
|
|
933
|
+
tools: createTools(nodeEnv, request.projectPath, request.runtimeEnv, request.modelOverride?.bootstrapAgentMdPath, fullaccess, request.modelOverride?.personalMdPath, this.permissionContexts.get(request.sessionId)?.systemSessionGrants),
|
|
889
934
|
systemPrompt: [DEFAULT_SYSTEM_PROMPT, request.systemPromptAppend].filter(Boolean).join('\n\n'),
|
|
890
935
|
streamOptions: {
|
|
891
936
|
timeoutMs: this.config.timeoutMs,
|
|
@@ -1212,6 +1257,14 @@ export class EcagentRunner {
|
|
|
1212
1257
|
logger.warn(`[EcagentRunner] failed to record blocked operation: session=${sessionId} tool=${toolName} code=${policyCode} error=${error instanceof Error ? error.message : String(error)}`);
|
|
1213
1258
|
}
|
|
1214
1259
|
};
|
|
1260
|
+
// 系统会话:模块判定即最终结论,不进入 preflight / permissionMode 分支
|
|
1261
|
+
if (permissionContext?.systemSessionCheck) {
|
|
1262
|
+
const decision = permissionContext.systemSessionCheck(toolName, input);
|
|
1263
|
+
if (decision.allow)
|
|
1264
|
+
return {};
|
|
1265
|
+
await recordBlockedOperation(decision.code);
|
|
1266
|
+
return { block: true, reason: decision.reason };
|
|
1267
|
+
}
|
|
1215
1268
|
const policy = permissionContext?.policyHook?.(toolName, input, { turn });
|
|
1216
1269
|
if (policy?.block) {
|
|
1217
1270
|
await recordBlockedOperation(policy.policyCode ?? 'session_policy_hook');
|
|
@@ -1239,7 +1292,7 @@ export class EcagentRunner {
|
|
|
1239
1292
|
const checkedInput = preflight.input;
|
|
1240
1293
|
if (mode === 'readonly') {
|
|
1241
1294
|
const decision = checkReadonly(toolName, checkedInput, projectPath, {
|
|
1242
|
-
sessionId, managedTempDir: permissionContext?.managedTempDir, channel: permissionContext?.channel, peerId: permissionContext?.userId, role: permissionContext?.role,
|
|
1295
|
+
sessionId, managedTempDir: permissionContext?.managedTempDir, grantedReadRoots: permissionContext?.grantedReadRoots, channel: permissionContext?.channel, peerId: permissionContext?.userId, role: permissionContext?.role,
|
|
1243
1296
|
allowReadonlySourceDiagnostics: permissionContext?.allowReadonlySourceDiagnostics === true,
|
|
1244
1297
|
});
|
|
1245
1298
|
if (decision.behavior === 'deny') {
|
|
@@ -1351,7 +1404,7 @@ export class EcagentRunner {
|
|
|
1351
1404
|
? cached
|
|
1352
1405
|
: await this.openExistingRuntime(agentSessionId, cwd);
|
|
1353
1406
|
this.onCompactStart?.(sessionId);
|
|
1354
|
-
const compactModel =
|
|
1407
|
+
const compactModel = modelOverride?.model || this.model;
|
|
1355
1408
|
const compactEffort = modelOverride?.effortMode === 'model_default'
|
|
1356
1409
|
? undefined
|
|
1357
1410
|
: modelOverride?.effort ?? this.effort;
|
|
@@ -136,10 +136,9 @@ export function isOneMillionContextModel(model) {
|
|
|
136
136
|
return ONE_M_CONTEXT_MODEL_PREFIXES.some(prefix => base === prefix || base.startsWith(`${prefix}-`));
|
|
137
137
|
}
|
|
138
138
|
/**
|
|
139
|
-
*
|
|
140
|
-
* every other model falls back to 200,000
|
|
141
|
-
* This is an operational guardrail, not a claim about
|
|
142
|
-
* advertised capacity.
|
|
139
|
+
* Hardcoded context-window fallback for models missing from the parameter table:
|
|
140
|
+
* known 1M models use 1,000,000; every other model falls back to 200,000.
|
|
141
|
+
* This is an operational guardrail, not a claim about advertised capacity.
|
|
143
142
|
*/
|
|
144
143
|
export function realContextWindowForModel(model) {
|
|
145
144
|
return isOneMillionContextModel(model) ? 1000000 : 200000;
|
|
@@ -159,8 +158,8 @@ export function autoCompactWindowForModel(_model) {
|
|
|
159
158
|
* at the right point for small-context models (200k/128k), where EvolCore's
|
|
160
159
|
* fixed 650k threshold would never trigger.
|
|
161
160
|
*/
|
|
162
|
-
export function sdkAutoCompactWindowForModel(model) {
|
|
163
|
-
const contextWindow = realContextWindowForModel(model);
|
|
161
|
+
export function sdkAutoCompactWindowForModel(model, resolvedContextWindow) {
|
|
162
|
+
const contextWindow = resolvedContextWindow ?? realContextWindowForModel(model);
|
|
164
163
|
const reserve = Math.min(10_000, Math.floor(contextWindow * 0.05));
|
|
165
164
|
return Math.min(650_000, Math.max(1, contextWindow - reserve));
|
|
166
165
|
}
|
package/dist/aun/aid/identity.js
CHANGED
|
@@ -224,7 +224,7 @@ export async function aidCreate(aid, opts) {
|
|
|
224
224
|
// 新注册流程:AIDStore.register → downloadCaRoot → load → authenticate
|
|
225
225
|
const store = await getAidStore({ slotId: SLOT.cli, aunPath });
|
|
226
226
|
try {
|
|
227
|
-
const regResult = await store.register(aid);
|
|
227
|
+
const regResult = await store.register(aid, { type: 'agent' });
|
|
228
228
|
if (!regResult.ok) {
|
|
229
229
|
const e = new Error(regResult.error.message);
|
|
230
230
|
e.code = regResult.error.code;
|
package/dist/channels/aun.js
CHANGED
|
@@ -557,6 +557,11 @@ function setIfDefined(target, key, value) {
|
|
|
557
557
|
if (value !== undefined)
|
|
558
558
|
target[key] = value;
|
|
559
559
|
}
|
|
560
|
+
function appendRawErrorText(text, raw) {
|
|
561
|
+
if (typeof raw !== 'string' || !raw.trim() || text.includes(raw))
|
|
562
|
+
return text;
|
|
563
|
+
return `${text}\n原因:${raw}`;
|
|
564
|
+
}
|
|
560
565
|
/**
|
|
561
566
|
* 把 AUNChannel 投递的 opts 映射成渠道无关的 InboundMessage。
|
|
562
567
|
*
|
|
@@ -6415,6 +6420,7 @@ export class AUNChannelPlugin {
|
|
|
6415
6420
|
text: payload.text,
|
|
6416
6421
|
severity: 'info',
|
|
6417
6422
|
};
|
|
6423
|
+
setIfDefined(noticePayload, 'raw', payload.raw);
|
|
6418
6424
|
setIfDefined(noticePayload, 'subtype', payload.subtype);
|
|
6419
6425
|
await channel.sendReliableStructured(channelId, noticePayload, replyCtx, payload.text);
|
|
6420
6426
|
return;
|
|
@@ -6424,10 +6430,14 @@ export class AUNChannelPlugin {
|
|
|
6424
6430
|
type: payload.recoverable === true ? 'notice' : 'error',
|
|
6425
6431
|
...taskBase(),
|
|
6426
6432
|
subtype: payload.subtype,
|
|
6427
|
-
text: payload.
|
|
6433
|
+
text: payload.recoverable === true
|
|
6434
|
+
? payload.text
|
|
6435
|
+
: appendRawErrorText(payload.text, payload.raw),
|
|
6436
|
+
...(payload.raw !== undefined ? { raw: payload.raw } : {}),
|
|
6437
|
+
...(payload.reason !== undefined ? { reason: payload.reason } : {}),
|
|
6428
6438
|
...(payload.recoverable === true
|
|
6429
6439
|
? { severity: 'warn' }
|
|
6430
|
-
: {
|
|
6440
|
+
: { recoverable: false }),
|
|
6431
6441
|
};
|
|
6432
6442
|
await channel.sendReliableStructured(channelId, errorPayload, { ...(replyCtx ?? {}), suppressPeerMention: true }, payload.text);
|
|
6433
6443
|
return;
|
|
@@ -6436,11 +6446,11 @@ export class AUNChannelPlugin {
|
|
|
6436
6446
|
const errorPayload = {
|
|
6437
6447
|
type: 'error',
|
|
6438
6448
|
...taskBase(),
|
|
6439
|
-
|
|
6440
|
-
text: payload.text,
|
|
6441
|
-
message: payload.text,
|
|
6442
|
-
user_message: payload.text,
|
|
6449
|
+
text: appendRawErrorText(payload.text, payload.raw),
|
|
6443
6450
|
};
|
|
6451
|
+
setIfDefined(errorPayload, 'subtype', payload.subtype);
|
|
6452
|
+
setIfDefined(errorPayload, 'reason', payload.reason);
|
|
6453
|
+
setIfDefined(errorPayload, 'raw', payload.raw);
|
|
6444
6454
|
await channel.sendReliableStructured(channelId, errorPayload, { ...(replyCtx ?? {}), suppressPeerMention: true }, payload.text);
|
|
6445
6455
|
return;
|
|
6446
6456
|
}
|
package/dist/channels/daemon.js
CHANGED
|
@@ -2,6 +2,7 @@ import { appendExpireEntry, recordNextLaunchCleanup, cleanupPreviousByKind, runE
|
|
|
2
2
|
import { ExecutionTimeoutError } from '../utils/error-utils.js';
|
|
3
3
|
import { normalizeExecutionMode } from '../trigger/validation.js';
|
|
4
4
|
import { resolvePeerRoleDetail } from '../config/peer-role-resolver.js';
|
|
5
|
+
import { assertSystemSessionLaunchable } from '../core/system-session/registry.js';
|
|
5
6
|
const DEFAULT_WATCHDOG_MS = 11 * 60 * 1000;
|
|
6
7
|
export class DaemonChannel {
|
|
7
8
|
sessionManager;
|
|
@@ -253,6 +254,9 @@ export class DaemonChannel {
|
|
|
253
254
|
// 记忆整理会话:把会话原型与整理模式写进 metadata,供渲染层选 manifest / 手册,
|
|
254
255
|
// 供 ipc 侧校验写命令的 --scope。
|
|
255
256
|
const { memoryMode, memoryScope, consolidationBatchDir, consolidationChatDir, consolidationMemoryDir } = trigger.execution;
|
|
257
|
+
// 系统会话:类型 / subtype / runner 校验不过直接拒绝(Gemini 不支持),不降级成普通会话
|
|
258
|
+
if (memoryMode)
|
|
259
|
+
assertSystemSessionLaunchable({ type: 'memory', subtype: memoryMode }, baseagent);
|
|
256
260
|
// 反馈目标与触发方式(consolidation.ts 在 normalize 后补挂的字段):
|
|
257
261
|
// 收尾时据此投递反馈,并判断是否该反馈(定时触发不反馈)。
|
|
258
262
|
const { feedbackOrigin, consolidationTriggeredBy } = trigger.execution;
|
|
@@ -260,7 +264,7 @@ export class DaemonChannel {
|
|
|
260
264
|
channelKey: this.channelKey,
|
|
261
265
|
peerId: `trigger:${trigger.id}`,
|
|
262
266
|
peerName: trigger.name,
|
|
263
|
-
...(memoryMode ? { sessionType: 'memory', memoryMode } : {}),
|
|
267
|
+
...(memoryMode ? { systemSession: { type: 'memory', subtype: memoryMode }, sessionType: 'memory', memoryMode } : {}),
|
|
264
268
|
...(memoryScope ? { memoryScope } : {}),
|
|
265
269
|
...(consolidationBatchDir ? { consolidationBatchDir } : {}),
|
|
266
270
|
...(consolidationChatDir ? { consolidationChatDir } : {}),
|
|
@@ -570,8 +574,6 @@ export class DaemonChannel {
|
|
|
570
574
|
peerId: `bg:${spec.kind}`,
|
|
571
575
|
peerName: spec.kind,
|
|
572
576
|
peerType: 'system',
|
|
573
|
-
bgKind: spec.kind,
|
|
574
|
-
bgInstanceId: spec.instanceId,
|
|
575
577
|
...(spec.metadata ?? {}),
|
|
576
578
|
}, spec.kind, undefined, 'private', spec.baseagent, spec.agentAid, this.channelName, 'system');
|
|
577
579
|
const promise = new Promise((resolve) => {
|
|
@@ -586,6 +588,7 @@ export class DaemonChannel {
|
|
|
586
588
|
terminated: false,
|
|
587
589
|
cleanupPolicy,
|
|
588
590
|
agentAid: spec.agentAid,
|
|
591
|
+
runtimeDir: spec.runtimeDir,
|
|
589
592
|
watchdogTimer: setTimeout(() => {
|
|
590
593
|
this.finishBgSession(runId, slot, 'error', 'bg-session watchdog timeout');
|
|
591
594
|
}, this.watchdogMs),
|
package/dist/cli/aun-commands.js
CHANGED
|
@@ -2173,7 +2173,8 @@ Options:
|
|
|
2173
2173
|
无值时默认 5m;Trigger 名:check-<目标threadId>-from-<来源threadId>-<唯一后缀>
|
|
2174
2174
|
取消/调整用返回的 trigger_id(trig_…),show/update/cancel 只认 id
|
|
2175
2175
|
--trigger-prompt <text> 自定义复查 Trigger prompt 中的用户段(仅 --check-every)
|
|
2176
|
-
--mention
|
|
2176
|
+
--mention <...> 发送时 @ 某个成员。写法固定为单引号包住、逗号分隔多个 aid
|
|
2177
|
+
(如 --mention 'alice.agentid.pub,bob.agentid.pub'),可多次传入
|
|
2177
2178
|
--mention-all 发送时 @ 所有人
|
|
2178
2179
|
--content-type <mime> 显式覆盖 MIME(仅 --file 模式)
|
|
2179
2180
|
--as <type> 附件类型:image|video|voice|file(仅 --file 模式)
|
|
@@ -2187,7 +2188,7 @@ Options:
|
|
|
2187
2188
|
格式示例(.example.invalid 是保留的虚构域,以下 AID 均不是真实地址):
|
|
2188
2189
|
ec group create sender.example.invalid "Dev Team" --visibility private
|
|
2189
2190
|
ec group send sender.example.invalid 12345.example.invalid "hello team"
|
|
2190
|
-
ec group send sender.example.invalid 12345.example.invalid
|
|
2191
|
+
ec group send sender.example.invalid 12345.example.invalid '@member 看下 PR' --mention 'member.example.invalid'
|
|
2191
2192
|
ec group send sender.example.invalid 12345.example.invalid --file ./arch.png
|
|
2192
2193
|
ec group send sender.example.invalid g-12345.example.invalid "进度?" --thread thread-xxx --check-every 30m
|
|
2193
2194
|
ec group rules sender.example.invalid 12345.example.invalid set ./rules.md
|
package/dist/cli/ctl-command.js
CHANGED
|
@@ -25,7 +25,9 @@ const CTL_HELP = `用法: ec ctl <command> [args...]
|
|
|
25
25
|
ec ctl name "新会话名称"
|
|
26
26
|
ec ctl send "任务已完成"
|
|
27
27
|
ec ctl file report.md
|
|
28
|
-
ec ctl queue --full
|
|
28
|
+
ec ctl queue --full
|
|
29
|
+
ec ctl path list
|
|
30
|
+
ec ctl path grant "D:/shared/data" --access read`;
|
|
29
31
|
export async function cmdCtl(args) {
|
|
30
32
|
if (args.length === 0) {
|
|
31
33
|
console.error(CTL_HELP);
|