evolcore 0.0.21 → 0.0.23
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/AGENTS.md +62 -0
- package/CHANGELOG.md +53 -0
- package/README.md +2 -0
- package/bin/codex-managed-acl.ps1 +155 -0
- package/bin/codex-managed-hook.mjs +3 -0
- package/bin/install-codex-managed-hooks.mjs +376 -96
- package/dist/agents/baseagent-availability.js +48 -0
- package/dist/agents/baseagent.js +1 -1
- package/dist/agents/claude-runner.js +44 -226
- package/dist/agents/{codex-app-server-client.js → codex/app-server-client.js} +103 -17
- package/dist/{utils/codex-app-server-registry.js → agents/codex/app-server-registry.js} +2 -2
- package/dist/agents/codex/catalog.js +70 -0
- package/dist/agents/codex/diagnostics.js +154 -0
- package/dist/agents/codex-runner.js +1292 -219
- package/dist/agents/ecagent-runner.js +10 -31
- package/dist/agents/gemini-runner.js +2 -6
- package/dist/aun/aid/store.js +2 -0
- package/dist/aun/menu-client.js +272 -0
- package/dist/aun/msg/group.js +65 -4
- package/dist/aun/msg/index.js +1 -1
- package/dist/aun/msg/managed-operation.js +51 -4
- package/dist/aun/outbox.js +7 -0
- package/dist/aun/rpc/client.js +8 -1
- package/dist/channels/aun.js +240 -36
- package/dist/channels/wechat.js +81 -10
- package/dist/cli/aun-commands.js +48 -4
- package/dist/cli/command-log.js +21 -2
- package/dist/cli/daemon-commands.js +169 -51
- package/dist/cli/index.js +20 -0
- package/dist/cli/init.js +2 -10
- package/dist/cli/menu-client.js +95 -0
- package/dist/cli/model.js +23 -8
- package/dist/cli/task-context.js +16 -2
- package/dist/cli/trigger-command.js +22 -5
- package/dist/config/config-field-policy.js +3 -0
- package/dist/config/config-manager.js +32 -5
- package/dist/config/contact-book-store.js +25 -3
- package/dist/config/schema-migration.js +14 -2
- package/dist/core/auth/agent-delegation.js +15 -0
- package/dist/core/auth/auth-gateway.js +8 -0
- package/dist/core/auth/authorization-audit.js +70 -6
- package/dist/core/auth/operation-catalog.js +4 -0
- package/dist/core/auth/remote-access-store.js +135 -0
- package/dist/core/bootstrap-messages.js +8 -0
- package/dist/core/bootstrap-service.js +93 -25
- package/dist/core/command/command-handler.js +62 -5
- package/dist/core/command/daemon-diagnostics.js +448 -0
- package/dist/core/command/menu-catalog.js +3 -0
- package/dist/core/command/menu-handler.js +150 -33
- package/dist/core/command/menu-protocol.js +120 -1
- package/dist/core/command/slash-gate.js +3 -3
- package/dist/core/command/slash-handler.js +83 -40
- package/dist/core/data-migration.js +11 -1
- package/dist/core/event-catalog.js +32 -0
- package/dist/core/handoff/runtime.js +23 -3
- package/dist/core/message/im-renderer.js +7 -3
- package/dist/core/message/message-bridge.js +60 -2
- package/dist/core/message/message-log.js +33 -0
- package/dist/core/message/message-queue.js +41 -15
- package/dist/core/message/response-engine.js +246 -114
- package/dist/core/model/catalog-service.js +308 -0
- package/dist/core/model/model-catalog.js +124 -334
- package/dist/core/model/model-diagnostics.js +4 -5
- package/dist/core/model/model-fallback.js +9 -16
- package/dist/core/model/model-permission.js +1 -1
- package/dist/core/permission/approval-gateway.js +16 -1
- package/dist/core/permission/ec-command-parser.js +272 -70
- package/dist/core/permission/protected-paths.js +74 -14
- package/dist/core/permission/sandbox-runtime.js +4 -2
- package/dist/core/permission/tool-error-code.js +12 -0
- package/dist/core/permission/tool-policy.js +290 -30
- package/dist/core/runtime-lock.js +13 -8
- package/dist/core/session/session-manager.js +30 -0
- package/dist/core/session/session-renew.js +18 -1
- package/dist/core/session/session-turn-coordinator.js +5 -1
- package/dist/index.js +104 -34
- package/dist/ipc.js +218 -96
- package/dist/paths.js +18 -0
- package/dist/response-system/engines/v1/proactive-flow.js +7 -2
- package/dist/stats/price-resolver.js +4 -0
- package/dist/trigger/feedback.js +14 -2
- package/dist/trigger/manager.js +3 -1
- package/dist/trigger/parser.js +86 -13
- package/dist/trigger/patch.js +104 -1
- package/dist/trigger/scheduler.js +20 -3
- package/dist/utils/ecweb-supervisor.js +11 -2
- package/dist/utils/ecweb-utils.js +8 -26
- package/dist/utils/error-utils.js +7 -0
- package/dist/utils/logger.js +9 -4
- package/dist/utils/npm-ops.js +47 -15
- package/dist/utils/tool-summary.js +59 -0
- package/dist/utils/windows-shell-trust.js +201 -0
- package/kits/docs/evolcore/INDEX.md +3 -2
- package/kits/docs/evolcore/agent-create.md +159 -0
- package/kits/docs/evolcore/agent.md +6 -0
- package/kits/docs/evolcore/group-collaboration.md +256 -0
- package/kits/docs/evolcore/group-rules.md +1 -19
- package/kits/docs/evolcore/group.md +3 -1
- package/kits/docs/evolcore/menu-client.md +34 -0
- package/kits/docs/evolcore/trigger.md +6 -3
- package/kits/docs/prompt-loading-architecture.md +6 -0
- package/kits/eck_message_manifest.json +6 -6
- package/kits/migrations/migrate-contact-book-v2.mjs +9 -1
- package/kits/migrations/migrate-role-config-v4.mjs +11 -5
- package/kits/migrations/migrate-role-config-v5.mjs +8 -2
- package/kits/schemas/_meta.json +3 -2
- package/kits/schemas/agent-config.schema.12.json +427 -0
- package/kits/templates/message-fragments/item.md +1 -1
- package/kits/templates/roles/visitor.json +1 -0
- package/kits/templates/system-fragments/bootstrap.md +10 -2
- package/kits/templates/system-fragments/commands.md +2 -2
- package/package.json +11 -3
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { hasModelSwitcher, hasPermissionController } from '../../agents/runner-types.js';
|
|
2
|
-
import { getCodexEfforts } from '../../agents/codex-runner.js';
|
|
3
2
|
import { normalizeBaseagent } from '../../agents/baseagent.js';
|
|
4
3
|
import { buildEnvelope, isDeliveryTargetForChannel } from '../message/message-utils.js';
|
|
5
4
|
import { resolvePaths, getPackageRoot, daemonControlDir } from '../../paths.js';
|
|
@@ -10,13 +9,14 @@ import path from 'path';
|
|
|
10
9
|
import fs from 'fs';
|
|
11
10
|
import { checkLatestVersion, getLocalVersion, isLinkedInstall, compareVersions } from '../../utils/npm-ops.js';
|
|
12
11
|
import { loadDaemonConfig } from '../../config-store.js';
|
|
12
|
+
import { remoteAccessService } from '../auth/remote-access-store.js';
|
|
13
13
|
import { read as cfgRead, resolveEffective, routeFieldPath, write as cfgWrite, } from '../../config/config-manager.js';
|
|
14
14
|
import { execAgentAction } from './agent-control.js';
|
|
15
15
|
import { authorizeOperation, buildAuthSubject } from '../auth/auth-gateway.js';
|
|
16
16
|
import { authorizationNextStep, formatAuthorizationDenial } from '../auth/authorization-denial.js';
|
|
17
17
|
import { resolvePermissionMode, writeScope } from '../model/config-scope.js';
|
|
18
18
|
import { formatPeerKey } from '../relation/peer-identity.js';
|
|
19
|
-
import { modelMatches } from '../model/model-catalog.js';
|
|
19
|
+
import { modelMatches, getCatalog, assertCatalogSelectable, resolveCatalogModel } from '../model/model-catalog.js';
|
|
20
20
|
import { formatModelCheck, runModelCheck } from '../model/model-diagnostics.js';
|
|
21
21
|
import { constrainResolvedModelForRole, filterModelsForRole, validateModelSelectionForRole } from '../model/model-permission.js';
|
|
22
22
|
import { resolveRuntimeStringField } from '../role/runtime-policy.js';
|
|
@@ -26,8 +26,9 @@ import { normalizePermissionMode as normalizePermissionModeContract, PUBLIC_PERM
|
|
|
26
26
|
import { isManagementRole } from '../../config/builtin-roles.js';
|
|
27
27
|
import { isSystemControlChannel } from '../system-channels.js';
|
|
28
28
|
import { spawnDetachedNode } from '../../utils/cross-platform.js';
|
|
29
|
+
import { inspectDataMigrationRequirement } from '../data-migration.js';
|
|
29
30
|
import { guardIdleCommand, guardKnownCommand, guardRoleCommand, guardThreadCommand, isRecognizedSlashCommand, normalizeSlashContent, probeSessionActivity, } from './slash-gate.js';
|
|
30
|
-
const allEfforts = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
31
|
+
const allEfforts = ['none', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'];
|
|
31
32
|
const PERMISSION_MODE_KEYS = PUBLIC_PERMISSION_MODES;
|
|
32
33
|
function defaultSlashChatmode(field) {
|
|
33
34
|
return field === 'private' ? 'interactive' : 'proactive';
|
|
@@ -126,12 +127,8 @@ function resolveSlashRelationTarget(params) {
|
|
|
126
127
|
role: params.role,
|
|
127
128
|
};
|
|
128
129
|
}
|
|
129
|
-
function getAvailableEfforts(agent, model) {
|
|
130
|
-
|
|
131
|
-
return allEfforts;
|
|
132
|
-
if (agent.name === 'codex')
|
|
133
|
-
return getCodexEfforts(model);
|
|
134
|
-
return [];
|
|
130
|
+
async function getAvailableEfforts(agent, model) {
|
|
131
|
+
return (await agent.getAvailableEfforts?.(model) ?? []);
|
|
135
132
|
}
|
|
136
133
|
function modelDisplayLabel(agent, model) {
|
|
137
134
|
const full = agent.resolveModelId?.(model);
|
|
@@ -486,7 +483,8 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
486
483
|
const isProcessLevelSlash = normalizedContent === '/restart'
|
|
487
484
|
|| normalizedContent === '/upgrade'
|
|
488
485
|
|| normalizedContent === '/reload'
|
|
489
|
-
|| normalizedContent.startsWith('/reload ')
|
|
486
|
+
|| normalizedContent.startsWith('/reload ')
|
|
487
|
+
|| normalizedContent === '/pair';
|
|
490
488
|
const roleGuard = guardRoleCommand(normalizedContent, activeChatType, isAdmin || (isDaemonOwner && isProcessLevelSlash));
|
|
491
489
|
if (roleGuard)
|
|
492
490
|
return roleGuard;
|
|
@@ -634,7 +632,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
634
632
|
const appendProcessCommands = (lines) => {
|
|
635
633
|
if (!isDaemonOwner)
|
|
636
634
|
return;
|
|
637
|
-
lines.push('', '🛠️ 进程级运维:', ' /restart - 重启服务', ' /upgrade - 检查版本更新', ' /reload [aid] - 热重载 Agent 配置', ' /fa <提示词> - 单次使用宿主级 fullaccess 执行(别名: /fullaccess)');
|
|
635
|
+
lines.push('', '🛠️ 进程级运维:', ' /restart - 重启服务', ' /upgrade - 检查版本更新', ' /reload [aid] - 热重载 Agent 配置', ' /fa <提示词> - 单次使用宿主级 fullaccess 执行(别名: /fullaccess)', ' /pair - 获取远程控制配对码');
|
|
638
636
|
};
|
|
639
637
|
if (!isAdmin && activeChatType === 'group') {
|
|
640
638
|
const lines = [
|
|
@@ -774,6 +772,23 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
774
772
|
];
|
|
775
773
|
return { kind: 'command.result', text: lines.join('\n') };
|
|
776
774
|
}
|
|
775
|
+
// /pair is also recognized on an Agent channel so it cannot fall through
|
|
776
|
+
// into model input. The daemon control channel has its own fast path; this
|
|
777
|
+
// branch preserves the same daemon-owner boundary for ordinary AUN chats.
|
|
778
|
+
if (normalizedContent === '/pair') {
|
|
779
|
+
if (!isDaemonOwner) {
|
|
780
|
+
return {
|
|
781
|
+
kind: 'command.error',
|
|
782
|
+
text: '❌ /pair 仅限 daemon-owner 使用;请向 daemon 控制 AID 发送 /pair。',
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
const pair = remoteAccessService.getPairingCode(userId);
|
|
786
|
+
const mins = Math.max(0, Math.round((pair.expiresAt - Date.now()) / 60000));
|
|
787
|
+
return {
|
|
788
|
+
kind: 'command.result',
|
|
789
|
+
text: `远程控制配对码:${pair.code}(约 ${mins} 分钟内有效)\n可用于 ECWeb 登录或远程 Menu 客户端授权`,
|
|
790
|
+
};
|
|
791
|
+
}
|
|
777
792
|
// /evolhelp 命令:返回 JSON 格式的命令列表(供程序解析)
|
|
778
793
|
if (normalizedContent === '/evolhelp') {
|
|
779
794
|
const cmds = [];
|
|
@@ -834,6 +849,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
834
849
|
cmds.push({ command: '/restart', description: '重启服务', category: '运维', roles: ['daemon-owner'] });
|
|
835
850
|
cmds.push({ command: '/upgrade', description: '检查版本更新', category: '运维', roles: ['daemon-owner'] });
|
|
836
851
|
cmds.push({ command: '/reload', args: '[aid]', description: '热重载 Agent 配置', category: '运维', roles: ['daemon-owner'] });
|
|
852
|
+
cmds.push({ command: '/pair', description: '获取远程控制配对码', category: '运维', roles: ['daemon-owner'] });
|
|
837
853
|
}
|
|
838
854
|
if (!isDaemonOwner && isAdmin) {
|
|
839
855
|
cmds.push({ command: '/reload', description: '热重载当前 Agent 配置', category: '运维', roles: ['admin', 'owner'] });
|
|
@@ -1259,12 +1275,14 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1259
1275
|
catch { }
|
|
1260
1276
|
const configuredModel = modelConfig.model;
|
|
1261
1277
|
const configuredEffort = modelConfig.effort;
|
|
1262
|
-
const
|
|
1278
|
+
const catalog = await getCatalog(modelSelector.self, fallbackBaseagent);
|
|
1279
|
+
assertCatalogSelectable(catalog);
|
|
1280
|
+
const rawModels = catalog.models.map(m => m.id);
|
|
1263
1281
|
const models = hasModelSwitcher(modelAgent)
|
|
1264
|
-
? filterModelsForRole(identity.role, fallbackBaseagent, rawModels,
|
|
1282
|
+
? filterModelsForRole(identity.role, fallbackBaseagent, rawModels, model => resolveCatalogModel(catalog, model), modelSelector.self)
|
|
1265
1283
|
: rawModels;
|
|
1266
1284
|
const currentModel = hasModelSwitcher(modelAgent) ? (configuredModel || modelAgent.getModel()) : modelAgent.name;
|
|
1267
|
-
const efforts = getAvailableEfforts(modelAgent, currentModel);
|
|
1285
|
+
const efforts = await getAvailableEfforts(modelAgent, currentModel);
|
|
1268
1286
|
const currentEffort = configuredEffort ?? modelAgent.getEffort?.() ?? 'auto';
|
|
1269
1287
|
const canReadModelList = await canReadSlashModelList({
|
|
1270
1288
|
subject: authSubject,
|
|
@@ -1289,7 +1307,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1289
1307
|
kind: 'command-card',
|
|
1290
1308
|
title: '🤖 切换模型',
|
|
1291
1309
|
buttons: models.map((m) => {
|
|
1292
|
-
const display = modelDisplayLabel(modelAgent, m);
|
|
1310
|
+
const display = modelDisplayLabel(modelAgent, m) + (catalog.models.find(e => e.id === m)?.verification === 'unverified' ? ' [unverified]' : '');
|
|
1293
1311
|
return {
|
|
1294
1312
|
label: modelMatches(modelAgent, m, currentModel) ? `✓ ${display}` : display,
|
|
1295
1313
|
command: `/model ${m}`,
|
|
@@ -1306,6 +1324,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1306
1324
|
return { kind: 'command.result', text: cardResult };
|
|
1307
1325
|
}
|
|
1308
1326
|
// 降级:文本
|
|
1327
|
+
const catalogHint = `[${catalog.source}/${catalog.freshness}] ${catalog.diagnostics.map(d => d.message).join('; ')}`;
|
|
1309
1328
|
const modelList = models.map((m) => ` ${modelMatches(modelAgent, m, currentModel) ? '✓' : ' '} ${modelDisplayLabel(modelAgent, m)}`).join('\n');
|
|
1310
1329
|
const effortHint = efforts.length > 0
|
|
1311
1330
|
? `\n推理强度: ${currentEffort === 'auto' ? 'auto (SDK默认)' : currentEffort} (使用 /effort 调整)`
|
|
@@ -1321,8 +1340,8 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1321
1340
|
const usage = !args && isAdmin ? '\n\n用法: /model <模型>' : '';
|
|
1322
1341
|
return {
|
|
1323
1342
|
kind: 'command.result',
|
|
1324
|
-
text: `当前模型: ${modelDisplayLabel(modelAgent, currentModel)}${effortHint}\n\n可用模型:\n${modelList}${usage}`,
|
|
1325
|
-
...(args === 'list' ? { structured: { ok: true, model: currentModel, effort: currentEffort, baseagent: fallbackBaseagent, models } } : {}),
|
|
1343
|
+
text: `当前模型: ${modelDisplayLabel(modelAgent, currentModel)}${effortHint}${rawModels.includes(currentModel) ? '' : ' [当前配置,未列入目录]'}\n${catalogHint}\n\n可用模型:\n${modelList}${usage}`,
|
|
1344
|
+
...(args === 'list' ? { structured: { ok: true, model: currentModel, effort: currentEffort, baseagent: fallbackBaseagent, models, revision: catalog.revision, source: catalog.source, freshness: catalog.freshness, diagnostics: catalog.diagnostics } } : {}),
|
|
1326
1345
|
};
|
|
1327
1346
|
}
|
|
1328
1347
|
return { kind: 'command.result', text: `当前模型: ${modelDisplayLabel(modelAgent, currentModel)}${effortHint}` };
|
|
@@ -1383,7 +1402,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1383
1402
|
catch { }
|
|
1384
1403
|
const models = hasModelSwitcher(modelAgent) ? await modelAgent.listModels() : [];
|
|
1385
1404
|
const allowedModels = hasModelSwitcher(modelAgent)
|
|
1386
|
-
? filterModelsForRole(identity.role, fallbackBaseagent, models, modelAgent.resolveModelId?.bind(modelAgent))
|
|
1405
|
+
? filterModelsForRole(identity.role, fallbackBaseagent, models, modelAgent.resolveModelId?.bind(modelAgent), selfAID ?? this.resolveSelfAID(channel))
|
|
1387
1406
|
: models;
|
|
1388
1407
|
const parts = args.split(/\s+/);
|
|
1389
1408
|
let newModel;
|
|
@@ -1391,7 +1410,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1391
1410
|
if (parts.length === 1) {
|
|
1392
1411
|
const arg = parts[0];
|
|
1393
1412
|
const currentModel = hasModelSwitcher(modelAgent) ? (configuredModel || modelAgent.getModel()) : modelAgent.name;
|
|
1394
|
-
const efforts = getAvailableEfforts(modelAgent, currentModel);
|
|
1413
|
+
const efforts = await getAvailableEfforts(modelAgent, currentModel);
|
|
1395
1414
|
// effort 相关参数统一转发到 /effort
|
|
1396
1415
|
if (efforts.includes(arg) || arg === 'auto') {
|
|
1397
1416
|
const delegated = await this.handle(`/effort ${arg}`, channel, channelId, undefined, userId, threadId);
|
|
@@ -1424,7 +1443,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1424
1443
|
if (!models.includes(modelArg)) {
|
|
1425
1444
|
return { kind: 'command.error', text: `❌ 无效的模型ID: ${modelArgRaw}` };
|
|
1426
1445
|
}
|
|
1427
|
-
const targetEfforts = getAvailableEfforts(modelAgent, modelArg);
|
|
1446
|
+
const targetEfforts = await getAvailableEfforts(modelAgent, modelArg);
|
|
1428
1447
|
if (targetEfforts.length === 0) {
|
|
1429
1448
|
return { kind: 'command.error', text: `⚠️ ${modelArg} 不支持推理强度设置` };
|
|
1430
1449
|
}
|
|
@@ -1582,7 +1601,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1582
1601
|
const configuredModel = modelConfig.model;
|
|
1583
1602
|
const configuredEffort = modelConfig.effort;
|
|
1584
1603
|
const currentModel = hasModelSwitcher(effortAgent) ? (configuredModel || effortAgent.getModel()) : effortAgent.name;
|
|
1585
|
-
const efforts = getAvailableEfforts(effortAgent, currentModel);
|
|
1604
|
+
const efforts = await getAvailableEfforts(effortAgent, currentModel);
|
|
1586
1605
|
const currentEffort = configuredEffort ?? effortAgent.getEffort?.() ?? 'auto';
|
|
1587
1606
|
if (efforts.length === 0) {
|
|
1588
1607
|
return { kind: 'command.error', text: '⚠️ 当前模型不支持推理强度设置' };
|
|
@@ -1644,7 +1663,7 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
1644
1663
|
const configuredModel = modelConfig.model;
|
|
1645
1664
|
const configuredEffort = modelConfig.effort;
|
|
1646
1665
|
const currentModel = hasModelSwitcher(effortAgent) ? (configuredModel || effortAgent.getModel()) : effortAgent.name;
|
|
1647
|
-
const efforts = getAvailableEfforts(effortAgent, currentModel);
|
|
1666
|
+
const efforts = await getAvailableEfforts(effortAgent, currentModel);
|
|
1648
1667
|
const currentEffort = configuredEffort ?? effortAgent.getEffort?.() ?? 'auto';
|
|
1649
1668
|
if (efforts.length === 0) {
|
|
1650
1669
|
return { kind: 'command.error', text: '⚠️ 当前模型不支持推理强度设置' };
|
|
@@ -2142,15 +2161,15 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2142
2161
|
// 才会在新的 TurnLease 中懒创建并绑定新 backend。
|
|
2143
2162
|
if (normalizedContent === '/renew' || /^\/renew\s/.test(normalizedContent)) {
|
|
2144
2163
|
if (normalizedContent !== '/renew') {
|
|
2145
|
-
return { kind: '
|
|
2164
|
+
return { kind: 'system.error', text: '❌ /renew 不接受参数,请直接使用 /renew', subtype: 'session.renew.invalid_arguments', recoverable: true };
|
|
2146
2165
|
}
|
|
2147
2166
|
if (!threadId) {
|
|
2148
|
-
return { kind: '
|
|
2167
|
+
return { kind: 'system.error', text: '⚠️ /renew 仅支持话题会话', subtype: 'session.renew.unsupported', recoverable: true };
|
|
2149
2168
|
}
|
|
2150
2169
|
// Card callbacks use synthetic message IDs on several adapters. They are
|
|
2151
2170
|
// suitable for UI correlation, but not for the durable inbound claim.
|
|
2152
2171
|
if (source === 'card-trigger') {
|
|
2153
|
-
return { kind: '
|
|
2172
|
+
return { kind: 'system.error', text: '⚠️ /renew 仅支持携带原生消息 ID 的普通消息', subtype: 'session.renew.invalid_source', recoverable: true };
|
|
2154
2173
|
}
|
|
2155
2174
|
let renewSession;
|
|
2156
2175
|
try {
|
|
@@ -2160,19 +2179,19 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2160
2179
|
}
|
|
2161
2180
|
catch (error) {
|
|
2162
2181
|
logger.warn(`[CommandHandler] /renew topic lookup failed: thread=${threadId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
2163
|
-
return { kind: '
|
|
2182
|
+
return { kind: 'system.error', text: '⚠️ 当前会话状态未知,无法安全轮换,请稍后再试', subtype: 'session.renew.state_unknown', recoverable: true };
|
|
2164
2183
|
}
|
|
2165
2184
|
if (!renewSession) {
|
|
2166
|
-
return { kind: '
|
|
2185
|
+
return { kind: 'system.error', text: '❌ 找不到当前话题会话', subtype: 'session.renew.session_missing', recoverable: true };
|
|
2167
2186
|
}
|
|
2168
2187
|
const inboundMessageId = messageId?.trim();
|
|
2169
2188
|
if (!inboundMessageId) {
|
|
2170
|
-
return { kind: '
|
|
2189
|
+
return { kind: 'system.error', text: '❌ /renew 缺少稳定的消息 ID,当前渠道不支持安全重试', subtype: 'session.renew.message_id_missing', recoverable: true };
|
|
2171
2190
|
}
|
|
2172
2191
|
if (typeof this.sessionManager.rotateTopicBackend !== 'function'
|
|
2173
2192
|
|| typeof this.messageQueue.withSessionBarrier !== 'function'
|
|
2174
2193
|
|| typeof this.messageQueue.claimInbound !== 'function') {
|
|
2175
|
-
return { kind: '
|
|
2194
|
+
return { kind: 'system.error', text: '❌ 当前运行环境不支持安全 backend 轮换', subtype: 'session.renew.unavailable', recoverable: true };
|
|
2176
2195
|
}
|
|
2177
2196
|
try {
|
|
2178
2197
|
const outcome = await this.messageQueue.withSessionBarrier(renewSession.id, async (snapshot) => {
|
|
@@ -2211,33 +2230,36 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2211
2230
|
};
|
|
2212
2231
|
});
|
|
2213
2232
|
if (outcome.kind === 'missing') {
|
|
2214
|
-
return { kind: '
|
|
2233
|
+
return { kind: 'system.error', text: '❌ 当前话题会话已不存在或归属已变化', subtype: 'session.renew.session_changed', recoverable: true };
|
|
2215
2234
|
}
|
|
2216
2235
|
if (outcome.kind === 'claim_failed') {
|
|
2217
|
-
return { kind: '
|
|
2236
|
+
return { kind: 'system.error', text: '❌ 当前渠道无法安全记录该请求,未执行 backend 轮换', subtype: 'session.renew.claim_failed', recoverable: true };
|
|
2218
2237
|
}
|
|
2219
2238
|
if (outcome.kind === 'duplicate') {
|
|
2220
|
-
return { kind: '
|
|
2239
|
+
return { kind: 'system.notice', text: 'ℹ️ 该请求已接收过,不再重复执行', subtype: 'session.renew.duplicate' };
|
|
2221
2240
|
}
|
|
2222
2241
|
if (outcome.kind === 'busy' || outcome.kind === 'unknown') {
|
|
2223
2242
|
return {
|
|
2224
|
-
kind: '
|
|
2243
|
+
kind: 'system.error',
|
|
2225
2244
|
text: outcome.kind === 'busy'
|
|
2226
2245
|
? '⚠️ 当前会话忙碌,无法安全轮换,请稍后再试'
|
|
2227
2246
|
: '⚠️ 当前会话状态未知,无法安全轮换,请稍后再试',
|
|
2247
|
+
subtype: outcome.kind === 'busy' ? 'session.renew.busy' : 'session.renew.state_unknown',
|
|
2248
|
+
recoverable: true,
|
|
2228
2249
|
};
|
|
2229
2250
|
}
|
|
2230
2251
|
if (outcome.kind !== 'rotated') {
|
|
2231
|
-
return { kind: '
|
|
2252
|
+
return { kind: 'system.error', text: '⚠️ 当前会话状态未知,无法安全轮换,请稍后再试', subtype: 'session.renew.state_unknown', recoverable: true };
|
|
2232
2253
|
}
|
|
2233
2254
|
return {
|
|
2234
|
-
kind: '
|
|
2255
|
+
kind: 'system.notice',
|
|
2235
2256
|
text: `✅ backend 已切换${outcome.wasBound ? '' : '(当前未绑定 backend)'};下一条消息将初始化新 backend(阶段一不携带历史摘要)`,
|
|
2257
|
+
subtype: 'session.renewed',
|
|
2236
2258
|
};
|
|
2237
2259
|
}
|
|
2238
2260
|
catch (error) {
|
|
2239
2261
|
logger.error(`[CommandHandler] /renew failed: session=${renewSession.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
2240
|
-
return { kind: '
|
|
2262
|
+
return { kind: 'system.error', text: `❌ backend 轮换失败:${error instanceof Error ? error.message : String(error)}`, subtype: 'session.renew.failed', recoverable: true };
|
|
2241
2263
|
}
|
|
2242
2264
|
}
|
|
2243
2265
|
// /compact 命令:手动压缩会话上下文
|
|
@@ -2451,13 +2473,17 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2451
2473
|
if (sessionName) {
|
|
2452
2474
|
const existing = await this.sessionManager.getSessionByName(channel, channelId, sessionName);
|
|
2453
2475
|
if (existing) {
|
|
2454
|
-
return { kind: '
|
|
2476
|
+
return { kind: 'system.error', text: `❌ 会话名称 "${sessionName}" 已存在,请使用其他名称`, subtype: 'session.new.name_conflict', recoverable: true };
|
|
2455
2477
|
}
|
|
2456
2478
|
}
|
|
2457
2479
|
await interruptPausedSessionBeforeReplacement(session || activeSession);
|
|
2458
2480
|
const projectPath = this.getEffectiveDefaultPath(channel);
|
|
2459
2481
|
if (sendMessage && session) {
|
|
2460
|
-
await sendMessage(channelId, `⏳ 正在创建新会话${sessionName ? `: ${sessionName}` : ''}...`, this.getReplyContext(session)
|
|
2482
|
+
await sendMessage(channelId, `⏳ 正在创建新会话${sessionName ? `: ${sessionName}` : ''}...`, this.getReplyContext(session), {
|
|
2483
|
+
kind: 'system.notice',
|
|
2484
|
+
text: `⏳ 正在创建新会话${sessionName ? `: ${sessionName}` : ''}...`,
|
|
2485
|
+
subtype: 'session.creating',
|
|
2486
|
+
});
|
|
2461
2487
|
}
|
|
2462
2488
|
const newSessionBaseagent = this.agentRegistry?.resolveByChannel(channel)?.baseagent || this.parseDefaultBaseagent();
|
|
2463
2489
|
const previousMetadata = session?.metadata || activeSession?.metadata || {};
|
|
@@ -2494,6 +2520,8 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2494
2520
|
if (session && previousAgent) {
|
|
2495
2521
|
// Reset agent backend state so the new
|
|
2496
2522
|
// session starts with a fresh conversation history
|
|
2523
|
+
// Clearing is a pure backend lifecycle operation; model selection is
|
|
2524
|
+
// resolved only when the new session performs its next turn.
|
|
2497
2525
|
await previousAgent.clearSession(session.id, session.agentSessionId || '', session.projectPath);
|
|
2498
2526
|
await previousAgent.closeSession(session.id);
|
|
2499
2527
|
}
|
|
@@ -2524,7 +2552,11 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2524
2552
|
?? newRunner.getEffort?.()
|
|
2525
2553
|
?? newAgent?.effort;
|
|
2526
2554
|
const backendBits = [newBaseagent, backendModel, backendEffort].filter(Boolean).join(' · ');
|
|
2527
|
-
return {
|
|
2555
|
+
return {
|
|
2556
|
+
kind: 'system.notice',
|
|
2557
|
+
text: `✓ 已创建新会话${sessionName ? `: ${sessionName}` : ''}\n 项目: ${this.getProjectName(projectPath)}\n 后端: ${backendBits}\n 之前的对话历史已保留,可通过 /s 查看${handoffDiscardWarning ? `\n${handoffDiscardWarning}` : ''}`,
|
|
2558
|
+
subtype: 'session.created',
|
|
2559
|
+
};
|
|
2528
2560
|
}
|
|
2529
2561
|
// /check 命令:检查 EvolAgent 实例健康(visitor/member 可用,详情仅 admin)
|
|
2530
2562
|
if (normalizedContent === '/check' || normalizedContent.startsWith('/check ')) {
|
|
@@ -2773,7 +2805,6 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2773
2805
|
const count = this.messageCache.getCount(s.id);
|
|
2774
2806
|
return `${s.projectPath} 有 ${count} 条新消息`;
|
|
2775
2807
|
});
|
|
2776
|
-
// 执行重启逻辑(共用于卡片回调和文本确认)
|
|
2777
2808
|
const executeRestart = async () => {
|
|
2778
2809
|
const suppressRealRestart = shouldSuppressRealRestart();
|
|
2779
2810
|
let restartReplyContext = replyContext;
|
|
@@ -2814,6 +2845,11 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2814
2845
|
logger.warn(`[System] Refusing restart without a valid explicit delivery route: channel=${channel} channelId=${channelId}`);
|
|
2815
2846
|
return false;
|
|
2816
2847
|
}
|
|
2848
|
+
const migrationRequirement = inspectDataMigrationRequirement(resolvePaths().root);
|
|
2849
|
+
if (migrationRequirement.required) {
|
|
2850
|
+
logger.warn(`[System] Refusing restart while data migration is pending: operations=${migrationRequirement.operationCount}`);
|
|
2851
|
+
return { code: 'DATA_MIGRATION_REQUIRED', operationCount: migrationRequirement.operationCount };
|
|
2852
|
+
}
|
|
2817
2853
|
const restartInfo = {
|
|
2818
2854
|
channel,
|
|
2819
2855
|
channelId,
|
|
@@ -2892,6 +2928,13 @@ export async function handleSlashCommand(content, channel, channelId, sendMessag
|
|
|
2892
2928
|
}
|
|
2893
2929
|
}
|
|
2894
2930
|
const restarted = await executeRestart();
|
|
2931
|
+
if (typeof restarted === 'object' && restarted.code === 'DATA_MIGRATION_REQUIRED') {
|
|
2932
|
+
return {
|
|
2933
|
+
kind: 'command.error',
|
|
2934
|
+
text: `❌ 待处理的用户数据迁移(${restarted.operationCount} 项)阻止重启。请先运行 ec data migrate --dry-run,然后运行 ec data migrate --apply。`,
|
|
2935
|
+
reason: restarted.code,
|
|
2936
|
+
};
|
|
2937
|
+
}
|
|
2895
2938
|
if (!restarted) {
|
|
2896
2939
|
return { kind: 'command.error', text: '❌ 无法确定重启通知的出站路由,请从可信会话上下文重试' };
|
|
2897
2940
|
}
|
|
@@ -768,7 +768,17 @@ export function planDataMigration(root) {
|
|
|
768
768
|
}
|
|
769
769
|
catch { }
|
|
770
770
|
const contactAudit = path.join(root, 'data', 'contact-book-audit.jsonl');
|
|
771
|
-
|
|
771
|
+
// The legacy audit file may be provisioned as an empty placeholder (for
|
|
772
|
+
// example by a protected-path sandbox). An empty source has nothing to
|
|
773
|
+
// partition and must not block daemon startup.
|
|
774
|
+
let hasContactAuditRecords = false;
|
|
775
|
+
try {
|
|
776
|
+
const stat = fs.statSync(contactAudit);
|
|
777
|
+
hasContactAuditRecords = stat.isFile()
|
|
778
|
+
&& fs.readFileSync(contactAudit, 'utf8').trim().length > 0;
|
|
779
|
+
}
|
|
780
|
+
catch { }
|
|
781
|
+
if (hasContactAuditRecords) {
|
|
772
782
|
const operationId = nextId('contact-audit');
|
|
773
783
|
operations.push({ id: operationId, kind: 'contact-audit-partition', source: contactAudit, staging: path.join(stagingDir, operationId), status: 'planned' });
|
|
774
784
|
}
|
|
@@ -246,6 +246,8 @@ const CATALOG = [
|
|
|
246
246
|
description: 'agent 任务开始',
|
|
247
247
|
fields: [
|
|
248
248
|
{ path: 'sessionId', type: 'string' },
|
|
249
|
+
{ path: 'taskId', type: 'string', optional: true },
|
|
250
|
+
{ path: 'generation', type: 'number', optional: true },
|
|
249
251
|
{ path: 'agentName', type: 'string', optional: true },
|
|
250
252
|
{ path: 'encrypt', type: 'boolean', optional: true },
|
|
251
253
|
{ path: 'chatmode', type: 'string', optional: true },
|
|
@@ -269,6 +271,8 @@ const CATALOG = [
|
|
|
269
271
|
description: 'agent 任务完成',
|
|
270
272
|
fields: [
|
|
271
273
|
{ path: 'sessionId', type: 'string' },
|
|
274
|
+
{ path: 'taskId', type: 'string', optional: true },
|
|
275
|
+
{ path: 'generation', type: 'number', optional: true },
|
|
272
276
|
{ path: 'channel', type: 'string' },
|
|
273
277
|
{ path: 'channelName', type: 'string', optional: true },
|
|
274
278
|
{ path: 'channelId', type: 'string' },
|
|
@@ -287,6 +291,8 @@ const CATALOG = [
|
|
|
287
291
|
description: 'agent 任务失败',
|
|
288
292
|
fields: [
|
|
289
293
|
{ path: 'sessionId', type: 'string' },
|
|
294
|
+
{ path: 'taskId', type: 'string', optional: true },
|
|
295
|
+
{ path: 'generation', type: 'number', optional: true },
|
|
290
296
|
{ path: 'error', type: 'string' },
|
|
291
297
|
{ path: 'errorType', type: 'string' },
|
|
292
298
|
{ path: 'terminalReason', type: 'string', optional: true },
|
|
@@ -300,6 +306,8 @@ const CATALOG = [
|
|
|
300
306
|
description: 'agent 任务被中断',
|
|
301
307
|
fields: [
|
|
302
308
|
{ path: 'sessionId', type: 'string' },
|
|
309
|
+
{ path: 'taskId', type: 'string', optional: true },
|
|
310
|
+
{ path: 'generation', type: 'number', optional: true },
|
|
303
311
|
{ path: 'reason', type: 'string', optional: true },
|
|
304
312
|
{ path: 'agentName', type: 'string', optional: true },
|
|
305
313
|
],
|
|
@@ -339,13 +347,17 @@ const CATALOG = [
|
|
|
339
347
|
{ path: 'eventPhase', type: 'string' },
|
|
340
348
|
{ path: 'isError', type: 'boolean', optional: true },
|
|
341
349
|
{ path: 'errorCode', type: 'string', optional: true },
|
|
350
|
+
{ path: 'classificationMissing', type: 'boolean', optional: true },
|
|
342
351
|
{ path: 'agentName', type: 'string', optional: true },
|
|
343
352
|
{ path: 'callId', type: 'string', optional: true },
|
|
344
353
|
{ path: 'correlationId', type: 'string', optional: true },
|
|
354
|
+
{ path: 'requestId', type: 'string', optional: true },
|
|
345
355
|
{ path: 'agentAid', type: 'string', optional: true },
|
|
346
356
|
{ path: 'permissionMode', type: 'string', optional: true },
|
|
347
357
|
{ path: 'decision', type: 'string' },
|
|
348
358
|
{ path: 'decisionSource', type: 'string' },
|
|
359
|
+
{ path: 'policyCode', type: 'string', optional: true },
|
|
360
|
+
{ path: 'reason', type: 'string', optional: true },
|
|
349
361
|
{ path: 'executed', type: 'boolean' },
|
|
350
362
|
{ path: 'executionState', type: 'string' },
|
|
351
363
|
{ path: 'timestamp', type: 'number', optional: true },
|
|
@@ -399,6 +411,21 @@ const CATALOG = [
|
|
|
399
411
|
description: 'runner 开始压缩',
|
|
400
412
|
fields: [{ path: 'sessionId', type: 'string' }],
|
|
401
413
|
},
|
|
414
|
+
{
|
|
415
|
+
type: 'runner:proactive-reminder',
|
|
416
|
+
namespace: 'runner',
|
|
417
|
+
name: 'proactive-reminder',
|
|
418
|
+
description: '主动模式提醒已生成并请求注入模型上下文',
|
|
419
|
+
fields: [
|
|
420
|
+
{ path: 'sessionId', type: 'string' },
|
|
421
|
+
{ path: 'kind', type: 'string' },
|
|
422
|
+
{ path: 'text', type: 'string' },
|
|
423
|
+
{ path: 'queueLength', type: 'number', optional: true },
|
|
424
|
+
{ path: 'toolCount', type: 'number', optional: true },
|
|
425
|
+
{ path: 'injection', type: 'string' },
|
|
426
|
+
{ path: 'timestamp', type: 'number', optional: true },
|
|
427
|
+
],
|
|
428
|
+
},
|
|
402
429
|
{
|
|
403
430
|
type: 'runner:compact-complete',
|
|
404
431
|
namespace: 'runner',
|
|
@@ -690,6 +717,11 @@ const CATALOG = [
|
|
|
690
717
|
{ path: 'runId', type: 'string' },
|
|
691
718
|
{ path: 'originTriggerId', type: 'string' },
|
|
692
719
|
{ path: 'reason', type: 'string' },
|
|
720
|
+
{ path: 'reasonCode', type: 'string', optional: true },
|
|
721
|
+
{ path: 'decisionSource', type: 'string', optional: true },
|
|
722
|
+
{ path: 'executionState', type: 'string', optional: true },
|
|
723
|
+
{ path: 'generation', type: 'number', optional: true },
|
|
724
|
+
{ path: 'currentGeneration', type: 'number', optional: true },
|
|
693
725
|
{ path: 'targetChannel', type: 'string' },
|
|
694
726
|
{ path: 'targetChannelId', type: 'string' },
|
|
695
727
|
{ path: 'fireTime', type: 'number', optional: true },
|
|
@@ -266,8 +266,8 @@ export class HandoffRuntime {
|
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
268
|
}
|
|
269
|
-
buildPromptItem(message) {
|
|
270
|
-
return this.buildPromptItems(message)[0] ?? null;
|
|
269
|
+
buildPromptItem(message, fallbackPeerRole) {
|
|
270
|
+
return this.buildPromptItems(message, fallbackPeerRole)[0] ?? null;
|
|
271
271
|
}
|
|
272
272
|
isDiscardedDelivery(message) {
|
|
273
273
|
const delivery = message.handoffDelivery;
|
|
@@ -277,7 +277,7 @@ export class HandoffRuntime {
|
|
|
277
277
|
const ids = delivery.handoffIds?.length ? delivery.handoffIds : [delivery.handoffId];
|
|
278
278
|
return ids.length > 0 && ids.every(handoffId => this.store.get(selfAid, handoffId)?.state === 'discarded');
|
|
279
279
|
}
|
|
280
|
-
buildPromptItems(message) {
|
|
280
|
+
buildPromptItems(message, fallbackPeerRole) {
|
|
281
281
|
const delivery = message.handoffDelivery;
|
|
282
282
|
const selfAid = message.selfAID;
|
|
283
283
|
if (!delivery || !selfAid)
|
|
@@ -310,8 +310,18 @@ export class HandoffRuntime {
|
|
|
310
310
|
peerId: message.peerId,
|
|
311
311
|
peerName: message.peerName,
|
|
312
312
|
peerType: message.peerType,
|
|
313
|
+
peerRole: message.batchRole ?? message.resolvedIdentity?.role ?? fallbackPeerRole,
|
|
314
|
+
sameDevice: message.sameDevice,
|
|
315
|
+
sameNetwork: message.sameNetwork,
|
|
316
|
+
sameEgressIp: message.sameEgressIp,
|
|
317
|
+
encrypted: message.encrypted,
|
|
313
318
|
content: message.content,
|
|
314
319
|
timestamp: message.timestamp,
|
|
320
|
+
receivedAt: message.receivedAt,
|
|
321
|
+
gatewaySeq: message.gatewaySeq,
|
|
322
|
+
images: message.images,
|
|
323
|
+
mentions: message.mentions,
|
|
324
|
+
mentionAids: message.mentionAids,
|
|
315
325
|
causation: message.causation,
|
|
316
326
|
handoff: {
|
|
317
327
|
kind: 'response_to_origin',
|
|
@@ -348,8 +358,18 @@ export class HandoffRuntime {
|
|
|
348
358
|
peerId: message.peerId,
|
|
349
359
|
peerName: message.peerName,
|
|
350
360
|
peerType: message.peerType,
|
|
361
|
+
peerRole: message.batchRole ?? message.resolvedIdentity?.role ?? fallbackPeerRole,
|
|
362
|
+
sameDevice: message.sameDevice,
|
|
363
|
+
sameNetwork: message.sameNetwork,
|
|
364
|
+
sameEgressIp: message.sameEgressIp,
|
|
365
|
+
encrypted: message.encrypted,
|
|
351
366
|
content: message.content,
|
|
352
367
|
timestamp: message.timestamp,
|
|
368
|
+
receivedAt: message.receivedAt,
|
|
369
|
+
gatewaySeq: message.gatewaySeq,
|
|
370
|
+
images: message.images,
|
|
371
|
+
mentions: message.mentions,
|
|
372
|
+
mentionAids: message.mentionAids,
|
|
353
373
|
causation: message.causation,
|
|
354
374
|
handoff: {
|
|
355
375
|
kind: 'request_to_target',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { logger } from '../../utils/logger.js';
|
|
2
|
-
import { summarizeToolInput } from '../../utils/tool-summary.js';
|
|
2
|
+
import { summarizeToolInput, toolInputForDisplay } from '../../utils/tool-summary.js';
|
|
3
3
|
import { getErrorMessage, isContextTooLongText } from '../../utils/error-utils.js';
|
|
4
4
|
import { DEFAULT_FLUSH_DELAY_MS } from '../../types.js';
|
|
5
5
|
export class IMRenderer {
|
|
@@ -34,6 +34,9 @@ export class IMRenderer {
|
|
|
34
34
|
const correlatedEvent = event.type === 'tool_use' || event.type === 'tool_result'
|
|
35
35
|
? { ...event, correlationId: event.correlationId ?? event.callId }
|
|
36
36
|
: event;
|
|
37
|
+
const permissionMode = typeof this.opts.permissionMode === 'function'
|
|
38
|
+
? this.opts.permissionMode()
|
|
39
|
+
: this.opts.permissionMode;
|
|
37
40
|
logger.event({
|
|
38
41
|
source: 'runner',
|
|
39
42
|
taskId: this.opts.envelope.taskId,
|
|
@@ -41,6 +44,7 @@ export class IMRenderer {
|
|
|
41
44
|
channelId: this.opts.envelope.channelId,
|
|
42
45
|
agentAid: this.opts.agentAid,
|
|
43
46
|
agentName: this.opts.envelope.agentName,
|
|
47
|
+
...(permissionMode ? { permissionMode } : {}),
|
|
44
48
|
...(correlatedEvent.type === 'tool_use' || correlatedEvent.type === 'tool_result'
|
|
45
49
|
? { correlationId: correlatedEvent.correlationId, toolName: correlatedEvent.name }
|
|
46
50
|
: {}),
|
|
@@ -184,7 +188,7 @@ export class IMRenderer {
|
|
|
184
188
|
kind: 'tool_call',
|
|
185
189
|
call_id: callId || this.synthCallId(),
|
|
186
190
|
name,
|
|
187
|
-
arguments: input,
|
|
191
|
+
arguments: toolInputForDisplay(name, input),
|
|
188
192
|
text: descText,
|
|
189
193
|
});
|
|
190
194
|
this.messageTimestamps.push(Date.now());
|
|
@@ -568,7 +572,7 @@ export class IMRenderer {
|
|
|
568
572
|
text: desc,
|
|
569
573
|
};
|
|
570
574
|
if (event.input !== undefined)
|
|
571
|
-
item.arguments = event.input;
|
|
575
|
+
item.arguments = toolInputForDisplay(event.name, event.input);
|
|
572
576
|
return item;
|
|
573
577
|
}
|
|
574
578
|
case 'tool_result':
|