evolcore 0.0.2 → 0.0.4
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 +93 -778
- 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 +198 -48
- package/dist/agents/codex-app-server-client.js +68 -0
- package/dist/agents/codex-runner.js +203 -8
- 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/aun/outbox.js +8 -0
- package/dist/channels/aun.js +241 -116
- package/dist/channels/daemon.js +18 -4
- package/dist/channels/dingtalk.js +1005 -260
- package/dist/channels/feishu.js +184 -56
- package/dist/channels/qqbot.js +23 -1
- package/dist/channels/wechat.js +303 -155
- package/dist/channels/wecom.js +1132 -164
- package/dist/cli/agent-command.js +2 -1
- package/dist/cli/aun-commands.js +98 -43
- package/dist/cli/bench.js +2 -2
- package/dist/cli/contact.js +71 -0
- package/dist/cli/ctl-command.js +2 -2
- package/dist/cli/daemon-commands.js +77 -214
- package/dist/cli/handoff-command.js +4 -3
- package/dist/cli/help.js +9 -5
- package/dist/cli/index.js +132 -116
- package/dist/cli/init-channel.js +242 -129
- package/dist/cli/init.js +70 -31
- package/dist/cli/model.js +2 -1
- package/dist/cli/net-check.js +2 -2
- package/dist/cli/queue-command.js +30 -6
- package/dist/cli/raw-key-input.js +25 -0
- package/dist/cli/response.js +5 -6
- package/dist/cli/restart-monitor.js +25 -1
- package/dist/cli/stats.js +6 -4
- package/dist/cli/trigger-command.js +146 -25
- package/dist/cli/version.js +6 -1
- package/dist/config/access-policy-domain.js +38 -0
- package/dist/config/access-policy.js +134 -0
- package/dist/config/builtin-role-templates.js +42 -17
- package/dist/config/builtin-roles.js +31 -6
- package/dist/config/config-field-policy.js +17 -5
- package/dist/config/config-manager.js +409 -29
- package/dist/config/config-operation-service.js +35 -38
- package/dist/config/contact-alias.js +68 -0
- package/dist/config/contact-bind-code.js +274 -0
- package/dist/config/contact-book-store.js +622 -0
- package/dist/config/contact-book-v2-startup.js +35 -0
- package/dist/config/contact-book.js +185 -300
- package/dist/config/contact-operation-service.js +116 -0
- package/dist/config/contact-request-service.js +331 -0
- package/dist/config/peer-role-resolver.js +136 -55
- package/dist/config/role-ranks.js +18 -0
- package/dist/config/role-service.js +16 -19
- package/dist/config/role-store.js +16 -5
- package/dist/config/roles.js +10 -1
- package/dist/config/schema-registry.js +49 -24
- package/dist/config-store.js +14 -4
- package/dist/core/auth/agent-delegation.js +105 -11
- package/dist/core/auth/authorization-audit.js +16 -1
- package/dist/core/auth/operation-authorizer.js +10 -0
- package/dist/core/auth/operation-catalog.js +105 -1
- 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 +113 -21
- package/dist/core/command/connect-menu.js +599 -0
- 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 +382 -100
- 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 +128 -29
- package/dist/core/command/slash-gate.js +1 -1
- package/dist/core/command/slash-handler.js +186 -49
- package/dist/core/daemon-file-cache.js +40 -6
- package/dist/core/event-catalog.js +99 -0
- package/dist/core/evolagent-registry.js +4 -40
- package/dist/core/evolagent.js +20 -9
- 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 +20 -14
- package/dist/core/message/inbound-admission.js +124 -0
- package/dist/core/message/message-bridge.js +670 -57
- package/dist/core/message/message-log.js +1 -0
- package/dist/core/message/message-queue.js +195 -10
- package/dist/core/message/message-utils.js +8 -2
- package/dist/core/message/peer-mode.js +7 -8
- package/dist/core/message/response-engine.js +642 -96
- package/dist/core/message/send-receipt.js +24 -0
- package/dist/core/message/stream-debouncer.js +11 -2
- 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 +115 -38
- package/dist/core/protected-paths.js +38 -11
- package/dist/core/session/session-fs-store.js +44 -3
- package/dist/core/session/session-manager.js +86 -8
- 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 +285 -94
- package/dist/ipc.js +114 -8
- 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/stats/billing.js +20 -8
- package/dist/trigger/manager.js +3 -0
- package/dist/trigger/parser.js +126 -11
- package/dist/trigger/patch.js +12 -2
- package/dist/trigger/scheduler.js +444 -40
- package/dist/trigger/validation.js +13 -0
- package/dist/utils/aid-bind.js +43 -29
- package/dist/utils/error-dict.json +7 -0
- package/dist/utils/evolcore-version.js +21 -0
- package/dist/utils/instance-registry.js +14 -7
- package/dist/utils/log-writer.js +46 -0
- package/dist/utils/logger.js +2 -2
- package/dist/utils/media-cache.js +4 -1
- package/dist/utils/model-prices.jsonl +6 -3
- package/dist/utils/restart-safety.js +31 -0
- package/dist/utils/stable-semver.js +21 -0
- package/dist/utils/stats.js +33 -9
- package/dist/utils/system-memory.js +62 -0
- package/kits/docs/INDEX.md +2 -1
- package/kits/docs/channels/aun.md +4 -13
- package/kits/docs/evolcore/INDEX.md +5 -3
- package/kits/docs/evolcore/agent.md +9 -1
- package/kits/docs/evolcore/aid.md +5 -2
- package/kits/docs/evolcore/config.md +47 -2
- package/kits/docs/evolcore/contact.md +61 -0
- package/kits/docs/evolcore/fs.md +9 -0
- package/kits/docs/evolcore/group-rules.md +46 -4
- package/kits/docs/evolcore/group.md +15 -6
- package/kits/docs/evolcore/model.md +4 -1
- package/kits/docs/evolcore/msg.md +12 -6
- package/kits/docs/evolcore/response.md +16 -21
- package/kits/docs/evolcore/rpc.md +2 -0
- package/kits/docs/evolcore/stats.md +15 -2
- package/kits/docs/evolcore/storage.md +1 -0
- package/kits/docs/evolcore/trigger.md +42 -10
- package/kits/docs/path-registry.md +36 -17
- package/kits/eck_manifest.json +12 -0
- package/kits/eck_message_manifest.json +12 -1
- package/kits/migrations/migrate-contact-book-v2.mjs +754 -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 +21 -7
- package/kits/schemas/agent-config.schema.6.json +322 -0
- 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 +374 -0
- package/kits/schemas/contact-book.schema.2.json +43 -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.5.json +47 -0
- package/kits/schemas/relation-config.schema.6.json +46 -0
- package/kits/schemas/relation-config.schema.7.json +59 -0
- package/kits/schemas/role-config.schema.1.json +1 -0
- package/kits/schemas/role-registry.schema.1.json +2 -2
- 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 +47 -0
- package/kits/templates/roles/member.json +5 -0
- package/kits/templates/roles/owner.json +1 -0
- package/kits/templates/roles/visitor.json +5 -0
- package/kits/templates/system-fragments/channel.md +12 -2
- package/kits/templates/system-fragments/commands.md +3 -1
- 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 +7 -5
- package/MIGRATION-0.5.0.md +0 -378
- package/ROLE_ACCESS_CONTROL.md +0 -174
- package/assets/brand/evolcore/README.md +0 -19
- package/assets/brand/evolcore/evolcore-app-icon.png +0 -0
- package/assets/brand/evolcore/evolcore-app-icon.svg +0 -13
- package/assets/brand/evolcore/evolcore-brand-board.png +0 -0
- package/assets/brand/evolcore/evolcore-brand-board.svg +0 -126
- package/assets/brand/evolcore/evolcore-logo-kit.zip +0 -0
- package/assets/brand/evolcore/evolcore-logo-reverse.png +0 -0
- package/assets/brand/evolcore/evolcore-logo-reverse.svg +0 -14
- package/assets/brand/evolcore/evolcore-logo.png +0 -0
- package/assets/brand/evolcore/evolcore-logo.svg +0 -14
- package/assets/brand/evolcore/evolcore-mark.png +0 -0
- package/assets/brand/evolcore/evolcore-mark.svg +0 -10
|
@@ -3,6 +3,7 @@ import { getCodexEfforts } from '../../agents/codex-runner.js';
|
|
|
3
3
|
import { buildEnvelope } from '../message/message-utils.js';
|
|
4
4
|
import { resolvePaths, getPackageRoot } from '../../paths.js';
|
|
5
5
|
import { logger } from '../../utils/logger.js';
|
|
6
|
+
import { shouldSuppressRealRestart } from '../../utils/restart-safety.js';
|
|
6
7
|
import crypto from 'crypto';
|
|
7
8
|
import path from 'path';
|
|
8
9
|
import fs from 'fs';
|
|
@@ -186,7 +187,7 @@ function triggerOperationForSlash(content) {
|
|
|
186
187
|
return 'trigger.show';
|
|
187
188
|
if (subcommand === 'history')
|
|
188
189
|
return 'trigger.history';
|
|
189
|
-
if (subcommand === 'set')
|
|
190
|
+
if (subcommand === 'create' || subcommand === 'set')
|
|
190
191
|
return 'trigger.create';
|
|
191
192
|
if (subcommand === 'update')
|
|
192
193
|
return 'trigger.update';
|
|
@@ -351,7 +352,7 @@ async function getGitWorkingDirInfo(projectPath) {
|
|
|
351
352
|
return null; // git 命令失败时静默返回 null
|
|
352
353
|
}
|
|
353
354
|
}
|
|
354
|
-
export async function handleSlashCommand(content, channel, channelId, sendMessage, userId, threadId, chatType, source, messageId, selfAID, overrideIdentity, overrideSubject) {
|
|
355
|
+
export async function handleSlashCommand(content, channel, channelId, sendMessage, userId, threadId, chatType, source, messageId, selfAID, overrideIdentity, overrideSubject, replyContext) {
|
|
355
356
|
// 卡片回调的 chatType 不可靠(飞书 bot 单聊 chatId 也是 oc_ 前缀),
|
|
356
357
|
// 不应覆盖 session 中已有的正确值
|
|
357
358
|
if (source === 'card-trigger')
|
|
@@ -431,9 +432,23 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
431
432
|
...params,
|
|
432
433
|
subject: authSubject,
|
|
433
434
|
});
|
|
434
|
-
|
|
435
|
+
const canAccessSlashOperation = (operation, scope) => {
|
|
436
|
+
const args = scope === 'relation'
|
|
437
|
+
? buildSlashRelationIntentArgs({ selfAid: authSubject.selfAid, peerKey: authSubject.peerKey })
|
|
438
|
+
: {};
|
|
439
|
+
return authorizeOperation({
|
|
440
|
+
source: 'slash',
|
|
441
|
+
intent: { operation, scope, source: 'slash', args },
|
|
442
|
+
subject: authSubject,
|
|
443
|
+
audit: false,
|
|
444
|
+
}).allow;
|
|
445
|
+
};
|
|
446
|
+
// roleGuard 仅对进程级命令(/restart /upgrade /reload)放行 daemon owner 绕过,
|
|
435
447
|
// 其余命令严格按 agent-channel 的 isAdmin 判定,不越权。
|
|
436
|
-
const isProcessLevelSlash = normalizedContent === '/restart'
|
|
448
|
+
const isProcessLevelSlash = normalizedContent === '/restart'
|
|
449
|
+
|| normalizedContent === '/upgrade'
|
|
450
|
+
|| normalizedContent === '/reload'
|
|
451
|
+
|| normalizedContent.startsWith('/reload ');
|
|
437
452
|
const roleGuard = guardRoleCommand(normalizedContent, activeChatType, isAdmin || (isDaemonOwner && isProcessLevelSlash));
|
|
438
453
|
if (roleGuard)
|
|
439
454
|
return roleGuard;
|
|
@@ -458,18 +473,50 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
458
473
|
return undefined;
|
|
459
474
|
// /help 命令不需要会话
|
|
460
475
|
if (normalizedContent === '/help') {
|
|
476
|
+
const canReadModel = canAccessSlashOperation('model.current', 'relation')
|
|
477
|
+
|| canAccessSlashOperation('model.list', 'relation');
|
|
478
|
+
const canUseModel = canAccessSlashOperation('model.use', 'relation');
|
|
479
|
+
const canSetEffort = canAccessSlashOperation('model.effort', 'relation');
|
|
480
|
+
const canReadPermission = canAccessSlashOperation('permission.current', 'relation');
|
|
481
|
+
const canAnswerPermission = canAccessSlashOperation('permission.answer', 'relation');
|
|
482
|
+
const canReadChatmode = canAccessSlashOperation('chatmode.current', 'relation');
|
|
483
|
+
const canSetChatmode = canAccessSlashOperation('chatmode.update', 'relation');
|
|
484
|
+
const canReadMentionmode = activeChatType === 'group'
|
|
485
|
+
&& canAccessSlashOperation('mentionmode.current', 'relation');
|
|
486
|
+
const canSetMentionmode = activeChatType === 'group'
|
|
487
|
+
&& canAccessSlashOperation('mentionmode.update', 'relation');
|
|
488
|
+
const canUseFile = canAccessSlashOperation('file.fetch', 'filesystem');
|
|
461
489
|
const appendProcessCommands = (lines) => {
|
|
462
490
|
if (!isDaemonOwner)
|
|
463
491
|
return;
|
|
464
|
-
lines.push('', '🛠️ 进程级运维:', ' /restart - 重启服务', ' /reload [aid] - 热重载 Agent 配置');
|
|
492
|
+
lines.push('', '🛠️ 进程级运维:', ' /restart - 重启服务', ' /upgrade - 检查版本更新', ' /reload [aid] - 热重载 Agent 配置');
|
|
465
493
|
};
|
|
466
494
|
if (!isAdmin && activeChatType === 'group') {
|
|
467
495
|
const lines = [
|
|
468
496
|
'可用命令:',
|
|
497
|
+
...((canReadModel || canUseModel || canSetEffort) ? [
|
|
498
|
+
'',
|
|
499
|
+
'🤖 Agent 与模型:',
|
|
500
|
+
...(canReadModel || canUseModel ? [` /model${canUseModel ? ' [model]' : ''} - 查看${canUseModel ? '或切换' : ''}模型`] : []),
|
|
501
|
+
...(canSetEffort ? [' /effort [level] - 查看或切换推理强度'] : []),
|
|
502
|
+
] : []),
|
|
503
|
+
...((canReadChatmode || canSetChatmode || canReadMentionmode || canSetMentionmode) ? [
|
|
504
|
+
'',
|
|
505
|
+
'💬 聊天设置:',
|
|
506
|
+
...(canReadChatmode || canSetChatmode ? [` /chatmode${canSetChatmode ? ' [interactive|proactive]' : ''} - 查看${canSetChatmode ? '或切换' : ''}会话模式`] : []),
|
|
507
|
+
...(canReadMentionmode || canSetMentionmode ? [` /mentionmode${canSetMentionmode ? ' [mention-only|disabled]' : ''} - 查看${canSetMentionmode ? '或切换' : ''}群聊 @ 处理模式`] : []),
|
|
508
|
+
] : []),
|
|
509
|
+
...(canReadPermission || canAnswerPermission ? [
|
|
510
|
+
'',
|
|
511
|
+
'🔐 权限管理:',
|
|
512
|
+
...(canReadPermission ? [' /perm - 查看当前权限模式'] : []),
|
|
513
|
+
...(canAnswerPermission ? [' /perm allow|always|deny - 审批权限请求'] : []),
|
|
514
|
+
] : []),
|
|
469
515
|
'',
|
|
470
516
|
'其他:',
|
|
471
517
|
' /status - 显示会话状态',
|
|
472
518
|
' /check - 检查 EvolAgent 实例健康',
|
|
519
|
+
...(canUseFile ? [' /file <path> - 发送项目内文件'] : []),
|
|
473
520
|
' /help - 显示此帮助信息',
|
|
474
521
|
];
|
|
475
522
|
appendProcessCommands(lines);
|
|
@@ -486,6 +533,28 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
486
533
|
' /del <名称> - 删除指定会话(仅解绑,不删除文件)',
|
|
487
534
|
' /status - 显示会话状态',
|
|
488
535
|
' /check - 检查 EvolAgent 实例健康',
|
|
536
|
+
...((canReadModel || canUseModel || canSetEffort) ? [
|
|
537
|
+
'',
|
|
538
|
+
'🤖 Agent 与模型:',
|
|
539
|
+
...(canReadModel || canUseModel ? [` /model${canUseModel ? ' [model]' : ''} - 查看${canUseModel ? '或切换' : ''}模型`] : []),
|
|
540
|
+
...(canSetEffort ? [' /effort [level] - 查看或切换推理强度'] : []),
|
|
541
|
+
] : []),
|
|
542
|
+
...((canReadChatmode || canSetChatmode) ? [
|
|
543
|
+
'',
|
|
544
|
+
'💬 聊天设置:',
|
|
545
|
+
` /chatmode${canSetChatmode ? ' [interactive|proactive]' : ''} - 查看${canSetChatmode ? '或切换' : ''}会话模式`,
|
|
546
|
+
] : []),
|
|
547
|
+
...(canReadPermission || canAnswerPermission ? [
|
|
548
|
+
'',
|
|
549
|
+
'🔐 权限管理:',
|
|
550
|
+
...(canReadPermission ? [' /perm - 查看当前权限模式'] : []),
|
|
551
|
+
...(canAnswerPermission ? [' /perm allow|always|deny - 审批权限请求'] : []),
|
|
552
|
+
] : []),
|
|
553
|
+
...(canUseFile ? [
|
|
554
|
+
'',
|
|
555
|
+
'🧰 工具:',
|
|
556
|
+
' /file <path> - 发送项目内文件',
|
|
557
|
+
] : []),
|
|
489
558
|
'',
|
|
490
559
|
'❓ 帮助:',
|
|
491
560
|
' /help - 显示此帮助信息',
|
|
@@ -511,18 +580,18 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
511
580
|
'',
|
|
512
581
|
'🤖 Agent 与模型:',
|
|
513
582
|
' /baseagent [name] - 查看或切换 Agent 后端(别名: /base)',
|
|
514
|
-
|
|
515
|
-
' /effort [level] - 查看或切换推理强度',
|
|
583
|
+
...(canReadModel || canUseModel ? [` /model${canUseModel ? ' [model]' : ''} - 查看${canUseModel ? '或切换' : ''}模型`] : []),
|
|
584
|
+
...(canSetEffort ? [' /effort [level] - 查看或切换推理强度'] : []),
|
|
516
585
|
'',
|
|
517
586
|
'💬 聊天设置:',
|
|
518
587
|
' /activity [all|text|none] - 查看/控制中间输出显示模式',
|
|
519
|
-
|
|
520
|
-
|
|
588
|
+
...(canReadChatmode || canSetChatmode ? [` /chatmode${canSetChatmode ? ' [interactive|proactive]' : ''} - 查看${canSetChatmode ? '/切换' : ''}会话模式(被动响应或主动推进)`] : []),
|
|
589
|
+
...(canReadMentionmode || canSetMentionmode ? [` /mentionmode${canSetMentionmode ? ' [mention-only|disabled]' : ''} - 查看${canSetMentionmode ? '/切换' : ''}群聊 @ 处理模式`] : []),
|
|
521
590
|
'',
|
|
522
591
|
'🔐 权限管理:',
|
|
523
|
-
' /perm - 查看当前权限模式',
|
|
524
|
-
...(
|
|
525
|
-
' /perm allow|always|deny - 审批权限请求',
|
|
592
|
+
...(canReadPermission ? [' /perm - 查看当前权限模式'] : []),
|
|
593
|
+
...(canReadPermission ? [' 权限模式请通过角色策略编辑器修改'] : []),
|
|
594
|
+
...(canAnswerPermission ? [' /perm allow|always|deny - 审批权限请求'] : []),
|
|
526
595
|
'',
|
|
527
596
|
'🛠️ 运维:',
|
|
528
597
|
' /status - 显示会话状态',
|
|
@@ -538,7 +607,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
538
607
|
...(!isDaemonOwner && isAdmin ? [
|
|
539
608
|
' /reload - 热重载当前 Agent 配置',
|
|
540
609
|
] : []),
|
|
541
|
-
...(
|
|
610
|
+
...(canUseFile ? [
|
|
542
611
|
'',
|
|
543
612
|
'🧰 工具:',
|
|
544
613
|
` /file ${isOwner ? '[channel] ' : ''}<path> - 发送项目内文件`,
|
|
@@ -552,6 +621,19 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
552
621
|
// /evolhelp 命令:返回 JSON 格式的命令列表(供程序解析)
|
|
553
622
|
if (normalizedContent === '/evolhelp') {
|
|
554
623
|
const cmds = [];
|
|
624
|
+
const canReadModel = canAccessSlashOperation('model.current', 'relation')
|
|
625
|
+
|| canAccessSlashOperation('model.list', 'relation');
|
|
626
|
+
const canUseModel = canAccessSlashOperation('model.use', 'relation');
|
|
627
|
+
const canSetEffort = canAccessSlashOperation('model.effort', 'relation');
|
|
628
|
+
const canReadPermission = canAccessSlashOperation('permission.current', 'relation');
|
|
629
|
+
const canAnswerPermission = canAccessSlashOperation('permission.answer', 'relation');
|
|
630
|
+
const canReadChatmode = canAccessSlashOperation('chatmode.current', 'relation');
|
|
631
|
+
const canSetChatmode = canAccessSlashOperation('chatmode.update', 'relation');
|
|
632
|
+
const canReadMentionmode = activeChatType === 'group'
|
|
633
|
+
&& canAccessSlashOperation('mentionmode.current', 'relation');
|
|
634
|
+
const canSetMentionmode = activeChatType === 'group'
|
|
635
|
+
&& canAccessSlashOperation('mentionmode.update', 'relation');
|
|
636
|
+
const canUseFile = canAccessSlashOperation('file.fetch', 'filesystem');
|
|
555
637
|
// 项目
|
|
556
638
|
cmds.push({ command: '/pwd', description: '显示当前项目路径', category: '项目', roles: ['admin', 'owner'] });
|
|
557
639
|
// 会话管理
|
|
@@ -565,16 +647,17 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
565
647
|
cmds.push({ command: '/compact', description: '压缩会话上下文(减少 token 用量)', category: '会话管理', roles: ['admin', 'owner'] });
|
|
566
648
|
}
|
|
567
649
|
// Agent 与模型
|
|
568
|
-
if (isAdmin)
|
|
650
|
+
if (isAdmin)
|
|
569
651
|
cmds.push({ command: '/baseagent', aliases: ['/base'], args: '[name]', description: '查看或切换 Agent 后端', category: 'Agent 与模型', roles: ['admin', 'owner'] });
|
|
570
|
-
|
|
571
|
-
cmds.push({ command: '/
|
|
572
|
-
|
|
652
|
+
if (canReadModel || canUseModel)
|
|
653
|
+
cmds.push({ command: '/model', ...(canUseModel ? { args: '[model]' } : {}), description: `查看${canUseModel ? '或切换' : ''}模型`, category: 'Agent 与模型', roles: [identity.role] });
|
|
654
|
+
if (canSetEffort)
|
|
655
|
+
cmds.push({ command: '/effort', args: '[level]', description: '查看或切换推理强度', category: 'Agent 与模型', roles: [identity.role] });
|
|
573
656
|
// 权限管理
|
|
574
|
-
if (
|
|
575
|
-
cmds.push({ command: '/perm', description: '查看当前角色决定的权限模式', category: '权限管理', roles: [
|
|
576
|
-
|
|
577
|
-
|
|
657
|
+
if (canReadPermission)
|
|
658
|
+
cmds.push({ command: '/perm', description: '查看当前角色决定的权限模式', category: '权限管理', roles: [identity.role] });
|
|
659
|
+
if (canAnswerPermission)
|
|
660
|
+
cmds.push({ command: '/perm', args: 'allow|always|deny', description: '审批权限请求', category: '权限管理', roles: [identity.role] });
|
|
578
661
|
// 运维
|
|
579
662
|
cmds.push({ command: '/status', description: '显示会话状态', category: '运维', roles: ['visitor', 'member', 'admin', 'owner'] });
|
|
580
663
|
cmds.push({ command: '/stop', description: '中断当前任务', category: '运维', roles: ['admin', 'owner'] });
|
|
@@ -587,19 +670,19 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
587
670
|
}
|
|
588
671
|
if (isDaemonOwner) {
|
|
589
672
|
cmds.push({ command: '/restart', description: '重启服务', category: '运维', roles: ['daemon-owner'] });
|
|
673
|
+
cmds.push({ command: '/upgrade', description: '检查版本更新', category: '运维', roles: ['daemon-owner'] });
|
|
590
674
|
cmds.push({ command: '/reload', args: '[aid]', description: '热重载 Agent 配置', category: '运维', roles: ['daemon-owner'] });
|
|
591
675
|
}
|
|
592
676
|
if (!isDaemonOwner && isAdmin) {
|
|
593
677
|
cmds.push({ command: '/reload', description: '热重载当前 Agent 配置', category: '运维', roles: ['admin', 'owner'] });
|
|
594
678
|
}
|
|
595
|
-
if (
|
|
596
|
-
cmds.push({ command: '/file', args: isOwner ? '[channel] <path>' : '<path>', description: '发送项目内文件', category: '工具', roles: [
|
|
597
|
-
}
|
|
679
|
+
if (canUseFile)
|
|
680
|
+
cmds.push({ command: '/file', args: isOwner ? '[channel] <path>' : '<path>', description: '发送项目内文件', category: '工具', roles: [identity.role] });
|
|
598
681
|
// 聊天设置
|
|
599
|
-
if (
|
|
600
|
-
cmds.push({ command: '/chatmode', args: '[interactive|proactive]', description: '
|
|
601
|
-
|
|
602
|
-
|
|
682
|
+
if (canReadChatmode || canSetChatmode)
|
|
683
|
+
cmds.push({ command: '/chatmode', ...(canSetChatmode ? { args: '[interactive|proactive]' } : {}), description: `查看${canSetChatmode ? '/切换' : ''}会话模式(被动响应或主动推进)`, category: '聊天设置', roles: [identity.role] });
|
|
684
|
+
if (canReadMentionmode || canSetMentionmode)
|
|
685
|
+
cmds.push({ command: '/mentionmode', ...(canSetMentionmode ? { args: '[mention-only|disabled]' } : {}), description: `查看${canSetMentionmode ? '/切换' : ''}群聊 @ 处理模式`, category: '聊天设置', roles: [identity.role] });
|
|
603
686
|
// 交互
|
|
604
687
|
cmds.push({ command: '/ask', args: '<选项>', description: '回答 Agent 的交互式问题', category: '运维', roles: ['visitor', 'member', 'admin', 'owner'] });
|
|
605
688
|
// 帮助
|
|
@@ -1628,11 +1711,12 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1628
1711
|
}
|
|
1629
1712
|
if (normalizedContent === '/activity' || normalizedContent.startsWith('/activity ')) {
|
|
1630
1713
|
const activityArg = normalizedContent.slice(9).trim();
|
|
1714
|
+
const activitySession = await getExistingSessionForCommand();
|
|
1631
1715
|
// 带参(写操作)需 admin+;无参查询对所有人开放(owner 门在具体切换点还有一道)
|
|
1632
1716
|
if (activityArg && !isAdmin)
|
|
1633
1717
|
return { kind: 'command.error', text: '❌ 无权限:此命令仅限管理员使用' };
|
|
1634
1718
|
// proactive 模式下流式输出全部静默,activity 配置无意义
|
|
1635
|
-
if (getEffectiveChatmode(
|
|
1719
|
+
if (getEffectiveChatmode(activitySession) === 'proactive') {
|
|
1636
1720
|
return { kind: 'command.error', text: '❌ 当前会话为 proactive 模式,不支持 activity 配置(流式输出已全部静默)' };
|
|
1637
1721
|
}
|
|
1638
1722
|
const modeMap = {
|
|
@@ -1655,7 +1739,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1655
1739
|
type: 'interaction',
|
|
1656
1740
|
id: `activity-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`,
|
|
1657
1741
|
channelId,
|
|
1658
|
-
sessionId:
|
|
1742
|
+
sessionId: activitySession?.id || '',
|
|
1659
1743
|
initiatorId: userId,
|
|
1660
1744
|
kind: {
|
|
1661
1745
|
kind: 'command-card',
|
|
@@ -1669,7 +1753,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1669
1753
|
})),
|
|
1670
1754
|
},
|
|
1671
1755
|
};
|
|
1672
|
-
const replyCtx =
|
|
1756
|
+
const replyCtx = replyContext ?? (activitySession ? this.getReplyContext(activitySession) : undefined);
|
|
1673
1757
|
const cardResult = await this.sendCommandCard({ channel, channelId, interaction, replyCtx, canWrite: isOwner });
|
|
1674
1758
|
if (cardResult === null)
|
|
1675
1759
|
return null;
|
|
@@ -2081,7 +2165,21 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2081
2165
|
await sendMessage(channelId, `⏳ 正在创建新会话${sessionName ? `: ${sessionName}` : ''}...`, this.getReplyContext(session));
|
|
2082
2166
|
}
|
|
2083
2167
|
const newSessionBaseagent = this.agentRegistry?.resolveByChannel(channel)?.baseagent || this.parseDefaultBaseagent();
|
|
2084
|
-
const
|
|
2168
|
+
const previousMetadata = session?.metadata || activeSession?.metadata || {};
|
|
2169
|
+
const newSessionIdentityMetadata = activeChatType === 'group'
|
|
2170
|
+
? {
|
|
2171
|
+
...(previousMetadata.channelKey ? { channelKey: previousMetadata.channelKey } : {}),
|
|
2172
|
+
groupId: previousMetadata.groupId || channelId,
|
|
2173
|
+
...(previousMetadata.groupName ? { groupName: previousMetadata.groupName } : {}),
|
|
2174
|
+
...(previousMetadata.dispatchMode ? { dispatchMode: previousMetadata.dispatchMode } : {}),
|
|
2175
|
+
}
|
|
2176
|
+
: {
|
|
2177
|
+
...(previousMetadata.channelKey ? { channelKey: previousMetadata.channelKey } : {}),
|
|
2178
|
+
...((userId || previousMetadata.peerId) ? { peerId: userId || previousMetadata.peerId } : {}),
|
|
2179
|
+
...(previousMetadata.peerName ? { peerName: previousMetadata.peerName } : {}),
|
|
2180
|
+
...(previousMetadata.peerType ? { peerType: previousMetadata.peerType } : {}),
|
|
2181
|
+
};
|
|
2182
|
+
const newSession = await this.sessionManager.createNewSession(channel, channelId, projectPath, sessionName, newSessionBaseagent, newSessionIdentityMetadata);
|
|
2085
2183
|
const previousAgent = getActiveAgentIfAvailable();
|
|
2086
2184
|
if (session && previousAgent) {
|
|
2087
2185
|
// Reset agent backend state so the new
|
|
@@ -2370,6 +2468,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2370
2468
|
});
|
|
2371
2469
|
// 执行重启逻辑(共用于卡片回调和文本确认)
|
|
2372
2470
|
const executeRestart = async () => {
|
|
2471
|
+
const suppressRealRestart = shouldSuppressRealRestart();
|
|
2373
2472
|
let replyContext;
|
|
2374
2473
|
if (threadId) {
|
|
2375
2474
|
const threadSession = await this.sessionManager.getThreadSession(channel, channelId, threadId);
|
|
@@ -2382,15 +2481,20 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2382
2481
|
timestamp: Date.now(),
|
|
2383
2482
|
...(replyContext?.replyToMessageId ? { rootId: replyContext.replyToMessageId } : {}),
|
|
2384
2483
|
};
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2484
|
+
if (!suppressRealRestart) {
|
|
2485
|
+
const dataDir = resolvePaths().dataDir;
|
|
2486
|
+
fs.mkdirSync(dataDir, { recursive: true });
|
|
2487
|
+
fs.writeFileSync(path.join(dataDir, 'restart-pending.json'), JSON.stringify(restartInfo));
|
|
2488
|
+
const { spawn } = await import('child_process');
|
|
2489
|
+
spawn('node', [path.join(getPackageRoot(), 'dist', 'cli', 'index.js'), 'restart-monitor'], {
|
|
2490
|
+
detached: true,
|
|
2491
|
+
stdio: 'ignore',
|
|
2492
|
+
env: { ...process.env, EVOLCORE_HOME: resolvePaths().root }
|
|
2493
|
+
}).unref();
|
|
2494
|
+
}
|
|
2495
|
+
else {
|
|
2496
|
+
logger.info('[System] Suppressed real restart in test runtime');
|
|
2497
|
+
}
|
|
2394
2498
|
this.eventBus.publish({ type: 'system:restart', channel, channelId });
|
|
2395
2499
|
// 先发送重启反馈消息,等待发送完成后再 kill 进程
|
|
2396
2500
|
// 避免消息还没发出去进程就退出了
|
|
@@ -2416,10 +2520,12 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2416
2520
|
// 发 SIGTERM 而非直接 process.exit(0),让 index.ts 的 shutdown() 先
|
|
2417
2521
|
// 正常关闭所有 channel(包括 Feishu WebSocket close frame),
|
|
2418
2522
|
// 避免 Feishu 服务端因连接异常断开而重推未 ack 的消息给新进程。
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2523
|
+
if (!suppressRealRestart) {
|
|
2524
|
+
setTimeout(() => {
|
|
2525
|
+
logger.info('[System] Restarting by user command...');
|
|
2526
|
+
process.kill(process.pid, 'SIGTERM');
|
|
2527
|
+
}, 1000);
|
|
2528
|
+
}
|
|
2423
2529
|
return true;
|
|
2424
2530
|
};
|
|
2425
2531
|
// 文本确认流程
|
|
@@ -2450,8 +2556,24 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2450
2556
|
}
|
|
2451
2557
|
// /upgrade 命令:检查版本更新,提示用户手动重启
|
|
2452
2558
|
if (normalizedContent === '/upgrade') {
|
|
2453
|
-
|
|
2454
|
-
|
|
2559
|
+
const upgradeAuthDenied = await authorizeIntent({
|
|
2560
|
+
intent: {
|
|
2561
|
+
operation: 'system.upgrade',
|
|
2562
|
+
scope: 'process',
|
|
2563
|
+
source: 'slash',
|
|
2564
|
+
args: {},
|
|
2565
|
+
dangerous: true,
|
|
2566
|
+
},
|
|
2567
|
+
identity: isDaemonOwner ? { ...identity, role: 'owner' } : identity,
|
|
2568
|
+
session: activeSession,
|
|
2569
|
+
channel,
|
|
2570
|
+
channelId,
|
|
2571
|
+
userId,
|
|
2572
|
+
selfAid: this.agentRegistry?.resolveByChannel(channel)?.aid,
|
|
2573
|
+
isDaemonOwner,
|
|
2574
|
+
});
|
|
2575
|
+
if (upgradeAuthDenied)
|
|
2576
|
+
return upgradeAuthDenied;
|
|
2455
2577
|
if (isLinkedInstall()) {
|
|
2456
2578
|
return { kind: 'command.result', text: '⏭ 开发模式,跳过升级检查' };
|
|
2457
2579
|
}
|
|
@@ -2483,11 +2605,26 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2483
2605
|
}
|
|
2484
2606
|
// /file 命令:发送项目内文件,支持 /file path 和 /file channel path
|
|
2485
2607
|
if (normalizedContent.startsWith('/file')) {
|
|
2486
|
-
if (!isAdmin)
|
|
2487
|
-
return { kind: 'command.error', text: '❌ 无权限:此命令仅限管理员使用' };
|
|
2488
2608
|
// 飞书会将 .md 等后缀自动转为 Markdown 链接: foo.md → [foo.md](http://foo.md/)
|
|
2489
2609
|
// 还原: 将 [text](url) 替换为 text
|
|
2490
2610
|
const rawArg = normalizedContent.slice(5).trim().replace(/\[([^\]]+)\]\([^)]+\)/g, '$1');
|
|
2611
|
+
const fileAuthDenied = await authorizeIntent({
|
|
2612
|
+
intent: {
|
|
2613
|
+
operation: 'file.fetch',
|
|
2614
|
+
scope: 'filesystem',
|
|
2615
|
+
source: 'slash',
|
|
2616
|
+
args: rawArg ? { filePath: rawArg } : {},
|
|
2617
|
+
},
|
|
2618
|
+
identity,
|
|
2619
|
+
session: activeSession,
|
|
2620
|
+
channel,
|
|
2621
|
+
channelId,
|
|
2622
|
+
userId,
|
|
2623
|
+
selfAid: this.agentRegistry?.resolveByChannel(channel)?.aid,
|
|
2624
|
+
isDaemonOwner,
|
|
2625
|
+
});
|
|
2626
|
+
if (fileAuthDenied)
|
|
2627
|
+
return fileAuthDenied;
|
|
2491
2628
|
if (!rawArg) {
|
|
2492
2629
|
const usage = isOwner
|
|
2493
2630
|
? '用法: /file <相对路径> 或 /file <渠道> <相对路径>\n示例: /file src/index.ts\n示例: /file feishu report.md'
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* 策略(reload/重启永远全量失效,无视策略;策略只决定"平时每次读怎么检查"):
|
|
13
13
|
* - on-reload:平时不检查,直接用缓存(kits 文件、persona)。靠 reload/重启刷新。
|
|
14
14
|
* - manual:同 on-reload,额外支持显式 invalidate(file) 单刷。
|
|
15
|
-
* - mtime:每次读 statSync 门控 mtime,变了自动重读(working.md、config.json)。
|
|
15
|
+
* - mtime:每次读 statSync 门控 size + mtime,变了自动重读(working.md、config.json)。
|
|
16
16
|
*
|
|
17
17
|
* 容量:项数可无界增长的组(如 relation-prefs,每 peer 一文件)设 LRU 硬上限
|
|
18
18
|
* (见 GROUP_CAPS),命中/写入移到末尾、超限驱逐同组最旧项;无 timer。
|
|
@@ -71,9 +71,9 @@ export class FileCache {
|
|
|
71
71
|
const read = opts.read ?? readFileOrNull;
|
|
72
72
|
this.bump(opts.group, opts.policy, 'gets');
|
|
73
73
|
if (opts.policy === 'mtime') {
|
|
74
|
-
const
|
|
74
|
+
const fingerprint = statFingerprint(file);
|
|
75
75
|
this.bump(opts.group, opts.policy, 'statChecks');
|
|
76
|
-
if (existing && existing.
|
|
76
|
+
if (existing && sameFingerprint(existing.fingerprint, fingerprint)) {
|
|
77
77
|
this.bump(opts.group, opts.policy, 'hits');
|
|
78
78
|
this.touch(file, existing);
|
|
79
79
|
return existing.value;
|
|
@@ -84,7 +84,7 @@ export class FileCache {
|
|
|
84
84
|
this.bump(opts.group, opts.policy, 'misses');
|
|
85
85
|
const raw = read(file);
|
|
86
86
|
const value = loader(raw);
|
|
87
|
-
this.store(file, { policy: 'mtime', group: opts.group,
|
|
87
|
+
this.store(file, { policy: 'mtime', group: opts.group, fingerprint, value, bytes: approxBytes(raw) });
|
|
88
88
|
return value;
|
|
89
89
|
}
|
|
90
90
|
// on-reload / manual:命中即用,不检查文件
|
|
@@ -192,14 +192,20 @@ export class FileCache {
|
|
|
192
192
|
};
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
|
-
function
|
|
195
|
+
function statFingerprint(file) {
|
|
196
196
|
try {
|
|
197
|
-
|
|
197
|
+
const stat = fs.statSync(file);
|
|
198
|
+
return { size: stat.size, mtimeMs: stat.mtimeMs };
|
|
198
199
|
}
|
|
199
200
|
catch {
|
|
200
201
|
return null; // 文件不存在
|
|
201
202
|
}
|
|
202
203
|
}
|
|
204
|
+
function sameFingerprint(left, right) {
|
|
205
|
+
if (left === null || right === null)
|
|
206
|
+
return left === right;
|
|
207
|
+
return !!left && left.size === right.size && left.mtimeMs === right.mtimeMs;
|
|
208
|
+
}
|
|
203
209
|
function readFileOrNull(file) {
|
|
204
210
|
try {
|
|
205
211
|
return fs.readFileSync(file, 'utf-8');
|
|
@@ -208,6 +214,34 @@ function readFileOrNull(file) {
|
|
|
208
214
|
return null;
|
|
209
215
|
}
|
|
210
216
|
}
|
|
217
|
+
/**
|
|
218
|
+
* 带错误捕获的 reader。默认 reader 把所有读盘异常吞成 null,调用方无从区分
|
|
219
|
+
* ENOENT(文件确实没有)与 EACCES/EISDIR(部署或权限事故)——对随包发布的
|
|
220
|
+
* 文件(schema、角色模板)来说这层信息正是定位问题的关键。
|
|
221
|
+
*
|
|
222
|
+
* 用法:建一个实例,把 `read` 交给 fileCache,loader 里拿到 null 时用
|
|
223
|
+
* `lastError()` 拼文案、把 `lastErrorCause()` 挂到新 Error 的 `cause` 上——
|
|
224
|
+
* 后者保住原始异常对象,`code`/`path`/`errno` 这些结构化字段不至于只剩字符串。
|
|
225
|
+
* 注意 loader 只在未命中时执行,与 read 同步成对调用,因此闭包里的 last
|
|
226
|
+
* 不会串到别的文件上。
|
|
227
|
+
*/
|
|
228
|
+
export function createErrorCapturingReader() {
|
|
229
|
+
let last = null;
|
|
230
|
+
return {
|
|
231
|
+
read: (file) => {
|
|
232
|
+
try {
|
|
233
|
+
last = null;
|
|
234
|
+
return fs.readFileSync(file, 'utf-8');
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
last = error;
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
lastError: () => (last instanceof Error ? last.message : last === null ? 'unreadable' : String(last)),
|
|
242
|
+
lastErrorCause: () => last,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
211
245
|
/** 缓存值内存占用近似:用读入的原始字符串长度(字节级近似),null 记 0。 */
|
|
212
246
|
function approxBytes(raw) {
|
|
213
247
|
return raw === null ? 0 : raw.length;
|
|
@@ -89,9 +89,37 @@ const CATALOG = [
|
|
|
89
89
|
{ path: 'name', type: 'string', optional: true },
|
|
90
90
|
{ path: 'chatType', type: 'string', optional: true },
|
|
91
91
|
{ path: 'threadId', type: 'string', optional: true },
|
|
92
|
+
{ path: 'cause', type: 'string', optional: true },
|
|
93
|
+
{ path: 'sourceSessionId', type: 'string', optional: true },
|
|
94
|
+
{ path: 'renewSource', type: 'string', optional: true },
|
|
92
95
|
{ path: 'timestamp', type: 'number', optional: true },
|
|
93
96
|
],
|
|
94
97
|
},
|
|
98
|
+
{
|
|
99
|
+
type: 'session:renew-evaluated',
|
|
100
|
+
namespace: 'session',
|
|
101
|
+
name: 'renew-evaluated',
|
|
102
|
+
description: 'Session Renew 判定完成',
|
|
103
|
+
fields: [
|
|
104
|
+
{ path: 'candidateSessionId', type: 'string' },
|
|
105
|
+
{ path: 'selectedSessionId', type: 'string' },
|
|
106
|
+
{ path: 'renewed', type: 'boolean' },
|
|
107
|
+
{ path: 'decision', type: 'string' },
|
|
108
|
+
{ path: 'source', type: 'string' },
|
|
109
|
+
{ path: 'channel', type: 'string' },
|
|
110
|
+
{ path: 'channelName', type: 'string', optional: true },
|
|
111
|
+
{ path: 'channelId', type: 'string' },
|
|
112
|
+
{ path: 'selfAid', type: 'string', optional: true },
|
|
113
|
+
{ path: 'idleHours', type: 'number' },
|
|
114
|
+
{ path: 'responseMode', type: 'string', optional: true },
|
|
115
|
+
{ path: 'baseagent', type: 'string', optional: true },
|
|
116
|
+
{ path: 'model', type: 'string', optional: true },
|
|
117
|
+
{ path: 'effort', type: 'string', optional: true },
|
|
118
|
+
{ path: 'fallbackReason', type: 'string', optional: true },
|
|
119
|
+
{ path: 'durationMs', type: 'number' },
|
|
120
|
+
{ path: 'timestamp', type: 'number' },
|
|
121
|
+
],
|
|
122
|
+
},
|
|
95
123
|
{
|
|
96
124
|
type: 'session:switched',
|
|
97
125
|
namespace: 'session',
|
|
@@ -355,6 +383,77 @@ const CATALOG = [
|
|
|
355
383
|
{ path: 'preTokens', type: 'number' },
|
|
356
384
|
],
|
|
357
385
|
},
|
|
386
|
+
{
|
|
387
|
+
type: 'runner:task-started',
|
|
388
|
+
namespace: 'runner',
|
|
389
|
+
name: 'task-started',
|
|
390
|
+
description: 'Runner 子任务已创建',
|
|
391
|
+
fields: [
|
|
392
|
+
{ path: 'sessionId', type: 'string' },
|
|
393
|
+
{ path: 'taskId', type: 'string' },
|
|
394
|
+
{ path: 'taskKind', type: 'string' },
|
|
395
|
+
{ path: 'toolUseId', type: 'string', optional: true },
|
|
396
|
+
{ path: 'description', type: 'string' },
|
|
397
|
+
{ path: 'subagentType', type: 'string', optional: true },
|
|
398
|
+
{ path: 'taskType', type: 'string', optional: true },
|
|
399
|
+
{ path: 'workflowName', type: 'string', optional: true },
|
|
400
|
+
{ path: 'prompt', type: 'string', optional: true },
|
|
401
|
+
{ path: 'skipTranscript', type: 'boolean', optional: true },
|
|
402
|
+
{ path: 'timestamp', type: 'number', optional: true },
|
|
403
|
+
],
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
type: 'runner:task-progress',
|
|
407
|
+
namespace: 'runner',
|
|
408
|
+
name: 'task-progress',
|
|
409
|
+
description: 'Runner 子任务进度',
|
|
410
|
+
fields: [
|
|
411
|
+
{ path: 'sessionId', type: 'string' },
|
|
412
|
+
{ path: 'taskId', type: 'string', optional: true },
|
|
413
|
+
{ path: 'taskKind', type: 'string', optional: true },
|
|
414
|
+
{ path: 'toolUseId', type: 'string', optional: true },
|
|
415
|
+
{ path: 'description', type: 'string', optional: true },
|
|
416
|
+
{ path: 'subagentType', type: 'string', optional: true },
|
|
417
|
+
{ path: 'summary', type: 'string', optional: true },
|
|
418
|
+
{ path: 'lastToolName', type: 'string', optional: true },
|
|
419
|
+
{ path: 'totalTokens', type: 'number', optional: true },
|
|
420
|
+
{ path: 'toolUses', type: 'number', optional: true },
|
|
421
|
+
{ path: 'durationMs', type: 'number', optional: true },
|
|
422
|
+
{ path: 'timestamp', type: 'number', optional: true },
|
|
423
|
+
],
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
type: 'runner:task-notification',
|
|
427
|
+
namespace: 'runner',
|
|
428
|
+
name: 'task-notification',
|
|
429
|
+
description: 'Runner 子任务终态和输出',
|
|
430
|
+
fields: [
|
|
431
|
+
{ path: 'sessionId', type: 'string' },
|
|
432
|
+
{ path: 'taskId', type: 'string' },
|
|
433
|
+
{ path: 'taskKind', type: 'string' },
|
|
434
|
+
{ path: 'toolUseId', type: 'string', optional: true },
|
|
435
|
+
{ path: 'description', type: 'string', optional: true },
|
|
436
|
+
{ path: 'subagentType', type: 'string', optional: true },
|
|
437
|
+
{ path: 'status', type: 'string' },
|
|
438
|
+
{ path: 'terminalReason', type: 'string', optional: true },
|
|
439
|
+
{ path: 'outputFile', type: 'string', optional: true },
|
|
440
|
+
{ path: 'summary', type: 'string', optional: true },
|
|
441
|
+
{ path: 'usage', type: 'object', optional: true },
|
|
442
|
+
{ path: 'skipTranscript', type: 'boolean', optional: true },
|
|
443
|
+
{ path: 'timestamp', type: 'number', optional: true },
|
|
444
|
+
],
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
type: 'runner:background-tasks-changed',
|
|
448
|
+
namespace: 'runner',
|
|
449
|
+
name: 'background-tasks-changed',
|
|
450
|
+
description: 'Runner 后台任务集合变化',
|
|
451
|
+
fields: [
|
|
452
|
+
{ path: 'sessionId', type: 'string' },
|
|
453
|
+
{ path: 'tasks', type: 'array' },
|
|
454
|
+
{ path: 'timestamp', type: 'number', optional: true },
|
|
455
|
+
],
|
|
456
|
+
},
|
|
358
457
|
{
|
|
359
458
|
type: 'runner:model-changed',
|
|
360
459
|
namespace: 'runner',
|