evolcore 0.0.31 → 0.0.33
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 +35 -0
- package/bin/install-codex-managed-hooks.mjs +124 -37
- package/dist/agents/claude-runner.js +29 -2
- package/dist/agents/codex/app-server-client.js +3 -0
- package/dist/agents/codex/diagnostics.js +76 -44
- package/dist/agents/codex-runner.js +51 -24
- package/dist/agents/ecagent-runner.js +9 -13
- package/dist/agents/gemini-runner.js +4 -0
- package/dist/aun/aid/store.js +0 -81
- package/dist/aun/group/fs-download.js +1 -10
- package/dist/aun/group/operations.js +0 -1
- package/dist/aun/msg/history.js +1 -0
- package/dist/aun/msg/managed-operation.js +130 -32
- package/dist/aun/msg/p2p.js +0 -1
- package/dist/aun/outbox.js +50 -1
- package/dist/aun/service-proxy.js +12 -18
- package/dist/aun/storage/index.js +29 -0
- package/dist/channels/aun.js +38 -137
- package/dist/channels/daemon.js +257 -2
- package/dist/cli/agent-command.js +64 -31
- package/dist/cli/agent-create.js +43 -24
- package/dist/cli/agent.js +16 -70
- package/dist/cli/aun-commands.js +512 -32
- package/dist/cli/contact.js +8 -2
- package/dist/cli/ctl-command.js +1 -2
- package/dist/cli/daemon-commands.js +82 -13
- package/dist/cli/debug-mode.js +154 -0
- package/dist/cli/diag.js +2 -2
- package/dist/cli/handoff-command.js +18 -5
- package/dist/cli/index.js +81 -64
- package/dist/cli/init.js +2 -2
- package/dist/cli/managed-command-guard.js +5 -0
- package/dist/cli/memory-command.js +93 -12
- package/dist/cli/model.js +14 -138
- package/dist/cli/queue-command.js +51 -0
- package/dist/cli/response.js +5 -54
- package/dist/cli/session-command.js +194 -0
- package/dist/cli/skill-command.js +85 -3
- package/dist/cli/stats.js +10 -4
- package/dist/cli/task-command.js +1 -0
- package/dist/cli/task-context.js +16 -0
- package/dist/cli/thread-command.js +620 -0
- package/dist/cli/trigger-command.js +76 -50
- package/dist/config/builtin-roles.js +9 -7
- package/dist/config/config-field-policy.js +2 -3
- package/dist/config/config-manager.js +7 -2
- package/dist/config/resolved-config-op.js +3 -0
- package/dist/config-store.js +15 -0
- package/dist/core/agent-ipc-registration.js +65 -22
- package/dist/core/auth/agent-delegation.js +42 -2
- package/dist/core/auth/debug-context.js +139 -0
- package/dist/core/auth/delegation-authorization.js +1 -0
- package/dist/core/auth/operation-authorizer.js +24 -1
- package/dist/core/auth/operation-catalog.js +44 -3
- package/dist/core/background-session/session-cleanup.js +212 -0
- package/dist/core/background-session/types.js +10 -0
- package/dist/core/bootstrap-messages.js +1 -1
- package/dist/core/bootstrap-service.js +6 -3
- package/dist/core/command/command-handler.js +224 -45
- package/dist/core/command/diag-service.js +5 -1
- package/dist/core/command/memory-slash.js +6 -2
- package/dist/core/command/menu-catalog.js +48 -1
- package/dist/core/command/menu-handler.js +92 -16
- package/dist/core/command/menu-protocol.js +24 -1
- package/dist/core/command/skill-slash.js +322 -0
- package/dist/core/command/slash-gate.js +6 -4
- package/dist/core/command/slash-handler.js +193 -13
- package/dist/core/command/topic-slash.js +528 -0
- package/dist/core/evolagent-registry.js +20 -5
- package/dist/core/handoff/ipc-registration.js +38 -0
- package/dist/core/handoff/runtime.js +5 -11
- package/dist/core/handoff/store.js +5 -0
- package/dist/core/ipc-registration.js +210 -9
- package/dist/core/memory/consolidation-context.js +49 -16
- package/dist/core/memory/consolidation-ops-records.js +35 -0
- package/dist/core/memory/consolidation-queue-format.js +21 -0
- package/dist/core/memory/consolidation.js +174 -180
- package/dist/core/message/aun-ipc-sender.js +207 -8
- package/dist/core/message/im-renderer.js +149 -6
- package/dist/core/message/message-bridge.js +13 -3
- package/dist/core/message/message-log.js +1 -0
- package/dist/core/message/message-queue.js +131 -3
- package/dist/core/message/peer-mode.js +6 -1
- package/dist/core/message/response-engine.js +379 -69
- package/dist/core/message/subtask-tool-projection.js +140 -0
- package/dist/core/model/catalog-service.js +17 -12
- package/dist/core/permission/ec-command-parser.js +126 -7
- package/dist/core/permission/sandbox-runtime.js +14 -1
- package/dist/core/session/session-idle-monitor.js +249 -22
- package/dist/core/session/session-manager.js +54 -9
- package/dist/core/skill/command-parser.js +13 -0
- package/dist/core/skill/index-generator.js +4 -1
- package/dist/core/skill/startup.js +41 -0
- package/dist/core/skill/switch-resolver.js +55 -29
- package/dist/core/task/task-recovery-service.js +2 -0
- package/dist/core/task/task-resume-operation.js +11 -0
- package/dist/core/thread/command-parser.js +125 -0
- package/dist/core/thread/index.js +1 -0
- package/dist/core/thread/ipc-operation.js +95 -0
- package/dist/core/thread/thread-context-storage.js +131 -0
- package/dist/core/thread/thread-operation.js +258 -0
- package/dist/core/thread/thread-route.js +33 -0
- package/dist/core/thread/thread-service.js +777 -0
- package/dist/core/thread/types.js +1 -0
- package/dist/eck/message-renderer.js +35 -0
- package/dist/index.js +10 -7
- package/dist/ipc.js +234 -17
- package/dist/paths.js +23 -0
- package/dist/response-system/engines/v1/proactive-flow.js +169 -80
- package/dist/trigger/authorization.js +59 -29
- package/dist/trigger/feedback.js +7 -1
- package/dist/trigger/ipc-service.js +49 -35
- package/dist/trigger/parser.js +63 -1
- package/dist/trigger/script-sandbox.js +58 -77
- package/dist/trigger/validation.js +14 -0
- package/dist/utils/error-utils.js +22 -1
- package/kits/docs/AUTHORING.md +1 -1
- package/kits/docs/channels/aun.md +8 -0
- package/kits/docs/context-assembly.md +1 -0
- package/kits/docs/evolcore/INDEX.md +3 -2
- package/kits/docs/evolcore/agent-create.md +39 -28
- package/kits/docs/evolcore/agent.md +19 -4
- package/kits/docs/evolcore/ec-capabilities.md +4 -0
- package/kits/docs/evolcore/group-collaboration.md +3 -5
- package/kits/docs/evolcore/group.md +3 -4
- package/kits/docs/evolcore/memory-consolidation.md +1 -1
- package/kits/docs/evolcore/menu-exec-schema-commands.md +2 -2
- package/kits/docs/evolcore/menu-protocol.md +7 -0
- package/kits/docs/evolcore/msg.md +5 -8
- package/kits/docs/evolcore/task.md +2 -0
- package/kits/docs/evolcore/thread-chain.md +267 -0
- package/kits/docs/evolcore/trigger.md +2 -2
- package/kits/docs/prompt-loading-architecture.md +1 -0
- package/kits/eck_manifest.json +61 -26
- package/kits/eck_message_manifest.json +169 -10
- package/kits/rules/01-overview.md +0 -9
- package/kits/rules/05-venue.md +1 -1
- package/kits/rules/06-channel.md +7 -1
- package/kits/rules/07-memory-and-thread.md +202 -0
- package/kits/schemas/relation-config.schema.9.json +18 -3
- package/kits/schemas/role-config.schema.1.json +6 -6
- package/kits/schemas/single-session.schema.1.json +6 -6
- package/kits/schemas/single-session.schema.2.json +6 -6
- package/kits/schemas/single-session.schema.3.json +6 -6
- package/kits/skills/.switches.json +12 -1
- package/kits/skills/ec-group/SKILL.md +234 -0
- package/kits/skills/ec-skill/SKILL.md +10 -1
- package/kits/skills/ec-skill/scripts/cli.mjs +15 -1
- package/kits/skills/scrapling-article-fetch/SKILL.md +128 -0
- package/kits/skills/scrapling-article-fetch/scripts/check_python_env.py +54 -0
- package/kits/skills/scrapling-article-fetch/scripts/render_markdown_reply.py +35 -0
- package/kits/skills/scrapling-article-fetch/scripts/run_pipeline.sh +16 -0
- package/kits/skills/scrapling-article-fetch/scripts/scrapling_fetch.py +344 -0
- package/kits/skills/thread-ops/SKILL.md +492 -0
- package/kits/skills/wechat-article-media-download/SKILL.md +65 -0
- package/kits/skills/wechat-article-media-download/scripts/download.py +163 -0
- package/kits/skills/wechat-article-reader/SKILL.md +97 -0
- package/kits/skills/wechat-article-reader/scripts/fetch.mjs +256 -0
- package/kits/templates/bootstrap-welcome.md +7 -7
- package/kits/templates/memory-consolidation/forget.md +5 -0
- package/kits/templates/memory-consolidation/generalize.md +5 -0
- package/kits/templates/memory-consolidation/profile.md +5 -0
- package/kits/templates/memory-consolidation/promote.md +5 -0
- package/kits/templates/message-fragments/item.md +2 -1
- package/kits/templates/message-fragments/thread-context.md +6 -0
- package/kits/templates/message-fragments/trigger-session.md +2 -0
- package/kits/templates/message-fragments/trigger-thread-check.md +2 -0
- package/kits/templates/roles/member.json +2 -0
- package/kits/templates/roles/visitor.json +2 -0
- package/kits/templates/system-fragments/bootstrap.md +66 -72
- package/kits/templates/system-fragments/channel.md +3 -6
- package/kits/templates/system-fragments/commands.md +2 -1
- package/kits/templates/system-fragments/managed-runtime.md +15 -0
- package/kits/templates/system-fragments/reply.md +3 -2
- package/kits/templates/system-fragments/session.md +5 -14
- package/package.json +3 -1
- package/kits/docs/evolcore/group-fs.md +0 -17
- package/kits/docs/venues/aun-group.md +0 -45
- package/kits/docs/venues/group.md +0 -43
|
@@ -21,6 +21,20 @@ export class MessageQueue {
|
|
|
21
21
|
interruptBarriers = new Map();
|
|
22
22
|
interruptFailures = new Map();
|
|
23
23
|
activeTerminalReasons = new Map();
|
|
24
|
+
/**
|
|
25
|
+
* 允许「未提交输入」回队的 key(仅新消息到达触发的中断)。
|
|
26
|
+
* 与 activeTerminalReasons 分开:后者还承载 stop/timeout/priority 抢占等
|
|
27
|
+
* 语义,那些场景绝不能复活旧输入。
|
|
28
|
+
*/
|
|
29
|
+
requeueableInterrupts = new Set();
|
|
30
|
+
/**
|
|
31
|
+
* queueKey → 触发本次 new_message 中断的消息。
|
|
32
|
+
*
|
|
33
|
+
* 回队前用它把「打断消息」从 pending 中排除:只有当队列里没有其它等待项时
|
|
34
|
+
* 才回队。否则重放旧输入会插到那些等待项(如被 defer 的群聊消息)前面,
|
|
35
|
+
* 打乱既有调度顺序。
|
|
36
|
+
*/
|
|
37
|
+
interruptingMessages = new Map();
|
|
24
38
|
eventBus;
|
|
25
39
|
recentMessageIds = new Set();
|
|
26
40
|
DEDUP_WINDOW = 60_000; // 1 分钟窗口
|
|
@@ -108,6 +122,19 @@ export class MessageQueue {
|
|
|
108
122
|
}
|
|
109
123
|
}
|
|
110
124
|
});
|
|
125
|
+
subscribe.call(eventBus, 'input_accepted', event => {
|
|
126
|
+
if (!('inputId' in event) || !event.inputId)
|
|
127
|
+
return;
|
|
128
|
+
const inputEvent = event;
|
|
129
|
+
// inputId 格式为 sessionId 或 sessionId:xxx,取第一段匹配
|
|
130
|
+
const sessionId = inputEvent.inputId.split(':')[0];
|
|
131
|
+
for (const [queueKey, state] of this.activeStates) {
|
|
132
|
+
if (this.matchesSession(queueKey, sessionId)) {
|
|
133
|
+
state.inputSubmitted = true;
|
|
134
|
+
logger.debug(`[MessageQueue] input_accepted for ${queueKey}, taskId=${state.taskId}, generation=${state.generation}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
});
|
|
111
138
|
subscribe.call(eventBus, 'task:completed', event => {
|
|
112
139
|
if ('sessionId' in event && event.sessionId)
|
|
113
140
|
this.markActiveTerminal(event.sessionId, 'completed');
|
|
@@ -124,6 +151,37 @@ export class MessageQueue {
|
|
|
124
151
|
this.activeTerminalReasons.set(queueKey, reason);
|
|
125
152
|
}
|
|
126
153
|
}
|
|
154
|
+
/**
|
|
155
|
+
* 显式允许/禁止该 key 的 active 批次在中断后回队。
|
|
156
|
+
*
|
|
157
|
+
* 只有「新消息到达触发的中断」才置 true:那种场景下旧输入尚未提交给模型,
|
|
158
|
+
* 用户也确实期望两条一起被看到。stop / 优先级抢占 / 超时等一律不允许复活。
|
|
159
|
+
*/
|
|
160
|
+
markRequeueable(queueKey, requeueable) {
|
|
161
|
+
if (requeueable)
|
|
162
|
+
this.requeueableInterrupts.add(queueKey);
|
|
163
|
+
else
|
|
164
|
+
this.requeueableInterrupts.delete(queueKey);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* 标记 active 批次的输入已真正提交给模型(runner 发出 input_accepted 后调用)。
|
|
168
|
+
*
|
|
169
|
+
* 这是 pre-submit 回队的关键判据:只有「未提交」的 active 才能在 new_message
|
|
170
|
+
* 中断后安全放回队列;已提交的批次若回队,会在 provider session 里产生重复用户轮次。
|
|
171
|
+
*/
|
|
172
|
+
markInputSubmitted(sessionId, taskId) {
|
|
173
|
+
for (const [queueKey, state] of this.activeStates) {
|
|
174
|
+
if (!this.matchesSession(queueKey, sessionId))
|
|
175
|
+
continue;
|
|
176
|
+
// 同一 session 可能有多个 queueKey(不同 agent/project),taskId 用来精确定位。
|
|
177
|
+
if (taskId !== undefined && state.taskId !== undefined && state.taskId !== taskId)
|
|
178
|
+
continue;
|
|
179
|
+
state.inputSubmitted = true;
|
|
180
|
+
state.submittedMessageIds = Array.from(state.messageIds);
|
|
181
|
+
logger.debug(`[Queue] input submitted: key=${queueKey} task=${taskId ?? '<none>'} ids=${state.submittedMessageIds.join(',')}`);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
127
185
|
/**
|
|
128
186
|
* 注册一次性消息拦截器:下一条来自 sessionKey 的消息不入队、不触发 interrupt,
|
|
129
187
|
* 直接传给 handler。用于 AskUserQuestion 的"手动输入"场景。
|
|
@@ -1082,7 +1140,12 @@ export class MessageQueue {
|
|
|
1082
1140
|
activeState?.peerId === message.peerId &&
|
|
1083
1141
|
!this.hasOtherPeerQueued(queueKey, message.peerId);
|
|
1084
1142
|
if (interruptSingle || interruptGroupSamePeer) {
|
|
1085
|
-
|
|
1143
|
+
const inputSubmitted = activeState?.inputSubmitted ?? false;
|
|
1144
|
+
logger.info(`[Queue] new_message interrupt: key=${queueKey} samePeer=${interruptGroupSamePeer} taskId=${activeState?.taskId ?? '<none>'} generation=${activeState?.generation ?? '<none>'} inputSubmitted=${inputSubmitted} activeMsg=${Array.from(activeState?.messageIds ?? []).join(',')}`);
|
|
1145
|
+
// 新消息到达才允许 pre-submit 回队:旧输入尚未提交给模型,
|
|
1146
|
+
// 且用户期望它与刚到的消息一起被看到。
|
|
1147
|
+
this.markRequeueable(queueKey, true);
|
|
1148
|
+
this.interruptingMessages.set(queueKey, message);
|
|
1086
1149
|
this.eventBus?.publish({
|
|
1087
1150
|
type: 'task:interrupted',
|
|
1088
1151
|
sessionId: sessionKey,
|
|
@@ -1218,7 +1281,7 @@ export class MessageQueue {
|
|
|
1218
1281
|
this.activeBatches.set(queueKey, activeItem);
|
|
1219
1282
|
this.processingStartTime.set(queueKey, Date.now());
|
|
1220
1283
|
this.persistQueuesImmediate();
|
|
1221
|
-
logger.info(`[Queue] processing batch: key=${queueKey} items=${rawItems.length} pending=${queue.length} rawPending=${this.queueRawMessageCount(queue)} batchRole=${merged.message.batchRole ?? '<mixed>'} peer=${activeState.peerId ?? '<multi>'} msg=${merged.message.messageId ?? '<none>'}`);
|
|
1284
|
+
logger.info(`[Queue] processing batch: key=${queueKey} items=${rawItems.length} pending=${queue.length} rawPending=${this.queueRawMessageCount(queue)} batchRole=${merged.message.batchRole ?? '<mixed>'} peer=${activeState.peerId ?? '<multi>'} msg=${merged.message.messageId ?? '<none>'} sourceIds=${Array.from(activeMessageIds).join(',')}`);
|
|
1222
1285
|
try {
|
|
1223
1286
|
await this.handler(merged.message);
|
|
1224
1287
|
logger.debug(`[Queue] Message processed successfully`);
|
|
@@ -1230,10 +1293,17 @@ export class MessageQueue {
|
|
|
1230
1293
|
}
|
|
1231
1294
|
finally {
|
|
1232
1295
|
if (!this.shuttingDown) {
|
|
1296
|
+
const terminalReason = this.activeTerminalReasons.get(queueKey);
|
|
1297
|
+
const disposition = this.disposeInterruptedBatch(queueKey, activeState, rawParts, merged.message.causation);
|
|
1298
|
+
if (disposition !== 'none') {
|
|
1299
|
+
logger.info(`[Queue] batch disposition: key=${queueKey} reason=${terminalReason ?? '<completed>'} disposition=${disposition}`);
|
|
1300
|
+
}
|
|
1233
1301
|
this.activeBatches.delete(queueKey);
|
|
1234
1302
|
this.processingStartTime.delete(queueKey);
|
|
1235
1303
|
this.activeStates.delete(queueKey);
|
|
1236
1304
|
this.activeTerminalReasons.delete(queueKey);
|
|
1305
|
+
this.requeueableInterrupts.delete(queueKey);
|
|
1306
|
+
this.interruptingMessages.delete(queueKey);
|
|
1237
1307
|
this.persistQueuesImmediate();
|
|
1238
1308
|
}
|
|
1239
1309
|
}
|
|
@@ -1244,6 +1314,63 @@ export class MessageQueue {
|
|
|
1244
1314
|
}
|
|
1245
1315
|
}
|
|
1246
1316
|
}
|
|
1317
|
+
/**
|
|
1318
|
+
* 决定被中断的 active 批次的下落。
|
|
1319
|
+
*
|
|
1320
|
+
* 只有同时满足两个条件才回队:
|
|
1321
|
+
* 1) 该 key 被显式标记为「新消息到达」(markRequeueable),而不是 stop/超时/优先级抢占;
|
|
1322
|
+
* 2) 该批次的输入尚未提交给模型(未收到 input_accepted / 未产出输出)。
|
|
1323
|
+
*
|
|
1324
|
+
* 已提交的批次若回队,会在 provider session 里产生重复用户轮次;
|
|
1325
|
+
* stop/timeout/recalled 是用户或系统的明确意图,绝不复活;
|
|
1326
|
+
* daemon_restart 由启动恢复流程处理,这里不重复入队。
|
|
1327
|
+
*
|
|
1328
|
+
* 回队到物理队首并保留原始 messageId/receivedAt,下一次 dequeueGreedy 会把它
|
|
1329
|
+
* 与期间到达的 pending 消息一起合并,等价于「未提交的旧输入 + 新输入」同批提交。
|
|
1330
|
+
*/
|
|
1331
|
+
disposeInterruptedBatch(queueKey, activeState, rawParts, causation) {
|
|
1332
|
+
if (!this.requeueableInterrupts.has(queueKey))
|
|
1333
|
+
return 'none';
|
|
1334
|
+
if (!this.interruptCallback
|
|
1335
|
+
|| this.activeTerminalReasons.get(queueKey) !== 'new_message')
|
|
1336
|
+
return 'none';
|
|
1337
|
+
if (rawParts.length === 0)
|
|
1338
|
+
return 'none';
|
|
1339
|
+
// 已提交:不能重放,交由 provider/session 侧的既有用户轮次保证上下文完整。
|
|
1340
|
+
if (activeState.inputSubmitted)
|
|
1341
|
+
return 'input_already_submitted';
|
|
1342
|
+
const queue = this.queues.get(queueKey);
|
|
1343
|
+
if (!queue) {
|
|
1344
|
+
logger.warn(`[Queue] pre-submit requeue skipped: queue gone key=${queueKey}`);
|
|
1345
|
+
return 'none';
|
|
1346
|
+
}
|
|
1347
|
+
const requeued = rawParts.map(part => this.itemFromPart(part));
|
|
1348
|
+
// 只有当队列里除打断消息外没有其它等待项时才回队。
|
|
1349
|
+
// 若已有其它 pending(例如被 defer 的群聊消息),说明旧输入本可在当前轮
|
|
1350
|
+
// 处理完毕,回队会插入一个与它们无关的额外轮次并打乱既有调度顺序;
|
|
1351
|
+
// 那种情况下保持原有中断行为。
|
|
1352
|
+
const interrupting = this.interruptingMessages.get(queueKey);
|
|
1353
|
+
const pendingWithoutInterrupt = interrupting
|
|
1354
|
+
? queue.filter(item => item.message.messageId !== interrupting.messageId)
|
|
1355
|
+
: queue;
|
|
1356
|
+
if (pendingWithoutInterrupt.length > 0) {
|
|
1357
|
+
logger.info(`[Queue] pre-submit requeue skipped: key=${queueKey} other pending=${pendingWithoutInterrupt.length}`);
|
|
1358
|
+
return 'none';
|
|
1359
|
+
}
|
|
1360
|
+
queue.unshift(...requeued);
|
|
1361
|
+
// 按物理顺序重建逻辑队列,避免把旧输入追加到新消息之后,导致 FIFO
|
|
1362
|
+
// 在下一次 reorderPhysical 时颠倒回队消息与打断消息的顺序。
|
|
1363
|
+
// 与 enqueue 路径保持同一条件,避免把 owner-inject/interrupt 消息写进逻辑队列。
|
|
1364
|
+
this.logicalQueue.clear(queueKey);
|
|
1365
|
+
for (const item of queue) {
|
|
1366
|
+
if (item.message.source !== 'owner-inject' && item.message.attentionPolicy !== 'interrupt') {
|
|
1367
|
+
this.logicalQueue.enqueue(queueKey, item.message);
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
logger.info(`[Queue] requeued pre-submit batch: key=${queueKey} ids=${requeued
|
|
1371
|
+
.flatMap(item => this.messageIdsFor(item)).join(',')} causation=${causation?.traceId ?? '<none>'}`);
|
|
1372
|
+
return 'requeued_pre_submit';
|
|
1373
|
+
}
|
|
1247
1374
|
/**
|
|
1248
1375
|
* 贪心弹出队首可合并消息。
|
|
1249
1376
|
* 群聊入队携带 role,此时取出当前所有群聊 pending 并按时间线合并;
|
|
@@ -1337,7 +1464,8 @@ export class MessageQueue {
|
|
|
1337
1464
|
&& a.channelKey === b.channelKey
|
|
1338
1465
|
&& a.channelType === b.channelType
|
|
1339
1466
|
&& a.chatType === b.chatType
|
|
1340
|
-
&& a.peerKey === b.peerKey
|
|
1467
|
+
&& a.peerKey === b.peerKey
|
|
1468
|
+
&& a.approvalInteractionPolicy === b.approvalInteractionPolicy;
|
|
1341
1469
|
}
|
|
1342
1470
|
firstTimestamp(item) {
|
|
1343
1471
|
const parts = this.partsOf(item);
|
|
@@ -14,8 +14,11 @@ export function resolveChatMode(params) {
|
|
|
14
14
|
configured = undefined;
|
|
15
15
|
}
|
|
16
16
|
const kind = normalizePeerType(params.peerType);
|
|
17
|
+
// 运行时硬约束(非配置项):system/service 始终 interactive;agent 始终 proactive
|
|
17
18
|
if (kind === 'system' || kind === 'service')
|
|
18
19
|
return 'interactive';
|
|
20
|
+
if (kind === 'agent')
|
|
21
|
+
return 'proactive';
|
|
19
22
|
const field = chatmodeFieldForPeer(params.chatType, params.peerType);
|
|
20
23
|
const decision = resolveRuntimeStringField({
|
|
21
24
|
selfAid: params.self,
|
|
@@ -70,9 +73,11 @@ export function isSystemOrServicePeer(peerType) {
|
|
|
70
73
|
*/
|
|
71
74
|
export function resolveChatModeForPeer(params) {
|
|
72
75
|
const kind = normalizePeerType(params.peerType);
|
|
73
|
-
// 运行时硬约束(非配置项):system/service
|
|
76
|
+
// 运行时硬约束(非配置项):system/service 对端始终同步交互;agent 对端始终主动响应
|
|
74
77
|
if (kind === 'system' || kind === 'service')
|
|
75
78
|
return 'interactive';
|
|
79
|
+
if (kind === 'agent')
|
|
80
|
+
return 'proactive';
|
|
76
81
|
// 合并后的场景表 → 出厂默认表
|
|
77
82
|
const field = chatmodeFieldForPeer(params.chatType, params.peerType);
|
|
78
83
|
return params.configured?.[field] ?? chatmodeFactoryDefaults()[field];
|